161 lines · 3.3 KB · C
RawDownload
#include "mplot.h"Image *offscreen;static int buffer; static Pointxlp(Point p){	p.x += screen->r.min.x + 4 - offscreen->r.min.x;	p.y += screen->r.min.y + 4 - offscreen->r.min.y;	return p;} static Rectanglexlr(Rectangle r){	int dx, dy; 	dx = screen->r.min.x + 4 - offscreen->r.min.x;	dy = screen->r.min.y + 4 - offscreen->r.min.y;	r.min.x += dx;	r.min.y += dy;	r.max.x += dx;	r.max.y += dy;	return r;} /* * Clear the window from x0, y0 to x1, y1 (inclusive) to color c */voidm_clrwin(int x0, int y0, int x1, int y1, int c){	draw(offscreen, Rect(x0, y0, x1+1, y1+1), getcolor(c), nil, ZP);	if(offscreen != screen && !buffer)		draw(screen, xlr(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. */intm_text(int x, int y, char *p, char *q, int c, int cen, int right){	Point tsize; 	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);	if(offscreen != screen && !buffer)		stringn(screen, xlp(Pt(x, y-tsize.y/2)), getcolor(c), ZP, font, p, q-p);	return y+tsize.y;}/* * draw point x, y */voidm_dpt(double x, double y){	Image *c; 	c = getcolor(e1->foregr);	draw(offscreen, Rect(SCX(x), SCY(y), SCX(x)+1, SCY(y)+1), c, nil, ZP);	if(offscreen != screen && !buffer)		draw(screen, xlr(Rect(SCX(x), SCY(y), SCX(x)+1, SCY(y)+1)), c, nil, ZP);} /* * Draw the vector from x0, y0 to x1, y1 in color c. * Clipped by caller */voidm_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);	if(offscreen != screen && !buffer)		line(screen, xlp(Pt(x0, y0)), xlp(Pt(x1, y1)), Endsquare, Endsquare, 0, getcolor(c), ZP);}/* * Startup initialization */void m_initialize(char*){	static int once;	int dx, dy; 	if(once)		return;	once = 1; 	if(initdraw(nil, nil, "plot") < 0)		sysfatal("initdraw: %r");/////	einit(Emouse);	offscreen = allocimage(display, insetrect(screen->r, 4), screen->chan, 0, -1);	if(offscreen == nil)		sysfatal("Can't double buffer\n");	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;	}}/* * Clean up when finished */void m_finish(void){	m_swapbuf();}void m_swapbuf(void){	draw(screen, insetrect(screen->r, 4), offscreen, nil, offscreen->r.min);	flushimage(display, 1);}void m_dblbuf(void){	buffer = 1;} /* * 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)		sysfatal("plot: can't allocate image for color: %r");	for(j=0; j<nelem(icache); j++)		if(icache[j].i == nil){			icache[j].v = v;			icache[j].i = i;			break;		}if(j == nelem(icache))sysfatal("icache: too small");	return i;}