00001
00002
00003
00004
00005
00006
00007 #ifndef lint
00008 static char vcid[] = "$Id: xdisplaylist.c,v 1.2 1994/12/08 23:37:00 duchier Exp $";
00009 #endif
00010
00011 #ifdef X11
00012
00013 #include <stdio.h>
00014
00015 #include <sys/types.h>
00016 #include <sys/stat.h>
00017 #include <fcntl.h>
00018 #include <limits.h>
00019
00020 #include <X11/Xlib.h>
00021 #include <X11/Xutil.h>
00022
00023 #include "extern.h"
00024 #include "xdisplaylist.h"
00025
00026
00027
00028
00029 typedef struct wl_Line
00030 {
00031 Action action;
00032 ListLinks links;
00033 int x0, y0, x1, y1;
00034 long function;
00035 long color;
00036 long linewidth;
00037 } Line;
00038
00039
00040 typedef struct wl_Rectangle
00041 {
00042 Action action;
00043 ListLinks links;
00044 int x, y, width, height;
00045 long function;
00046 long color;
00047 long linewidth;
00048 } Rectangle;
00049
00050
00051 typedef struct wl_Arc
00052 {
00053 Action action;
00054 ListLinks links;
00055 int x, y, width, height, startangle, arcangle;
00056 long function;
00057 long color;
00058 long linewidth;
00059 } Arc;
00060
00061
00062 typedef struct wl_String
00063 {
00064 Action action;
00065 ListLinks links;
00066 int x, y;
00067 char *str;
00068 long function;
00069 long color;
00070 long font;
00071 } String;
00072
00073
00074 typedef struct wl_GraphicClosure
00075 {
00076 Display *display;
00077 Drawable drawable;
00078 GC gc;
00079 } GraphicClosure;
00080
00081 typedef struct wl_PostScriptClosure
00082 {
00083 long display;
00084 Drawable window;
00085 long f;
00086 long height;
00087 } PostScriptClosure;
00088
00089 typedef struct wl_Polygon
00090 {
00091 Action action;
00092 ListLinks links;
00093 XPoint *points;
00094 long npoints;
00095 long function;
00096 long color;
00097 long linewidth;
00098 } Polygon;
00099
00100 typedef union wl_DisplayElt
00101 {
00102 Action action;
00103 Line line;
00104 Rectangle rectangle;
00105 Arc arc;
00106 String str;
00107 Polygon polygon;
00108 } DisplayElt;
00109
00110 typedef DisplayElt *RefDisplayElt;
00111
00112
00113
00114
00115
00116 static ListLinks *x_get_links_of_display_list (elt)
00117
00118 DisplayElt *elt;
00119
00120 {
00121 return &((Line *) elt)->links;
00122 }
00123
00124
00125 ListHeader * x_display_list ()
00126
00127 {
00128 ListHeader *display_list;
00129
00130 display_list = (ListHeader *) malloc (sizeof (ListHeader));
00131 List_SetLinkProc (display_list, x_get_links_of_display_list);
00132 return display_list;
00133 }
00134
00135
00136
00137 void x_set_gc (display, gc, function, color, linewidth, font)
00138
00139 Display *display;
00140 GC gc;
00141 long function;
00142 unsigned long color;
00143 long linewidth;
00144 Font font;
00145
00146 {
00147 XGCValues gcvalues;
00148 unsigned long valuemask;
00149
00150
00151 gcvalues.function = function;
00152 gcvalues.foreground = color;
00153 valuemask = GCFunction | GCForeground;
00154
00155 if (linewidth != xDefaultLineWidth)
00156 {
00157 gcvalues.line_width = linewidth;
00158 valuemask |= GCLineWidth;
00159 }
00160
00161 if (font != xDefaultFont)
00162 {
00163 gcvalues.font = font;
00164 valuemask |= GCFont;
00165 }
00166
00167 XChangeGC (display, gc, valuemask, &gcvalues);
00168 }
00169
00170
00171
00172
00173 #define AllocDisplayElt() malloc (sizeof (DisplayElt))
00174 #define FreeDisplayElt(E) free (E)
00175
00176
00177 void x_record_line (displaylist, action, x0, y0, x1, y1,
00178 function, color, linewidth)
00179
00180 ListHeader *displaylist;
00181 Action action;
00182 long x0, y0, x1, y1;
00183 unsigned long function, color, linewidth;
00184
00185 {
00186 Line * elt;
00187
00188 elt = (Line *) AllocDisplayElt ();
00189 elt->action = action;
00190 elt->x0 = x0;
00191 elt->y0 = y0;
00192 elt->x1 = x1;
00193 elt->y1 = y1;
00194 elt->function = function;
00195 elt->color = color;
00196 elt->linewidth = linewidth;
00197 List_Append (displaylist, (Ref) elt);
00198 }
00199
00200
00201
00202
00203
00204 void x_record_arc (displaylist, action, x, y, width, height,
00205 startangle, arcangle,
00206 function, color, linewidth)
00207
00208 ListHeader *displaylist;
00209 Action action;
00210 long x, y, width, height, startangle, arcangle;
00211 unsigned long function, color, linewidth;
00212
00213 {
00214 Arc * elt;
00215
00216 elt = (Arc *) AllocDisplayElt ();
00217 elt->action = action;
00218 elt->x = x;
00219 elt->y = y;
00220 elt->width = width;
00221 elt->height = height;
00222 elt->startangle = startangle;
00223 elt->arcangle = arcangle;
00224 elt->function = function;
00225 elt->color = color;
00226 elt->linewidth = linewidth;
00227 List_Append (displaylist, (Ref) elt);
00228 }
00229
00230
00231
00232
00233 void x_record_rectangle (displaylist, action, x, y, width, height,
00234 function, color, linewidth)
00235
00236 ListHeader *displaylist;
00237 Action action;
00238 long x, y, width, height;
00239 unsigned long function, color, linewidth;
00240
00241 {
00242 Rectangle * elt;
00243
00244 elt = (Rectangle *) AllocDisplayElt ();
00245 elt->action = action;
00246 elt->x = x;
00247 elt->y = y;
00248 elt->width = width;
00249 elt->height = height;
00250 elt->function = function;
00251 elt->color = color;
00252 elt->linewidth = linewidth;
00253 List_Append (displaylist, (Ref) elt);
00254 }
00255
00256
00257
00258
00259 void x_record_polygon (displaylist, action, points, npoints,
00260 function, color, linewidth)
00261
00262 ListHeader *displaylist;
00263 Action action;
00264 XPoint *points;
00265 long npoints;
00266 unsigned long function, color, linewidth;
00267
00268 {
00269 Polygon * elt;
00270 XPoint *p;
00271
00272
00273 elt = (Polygon *) AllocDisplayElt ();
00274 elt->action = action;
00275 elt->npoints = npoints;
00276 elt->points = p = (XPoint *) malloc (npoints*2*sizeof(short));
00277 for (; npoints > 0; npoints--, p++, points++)
00278 *p = *points;
00279 elt->function = function;
00280 elt->color = color;
00281 elt->linewidth = linewidth;
00282 List_Append (displaylist, (Ref) elt);
00283 }
00284
00285
00286
00287
00288 void x_record_string (displaylist, action, x, y, str, font,
00289 function, color)
00290
00291 ListHeader *displaylist;
00292 Action action;
00293 long x, y, font;
00294 char *str;
00295 unsigned long function, color;
00296
00297 {
00298 String * elt;
00299
00300 elt = (String *) AllocDisplayElt ();
00301 elt->action = action;
00302 elt->x = x;
00303 elt->y = y;
00304 elt->str = (char *) malloc (strlen (str)+1);
00305 strcpy (elt->str, str);
00306 *(elt->str+strlen(str)) = '\0';
00307 elt->function = function;
00308 elt->color = color;
00309 elt->font = font;
00310 List_Append (displaylist, (Ref) elt);
00311 }
00312
00313
00314
00315
00316 static long x_draw_elt (elt, g)
00317
00318 DisplayElt *elt;
00319 GraphicClosure *g;
00320
00321 {
00322 Line *line;
00323 Arc *arc;
00324 Rectangle *rectangle;
00325 String *s;
00326 Polygon *polygon;
00327
00328
00329 switch (elt->action)
00330 {
00331 case DRAW_LINE:
00332 line = (Line *) elt;
00333 x_set_gc (g->display, g->gc, line->function,
00334 line->color, line->linewidth, xDefaultFont);
00335 XDrawLine (g->display, g->drawable, g->gc,
00336 line->x0, line->y0, line->x1, line->y1);
00337 break;
00338
00339 case DRAW_ARC:
00340 case FILL_ARC:
00341 arc = (Arc *) elt;
00342 x_set_gc (g->display, g->gc, arc->function,
00343 arc->color, arc->linewidth, xDefaultFont);
00344 if (arc->action == DRAW_ARC)
00345 XDrawArc (g->display, g->drawable, g->gc,
00346 arc->x, arc->y,
00347 arc->width, arc->height,
00348 arc->startangle, arc->arcangle);
00349 else
00350 XFillArc (g->display, g->drawable, g->gc,
00351 arc->x, arc->y,
00352 arc->width, arc->height,
00353 arc->startangle, arc->arcangle);
00354 break;
00355
00356 case DRAW_RECTANGLE:
00357 case FILL_RECTANGLE:
00358 rectangle = (Rectangle *) elt;
00359 x_set_gc (g->display, g->gc, rectangle->function,
00360 rectangle->color, rectangle->linewidth, xDefaultFont);
00361 if (rectangle->action == DRAW_RECTANGLE)
00362 XDrawRectangle (g->display, g->drawable, g->gc,
00363 rectangle->x, rectangle->y,
00364 rectangle->width, rectangle->height);
00365 else
00366 XFillRectangle (g->display, g->drawable, g->gc,
00367 rectangle->x, rectangle->y,
00368 rectangle->width, rectangle->height);
00369 break;
00370
00371 case DRAW_STRING:
00372 case DRAW_IMAGE_STRING:
00373 s = (String *) elt;
00374 x_set_gc (g->display, g->gc, s->function,
00375 s->color, xDefaultLineWidth, s->font);
00376 if (s->action == DRAW_STRING)
00377 XDrawString (g->display, g->drawable, g->gc,
00378 s->x, s->y,
00379 s->str, strlen (s->str));
00380 else
00381 XDrawImageString (g->display, g->drawable, g->gc,
00382 s->x, s->y,
00383 s->str, strlen (s->str));
00384 break;
00385
00386 case DRAW_POLYGON:
00387 case FILL_POLYGON:
00388 polygon = (Polygon *) elt;
00389 x_set_gc (g->display, g->gc, polygon->function,
00390 polygon->color, polygon->linewidth, xDefaultFont);
00391 if (polygon->action == FILL_POLYGON)
00392 XFillPolygon (g->display, g->drawable, g->gc,
00393 polygon->points, polygon->npoints,
00394 Complex, CoordModeOrigin);
00395 else
00396 XDrawLines (g->display, g->drawable, g->gc,
00397 polygon->points, polygon->npoints,
00398 CoordModeOrigin);
00399 break;
00400
00401 }
00402
00403 return TRUE;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413 void x_refresh_window (display, window, pixmap, pixmapgc, displaylist)
00414
00415 Display *display;
00416 Window window;
00417 Pixmap pixmap;
00418 GC pixmapgc;
00419 ListHeader *displaylist;
00420
00421 {
00422 XWindowAttributes attr;
00423 GraphicClosure g;
00424
00425
00426
00427 XSetGraphicsExposures (display, pixmapgc, False);
00428
00429
00430 XGetWindowAttributes (display, window, &attr);
00431
00432 #if 0
00433
00434 XClearArea (display, pixmap, 0, 0,
00435 attr.width, attr.height, False);
00436 #endif
00437
00438 x_set_gc (display, pixmapgc, GXcopy, attr.backing_pixel,
00439 xDefaultLineWidth, xDefaultFont);
00440
00441 XFillRectangle (display, pixmap, pixmapgc,
00442 0, 0, attr.width, attr.height);
00443
00444 g.display = display;
00445 g.drawable = pixmap;
00446 g.gc = pixmapgc;
00447
00448 List_Enum (displaylist, x_draw_elt, &g);
00449
00450
00451 if (window != pixmap)
00452 XCopyArea (display, pixmap, window, pixmapgc, 0, 0,
00453 attr.width, attr.height, 0, 0);
00454
00455 XSync (display, 0);
00456 }
00457
00458
00459
00460 static long x_free_elt (elt, closure)
00461
00462 DisplayElt *elt;
00463 long *closure;
00464
00465 {
00466 Line *line;
00467 Arc *arc;
00468 Rectangle *rectangle;
00469 String *s;
00470 Polygon *polygon;
00471
00472
00473
00474 switch (elt->action)
00475 {
00476 case DRAW_LINE:
00477
00478 break;
00479
00480 case DRAW_ARC:
00481 case FILL_ARC:
00482
00483 break;
00484
00485 case DRAW_RECTANGLE:
00486 case FILL_RECTANGLE:
00487
00488 break;
00489
00490 case DRAW_STRING:
00491 case DRAW_IMAGE_STRING:
00492 s = (String *) elt;
00493 free (s->str);
00494 break;
00495
00496 case DRAW_POLYGON:
00497 case FILL_POLYGON:
00498 polygon = (Polygon *) elt;
00499 free (polygon->points);
00500 break;
00501
00502 }
00503
00504
00505 FreeDisplayElt (elt);
00506
00507 return TRUE;
00508 }
00509
00510
00511
00512 void x_free_display_list (displaylist)
00513
00514 ListHeader *displaylist;
00515
00516 {
00517 List_Enum (displaylist, x_free_elt, NULL);
00518 }
00519
00520
00521
00522 static char *prolog[] = {
00523 "%!PS-Adobe-2.0\n",
00524 "/mt {moveto} def /lt {lineto} def /slw {setlinewidth} def\n",
00525 "/np {newpath} def /st {stroke} def /fi {fill} def /cp {closepath} def\n",
00526 "1 setlinecap 1 setlinejoin\n",
00527 "/line {/lw exch def /b exch def /g exch def /r exch def\n",
00528 " /y1 exch def /x1 exch def \n",
00529 " /y0 exch def /x0 exch def\n",
00530 " r 65535 div g 65535 div b 65535 div setrgbcolor\n",
00531 " np lw slw x0 y0 mt x1 y1 lt st} def\n",
00532 "/rect {/sf exch def /lw exch def\n",
00533 " /b exch def /g exch def /r exch def\n",
00534 " /h exch def /w exch def \n",
00535 " /y exch def /x exch def\n",
00536 " r 65535 div g 65535 div b 65535 div setrgbcolor\n",
00537 " np lw slw x y mt x w add y lt x w add y h sub lt\n",
00538 " x y h sub lt cp sf {st} {fi} ifelse} def\n",
00539 "/earcdict 100 dict def\n",
00540 "earcdict /mtrx matrix put\n",
00541 "/earc {earcdict begin\n",
00542 " /sf exch def /lw exch def\n",
00543 " /b exch def /g exch def /r exch def\n",
00544 " r 65535 div g 65535 div b 65535 div setrgbcolor\n",
00545 " /ea exch def /sa exch def\n",
00546 " /yr exch def /xr exch def /y exch def /x exch def\n",
00547 " /savematrix mtrx currentmatrix def\n",
00548 " np x y translate xr yr scale 0 0 1 sa ea arc\n",
00549 " savematrix setmatrix lw slw sf {st} {fi} ifelse\n",
00550 " end} def\n",
00551 "/Helvetica findfont 18 scalefont setfont\n",
00552 "/dstr {/sf exch def\n",
00553 " /b exch def /g exch def /r exch def\n",
00554 " /str exch def /y exch def /x exch def\n",
00555 " r 65535 div g 65535 div b 65535 div setrgbcolor\n",
00556 " x y mt str show} def\n",
00557 0
00558 };
00559
00560
00561 static void x_postscript_prolog (f)
00562
00563 long f;
00564
00565 {
00566 long i;
00567
00568 for (i = 0; prolog[i] != 0; i++)
00569 write (f, prolog[i], strlen (prolog[i]));
00570 }
00571
00572
00573
00574 #define BUF_SIZE 512
00575
00576 static char nstr[BUF_SIZE];
00577
00578 static char *add_number (buf, n)
00579
00580 char *buf;
00581 long n;
00582
00583 {
00584 long m, i;
00585 char *s;
00586
00587 for (m=n, i=1; m>=10; i++)
00588 m /= 10;
00589
00590 if (i < BUF_SIZE && strlen (buf) + i < BUF_SIZE)
00591 {
00592 sprintf (nstr, "%ld ", n);
00593 strcat (buf, nstr);
00594 }
00595
00596 return buf;
00597 }
00598
00599
00600 static char *add_string (buf, s)
00601
00602 char *buf, *s;
00603
00604 {
00605 if (strlen (buf) + strlen(s) < BUF_SIZE)
00606 strcat (buf, s);
00607
00608 return buf;
00609 }
00610
00611
00612 static void x_get_rgb_values (display, window, color, rgb)
00613
00614 Display *display;
00615 Window window;
00616 unsigned long color;
00617 XColor *rgb;
00618
00619 {
00620 XWindowAttributes windowAttributes;
00621
00622 XGetWindowAttributes (display, window, &windowAttributes);
00623 rgb->pixel = color;
00624 XQueryColor (display, windowAttributes.colormap, rgb);
00625 }
00626
00627
00628 static long x_postscript_elt (elt, psc)
00629
00630 DisplayElt *elt;
00631 PostScriptClosure *psc;
00632
00633 {
00634 Line *line;
00635 Arc *arc;
00636 Rectangle *rectangle;
00637 String *s;
00638 Polygon *polygon;
00639 char buf[BUF_SIZE];
00640 char *pbuf;
00641 XPoint *p;
00642 XColor color;
00643 long i;
00644
00645
00646 buf[0] = 0;
00647 pbuf = buf;
00648
00649 switch (elt->action)
00650 {
00651 case DRAW_LINE:
00652 line = (Line *) elt;
00653
00654 pbuf = add_number (pbuf, line->x0);
00655 pbuf = add_number (pbuf, psc->height - line->y0);
00656 pbuf = add_number (pbuf, line->x1);
00657 pbuf = add_number (pbuf, psc->height - line->y1);
00658 x_get_rgb_values (psc->display, psc->window, line->color, &color);
00659 pbuf = add_number (pbuf, color.red);
00660 pbuf = add_number (pbuf, color.green);
00661 pbuf = add_number (pbuf, color.blue);
00662 pbuf = add_number (pbuf, line->linewidth);
00663 pbuf = add_string (pbuf, "line\n");
00664 write (psc->f, pbuf, strlen (pbuf));
00665 break;
00666
00667 case DRAW_RECTANGLE:
00668 case FILL_RECTANGLE:
00669 rectangle = (Rectangle *) elt;
00670
00671 pbuf = add_number (pbuf, rectangle->x);
00672 pbuf = add_number (pbuf, psc->height - rectangle->y);
00673 pbuf = add_number (pbuf, rectangle->width);
00674 pbuf = add_number (pbuf, rectangle->height);
00675 x_get_rgb_values (psc->display, psc->window, rectangle->color, &color);
00676 pbuf = add_number (pbuf, color.red);
00677 pbuf = add_number (pbuf, color.green);
00678 pbuf = add_number (pbuf, color.blue);
00679
00680 if (rectangle->action == DRAW_RECTANGLE)
00681 {
00682 pbuf = add_number (pbuf, rectangle->linewidth);
00683 pbuf = add_string (pbuf, "true ");
00684 }
00685 else
00686 {
00687 pbuf = add_number (pbuf, 1);
00688 pbuf = add_string (pbuf, "false ");
00689 }
00690
00691 pbuf = add_string (pbuf, "rect\n");
00692 write (psc->f, pbuf, strlen (pbuf));
00693 break;
00694
00695 case DRAW_ARC:
00696 case FILL_ARC:
00697 arc = (Arc *) elt;
00698 pbuf = add_number (pbuf, arc->x+arc->width/2);
00699 pbuf = add_number (pbuf, psc->height - (arc->y+arc->height/2));
00700 pbuf = add_number (pbuf, arc->width/2);
00701 pbuf = add_number (pbuf, arc->height/2);
00702 pbuf = add_number (pbuf, arc->startangle);
00703 pbuf = add_number (pbuf, (arc->startangle+arc->arcangle)/64);
00704 x_get_rgb_values (psc->display, psc->window, arc->color, &color);
00705 pbuf = add_number (pbuf, color.red);
00706 pbuf = add_number (pbuf, color.green);
00707 pbuf = add_number (pbuf, color.blue);
00708
00709 if (arc->action == DRAW_ARC)
00710 {
00711 pbuf = add_number (pbuf, arc->linewidth);
00712 pbuf = add_string (pbuf, "true ");
00713 }
00714 else
00715 {
00716 pbuf = add_number (pbuf, 1);
00717 pbuf = add_string (pbuf, "false ");
00718 }
00719
00720 pbuf = add_string (pbuf, "earc\n");
00721 write (psc->f, pbuf, strlen (pbuf));
00722 break;
00723
00724 case DRAW_STRING:
00725 case DRAW_IMAGE_STRING:
00726 s = (String *) elt;
00727 pbuf = add_number (pbuf, s->x);
00728 pbuf = add_number (pbuf, psc->height - s->y);
00729 pbuf = add_string (pbuf, "(");
00730 pbuf = add_string (pbuf, s->str);
00731 pbuf = add_string (pbuf, ") ");
00732 x_get_rgb_values (psc->display, psc->window, s->color, &color);
00733 pbuf = add_number (pbuf, color.red);
00734 pbuf = add_number (pbuf, color.green);
00735 pbuf = add_number (pbuf, color.blue);
00736
00737 if (s->action == DRAW_STRING)
00738 pbuf = add_string (pbuf, "true ");
00739 else
00740 pbuf = add_string (pbuf, "false ");
00741
00742 pbuf = add_string (pbuf, "dstr\n");
00743 write (psc->f, pbuf, strlen (pbuf));
00744 break;
00745
00746 case FILL_POLYGON:
00747 polygon = (Polygon *) elt;
00748
00749 x_get_rgb_values (psc->display, psc->window, polygon->color, &color);
00750 pbuf = add_number (pbuf, color.red);
00751 pbuf = add_string (pbuf, "65535 div ");
00752 pbuf = add_number (pbuf, color.green);
00753 pbuf = add_string (pbuf, "65535 div ");
00754 pbuf = add_number (pbuf, color.blue);
00755 pbuf = add_string (pbuf, "65535 div ");
00756 pbuf = add_string (pbuf, "setrgbcolor ");
00757
00758 p = polygon->points;
00759 pbuf = add_string (pbuf, "np ");
00760 pbuf = add_number (pbuf, p->x);
00761 pbuf = add_number (pbuf, psc->height - p->y);
00762 pbuf = add_string (pbuf, "mt\n");
00763 ++p;
00764 for (i=1; i<polygon->npoints; i++, p++)
00765 {
00766 pbuf = add_number (pbuf, p->x);
00767 pbuf = add_number (pbuf, psc->height - p->y);
00768 pbuf = add_string (pbuf, "lt ");
00769 if (i%4==0)
00770 pbuf = add_string (pbuf, "\n");
00771 }
00772
00773 pbuf = add_string (pbuf, "cp fi\n");
00774 write (psc->f, pbuf, strlen (pbuf));
00775 break;
00776 }
00777
00778 return TRUE;
00779 }
00780
00781
00782
00783
00784 long x_postscript_window (display, window, displaylist, filename)
00785
00786 Display *display;
00787 Window window;
00788 ListHeader *displaylist;
00789 char *filename;
00790
00791 {
00792 XWindowAttributes windowAttributes;
00793 PostScriptClosure psc;
00794
00795
00796 psc.display =(long)display;
00797 psc.window = window;
00798 if ((psc.f = open (filename, O_CREAT|O_WRONLY|O_TRUNC,
00799 S_IRUSR|S_IWUSR|S_IRWXG)) == -1)
00800 {
00801 Errorline ("\n*** Error: cannot open file %s.\n", filename);
00802 return FALSE;
00803 }
00804
00805 XGetWindowAttributes (display, window, &windowAttributes);
00806 psc.height = windowAttributes.height;
00807 x_postscript_prolog (psc.f);
00808 List_Enum (displaylist, x_postscript_elt, &psc);
00809 write (psc.f, "showpage\n", strlen ("showpage\n"));
00810 close (psc.f);
00811
00812 return TRUE;
00813 }
00814
00815
00816
00817 #endif