]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/plot/libplot/machdep.c
- use the double-buffer buffer to allow redrawing on resize events.
[plan9front.git] / sys / src / cmd / plot / libplot / machdep.c
1 #include "mplot.h"
2 Image *offscreen;
3 static int buffer;
4
5 static Point
6 xlp(Point p)
7 {
8         p.x += screen->r.min.x + 4 - offscreen->r.min.x;
9         p.y += screen->r.min.y + 4 - offscreen->r.min.y;
10         return p;
11 }
12
13 static Rectangle
14 xlr(Rectangle r)
15 {
16         int dx, dy;
17
18         dx = screen->r.min.x + 4 - offscreen->r.min.x;
19         dy = screen->r.min.y + 4 - offscreen->r.min.y;
20         r.min.x += dx;
21         r.min.y += dy;
22         r.max.x += dx;
23         r.max.y += dy;
24         return r;
25 }
26
27 /*
28  * Clear the window from x0, y0 to x1, y1 (inclusive) to color c
29  */
30 void
31 m_clrwin(int x0, int y0, int x1, int y1, int c)
32 {
33         draw(offscreen, Rect(x0, y0, x1+1, y1+1), getcolor(c), nil, ZP);
34         if(offscreen != screen && !buffer)
35                 draw(screen, xlr(Rect(x0, y0, x1+1, y1+1)), getcolor(c), nil, ZP);
36 }
37 /*
38  * Draw text between pointers p and q with first character centered at x, y.
39  * Use color c.  Centered if cen is non-zero, right-justified if right is non-zero.
40  * Returns the y coordinate for any following line of text.
41  */
42 int
43 m_text(int x, int y, char *p, char *q, int c, int cen, int right)
44 {
45         Point tsize;
46
47         tsize = stringsize(font, p);
48         if(cen)
49                 x -= tsize.x/2;
50         else if(right)
51                 x -= tsize.x;
52         stringn(offscreen, Pt(x, y-tsize.y/2), getcolor(c), ZP, font, p, q-p);
53         if(offscreen != screen && !buffer)
54                 stringn(screen, xlp(Pt(x, y-tsize.y/2)), getcolor(c), ZP, font, p, q-p);
55         return y+tsize.y;
56 }
57 /*
58  * draw point x, y
59  */
60 void
61 m_dpt(double x, double y)
62 {
63         Image *c;
64
65         c = getcolor(e1->foregr);
66         draw(offscreen, Rect(SCX(x), SCY(y), SCX(x)+1, SCY(y)+1), c, nil, ZP);
67         if(offscreen != screen && !buffer)
68                 draw(screen, xlr(Rect(SCX(x), SCY(y), SCX(x)+1, SCY(y)+1)), c, nil, ZP);
69 }
70
71 /*
72  * Draw the vector from x0, y0 to x1, y1 in color c.
73  * Clipped by caller
74  */
75 void
76 m_vector(int x0, int y0, int x1, int y1, int c)
77 {
78         line(offscreen, Pt(x0, y0), Pt(x1, y1), Endsquare, Endsquare, 0, getcolor(c), ZP);
79         if(offscreen != screen && !buffer)
80                 line(screen, xlp(Pt(x0, y0)), xlp(Pt(x1, y1)), Endsquare, Endsquare, 0, getcolor(c), ZP);
81 }
82 /*
83  * Startup initialization
84  */
85 void m_initialize(char*)
86 {
87         static int once;
88         int dx, dy;
89
90         if(once)
91                 return;
92         once = 1;
93
94         if(initdraw(nil, nil, "plot") < 0)
95                 sysfatal("initdraw: %r");
96 /////   einit(Emouse);
97         offscreen = allocimage(display, insetrect(screen->r, 4), screen->chan, 0, -1);
98         if(offscreen == nil)
99                 sysfatal("Can't double buffer\n");
100         clipminx = mapminx = screen->r.min.x+4;
101         clipminy = mapminy = screen->r.min.y+4;
102         clipmaxx = mapmaxx = screen->r.max.x-5;
103         clipmaxy = mapmaxy = screen->r.max.y-5;
104         dx = clipmaxx-clipminx;
105         dy = clipmaxy-clipminy;
106         if(dx>dy){
107                 mapminx += (dx-dy)/2;
108                 mapmaxx = mapminx+dy;
109         }
110         else{
111                 mapminy += (dy-dx)/2;
112                 mapmaxy = mapminy+dx;
113         }
114 }
115 /*
116  * Clean up when finished
117  */
118 void m_finish(void)
119 {
120         m_swapbuf();
121 }
122 void m_swapbuf(void)
123 {
124         draw(screen, insetrect(screen->r, 4), offscreen, nil, offscreen->r.min);
125         flushimage(display, 1);
126 }
127 void m_dblbuf(void)
128 {
129         buffer = 1;
130 }
131
132 /*
133  * Use cache to avoid repeated allocation.
134  */
135 struct{
136         int             v;
137         Image   *i;
138 }icache[32];
139
140 Image*
141 getcolor(int v)
142 {
143         Image *i;
144         int j;
145
146         for(j=0; j<nelem(icache); j++)
147                 if(icache[j].v==v && icache[j].i!=nil)
148                         return icache[j].i;
149
150         i = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, v);
151         if(i == nil)
152                 sysfatal("plot: can't allocate image for color: %r");
153         for(j=0; j<nelem(icache); j++)
154                 if(icache[j].i == nil){
155                         icache[j].v = v;
156                         icache[j].i = i;
157                         break;
158                 }
159 if(j == nelem(icache))sysfatal("icache: too small");
160         return i;
161 }