| 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...) */