Bill Allombert on Fri, 26 Aug 2005 14:17:13 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

object-oriented graphic engine


Hello PARI-dev,

I would like to propose a rewrite of the graphic code in
an object-oriented fashion to avoid duplication.
This one follow more closely the RectObj code.

struct plot_eng
{
  /*Set color*/
  void (*sc)(void *data, long col);
  /*Point*/
  void (*pt)(void *data, long x, long y);
  /*Line*/
  void (*ln)(void *data, long x1, long y1, long x2, long y2);
  /*Box*/
  void (*bx)(void *data, long x, long y, long w, long h);
  /*Multi-point*/
  void (*mp)(void *data, long n, struct plot_points *points);
  /*Multi-line*/
  void (*ml)(void *data, long n, struct plot_points *points);
  /*Text*/
  void (*st)(void *data, long x, long y, char *s, long l);
};

and a function:
void gen_rectdraw0(struct plot_eng *eng, void *data, long *w, long *x,
long *y, long lw, double xs, double ys);

The attached patch implement gen_rectdraw0 and use it for the X11
display.

Once this patch is accepted, we should use gen_rectdraw0 for the
other graphic output.

A possible change would be to handle color using a new atom (set color)
instead of hard-coding colors in each nodes.

Cheers,
Bill
Index: pari/src/graph/plotX.c
===================================================================
--- pari.orig/src/graph/plotX.c	2004-11-30 16:15:47.000000000 +0100
+++ pari/src/graph/plotX.c	2005-08-26 11:50:20.000000000 +0200
@@ -48,6 +48,73 @@
 static XColor  *PARI_Colors;
 static XColor  *PARI_ExactColors;
 
+struct data_x
+{
+  Display *display;
+  Window win;
+  GC gc;
+};
+
+static void SetForeground(void *data, long col)
+{
+   struct data_x *dx = (struct data_x *) data;
+   XSetForeground(dx->display,dx->gc, PARI_Colors[col].pixel);
+}
+
+
+static void DrawPoint(void *data, long x, long y)
+{
+   struct data_x *dx = (struct data_x *) data;
+   XDrawPoint(dx->display,dx->win,dx->gc, x,y);
+}
+
+static void DrawLine(void *data, long x1, long y1, long x2, long y2)
+{
+   struct data_x *dx = (struct data_x *) data;
+   XDrawLine(dx->display,dx->win,dx->gc, x1,y1, x2,y2);
+}
+
+static void DrawRectangle(void *data, long x, long y, long w, long h)
+{
+   struct data_x *dx = (struct data_x *) data;
+   XDrawRectangle(dx->display,dx->win,dx->gc, x,y, w,h);
+}
+
+static void DrawPoints(void *data, long nb, struct plot_points *p)
+{
+   struct data_x *dx = (struct data_x *) data;
+   XPoint *xp=(XPoint*)gpmalloc(sizeof(xp)*nb);
+   long i;
+   for (i=0;i<nb;i++)
+   {
+     xp[i].x=p[i].x;
+     xp[i].y=p[i].y;
+   }
+   XDrawPoints(dx->display,dx->win,dx->gc, xp, nb, 0);
+   free(xp);
+}
+
+static void DrawLines(void *data, long nb, struct plot_points *p)
+{
+   struct data_x *dx = (struct data_x *) data;
+   XPoint *xp=(XPoint*)gpmalloc(sizeof(xp)*nb);
+   long i;
+   for (i=0;i<nb;i++)
+   {
+     xp[i].x=p[i].x;
+     xp[i].y=p[i].y;
+   }
+   XDrawLines(dx->display,dx->win,dx->gc, xp, nb, 0);
+   free(xp);
+}
+
+static void DrawString(void *data, long x, long y, char *text, long numtext)
+{
+  struct data_x *dx = (struct data_x *) data;
+  XDrawString(dx->display,dx->win,dx->gc, x,y, text, numtext);
+}
+
+
 static char *PARI_DefaultColors[MAX_COLORS] =
 {
   " ",
@@ -111,18 +178,10 @@
 void
 rectdraw0(long *w, long *x, long *y, long lw, long do_free)
 {
-  double *ptx,*pty;
-  long *c, shift;
-  long *numpoints[MAX_COLORS],*numtexts[MAX_COLORS];
-  long *xtexts[MAX_COLORS],*ytexts[MAX_COLORS];
-  col_counter rcolcnt;
-  long col,i,j,x0,y0,oldwidth,oldheight;
-  long hjust, vjust, hgap, vgap, hgapsize = h_unit, vgapsize = v_unit;
-  char **texts[MAX_COLORS];
-  PariRect *e;
-  RectObj *p1;
+  long oldwidth,oldheight;
+  struct plot_eng plotX;
+  struct data_x dx;
   double xs = 1, ys = 1;
-
   int screen;
   Display *display;
   GC gc;
@@ -131,9 +190,6 @@
   XSizeHints size_hints;
   XFontStruct *font_info;
   XSetWindowAttributes attrib;
-  XPoint *points[MAX_COLORS],**lines[MAX_COLORS];
-  XSegment *seg[MAX_COLORS];
-  XRectangle *rec[MAX_COLORS];
   Atom wm_delete_window, wm_protocols;
 
   if (fork()) return;  /* parent process returns */
@@ -150,28 +206,6 @@
   XSetIOErrorHandler(IOerror);
   PARI_ColorSetUp(display,PARI_DefaultColors,MAX_COLORS);
 
-  plot_count(w, lw, rcolcnt);
-  for (col=1; col<MAX_COLORS; col++)
-  {
-    char *m;
-    long *c = rcolcnt[col];
-    points[col]=(XPoint*)zmalloc(c[ROt_PT]*sizeof(XPoint));
-    seg[col]=(XSegment*)zmalloc(c[ROt_LN]*sizeof(XSegment));
-    rec[col]=(XRectangle*)zmalloc(c[ROt_BX]*sizeof(XRectangle));
-
-    i = c[ROt_ML]; m = zmalloc(i * (sizeof(long) + sizeof(XPoint*)));
-    numpoints[col]=(long*)m; i *= sizeof(XPoint*);
-    m += i; lines[col]=(XPoint**)m;
-
-    i = c[ROt_ST]; m = zmalloc(i * (sizeof(char*) + 3*sizeof(long)));
-    texts[col]=(char**)m; i *= sizeof(long);
-    m += i; numtexts[col]=(long*)m;
-    m += i; xtexts[col]=(long*)m;
-    m += i; ytexts[col]=(long*)m;
-
-    c[ROt_PT]=c[ROt_LN]=c[ROt_BX]=c[ROt_ML]=c[ROt_ST]=0;
-  }
-
   screen = DefaultScreen(display);
   win = XCreateSimpleWindow
     (display, RootWindow(display, screen), 0, 0, w_width, w_height,
@@ -204,6 +238,16 @@
   XMapWindow(display, win);
   oldwidth  = w_width;
   oldheight = w_height;
+  dx.display= display;
+  dx.win =win;
+  dx.gc=gc;
+  plotX.sc=&SetForeground;
+  plotX.pt=&DrawPoint;
+  plotX.ln=&DrawLine;
+  plotX.bx=&DrawRectangle;
+  plotX.mp=&DrawPoints;
+  plotX.ml=&DrawLines;
+  plotX.st=&DrawString;
 
   for(;;)
   {
@@ -216,14 +260,6 @@
       case ButtonPress:
       case DestroyNotify:
 	XUnloadFont(display,font_info->fid); XFreeGC(display,gc);
-#define myfree(x) if (x) free(x)
-	for(col=1;col<MAX_COLORS;col++)
-	{
-	  myfree(points[col]); myfree(seg[col]); myfree(rec[col]);
-	  for(i=0;i<rcolcnt[col][ROt_ML];i++) myfree(lines[col][i]);
-	  myfree(numpoints[col]); myfree(texts[col]);
-        }
-#undef myfree
 	free_graph(); if (do_free) { free(w); free(x); free(y); }
 	XCloseDisplay(display); exit(0);
 
@@ -240,90 +276,7 @@
 	xs = ((double)width)/w_width; ys=((double)height)/w_height;
       }
       case Expose: 
-	for(i=0; i<lw; i++)
-	{
-	  e=rectgraph[w[i]]; x0=x[i]; y0=y[i];
-	  for (p1 = RHead(e); p1; p1 = RoNext(p1))
-	  {
-	    col = RoCol(p1);
-            c = rcolcnt[col];
-	    switch(RoType(p1))
-	    {
-	      case ROt_PT:
-		points[col][c[ROt_PT]].x = DTOL((RoPTx(p1)+x0)*xs);
-		points[col][c[ROt_PT]].y = DTOL((RoPTy(p1)+y0)*ys);
-		c[ROt_PT]++;break;
-	      case ROt_LN:
-		seg[col][c[ROt_LN]].x1 = DTOL((RoLNx1(p1)+x0)*xs);
-		seg[col][c[ROt_LN]].y1 = DTOL((RoLNy1(p1)+y0)*ys);
-		seg[col][c[ROt_LN]].x2 = DTOL((RoLNx2(p1)+x0)*xs);
-		seg[col][c[ROt_LN]].y2 = DTOL((RoLNy2(p1)+y0)*ys);
-		c[ROt_LN]++;break;
-	      case ROt_BX:
-                rec[col][c[ROt_BX]].x = DTOL((RoBXx1(p1)+x0)*xs);
-                rec[col][c[ROt_BX]].y = DTOL((RoBXy1(p1)+y0)*ys);
-                rec[col][c[ROt_BX]].width = DTOL((RoBXx2(p1)-RoBXx1(p1))*xs);
-                rec[col][c[ROt_BX]].height = DTOL((RoBXy2(p1)-RoBXy1(p1))*ys);
-                c[ROt_BX]++;break;
-	      case ROt_MP:
-		ptx = RoMPxs(p1); pty = RoMPys(p1);
-		for(j=0;j<RoMPcnt(p1);j++)
-		{
-		  points[col][c[ROt_PT]+j].x = DTOL((ptx[j]+x0)*xs);
-		  points[col][c[ROt_PT]+j].y = DTOL((pty[j]+y0)*ys);
-		}
-		c[ROt_PT]+=RoMPcnt(p1);break;
-	      case ROt_ML:
-		ptx=RoMLxs(p1); pty=RoMLys(p1);
-		numpoints[col][c[ROt_ML]] = RoMLcnt(p1);
-		lines[col][c[ROt_ML]] =
-		  (XPoint*)zmalloc(RoMLcnt(p1)*sizeof(XPoint));
-		for(j=0;j<RoMLcnt(p1);j++)
-		{
-		  lines[col][c[ROt_ML]][j].x = DTOL((ptx[j]+x0)*xs);
-		  lines[col][c[ROt_ML]][j].y = DTOL((pty[j]+y0)*ys);
-		}
-		c[ROt_ML]++;break;
-	      case ROt_ST:
-		hjust = RoSTdir(p1) & RoSTdirHPOS_mask;
-		vjust = RoSTdir(p1) & RoSTdirVPOS_mask;
-		hgap = RoSTdir(p1) & RoSTdirHGAP;
-		if (hgap)
-		  hgap = (hjust == RoSTdirLEFT) ? hgapsize : -hgapsize;
-		vgap = RoSTdir(p1) & RoSTdirVGAP;
-		if (vgap)
-		  vgap = (vjust == RoSTdirBOTTOM) ? 2*vgapsize : -2*vgapsize;
-		if (vjust != RoSTdirBOTTOM)
-		  vgap -= ((vjust == RoSTdirTOP) ? 2 : 1)*(f_height - 1);
-		texts[col][c[ROt_ST]]=RoSTs(p1);
-		numtexts[col][c[ROt_ST]]=RoSTl(p1);
-		shift = (hjust == RoSTdirLEFT ? 0 :
-			 (hjust == RoSTdirRIGHT ? 2 : 1));
-		xtexts[col][c[ROt_ST]] 
-		    = DTOL(( RoSTx(p1) + x0 + hgap
-			       - (strlen(RoSTs(p1)) * pari_plot.fwidth
-				  * shift)/2)*xs);
-		ytexts[col][c[ROt_ST]] = DTOL((RoSTy(p1)+y0-vgap/2)*ys);
-		c[ROt_ST]++;break;
-	      default: break;
-	    }
-	  }
-	}
-	for(col=1; col<MAX_COLORS; col++)
-	{
-          long *c = rcolcnt[col];
-	  XSetForeground(display, gc, PARI_Colors[col].pixel);
-	  if(c[ROt_PT]) XDrawPoints(display,win,gc,points[col],c[ROt_PT],0);
-	  if(c[ROt_LN]) XDrawSegments(display,win,gc,seg[col],c[ROt_LN]);
-	  if(c[ROt_BX]) XDrawRectangles(display,win,gc,rec[col],c[ROt_BX]);
-	  for(i=0;i<c[ROt_ML];i++)
-	    XDrawLines(display,win,gc,lines[col][i],numpoints[col][i],0);
-	  for(i=0;i<c[ROt_ST];i++)
-	    XDrawString(display,win,gc, xtexts[col][i],ytexts[col][i],
-              texts[col][i],numtexts[col][i]);
-
-	  c[ROt_PT]=c[ROt_LN]=c[ROt_BX]=c[ROt_ML]=c[ROt_ST]=0;
-        }
+        gen_rectdraw0(&plotX, (void *)&dx, w, x, y,lw,xs,ys);
     }
   }
 }
@@ -357,3 +310,4 @@
 
 void
 set_pointsize(double d) { (void)d; }
+
Index: pari/src/graph/plotport.c
===================================================================
--- pari.orig/src/graph/plotport.c	2005-08-25 23:14:20.000000000 +0200
+++ pari/src/graph/plotport.c	2005-08-26 11:52:15.000000000 +0200
@@ -2164,3 +2164,98 @@
 	    ((dir & RoSTdirHPOS_mask) == RoSTdirLEFT ? "L"
 	     : ((dir & RoSTdirHPOS_mask) == RoSTdirRIGHT ? "R" : "C")));
 }
+
+void
+gen_rectdraw0(struct plot_eng *eng, void *data, long *w, long *x, long *y, long lw, double xs, double ys)
+{
+  long i, j;
+  long hgapsize = h_unit,  vgapsize = v_unit;
+  for(i=0; i<lw; i++)
+  {
+    PariRect *e=rectgraph[w[i]];
+    RectObj *p1=RHead(e);
+    long x0=x[i],y0=y[i];
+    for (p1 = RHead(e); p1; p1 = RoNext(p1))
+    {
+      switch(RoType(p1))
+      {
+      case ROt_PT:
+        eng->sc(data,RoCol(p1));
+        eng->pt(data, DTOL((RoPTx(p1)+x0)*xs), DTOL((RoPTy(p1)+y0)*ys));
+        break;
+      case ROt_LN:
+        eng->sc(data,RoCol(p1));
+        eng->ln(data, DTOL((RoLNx1(p1)+x0)*xs), DTOL((RoLNy1(p1)+y0)*ys),
+            DTOL((RoLNx2(p1)+x0)*xs), DTOL((RoLNy2(p1)+y0)*ys));
+        break;
+      case ROt_BX:
+        eng->sc(data,RoCol(p1));
+        eng->bx(data, DTOL((RoBXx1(p1)+x0)*xs), DTOL((RoBXy1(p1)+y0)*ys),
+            DTOL((RoBXx2(p1)-RoBXx1(p1))*xs), 
+            DTOL((RoBXy2(p1)-RoBXy1(p1))*ys));
+        break;
+      case ROt_MP:
+        {
+          double *ptx = RoMPxs(p1); 
+          double *pty = RoMPys(p1);
+          long     nb = RoMPcnt(p1);
+          struct plot_points *points = 
+            (struct plot_points *) gpmalloc(sizeof(*points)*nb);
+          for(j=0;j<nb;j++)
+          {
+            points[j].x = DTOL((ptx[j]+x0)*xs);
+            points[j].y = DTOL((pty[j]+y0)*ys);
+          }
+          eng->sc(data,RoCol(p1));
+          eng->mp(data, nb, points);
+          free(points);
+          break;
+        }
+      case ROt_ML:
+        {
+          double *ptx = RoMLxs(p1); 
+          double *pty = RoMLys(p1);
+          long     nb = RoMLcnt(p1);
+          struct plot_points *points = 
+            (struct plot_points *) gpmalloc(sizeof(*points)*nb);
+          for(j=0;j<nb;j++)
+          {
+            points[j].x = DTOL((ptx[j]+x0)*xs);
+            points[j].y = DTOL((pty[j]+y0)*ys);
+          }
+          eng->sc(data,RoCol(p1));
+          eng->ml(data, nb, points);
+          free(points);
+          break;
+        }
+      case ROt_ST:
+        {
+          long hjust = RoSTdir(p1) & RoSTdirHPOS_mask;
+          long vjust = RoSTdir(p1) & RoSTdirVPOS_mask;
+          char *text = RoSTs(p1);
+          long l     = RoSTl(p1);
+          long x, y;
+          long hgap  = RoSTdir(p1) & RoSTdirHGAP;
+          long vgap  = RoSTdir(p1) & RoSTdirVGAP;
+          long shift = (hjust == RoSTdirLEFT ? 0 :
+              (hjust == RoSTdirRIGHT ? 2 : 1));
+          if (hgap)
+            hgap = (hjust == RoSTdirLEFT) ? hgapsize : -hgapsize;
+          if (vgap)
+            vgap = (vjust == RoSTdirBOTTOM) ? 2*vgapsize : -2*vgapsize;
+          if (vjust != RoSTdirBOTTOM)
+            vgap -= ((vjust == RoSTdirTOP) ? 2 : 1)*(f_height - 1);
+          x = DTOL(( RoSTx(p1) + x0 + hgap
+                  - (strlen(RoSTs(p1)) * pari_plot.fwidth
+                    * shift)/2)*xs);
+          y = DTOL((RoSTy(p1)+y0-vgap/2)*ys);
+          eng->sc(data,RoCol(p1));
+          eng->st(data, x, y, text, l); 
+          break;
+        }
+      default: 
+        break;
+      }
+    }
+  }
+}
Index: pari/src/graph/rect.h
===================================================================
--- pari.orig/src/graph/rect.h	2005-08-25 23:14:20.000000000 +0200
+++ pari/src/graph/rect.h	2005-08-26 10:12:26.000000000 +0200
@@ -110,6 +110,23 @@
   double size;
 } RectObjPS;
 
+struct plot_points
+{
+  long x, y;
+};
+
+struct plot_eng
+{
+  void (*sc)(void *data, long col);
+  void (*pt)(void *data, long x, long y);
+  void (*ln)(void *data, long x1, long y1, long x2, long y2);
+  void (*bx)(void *data, long x, long y, long w, long h);
+  void (*mp)(void *data, long n, struct plot_points *points);
+  void (*ml)(void *data, long n, struct plot_points *points);
+  void (*st)(void *data, long x, long y, char *s, long l);
+};
+
+
 #define BLACK      1 /* Default */
 #define BLUE       2 /* Axes */
 #define VIOLET     3 /* Odd numbered curves in ploth */
@@ -296,6 +313,8 @@
 
 void  free_graph(void);
 
+void gen_rectdraw0(struct plot_eng *eng, void *data, long *w, long *x, long *y, long lw, double xs, double ys);
+
 /* architecture-dependent plot file (plotX.c, plognuplot.c...) */
 void  PARI_get_plot(long fatal);
 long  plot_outfile_set(char *s);