/* * Euler - a numerical lab * * platform : neutral * * file : meta.c -- portable independant graphic system */ #include #include #include #include #include #include #include #include "sysdep.h" #include "stack.h" #include "output.h" #include "meta.h" static double delay=0; double getcolor (int i, int j); extern int fillcolor1,fillcolor2,usecolors; double pswidth=15,psheight=15; typedef struct metastruct { char *start, *end; size_t size; int full, active, recording, playingframe; long nframes; int width, height; int wchar, hchar; int lines; short colors[3][MAX_COLORS]; metadevice *device; } metastruct; static struct metastruct *m = NULL; static void commandwrite (int i); static void longwrite (double n); static void shortwrite (short n); static void stringwrite (char *s); static int nextcommand (char **p); static double nextlong (char **p); static int nextint (char **p); //static void showcommand(int cmd); /**************************************************************************** * public metafile api * ****************************************************************************/ int openmeta(int size, metadevice *device) { m = (metastruct*)malloc(sizeof(metastruct)); if (m) { m->size = size*1024L; m->full = 0; m->active = 1; m->recording = 0; m->playingframe = 0; m->device = device; m->nframes = 0; m->lines = 40; m->wchar = m->hchar = 1; m->height = m->width = 0; m->start = m->end = (char*)malloc(m->size); if (m->start) return 1; } return 0; } void closemeta() { if (m) { if (m->start) free(m->start); free(m); } } metadevice * setmetadevice(metadevice *d) { metadevice *old = m->device; if (d) m->device = d; return old; } metadevice * getmetadevice() { return m->device; } void setmetawidth(int width) { m->width = width; } void setmetaheight(int height) { m->height = height; } int getmetawidth() { return m->width; } int getmetaheight() { return m->height; } void setmetacharwidth(int w) { m->wchar = w; } void setmetacharheight(int h) { m->hchar = h; } int getmetacharwidth() { return m->wchar; } int getmetacharheight() { return m->hchar; } void setmetalines(int lines) { m->lines = lines; } int getmetalines() { return m->lines; } void setmetacolors(short colors[3][MAX_COLORS]) { int i, j; for (i=0 ; i<3 ; i++) for (j=0 ; jcolors[i][j] = colors[i][j]; } short getmetacolor(int rgb, int index) { return m->colors[rgb][index]; } void playmeta() { char *p=m->start; double c,r,c1,r1,cc[16],hue; int col,st,width,n,i,co[16],again=-1; if (m->recording || !m->device) return; m->active = 0; if (!m->playingframe) again = 1; while (pend) { int command=nextcommand(&p); switch(command) { case 1 : if (!m->playingframe && !again) { m->active = 1; return; } else again--; if (m->playingframe) { sys_wait(delay,&n); if (n==escape) { m->active = 1; return; } // else if (n) { // m->active=1; // return; // } } m->device->clear(m->device->data); break; case 2 : c=nextlong(&p); r=nextlong(&p); c1=nextlong(&p); r1=nextlong(&p); m->device->clip(m->device->data,c,r,c1,r1); break; case 10 : c=nextlong(&p); r=nextlong(&p); c1=nextlong(&p); r1=nextlong(&p); col=nextint(&p); st=nextint(&p); width=nextint(&p); m->device->line(m->device->data,c,r,c1,r1,col,st,width); break; case 20 : c=nextlong(&p); r=nextlong(&p); col=nextint(&p); st=nextint(&p); m->device->marker(m->device->data,c,r,col,st); break; case 30 : n=nextint(&p); for (i=0; idevice->fill(m->device->data,cc,st,n,co); break; case 31 : for (i=0; i<8; i++) cc[i]=nextlong(&p); hue=nextlong(&p); col=nextint(&p); st=nextint(&p); m->device->fillh(m->device->data,cc,hue,col,st); break; case 32 : c=nextlong(&p); r=nextlong(&p); c1=nextlong(&p); r1=nextlong(&p); hue=nextlong(&p); col=nextint(&p); st=nextint(&p); m->device->bar(m->device->data,c,r,c1,r1,hue,col,st); break; case 33 : c=nextlong(&p); r=nextlong(&p); c1=nextlong(&p); r1=nextlong(&p); col=nextint(&p); st=nextint(&p); m->device->bar1(m->device->data,c,r,c1,r1,col,st); break; case 40 : c=nextlong(&p); r=nextlong(&p); col=nextint(&p); st=nextint(&p); m->device->text(m->device->data,c,r,p,col,st); p+=strlen(p)+1; break; case 41 : c=nextlong(&p); r=nextlong(&p); col=nextint(&p); st=nextint(&p); m->device->vtext(m->device->data,c,r,p,col,st); p+=strlen(p)+1; break; case 42 : c=nextlong(&p); r=nextlong(&p); col=nextint(&p); st=nextint(&p); m->device->vutext(m->device->data,c,r,p,col,st); p+=strlen(p)+1; break; case 50 : nextlong(&p); break; default : break; } } m->active = 1; } /**************************************************************************** * frame support * ****************************************************************************/ void mbeginframes(header *hd) { // gclear(); m->recording = 1; m->end = m->start; m->full = 0; m->nframes = 0; new_real(m->nframes,""); } void mendframes(header *h) { // gclear(); m->recording = 0; new_real(m->nframes,""); } void mframes (header *hd) { new_real(m->nframes,""); } void mplayframes(header *hd) { header *st=hd,*result; hd=getvalue(hd); if (error) return; if (hd->type!=s_real) wrong_arg_in("play"); graphic_mode(); delay = *realof(hd); m->playingframe = 1; m->device->begin(m->device->data); playmeta(); m->device->end(m->device->data); m->playingframe = 0; delay=0.0; result=new_real(m->nframes,""); moveresult(st,result); } /**************************************************************************** * basic drawing commands * ****************************************************************************/ void gclear() { if (!m->active) return; if (m->recording) { m->nframes++; } else { m->end = m->start; m->full = 0; m->nframes = 0; } commandwrite(1); if (!m->recording && m->device && m->device->clear) m->device->clear(m->device->data); } void gclip(double c, double r, double c1, double r1) { if (!m->active) return; if (fabs(r)>10000.0) return; if (fabs(c)>10000.0) return; if (fabs(r1)>10000.0) return; if (fabs(c1)>10000.0) return; commandwrite(2); longwrite(c); longwrite(r); longwrite(c1); longwrite(r1); if (!m->recording && m->device && m->device->clip) m->device->clip(m->device->data,c,r,c1,r1); } /***** gline draw a line. col is the color, where 0 should be white and 1 black. st is a style from linetyp. width is the linewidth, where 0 or 1 are equal defaults. *****/ void gline(double c, double r, double c1, double r1, int color, int st, int width) { if (!m->active) return; if (fabs(r)>10000.0) return; if (fabs(c)>10000.0) return; if (fabs(r1)>10000.0) return; if (fabs(c1)>10000.0) return; commandwrite(10); longwrite(c); longwrite(r); longwrite(c1); longwrite(r1); shortwrite(color); shortwrite(st); shortwrite(width); if (!m->recording && m->device && m->device->line) m->device->line(m->device->data,c,r,c1,r1,color,st,width); } /***** gmarker plot a single marker on screen. col is the color. type is a type from markertyp. *****/ void gmarker(double c, double r, int color, int type) { if (!m->active) return; commandwrite(20); longwrite(c); longwrite(r); shortwrite(color); shortwrite(type); if (!m->recording && m->device && m->device->marker) m->device->marker(m->device->data,c,r,color,type); } void gfill(double c[], int st, int n, int connect[]) { int i; if (!m->active) return; for (i=0; i<2*n; i++) if (fabs(c[i])>10000.0) return; commandwrite(30); shortwrite(n); for (i=0; irecording && m->device && m->device->fill) m->device->fill(m->device->data,c,st,n,connect); } /***** Draw a filled polygon. Works like gfill, but uses hue. *****/ void gfillh(double c[8], double hue, int color, int connect) { int i; if (!m->active) return; for (i=0; i<8; i++) if (fabs(c[i])>10000.0) return; hue-=floor(hue); commandwrite(31); for (i=0; i<8; i+=2) { longwrite(c[i]); longwrite(c[i+1]); } longwrite(hue); shortwrite(color); shortwrite(connect); if (!m->recording && m->device && m->device->fillh) m->device->fillh(m->device->data,c,hue,color,connect); } /***** Draw a rectangle. hue is a hue intensity from 0 to 1. style determines, if a black boundary should be drawn. ******/ void gbar(double c, double r, double c1, double r1, double hue, int color, int style) { if (!m->active) return; commandwrite(32); longwrite(c); longwrite(r); longwrite(c1); longwrite(r1); longwrite(hue); shortwrite(color); shortwrite(style); if (!m->recording && m->device && m->device->bar) m->device->bar(m->device->data,c,r,c1,r1,hue,color,style); } /***** Draw a rectangle. hue is a hue intensity from 0 to 1. style determines, if a black boundary should be drawn. ******/ void gbar1(double c, double r, double c1, double r1, int color, int style) { if (!m->active) return; commandwrite(33); longwrite(c); longwrite(r); longwrite(c1); longwrite(r1); shortwrite(color); shortwrite(style); if (!m->recording && m->device && m->device->bar1) m->device->bar1(m->device->data,c,r,c1,r1,color,style); } /***** gtext output a graphic text on screen. alignment is left=0, centered=1, right=2. *****/ void gtext(double c, double r, char *text, int color, int alignment) { if (!m->active) return; commandwrite(40); longwrite(c); longwrite(r); shortwrite(color); shortwrite(alignment); stringwrite(text); if (!m->recording && m->device && m->device->text) m->device->text(m->device->data,c,r,text,color,alignment); } /***** gvtext like gtext downwards *****/ void gvtext(double c, double r, char *text, int color, int alignment) { if (!m->active) return; commandwrite(41); longwrite(c); longwrite(r); shortwrite(color); shortwrite(alignment); stringwrite(text); if (!m->recording && m->device && m->device->vtext) m->device->vtext(m->device->data,c,r,text,color,alignment); } /***** gvutext like gtext upwards. *****/ void gvutext(double c, double r, char *text, int color, int alignment) { if (!m->active) return; commandwrite(42); longwrite(c); longwrite(r); shortwrite(color); shortwrite(alignment); stringwrite(text); if (!m->recording && m->device && m->device->vutext) m->device->vutext(m->device->data,c,r,text,color,alignment); } void gscale (double s) { if (!m->active) return; commandwrite(50); longwrite(s*1000); if (!m->recording && m->device && m->device->scale) m->device->scale(m->device->data,s); } int dump_meta (char *filename) { FILE *out=fopen(filename,"w"); if (!out) return 0; fwrite(m->start,m->end-m->start,1,out); fclose(out); return 1; } void pswindow (double w, double h) { pswidth=w; psheight=h; } /**************************************************************************** * private metafile * ****************************************************************************/ static void write (void *l, int n) { if (!m->active || m->full) return; memmove(m->end,l,n); m->end+=n; } static void commandwrite (int i) { if (!m->active) return; if ((int)(m->end-m->start)>(int)(m->size-512)) { m->full=1; return; } *m->end++=i; } /***** write a double to the metafile as long *****/ static void longwrite (double n) { long k=(long)(n*1000.0); write(&k,sizeof(long)); } /***** write an int to the metafile *****/ static void shortwrite (short n) { write(&n,sizeof(short)); } /***** write a string to the metafile *****/ static void stringwrite (char *s) { write(s,strlen(s)+1); } static int nextcommand (char **p) { int k=**p; (*p)++; return k; } static double nextlong (char **p) { long x; memmove(&x,*p,sizeof(long)); (*p)+=sizeof(long); return x/1000.0; } static int nextint (char **p) { short n; memmove(&n,*p,sizeof(short)); (*p)+=sizeof(short); return n; } #if 0 static void showcommand(int cmd) { switch (cmd) { case 1 : fprintf(stderr,"%2d : clear\n",cmd); break; case 2 : fprintf(stderr,"%2d : clip\n",cmd); break; case 10 : fprintf(stderr,"%2d : line\n",cmd); break; case 20 : fprintf(stderr,"%2d : marker\n",cmd); break; case 30 : fprintf(stderr,"%2d : fill\n",cmd); break; case 31 : fprintf(stderr,"%2d : fillh\n",cmd); break; case 32 : fprintf(stderr,"%2d : bar\n",cmd); break; case 33 : fprintf(stderr,"%2d : bar1\n",cmd); break; case 40 : fprintf(stderr,"%2d : text\n",cmd); break; case 41 : fprintf(stderr,"%2d : vtext\n",cmd); break; case 42 : fprintf(stderr,"%2d : vutext\n",cmd); break; case 50 : fprintf(stderr,"%2d : scale\n",cmd); break; default : fprintf(stderr,"%2d : unknown\n",cmd); break; } } #endif