1 #include "mplot.h"
2 Image *offscreen;
3 /*
4 * Clear the window from x0, y0 to x1, y1 (inclusive) to color c
5 */
m_clrwin(int x0,int y0,int x1,int y1,int c)6 void m_clrwin(int x0, int y0, int x1, int y1, int c){
7 draw(offscreen, Rect(x0, y0, x1+1, y1+1), getcolor(c), nil, ZP);
8 }
9 /*
10 * Draw text between pointers p and q with first character centered at x, y.
11 * Use color c. Centered if cen is non-zero, right-justified if right is non-zero.
12 * Returns the y coordinate for any following line of text.
13 */
m_text(int x,int y,char * p,char * q,int c,int cen,int right)14 int m_text(int x, int y, char *p, char *q, int c, int cen, int right){
15 Point tsize;
16 USED(c);
17 tsize=stringsize(font, p);
18 if(cen) x -= tsize.x/2;
19 else if(right) x -= tsize.x;
20 stringn(offscreen, Pt(x, y-tsize.y/2), getcolor(c), ZP, font, p, q-p);
21 return y+tsize.y;
22 }
23 /*
24 * Draw the vector from x0, y0 to x1, y1 in color c.
25 * Clipped by caller
26 */
m_vector(int x0,int y0,int x1,int y1,int c)27 void m_vector(int x0, int y0, int x1, int y1, int c){
28 line(offscreen, Pt(x0, y0), Pt(x1, y1), Endsquare, Endsquare, 0, getcolor(c), ZP);
29 }
scanint(char * s,int * n)30 char *scanint(char *s, int *n){
31 while(*s<'0' || '9'<*s){
32 if(*s=='\0'){
33 fprint(2, "plot: bad -Wxmin,ymin,xmax,ymax\n");
34 exits("bad arg");
35 }
36 s++;
37 }
38 *n=0;
39 while('0'<=*s && *s<='9'){
40 *n=*n*10+*s-'0';
41 s++;
42 }
43 return s;
44 }
rdenv(char * name)45 char *rdenv(char *name){
46 char *v;
47 int fd, size;
48 fd=open(name, OREAD);
49 if(fd<0) return 0;
50 size=seek(fd, 0, 2);
51 v=malloc(size+1);
52 if(v==0){
53 fprint(2, "Can't malloc: %r\n");
54 exits("no mem");
55 }
56 seek(fd, 0, 0);
57 read(fd, v, size);
58 v[size]=0;
59 close(fd);
60 return v;
61 }
62 /*
63 * Startup initialization
64 */
m_initialize(char * s)65 void m_initialize(char *s){
66 static int first=1;
67 int dx, dy;
68 USED(s);
69 if(first){
70 if(initdraw(0,0,"plot") < 0)
71 sysfatal("initdraw: %r");
72 einit(Emouse);
73 clipminx=mapminx=screen->r.min.x+4;
74 clipminy=mapminy=screen->r.min.y+4;
75 clipmaxx=mapmaxx=screen->r.max.x-5;
76 clipmaxy=mapmaxy=screen->r.max.y-5;
77 dx=clipmaxx-clipminx;
78 dy=clipmaxy-clipminy;
79 if(dx>dy){
80 mapminx+=(dx-dy)/2;
81 mapmaxx=mapminx+dy;
82 }
83 else{
84 mapminy+=(dy-dx)/2;
85 mapmaxy=mapminy+dx;
86 }
87 first=0;
88 offscreen = screen;
89 }
90 }
91 /*
92 * Clean up when finished
93 */
m_finish(void)94 void m_finish(void){
95 m_swapbuf();
96 }
m_swapbuf(void)97 void m_swapbuf(void){
98 if(offscreen!=screen)
99 draw(screen, offscreen->r, offscreen, nil, offscreen->r.min);
100 flushimage(display, 1);
101 }
m_dblbuf(void)102 void m_dblbuf(void){
103 if(offscreen==screen){
104 offscreen=allocimage(display, insetrect(screen->r, 4), screen->chan, 0, -1);
105 if(offscreen==0){
106 fprintf(stderr, "Can't double buffer\n");
107 offscreen=screen;
108 }
109 }
110 }
111 /* Assume colormap entry because
112 * Use cache to avoid repeated allocation.
113 */
114 struct{
115 int v;
116 Image *i;
117 }icache[32];
118
119 Image*
getcolor(int v)120 getcolor(int v)
121 {
122 Image *i;
123 int j;
124
125 for(j=0; j<nelem(icache); j++)
126 if(icache[j].v==v && icache[j].i!=nil)
127 return icache[j].i;
128
129 i = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, v);
130 if(i == nil){
131 fprint(2, "plot: can't allocate image for color: %r\n");
132 exits("allocimage");
133 }
134 for(j=0; j<nelem(icache); j++)
135 if(icache[j].i == nil){
136 icache[j].v = v;
137 icache[j].i = i;
138 break;
139 }
140
141 return i;
142 }
143