| #include "mplot.h" |
| int mapminx, mapminy, mapmaxx, mapmaxy; |
| Image *offscreen; |
| /* |
| * Clear the window from x0, y0 to x1, y1 (inclusive) to color c |
| */ |
| void m_clrwin(int x0, int y0, int x1, int y1, int c){ |
| draw(offscreen, Rect(x0, y0, x1+1, y1+1), getcolor(c), nil, ZP); |
| } |
| /* |
| * Draw text between pointers p and q with first character centered at x, y. |
| * Use color c. Centered if cen is non-zero, right-justified if right is non-zero. |
| * Returns the y coordinate for any following line of text. |
| */ |
| int m_text(int x, int y, char *p, char *q, int c, int cen, int right){ |
| Point tsize; |
| USED(c); |
| tsize=stringsize(font, p); |
| if(cen) x -= tsize.x/2; |
| else if(right) x -= tsize.x; |
| stringn(offscreen, Pt(x, y-tsize.y/2), getcolor(c), ZP, font, p, q-p); |
| return y+tsize.y; |
| } |
| /* |
| * Draw the vector from x0, y0 to x1, y1 in color c. |
| * Clipped by caller |
| */ |
| void m_vector(int x0, int y0, int x1, int y1, int c){ |
| line(offscreen, Pt(x0, y0), Pt(x1, y1), Endsquare, Endsquare, 0, getcolor(c), ZP); |
| } |
| char *scanint(char *s, int *n){ |
| while(*s<'0' || '9'<*s){ |
| if(*s=='\0'){ |
| fprint(2, "plot: bad -Wxmin,ymin,xmax,ymax\n"); |
| exits("bad arg"); |
| } |
| s++; |
| } |
| *n=0; |
| while('0'<=*s && *s<='9'){ |
| *n=*n*10+*s-'0'; |
| s++; |
| } |
| return s; |
| } |
| char *rdenv(char *name){ |
| char *v; |
| int fd, size; |
| fd=open(name, OREAD); |
| if(fd<0) return 0; |
| size=seek(fd, 0, 2); |
| v=malloc(size+1); |
| if(v==0){ |
| fprint(2, "Can't malloc: %r\n"); |
| exits("no mem"); |
| } |
| seek(fd, 0, 0); |
| read(fd, v, size); |
| v[size]=0; |
| close(fd); |
| return v; |
| } |
| /* |
| * Startup initialization |
| */ |
| void m_initialize(char *s){ |
| static int first=1; |
| int dx, dy; |
| USED(s); |
| if(first){ |
| if(initdraw(0,0,"plot") < 0) |
| sysfatal("plot: can't open display: %r"); |
| einit(Emouse); |
| clipminx=mapminx=screen->r.min.x+4; |
| clipminy=mapminy=screen->r.min.y+4; |
| clipmaxx=mapmaxx=screen->r.max.x-5; |
| clipmaxy=mapmaxy=screen->r.max.y-5; |
| dx=clipmaxx-clipminx; |
| dy=clipmaxy-clipminy; |
| if(dx>dy){ |
| mapminx+=(dx-dy)/2; |
| mapmaxx=mapminx+dy; |
| } |
| else{ |
| mapminy+=(dy-dx)/2; |
| mapmaxy=mapminy+dx; |
| } |
| first=0; |
| offscreen = screen; |
| } |
| } |
| /* |
| * Clean up when finished |
| */ |
| void m_finish(void){ |
| m_swapbuf(); |
| } |
| void m_swapbuf(void){ |
| if(offscreen!=screen) |
| draw(screen, offscreen->r, offscreen, nil, offscreen->r.min); |
| flushimage(display, 1); |
| } |
| void m_dblbuf(void){ |
| if(offscreen==screen){ |
| offscreen=allocimage(display, insetrect(screen->r, 4), screen->chan, 0, -1); |
| if(offscreen==0){ |
| fprintf(stderr, "Can't double buffer\n"); |
| offscreen=screen; |
| } |
| } |
| } |
| /* Assume colormap entry because |
| * Use cache to avoid repeated allocation. |
| */ |
| struct{ |
| int v; |
| Image *i; |
| }icache[32]; |
| |
| Image* |
| getcolor(int v) |
| { |
| Image *i; |
| int j; |
| |
| for(j=0; j<nelem(icache); j++) |
| if(icache[j].v==v && icache[j].i!=nil) |
| return icache[j].i; |
| |
| i = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, v); |
| if(i == nil){ |
| fprint(2, "plot: can't allocate image for color: %r\n"); |
| exits("allocimage"); |
| } |
| for(j=0; j<nelem(icache); j++) |
| if(icache[j].i == nil){ |
| icache[j].v = v; |
| icache[j].i = i; |
| break; |
| } |
| |
| return i; |
| } |