Ilya Zakharevich on Wed, 29 Sep 1999 23:40:02 -0400 (EDT) |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Plot strings justified |
I was writing small docs to show how use graphing commands of PARI, and found that a lot of time is spent in justifying strings on the screen. On the other hand, PARI can do it itself. So I added this ability to PARI. Enjoy, Ilya P.S. I also updated comments, and fixed a bug in ps output: the strings to output should have contained balanced parens only. Tested with ps, gnuplot and X output only (not on sun). --- ./src/gp/highlvl.c~ Thu Sep 16 09:50:18 1999 +++ ./src/gp/highlvl.c Wed Sep 29 22:56:32 1999 @@ -202,7 +202,7 @@ entree functions_highlevel[]={ {"plotrmove",35,(void*)rectrmove,10,"vLGG"}, {"plotrpoint",35,(void*)rectrpoint,10,"vLGG"}, {"plotscale",59,(void*)rectscale,10,"vLGGGG"}, -{"plotstring",57,(void*)rectstring,10,"vLs"}, +{"plotstring",57,(void*)rectstring3,10,"vLsD0,L,"}, {"plotterm",16,(void*)term_set,10,"ls"}, {"psdraw",99,(void*)postdraw,10,"vG"}, {"psploth",99,(void*)postploth,10,"V=GGIpD0,L,D0,L,"}, @@ -242,7 +242,7 @@ char *helpmessages_highlevel[]={ "plotrmove(w,dx,dy): move cursor to position (dx,dy) relative to the present position in the rectwindow w", "plotrpoint(w,dx,dy): draw a point (and move cursor) at position dx,dy relative to present position of the cursor in rectwindow w", "plotscale(w,x1,x2,y1,y2): scale the coordinates in rectwindow w so that x goes from x1 to x2 and y from y1 to y2 (y2<y1 is allowed)", - "plotstring(w,x): draw in rectwindow w the string corresponding to x", + "plotstring(w,x,{flags=0}): draw in rectwindow w the string corresponding to x, justify left if flag is 0, right if it is 2, center if 1", "plotterm(\"termname\"): set terminal to plot in high resolution to. Ignored by some drivers. In gnuplot driver possible terminals are the same as in gnuplot. Positive value means success", "psdraw(list): same as plotdraw, except that the output is a postscript program in psfile (pari.ps by default)", "psploth(X=a,b,expr,{flags=0},{n=0}): same as ploth, except that the output is a postscript program in psfile (pari.ps by default)", --- ./src/graph/plotport.c~ Thu Sep 16 09:50:20 1999 +++ ./src/graph/plotport.c Wed Sep 29 23:34:26 1999 @@ -297,19 +297,19 @@ rectmove0(long ne, double x, double y, l } void -rectmove(long ne, GEN x, GEN y) /* code = 0 */ +rectmove(long ne, GEN x, GEN y) { rectmove0(ne,gtodouble(x),gtodouble(y),0); } void -rectrmove(long ne, GEN x, GEN y) /* code = 0 */ +rectrmove(long ne, GEN x, GEN y) { rectmove0(ne,gtodouble(x),gtodouble(y),1); } void -rectpoint0(long ne, double x, double y,long relative) /* code = 1 */ +rectpoint0(long ne, double x, double y,long relative) /* code = ROt_MV/ROt_PT */ { PariRect *e = check_rect_init(ne); RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj1P)); @@ -329,13 +329,13 @@ rectpoint0(long ne, double x, double y,l } void -rectpoint(long ne, GEN x, GEN y) /* code = 1 */ +rectpoint(long ne, GEN x, GEN y) { rectpoint0(ne,gtodouble(x),gtodouble(y),0); } void -rectrpoint(long ne, GEN x, GEN y) /* code = 1 */ +rectrpoint(long ne, GEN x, GEN y) { rectpoint0(ne,gtodouble(x),gtodouble(y),1); } @@ -349,7 +349,7 @@ rectcolor(long ne, long color) } void -rectline0(long ne, double gx2, double gy2, long relative) /* code = 2 */ +rectline0(long ne, double gx2, double gy2, long relative) /* code = ROt_MV/ROt_LN */ { long dx,dy,dxy,xmin,xmax,ymin,ymax,x1,y1,x2,y2; PariRect *e = check_rect_init(ne); @@ -391,13 +391,13 @@ rectline0(long ne, double gx2, double gy } void -rectline(long ne, GEN gx2, GEN gy2) /* code = 2 */ +rectline(long ne, GEN gx2, GEN gy2) { rectline0(ne, gtodouble(gx2), gtodouble(gy2),0); } void -rectrline(long ne, GEN gx2, GEN gy2) /* code = 2 */ +rectrline(long ne, GEN gx2, GEN gy2) { rectline0(ne, gtodouble(gx2), gtodouble(gy2),1); } @@ -430,13 +430,13 @@ rectbox0(long ne, double gx2, double gy2 } void -rectbox(long ne, GEN gx2, GEN gy2) /* code = 3 */ +rectbox(long ne, GEN gx2, GEN gy2) { rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 0); } void -rectrbox(long ne, GEN gx2, GEN gy2) /* code = 3 */ +rectrbox(long ne, GEN gx2, GEN gy2) { rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 1); } @@ -466,7 +466,7 @@ killrect(long ne) } void -rectpoints0(long ne, double *listx, double *listy, long lx) /* code = 4 */ +rectpoints0(long ne, double *listx, double *listy, long lx) /* code = ROt_MP */ { long *ptx,*pty,x,y,i,cp=0; PariRect *e = check_rect_init(ne); @@ -491,7 +491,7 @@ rectpoints0(long ne, double *listx, doub } void -rectpoints(long ne, GEN listx, GEN listy) /* code = 4 */ +rectpoints(long ne, GEN listx, GEN listy) { long i,lx, tx=typ(listx), ty=typ(listy); double *px,*py; @@ -515,7 +515,7 @@ rectpoints(long ne, GEN listx, GEN listy } void -rectlines0(long ne, double *x, double *y, long lx, long flag) /* code = 5 */ +rectlines0(long ne, double *x, double *y, long lx, long flag) /* code = ROt_ML */ { long i,I,*ptx,*pty; PariRect *e = check_rect_init(ne); @@ -542,7 +542,7 @@ rectlines0(long ne, double *x, double *y } void -rectlines(long ne, GEN listx, GEN listy, long flag) /* code = 5 */ +rectlines(long ne, GEN listx, GEN listy, long flag) { long tx=typ(listx), ty=typ(listy), lx=lg(listx), i; double *x, *y; @@ -566,14 +566,20 @@ rectlines(long ne, GEN listx, GEN listy, } static void -put_string(long win, long x, long y, char *str) +put_string(long win, long x, long y, char *str, long dir) { - rectmove0(win,(double)x,(double)y,0); rectstring(win,str); + rectmove0(win,(double)x,(double)y,0); rectstring3(win,str,dir); +} + +void +rectstring(long ne, char *str) +{ + rectstring3(ne,str,RoSTdirLEFT); } /* Allocate memory, then put string */ void -rectstring(long ne, char *str) /* code = 6 */ +rectstring3(long ne, char *str, long dir) /* code = ROt_ST */ { PariRect *e = check_rect_init(ne); RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjST)); @@ -585,13 +591,14 @@ rectstring(long ne, char *str) /* code = RoSTl(z) = l; RoSTs(z) = s; RoSTx(z) = DTOL(RXscale(e)*RXcursor(e)+RXshift(e)); RoSTy(z) = DTOL(RYscale(e)*RYcursor(e)+RYshift(e)); + RoSTdir(z) = dir; if (!RHead(e)) RHead(e)=RTail(e)=z; else { RoNext(RTail(e))=z; RTail(e)=z; } RoCol(z)=current_color[ne]; } void -rectpointtype(long ne, long type) /* code = 0 */ +rectpointtype(long ne, long type) /* code = ROt_PTT */ { if (ne == -1) { rectpoint_itype = type; @@ -607,7 +614,7 @@ rectpointtype(long ne, long type) /* cod } void -rectpointsize(long ne, GEN size) /* code = 0 */ +rectpointsize(long ne, GEN size) /* code = ROt_PTS */ { if (ne == -1) { set_pointsize(gtodouble(size)); /* Immediate set */ @@ -678,7 +685,7 @@ rectcopy(long source, long dest, long xo RoNext(tail) = next; tail = next; break; case ROt_ST: - next = (RectObj*) gpmalloc(sizeof(RectObjMP)); + next = (RectObj*) gpmalloc(sizeof(RectObjST)); memcpy(next,p1,sizeof(RectObjMP)); RoSTs(next) = (char*) gpmalloc(RoSTl(p1)+1); memcpy(RoSTs(next),RoSTs(p1),RoSTl(p1)+1); @@ -1493,16 +1500,19 @@ rectplothrawin(long stringrect, long dra if (WW) { char c1[16],c2[16],c3[16],c4[16]; + int gap = rm + 2; - sprintf(c1,"%9.3f",ybig); sprintf(c2,"%9.3f",ysml); - sprintf(c3,"%9.3f",xsml); sprintf(c4,"%9.3f",xbig); + sprintf(c1,"%5.3f",ybig); sprintf(c2,"%5.3f",ysml); + sprintf(c3,"%5.3f",xsml); sprintf(c4,"%5.3f",xbig); rectlinetype(stringrect,-2); /* Frame */ current_color[stringrect]=BLACK; - put_string(stringrect, 0, W.fheight - 1, c1); - put_string(stringrect, 0, W.height - (bm+ 2 * W.vunit), c2); - put_string(stringrect, lm-(W.fwidth*2), W.height-bm+W.fheight-1, c3); - put_string(stringrect, W.width-(W.fwidth*10), W.height-bm+W.fheight-1,c4); + put_string(stringrect, lm - gap, W.fheight - 1, c1, RoSTdirRIGHT); + put_string(stringrect, lm - gap, W.height - (bm+ 2 * W.vunit), c2, RoSTdirRIGHT); + put_string(stringrect, lm, W.height - bm + W.fheight - 1, + c3, RoSTdirLEFT); + put_string(stringrect, W.width - rm - 1, W.height - bm + W.fheight - 1, + c4, RoSTdirRIGHT); if (flags & PLOT_POSTSCRIPT) postdraw0(w,wx,wy,2); @@ -1650,7 +1660,7 @@ typedef struct srectangle { static void ps_point(FILE *psfile, int x, int y); static void ps_line(FILE *psfile, int x1, int y1, int x2, int y2); static void ps_rect(FILE *psfile, int x1, int y1, int x2, int y2); -static void ps_string(FILE *psfile, int x, int y, char *c); +static void ps_string(FILE *psfile, int x, int y, char *c, long dir); #undef ISCR #undef JSCR @@ -1708,7 +1718,7 @@ zmalloc(size_t x) void postdraw0(long *w, long *x, long *y, long lw) { - long *ptx,*pty,*numpoints,*numtexts,*xtexts,*ytexts; + long *ptx,*pty,*numpoints,*numtexts,*xtexts,*ytexts,*dirtexts; RectObj *p1; PariRect *e; long i,j,x0,y0; @@ -1745,6 +1755,7 @@ postdraw0(long *w, long *x, long *y, lon numtexts=(long*) zmalloc(nd[ROt_ST]*sizeof(long)); xtexts = (long*) zmalloc(nd[ROt_ST]*sizeof(long)); ytexts = (long*) zmalloc(nd[ROt_ST]*sizeof(long)); + dirtexts = (long*) zmalloc(nd[ROt_ST]*sizeof(long)); for (i=0; i<=ROt_MAX; i++) nd[i]=0; for (i=0; i<lw; i++) @@ -1793,13 +1804,16 @@ postdraw0(long *w, long *x, long *y, lon numtexts[nd[ROt_ST]]=RoSTl(p1); xtexts[nd[ROt_ST]]=RoSTx(p1)+x0; ytexts[nd[ROt_ST]]=RoSTy(p1)+y0; + dirtexts[nd[ROt_ST]]=RoSTdir(p1); nd[ROt_ST]++; break; default: break; } p1=RoNext(p1); } } + /* Definitions taken from post terminal of Gnuplot. */ fprintf(psfile,"%%!\n50 50 translate\n/Times-Roman findfont 16 scalefont setfont\n0.65 0.65 scale\n"); + fprintf(psfile,"/Lshow { moveto 90 rotate show -90 rotate } def\n/Rshow { 3 -1 roll dup 4 1 roll stringwidth pop sub Lshow } def\n/Cshow { 3 -1 roll dup 4 1 roll stringwidth pop 2 div sub Lshow } def\n"); for (i=0; i<nd[ROt_PT]; i++) ps_point(psfile,points[i].x,points[i].y); for (i=0; i<nd[ROt_LN]; i++) @@ -1819,7 +1833,7 @@ postdraw0(long *w, long *x, long *y, lon } } for (i=0; i<nd[ROt_ST]; i++) - ps_string(psfile,xtexts[i],ytexts[i],texts[i]); + ps_string(psfile,xtexts[i],ytexts[i],texts[i], dirtexts[i]); fprintf(psfile,"stroke showpage\n"); fclose(psfile); #define xfree(pointer) if (pointer) free(pointer) xfree(points); xfree(seg); xfree(rect); xfree(numpoints); @@ -1847,7 +1861,19 @@ ps_rect(FILE *psfile, int x1, int y1, in } static void -ps_string(FILE *psfile, int x, int y, char *c) +ps_string(FILE *psfile, int x, int y, char *s, long dir) { - fprintf(psfile,"%d %d moveto 90 rotate\n(%s) show -90 rotate\n",y,x,c); + if (strpbrk(s, "(\\)")) { + fprintf(psfile,"("); + while (*s) { + if ( *s=='(' || *s==')' || *s=='\\' ) + fputc('\\', psfile); + fputc(*s, psfile); + s++; + } + } else + fprintf(psfile,"(%s", s); + fprintf(psfile,") %d %d %sshow\n", + y, x, + (dir == RoSTdirLEFT ? "L" : (dir == RoSTdirRIGHT ? "R" : "C"))); } --- ./src/graph/plotgnuplot.c~ Thu Sep 16 09:50:20 1999 +++ ./src/graph/plotgnuplot.c Wed Sep 29 23:30:41 1999 @@ -30,6 +30,7 @@ rectdraw0(long *w, long *x, long *y, lon int point_type = -1, line_type = 0; PariRect *e; RectObj *p1; + int strdir = RoSTdirLEFT, can_justify = 1, shift = 0, xstart, xend; PARI_get_plot(0); @@ -100,12 +101,23 @@ rectdraw0(long *w, long *x, long *y, lon } break; case ROt_ST: - if (RoSTx(p1)+x0 < 0 || RoSTx(p1)+x0+RoSTl(p1)-1 >= w_width + if (strdir != RoSTdir(p1)) { + shift = (RoSTdir(p1) == RoSTdirLEFT ? 0 : + (RoSTdir(p1) == RoSTdirRIGHT ? 2 : 1)); + + can_justify = justify_text(shift); /* 1 for LEFT */ + strdir = RoSTdir(p1); + } + xstart = RoSTx(p1) + x0 + - (can_justify ? 0 + : ((RoSTl(p1) * pari_plot.fwidth - 1) * shift / 2)); + xend = xstart + (can_justify ? 0 : RoSTl(p1) * pari_plot.fwidth - 1); + if (xstart < 0 || xend >= w_width || RoSTy(p1) + y0 < 0 || RoSTy(p1) + y0 >= w_height) { } else { - put_text(RoSTx(p1)+x0, - w_height - 1 - RoSTy(p1) - y0 + (f_height - 1)/2, - RoSTs(p1)); + put_text(xstart, + w_height - 1 - RoSTy(p1) - y0 + (f_height - 1)/2, + RoSTs(p1)); } break; case ROt_PTT: @@ -147,6 +159,7 @@ term_set(char *s) char *t, *size = NULL; double x, y; + setup_gpshim(); if (*s == 0) s = pari_plot.name; t = s; --- ./src/graph/plotX.c~ Thu Sep 16 09:50:19 1999 +++ ./src/graph/plotX.c Wed Sep 29 22:44:23 1999 @@ -116,7 +116,7 @@ zmalloc(size_t x) void rectdraw0(long *w, long *x, long *y, long lw, long do_free) { - long *ptx,*pty,*c; + long *ptx,*pty,*c, shift; long *numpoints[MAX_COLORS],*numtexts[MAX_COLORS]; long *xtexts[MAX_COLORS],*ytexts[MAX_COLORS]; long rcolcnt[MAX_COLORS][ROt_MAX]; @@ -318,7 +318,12 @@ rectdraw0(long *w, long *x, long *y, lon case ROt_ST: texts[col][c[ROt_ST]]=RoSTs(p1); numtexts[col][c[ROt_ST]]=RoSTl(p1); - xtexts[col][c[ROt_ST]]= (long)((RoSTx(p1)+x0)*xs); + shift = (RoSTdir(p1) == RoSTdirLEFT ? 0 : + (RoSTdir(p1) == RoSTdirRIGHT ? 2 : 1)); + xtexts[col][c[ROt_ST]] + = (long)(( RoSTx(p1) + x0 + - (strlen(RoSTs(p1)) * pari_plot.fwidth + * shift)/2)*xs); ytexts[col][c[ROt_ST]]= (long)((RoSTy(p1)+y0)*ys); c[ROt_ST]++;break; default: break; --- ./src/graph/plotsun.c~ Thu Sep 16 09:50:21 1999 +++ ./src/graph/plotsun.c Wed Sep 29 22:46:32 1999 @@ -22,7 +22,7 @@ void rectdraw0(long *w, long *x, long *y, long lw, long do_free) { long *ptx,*pty,*numpoints,*numtexts,*xtexts,*ytexts; - long n,i,j,x0,y0; + long n,i,j,x0,y0,shift; long a,b,c,d,ne; long rcnt[ROt_MAX+1]; char **texts; @@ -111,7 +111,11 @@ rectdraw0(long *w, long *x, long *y, lon rcnt[ROt_ML]++;break; case ROt_ST: texts[rcnt[ROt_ST]]=RoSTs(p1); numtexts[rcnt[ROt_ST]]=RoSTl(p1); - xtexts[rcnt[ROt_ST]]=RoSTx(p1)+x0; ytexts[rcnt[ROt_ST]]=RoSTy(p1)+y0; + shift = (RoSTdir(p1) == RoSTdirLEFT ? 0 : + (RoSTdir(p1) == RoSTdirRIGHT ? 2 : 1)); + xtexts[rcnt[ROt_ST]]=RoSTx(p1)+x0 + - (strlen(RoSTs(p1)) * pari_plot.fwidth * shift)/2; + ytexts[rcnt[ROt_ST]]=RoSTy(p1)+y0; rcnt[ROt_ST]++;break; default: break; } --- ./src/graph/rect.h~ Thu Sep 16 09:50:21 1999 +++ ./src/graph/rect.h Wed Sep 29 20:33:20 1999 @@ -73,7 +73,7 @@ typedef struct RectObjST { long code,color; long length; char *s; - long x,y; + long x,y,dir; } RectObjST; typedef struct RectObjPN { @@ -168,6 +168,11 @@ typedef struct RectObjPS { #define RoSTl(rop) (RoST(rop)->length) #define RoSTx(rop) (RoST(rop)->x) #define RoSTy(rop) (RoST(rop)->y) +#define RoSTdir(rop) (RoST(rop)->dir) + +#define RoSTdirLEFT 0 +#define RoSTdirCENTER 1 +#define RoSTdirRIGHT 2 #define RoPTTpen(rop) (RoPTT(rop)->pen) #define RoLNTpen(rop) (RoLNT(rop)->pen) @@ -228,6 +233,7 @@ void rectrmove(long ne, GEN x, GEN y) void rectrpoint(long ne, GEN x, GEN y); void rectscale(long ne, GEN x1, GEN x2, GEN y1, GEN y2); void rectstring(long ne, char *x); +void rectstring3(long ne, char *x, long dir); void rectclip(long rect); /* architecture-dependent plot file (plotX.c, plotsun.c, plognuplot.c...) */