Annotation of OpenXM_contrib/gnuplot/term/pdf.trm, Revision 1.1
1.1 ! ohara 1: /*Hello, Emacs, this is -*-C-*- ! */
! 2: /*------------------------------
! 3: GNUPLOT - pdf.trm
! 4:
! 5: This file is included by ../term.c.
! 6:
! 7: This driver uses PDFlib from www.pdflib.com
! 8:
! 9: Author:
! 10:
! 11: Hans-Bernhard Br"oker
! 12: broeker@physik.rwth-aachen.de
! 13:
! 14: Licence: see the gnuplot copyright (to be merged into here...)
! 15:
! 16: Options: can #define PDF_DONT_COMPRESS to avoid PDF output
! 17: generated being compressed (by the 'deflate' algorithm as used
! 18: in 'zip' or 'gzip'). That helps in debugging.
! 19:
! 20: ------------------------------*/
! 21:
! 22: /* CODEME: Add patterned lines (?). Implement the PM3D stuff. */
! 23:
! 24: #include "driver.h"
! 25:
! 26: #ifdef TERM_REGISTER
! 27: register_term (pdf)
! 28: #endif
! 29:
! 30: #ifdef TERM_PROTO
! 31: TERM_PUBLIC void PDF_options __PROTO ((void));
! 32: TERM_PUBLIC void PDF_init __PROTO ((void));
! 33: TERM_PUBLIC void PDF_graphics __PROTO ((void));
! 34: TERM_PUBLIC void PDF_text __PROTO ((void));
! 35: TERM_PUBLIC void PDF_linetype __PROTO ((int linetype));
! 36: TERM_PUBLIC void PDF_move __PROTO ((unsigned int x, unsigned int y));
! 37: TERM_PUBLIC void PDF_vector __PROTO ((unsigned int x, unsigned int y));
! 38: TERM_PUBLIC void PDF_put_text __PROTO ((unsigned int x, unsigned int y, char *str));
! 39: TERM_PUBLIC void PDF_reset __PROTO ((void));
! 40: TERM_PUBLIC int PDF_justify_text __PROTO ((enum JUSTIFY mode));
! 41: TERM_PUBLIC int PDF_text_angle __PROTO ((int ang));
! 42: TERM_PUBLIC void PDF_point __PROTO ((unsigned int x, unsigned int y, int pointstyle));
! 43: TERM_PUBLIC int PDF_set_font __PROTO ((char *font));
! 44: TERM_PUBLIC void PDF_boxfill __PROTO((int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height));
! 45: TERM_PUBLIC void PDF_linewidth __PROTO ((double linewidth));
! 46:
! 47: #define PDF_NUM_POINTTYPES 75 /* number of point symbol types not counting the dot */
! 48:
! 49: #define PDF_RESOLUTION (20) /* number of terminal pixels per pt */
! 50: #define PDF_XMAX (5*72*PDF_RESOLUTION) /* 5 inches, 72 pt/inch */
! 51: #define PDF_YMAX (3*72*PDF_RESOLUTION) /* 3 inches, 72 pt/inch */
! 52:
! 53: #endif /* TERM_PROTO */
! 54:
! 55: #ifndef TERM_PROTO_ONLY
! 56: #ifdef TERM_BODY
! 57:
! 58: #include <pdflib.h>
! 59:
! 60: PDF *myPDF = NULL;
! 61:
! 62: unsigned int PDF_xLast = UINT_MAX; /* current pen horizontal position*/
! 63: unsigned int PDF_yLast = UINT_MAX; /* current pen vertical position*/
! 64:
! 65: int PDF_LineType = -3; /* current line type*/
! 66: double PDF_LineWidth = 1.0; /* current line width*/
! 67: int PDF_TextAngle = 0; /* current text orientation*/
! 68: enum JUSTIFY PDF_TextJust = LEFT; /* current text justification*/
! 69:
! 70: char PDF_fontNameDef[MAX_ID_LEN + 1] = "Helvetica"; /* default text font family*/
! 71: double PDF_fontSizeDef = 6; /* default text size*/
! 72: char PDF_fontNameCur[MAX_ID_LEN + 1] = "Helvetica"; /* current text font family*/
! 73: double PDF_fontSizeCur = 6; /* current text size*/
! 74:
! 75: TBOOLEAN PDF_pageIsOpen = FALSE; /* already started a page ?? */
! 76: TBOOLEAN PDF_pathIsOpen = FALSE; /* open path flag*/
! 77:
! 78: int PDF_fontAscent = 0; /* estimated current font ascent*/
! 79: int PDF_fontDescent = 0; /* estimated current font descent*/
! 80: int PDF_fontLeading = 0; /* estimated current font leading*/
! 81: int PDF_fontAvWidth = 0; /* estimated current font char average width*/
! 82:
! 83: static short PDF_Pen_RealID __PROTO ((int));
! 84: static void PDF_PathOpen __PROTO ((void));
! 85: static void PDF_PathClose __PROTO ((void));
! 86: static void PDF_SetFont __PROTO ((void));
! 87:
! 88: /*------------------------ helper functions -------------------*/
! 89:
! 90: static short
! 91: PDF_Pen_RealID (inPenCode)
! 92: int inPenCode;
! 93: {
! 94: if (inPenCode >= 13)
! 95: inPenCode %= 13; /* normalize pen code*/
! 96: if (inPenCode < -2)
! 97: inPenCode = -2;
! 98:
! 99: return (inPenCode + 2);
! 100: }
! 101:
! 102: /* Functions to ensure that as many move() and vector() calls as
! 103: * possible get converted into a single long 'path', before closing it
! 104: * with a stroke or similar command. */
! 105: static void
! 106: PDF_PathOpen ()
! 107: {
! 108: PDF_pathIsOpen = TRUE;
! 109: }
! 110:
! 111: static void
! 112: PDF_PathClose ()
! 113: {
! 114: if (PDF_pathIsOpen) {
! 115: PDF_stroke(myPDF);
! 116:
! 117: PDF_pathIsOpen = FALSE;
! 118: }
! 119: }
! 120:
! 121: /* Helper function to deal with switching over to a newly selected
! 122: * font. For now, this does not try to embed fonts into the PDF
! 123: * file. This relies on the user restricting herself to the 14
! 124: * 'classical' fonts built into every valid PDF reader application */
! 125: static void
! 126: PDF_SetFont ()
! 127: {
! 128: int font_handle = PDF_findfont(myPDF, PDF_fontNameCur, "host", 0);
! 129:
! 130: PDF_setfont(myPDF, font_handle, PDF_fontSizeCur * PDF_RESOLUTION);
! 131:
! 132: /* Ask PDFlib for the actual numbers */
! 133: PDF_fontAscent = (int) (PDF_RESOLUTION * PDF_fontSizeCur * PDF_get_value(myPDF, "ascender", 0));
! 134: PDF_fontDescent = (int) (- PDF_RESOLUTION * PDF_fontSizeCur * PDF_get_value(myPDF, "descender", 0));
! 135: PDF_fontLeading = (int) (PDF_RESOLUTION * PDF_fontSizeCur * 0.25);
! 136:
! 137: /* Assume this particular string is a somewhat reasonable typical
! 138: * output, for getting at the average character width */
! 139: PDF_fontAvWidth = (int)
! 140: (PDF_RESOLUTION * PDF_stringwidth(myPDF, "01234567890123456789",
! 141: font_handle, PDF_fontSizeCur)
! 142: / 20.0);
! 143: }
! 144:
! 145: /*------------------- the terminal entry functions --------------------*/
! 146:
! 147:
! 148: TERM_PUBLIC void
! 149: PDF_options ()
! 150: {
! 151: struct value a;
! 152:
! 153: if (!END_OF_COMMAND) { /* get default font family name*/
! 154: if (almost_equals (c_token, "fn$ame")) {
! 155: c_token++;
! 156:
! 157: if (!END_OF_COMMAND && isstring (c_token)) {
! 158: quote_str (PDF_fontNameDef, c_token, MAX_ID_LEN);
! 159: c_token++;
! 160: } else
! 161: int_error("fname: expecting font name", c_token);
! 162: }
! 163: }
! 164:
! 165: if (!END_OF_COMMAND) { /* get default font size*/
! 166: if (almost_equals (c_token, "fs$ize")) {
! 167: c_token++;
! 168:
! 169: if (END_OF_COMMAND)
! 170: int_error("fsize: expecting font size", c_token);
! 171: PDF_fontSizeDef = real (const_express (&a));
! 172: }
! 173: }
! 174:
! 175: if (!END_OF_COMMAND)
! 176: int_error("unexpected text at end of command", c_token);
! 177:
! 178: /* Save options back into options string in normalized format */
! 179: sprintf(term_options, "fname '%s' fsize %g",
! 180: PDF_fontNameDef, PDF_fontSizeDef);
! 181: }
! 182:
! 183:
! 184: TERM_PUBLIC void
! 185: PDF_init ()
! 186: {
! 187: static TBOOLEAN PDFlib_booted = FALSE;
! 188:
! 189: if (!PDFlib_booted) {
! 190: PDF_boot();
! 191: PDFlib_booted = TRUE;
! 192: }
! 193:
! 194: if (!myPDF)
! 195: myPDF = PDF_new();
! 196:
! 197: /*open new PDF file */
! 198: if (PDF_open_fp(myPDF, gpoutfile) == -1)
! 199: int_error("Error:cannot open PDF file .\n", NO_CARET);
! 200:
! 201: #ifdef PDF_DONT_COMPRESS
! 202: /* for easier debugging of the output, turn off PDF stream
! 203: * compression */
! 204: PDF_set_value(myPDF, "compress", 0);
! 205: #endif
! 206:
! 207: PDF_set_info(myPDF,"Creator","gnuplot-3.8e");
! 208: PDF_set_info(myPDF,"Author","Hans-Bernhard Broeker"); /* FIXME: put in username? */
! 209: PDF_set_info(myPDF,"Title","gnuplot diagram"); /* FIXME: use 'set title', if any ? */
! 210:
! 211: PDF_LineType = -3;
! 212:
! 213: /* set current font to default */
! 214: strcpy(PDF_fontNameCur, PDF_fontNameDef);
! 215: PDF_fontSizeCur = PDF_fontSizeDef;
! 216:
! 217: /* Have to start the first page now, in order to know the actual
! 218: * size of the selected font */
! 219: PDF_graphics();
! 220:
! 221: /* set h_char, v_char*/
! 222: term->h_char = PDF_fontAvWidth;
! 223: term->v_char = (PDF_fontAscent + PDF_fontDescent + PDF_fontLeading);
! 224:
! 225: /* set h_tic, v_tic*/
! 226: term->h_tic = term->v_tic = 3 * PDF_RESOLUTION;
! 227:
! 228: /* initialize terminal's pointsize from "set pointsize" value */
! 229: term_pointsize = pointsize;
! 230: }
! 231:
! 232:
! 233: TERM_PUBLIC void
! 234: PDF_graphics ()
! 235: {
! 236: if (PDF_pageIsOpen)
! 237: return; /* already open --> nothing to do */
! 238:
! 239: PDF_pathIsOpen = FALSE;
! 240: PDF_xLast = PDF_yLast = UINT_MAX;
! 241:
! 242: /* set xmax, ymax*/
! 243: term->xmax = PDF_XMAX * xsize;
! 244: term->ymax = PDF_YMAX * ysize;
! 245:
! 246: PDF_begin_page(myPDF, (double)term->xmax / PDF_RESOLUTION,
! 247: (double)term->ymax / PDF_RESOLUTION);
! 248: PDF_scale(myPDF, 1.0/PDF_RESOLUTION, 1.0/PDF_RESOLUTION);
! 249: if (title.text && title.text[0])
! 250: /* a title has been set --> use it as the bookmark name, too */
! 251: PDF_add_bookmark(myPDF, title.text, 0, 1);
! 252: PDF_pageIsOpen = TRUE;
! 253:
! 254: PDF_SetFont();
! 255: }
! 256:
! 257:
! 258: TERM_PUBLIC void
! 259: PDF_text ()
! 260: {
! 261: PDF_PathClose();
! 262: PDF_end_page(myPDF);
! 263: PDF_pageIsOpen = FALSE;
! 264: }
! 265:
! 266:
! 267: TERM_PUBLIC void
! 268: PDF_reset ()
! 269: {
! 270: assert(PDF_pageIsOpen == FALSE);
! 271: PDF_close(myPDF);
! 272: PDF_delete(myPDF);
! 273: myPDF = NULL;
! 274: }
! 275:
! 276:
! 277: TERM_PUBLIC void
! 278: PDF_linetype (int linetype)
! 279: {
! 280: if (linetype != PDF_LineType) {
! 281: int real_linetype = PDF_Pen_RealID(linetype);
! 282: struct rgb *this_color = web_color_rgbs + 1 + real_linetype;
! 283:
! 284: PDF_PathClose ();
! 285: PDF_LineType = linetype;
! 286:
! 287: PDF_setrgbcolor(myPDF, this_color->r / 255.0,
! 288: this_color->g / 255.0, this_color->b / 255.0);
! 289: }
! 290: }
! 291:
! 292:
! 293: TERM_PUBLIC void
! 294: PDF_linewidth (double linewidth)
! 295: {
! 296: PDF_PathClose();
! 297: PDF_LineWidth = PDF_RESOLUTION * linewidth / 4.0;
! 298: PDF_setlinewidth(myPDF, PDF_LineWidth);
! 299: }
! 300:
! 301:
! 302: TERM_PUBLIC void
! 303: PDF_move (unsigned int x, unsigned int y)
! 304: {
! 305: if (PDF_pathIsOpen && x == PDF_xLast && y == PDF_yLast)
! 306: return;
! 307:
! 308: PDF_PathOpen ();
! 309: PDF_moveto(myPDF, x, y);
! 310:
! 311: PDF_xLast = x;
! 312: PDF_yLast = y;
! 313: }
! 314:
! 315:
! 316: TERM_PUBLIC void
! 317: PDF_vector (unsigned int x, unsigned int y)
! 318: {
! 319: if (PDF_pathIsOpen && x == PDF_xLast && y == PDF_yLast)
! 320: return;
! 321:
! 322: PDF_PathOpen ();
! 323: PDF_lineto(myPDF, x, y);
! 324:
! 325: PDF_xLast = x;
! 326: PDF_yLast = y;
! 327: }
! 328:
! 329: /* Helper function. Many symbols have an additional dot in their
! 330: * center, so isolate its drawing into a separate function. */
! 331: static GP_INLINE void
! 332: PDF_dot (unsigned int x, unsigned int y)
! 333: {
! 334: /* Imitate PS's way of creating a small dot by a zero-length line
! 335: * segment with rounded endpoints */
! 336: PDF_setlinecap(myPDF, 1); /* rounded ends */
! 337: PDF_moveto(myPDF, x, y);
! 338: PDF_lineto(myPDF, x, y);
! 339: PDF_stroke(myPDF);
! 340: }
! 341:
! 342:
! 343: TERM_PUBLIC void
! 344: PDF_point (unsigned int x, unsigned int y, int number)
! 345: {
! 346: PDF_PathClose ();
! 347: PDF_save(myPDF);
! 348:
! 349: if (number < 0) {
! 350: /* Like the PostScript driver, treat all negative numbers as
! 351: * 'with dots'. */
! 352: PDF_dot(x, y);
! 353: } else {
! 354: /* Change coordinate system so the point symbols themselves
! 355: * can be drawn without depending on position or size (-->
! 356: * better compression and less coding for gnuplot) */
! 357: /* NB: I use the do_pointsize() default implementation, which
! 358: * just stores the last set pointsize into `term_pointsize',
! 359: * to avoid introducing another static driver-local variable
! 360: * */
! 361: PDF_translate(myPDF, x, y);
! 362: PDF_scale(myPDF, term->h_tic / 2.0 * term_pointsize,
! 363: term->v_tic / 2.0 * term_pointsize);
! 364: /* Correct linewidth to counter the scaling effect --- assume
! 365: * h_tic is usable, to avoid having to average h_ and v_tic */
! 366: PDF_setlinewidth(myPDF,
! 367: PDF_LineWidth / (term->h_tic / 2.0 * term_pointsize));
! 368: switch (number %= PDF_NUM_POINTTYPES) {
! 369: case 0: /* Plus */
! 370: PDF_moveto(myPDF, -1, 0);
! 371: PDF_lineto(myPDF, 1, 0);
! 372: PDF_moveto(myPDF, 0, -1);
! 373: PDF_lineto(myPDF, 0, 1);
! 374: PDF_stroke(myPDF);
! 375: break;
! 376: case 2: /* Star */
! 377: PDF_moveto(myPDF, -1, 0);
! 378: PDF_lineto(myPDF, 1, 0);
! 379: PDF_moveto(myPDF, 0, -1);
! 380: PDF_lineto(myPDF, 0, 1);
! 381: /* FALLTHROUGH */
! 382: case 1: /* Cross */
! 383: PDF_moveto(myPDF, -1, -1);
! 384: PDF_lineto(myPDF, 1, 1);
! 385: PDF_moveto(myPDF, 1, -1);
! 386: PDF_lineto(myPDF, -1, 1);
! 387: PDF_stroke(myPDF);
! 388: break;
! 389:
! 390: /* For each x = 0..5, 4 shapes are defined:
! 391: * 3 + 2*x --> hollow symbol with a dot at its center
! 392: * 4 + 2*x --> solid symbol filled in linetype's color
! 393: * 63 + x --> hollow symbol without the center dot
! 394: * 69 + x --> symbol filled with white --> opaque symbol */
! 395:
! 396: case 63+0: /* BoxEmpty */
! 397: case 3+2*0: /* Box */
! 398: PDF_moveto(myPDF, -1, -1);
! 399: PDF_lineto(myPDF, 1, -1);
! 400: PDF_lineto(myPDF, 1, 1);
! 401: PDF_lineto(myPDF, -1, 1);
! 402: PDF_closepath_stroke(myPDF);
! 403: if (number == 3) PDF_dot(0,0);
! 404: break;
! 405: case 69+0: /* BoxWhitefilled */
! 406: PDF_setgray_fill(myPDF, 1);
! 407: /* FALLTHROUGH */
! 408: case 4+2*0: /* BoxFilled */
! 409: PDF_moveto(myPDF, -1, -1);
! 410: PDF_lineto(myPDF, 1, -1);
! 411: PDF_lineto(myPDF, 1, 1);
! 412: PDF_lineto(myPDF, -1, 1);
! 413: PDF_closepath_fill_stroke(myPDF);
! 414: break;
! 415:
! 416: case 63+1: /* CircleEmpty */
! 417: case 3+2*1: /* Circle */
! 418: PDF_circle(myPDF, 0, 0, 1);
! 419: PDF_stroke(myPDF);
! 420: if (number == 5) PDF_dot(0,0);
! 421: break;
! 422: case 69+1: /* CircleWhitefilled */
! 423: PDF_setgray_fill(myPDF, 1);
! 424: /* FALLTHROUGH */
! 425: case 4+2*1: /* CircleFilled */
! 426: PDF_circle(myPDF, 0, 0, 1);
! 427: PDF_fill_stroke(myPDF);
! 428: break;
! 429:
! 430: case 63+2: /* TriangleUpEmpty */
! 431: case 3+2*2: /* TriangleUp */
! 432: PDF_moveto(myPDF, 0, 1.12);
! 433: PDF_lineto(myPDF, -1, -0.5);
! 434: PDF_lineto(myPDF, 1, -0.5);
! 435: PDF_closepath_stroke(myPDF);
! 436: if (number == 7) PDF_dot(0,0);
! 437: break;
! 438: case 69+2: /* TriangleUpWhitefilled */
! 439: PDF_setgray_fill(myPDF, 1);
! 440: /* FALLTHROUGH */
! 441: case 4+2*2: /* TriangleUpFilled */
! 442: PDF_moveto(myPDF, 0, 1.12);
! 443: PDF_lineto(myPDF, -1, -0.5);
! 444: PDF_lineto(myPDF, 1, -0.5);
! 445: PDF_closepath_fill_stroke(myPDF);
! 446: break;
! 447:
! 448: case 63+3: /* TriangleDownEmpty */
! 449: case 3+2*3: /* TriangleDown */
! 450: PDF_moveto(myPDF, 0, -1.12);
! 451: PDF_lineto(myPDF, -1, 0.5);
! 452: PDF_lineto(myPDF, 1, 0.5);
! 453: PDF_closepath_stroke(myPDF);
! 454: if (number == 9) PDF_dot(0,0);
! 455: break;
! 456: case 69+3: /* TriangleDownWhitefilled */
! 457: PDF_setgray_fill(myPDF, 1);
! 458: /* FALLTHROUGH */
! 459: case 4+2*3: /* TriangleDownFilled */
! 460: PDF_moveto(myPDF, 0, -1.12);
! 461: PDF_lineto(myPDF, -1, 0.5);
! 462: PDF_lineto(myPDF, 1, 0.5);
! 463: PDF_closepath_fill_stroke(myPDF);
! 464: break;
! 465:
! 466: case 63+4: /* DiamondEmpty */
! 467: case 3+2*4: /* Diamond */
! 468: PDF_moveto(myPDF, 0, -1);
! 469: PDF_lineto(myPDF, 1, 0);
! 470: PDF_lineto(myPDF, 0, 1);
! 471: PDF_lineto(myPDF, -1, 0);
! 472: PDF_closepath_stroke(myPDF);
! 473: if (number == 11) PDF_dot(0,0);
! 474: break;
! 475: case 69+4: /* DiamondWhitefilled */
! 476: PDF_setgray_fill(myPDF, 1);
! 477: /* FALLTHROUGH */
! 478: case 4+2*4: /* DiamondFilled */
! 479: PDF_moveto(myPDF, 0, -1);
! 480: PDF_lineto(myPDF, 1, 0);
! 481: PDF_lineto(myPDF, 0, 1);
! 482: PDF_lineto(myPDF, -1, 0);
! 483: PDF_closepath_fill_stroke(myPDF);
! 484: break;
! 485:
! 486: case 63+5: /* PentagonEmpty */
! 487: case 3+2*5: /* Pentagon */
! 488: PDF_moveto(myPDF, 0, 1);
! 489: PDF_lineto(myPDF, -0.95, 0.31);
! 490: PDF_lineto(myPDF, -0.58, -0.81);
! 491: PDF_lineto(myPDF, +0.58, -0.81);
! 492: PDF_lineto(myPDF, +0.95, 0.31);
! 493: PDF_closepath_stroke(myPDF);
! 494: if (number == 13) PDF_dot(0,0);
! 495: break;
! 496: case 69+5: /* PentagonWhitefilled */
! 497: PDF_setgray_fill(myPDF, 1);
! 498: /* FALLTHROUGH */
! 499: case 4+2*5: /* PentagonFilled */
! 500: PDF_moveto(myPDF, 0, 1);
! 501: PDF_lineto(myPDF, -0.95, 0.31);
! 502: PDF_lineto(myPDF, -0.58, -0.81);
! 503: PDF_lineto(myPDF, +0.58, -0.81);
! 504: PDF_lineto(myPDF, +0.95, 0.31);
! 505: PDF_closepath_fill_stroke(myPDF);
! 506: break;
! 507:
! 508: /* 15 + (0..15): circles with varying parts of'em filled. The added
! 509: * number is a bit-pattern of the 4 quadrants: 1 signals a quadrant
! 510: * filled */
! 511: case 15+0:
! 512: PDF_moveto(myPDF, 0, 0);
! 513: PDF_lineto(myPDF, 0, 1);
! 514: PDF_arc(myPDF, 0, 0, 1, 90, 360+90);
! 515: PDF_closepath_stroke(myPDF);
! 516: break;
! 517:
! 518: /* Generalize common code into a macro... */
! 519: #define CIRCLE_SINGLE_PIESLICE(x, y, angle1, angle2) \
! 520: PDF_moveto(myPDF, 0, 0); \
! 521: PDF_lineto(myPDF, (x), (y)); \
! 522: PDF_arc(myPDF, 0, 0, 1, (angle1), (angle2)); \
! 523: PDF_lineto(myPDF, 0, 0); \
! 524: PDF_closepath(myPDF); \
! 525: PDF_fill_stroke(myPDF); \
! 526: PDF_arc(myPDF, 0, 0, 1, (angle2), (angle1) + 360); \
! 527: PDF_stroke(myPDF); \
! 528: break;
! 529:
! 530: #define CIRCLE_SINGLE_QUADRANT(x, y, angle) \
! 531: CIRCLE_SINGLE_PIESLICE(x, y, angle, angle+90);
! 532: case 15+1:
! 533: CIRCLE_SINGLE_QUADRANT(1, 0, 0);
! 534: case 15+2:
! 535: CIRCLE_SINGLE_QUADRANT(0, 1, 90);
! 536: case 15+4:
! 537: CIRCLE_SINGLE_QUADRANT(-1, 0, 180);
! 538: case 15+8:
! 539: CIRCLE_SINGLE_QUADRANT(0, -1, 270);
! 540: #undef CIRCLE_SINGLE_QUADRANT
! 541:
! 542: #define CIRCLE_TWO_NEIGHBOR_QUADRANTS(x, y, angle) \
! 543: CIRCLE_SINGLE_PIESLICE(x, y, angle, angle+180)
! 544: case 15+3:
! 545: CIRCLE_TWO_NEIGHBOR_QUADRANTS(1, 0, 0);
! 546: case 15+6:
! 547: CIRCLE_TWO_NEIGHBOR_QUADRANTS(0, 1, 90);
! 548: case 15+12:
! 549: CIRCLE_TWO_NEIGHBOR_QUADRANTS(-1, 0, 180);
! 550: case 15+9:
! 551: CIRCLE_TWO_NEIGHBOR_QUADRANTS(0, -1, 270);
! 552: #undef CIRCLE_TWO_NEIGHBOR_QUADRANTS
! 553:
! 554: #define CIRCLE_TWO_OPPOSING_QUADRANTS(x, y, angle) \
! 555: PDF_moveto(myPDF, 0, 0); \
! 556: PDF_lineto(myPDF, x, y); \
! 557: PDF_arc(myPDF, 0, 0, 1, angle, angle + 90); \
! 558: PDF_lineto(myPDF, 0, 0); \
! 559: PDF_fill_stroke(myPDF); \
! 560: PDF_moveto(myPDF, 0, 0); \
! 561: PDF_lineto(myPDF, -x, -y); \
! 562: PDF_arc(myPDF, 0, 0, 1, angle + 180, angle + 270); \
! 563: PDF_lineto(myPDF, 0, 0); \
! 564: PDF_fill_stroke(myPDF); \
! 565: PDF_arc(myPDF, 0, 0, 1, angle + 90, angle + 360); \
! 566: PDF_stroke(myPDF); \
! 567: break;
! 568: case 15+5:
! 569: CIRCLE_TWO_OPPOSING_QUADRANTS(1, 0, 0);
! 570: case 15+10:
! 571: CIRCLE_TWO_OPPOSING_QUADRANTS(0, 1, 90);
! 572: #undef CIRCLE_TWO_OPPOSING_QUADRANTS
! 573:
! 574: #define CIRCLE_THREE_QUADRANTS(x, y, angle) \
! 575: CIRCLE_SINGLE_PIESLICE(x, y, angle, angle+270)
! 576: case 15+7:
! 577: CIRCLE_THREE_QUADRANTS(1, 0, 0);
! 578: case 15+14:
! 579: CIRCLE_THREE_QUADRANTS(0, 1, 90);
! 580: case 15+13:
! 581: CIRCLE_THREE_QUADRANTS(-1, 0, 180);
! 582: case 15+11:
! 583: CIRCLE_THREE_QUADRANTS(0, -1, 270);
! 584: #undef CIRCLE_THREE_QUADRANTS
! 585: #undef CIRCLE_SINGLE_PIESLICE
! 586:
! 587: case 15+15:
! 588: PDF_circle(myPDF, 0, 0, 1);
! 589: PDF_closepath_fill_stroke(myPDF);
! 590: break;
! 591:
! 592:
! 593: /*************************************************************************/
! 594: /* 31 + (0..15): squares with different quadrants of them filled in. */
! 595: /*************************************************************************/
! 596: /*************************************************************************/
! 597: /* 47 + (0..15): diamonds with filled quadrants as given by bit pattern */
! 598: /* Diamonds are drawn as squares rotated by 45 degrees, so can use
! 599: * fall-through from diamond to squares, and re-use some macros. */
! 600: /*************************************************************************/
! 601: case 47+0:
! 602: PDF_rotate(myPDF, 45);
! 603: /* FALLTHROUGH */
! 604: case 31+0:
! 605: PDF_moveto(myPDF, 0, 0);
! 606: PDF_lineto(myPDF, 0, 1);
! 607: PDF_lineto(myPDF, -1, 1);
! 608: PDF_lineto(myPDF, -1, -1);
! 609: PDF_lineto(myPDF, 1, -1);
! 610: PDF_lineto(myPDF, 1, 1);
! 611: PDF_lineto(myPDF, 0, 1);
! 612: PDF_stroke(myPDF);
! 613: break;
! 614:
! 615: case 47+15:
! 616: PDF_rotate(myPDF, 45);
! 617: /* FALLTHROUGH */
! 618: case 31+15:
! 619: PDF_moveto(myPDF, -1, 1);
! 620: PDF_lineto(myPDF, -1, -1);
! 621: PDF_lineto(myPDF, 1, -1);
! 622: PDF_lineto(myPDF, 1, 1);
! 623: PDF_closepath_fill_stroke(myPDF);
! 624: break;
! 625:
! 626: /* macros defining shapes of the partly filled symbols. Done by
! 627: * rotating the starting point (x0, y0) by 90 degrees or 45 degrees
! 628: * (with length adjustment). The rotations can be done without
! 629: * trigonometric function calls, since their values are known:
! 630: * cos(90)=0, sin(90)=1, cos(45)=sin(45)=1/sqrt(2). A good compiler
! 631: * should be able to optimize away all the local variables and
! 632: * loops... */
! 633:
! 634: #define SQUARE_SINGLE_PIESLICE(x0, y0, quadrants) \
! 635: { \
! 636: int quadrant = 0; \
! 637: int x= x0, y=y0; \
! 638: PDF_moveto(myPDF, 0, 0); \
! 639: PDF_lineto(myPDF, x, y); \
! 640: /* poor man's rotation by 45 and 90 degrees around the \
! 641: * square's outline. */ \
! 642: while (quadrant++ < quadrants) { \
! 643: int dummy; \
! 644: PDF_lineto(myPDF, x-y, x+y); \
! 645: dummy = x; x = -y; y = dummy; \
! 646: } \
! 647: PDF_lineto(myPDF, x, y); \
! 648: PDF_closepath_fill_stroke(myPDF); \
! 649: PDF_moveto(myPDF, x, y); \
! 650: while (quadrant++ <= 4) { \
! 651: int dummy; \
! 652: PDF_lineto(myPDF, x-y, x+y); \
! 653: dummy = x; x = -y; y = dummy; \
! 654: } \
! 655: PDF_lineto(myPDF, x, y); \
! 656: PDF_stroke(myPDF); \
! 657: } \
! 658: break;
! 659:
! 660: #define SQUARE_TWO_OPPOSING_QUADRANTS(x0, y0, angle) \
! 661: { \
! 662: int x = x0, y = y0, dummy; \
! 663: int counter = 0; \
! 664: \
! 665: while (counter++ < 2) { \
! 666: PDF_moveto(myPDF, 0, 0); \
! 667: PDF_lineto(myPDF, x, y); \
! 668: PDF_lineto(myPDF, x-y, x+y); \
! 669: dummy = x; x = -y; y = dummy; \
! 670: PDF_lineto(myPDF, x, y); \
! 671: PDF_closepath_fill_stroke(myPDF); \
! 672: \
! 673: PDF_moveto(myPDF, x, y); \
! 674: PDF_lineto(myPDF, x-y, x+y); \
! 675: dummy = x; x = -y; y = dummy; \
! 676: PDF_lineto(myPDF, x, y); \
! 677: PDF_stroke(myPDF); \
! 678: } \
! 679: break; \
! 680: }
! 681:
! 682: /* Macros for diamonds just prepend the rotation and then call those
! 683: * for squares: */
! 684: #define DIAMOND_SINGLE_PIESLICE(x, y, quadrants) \
! 685: PDF_rotate(myPDF, 45); \
! 686: SQUARE_SINGLE_PIESLICE(x, y, quadrants);
! 687: #define DIAMOND_TWO_OPPOSING_QUADRANTS(x, y, angle) \
! 688: PDF_rotate(myPDF, 45); \
! 689: SQUARE_TWO_OPPOSING_QUADRANTS(x, y, angle);
! 690:
! 691: /* ... and now all the individual cases. The 'angle' arguments' are
! 692: * purely for the sake of easing cut'n'paste with the circle case */
! 693: #define SQUARE_SINGLE_QUADRANT(x, y, angle) \
! 694: SQUARE_SINGLE_PIESLICE(x, y, 1);
! 695: case 31+1:
! 696: SQUARE_SINGLE_QUADRANT(1, 0, 0);
! 697: case 31+2:
! 698: SQUARE_SINGLE_QUADRANT(0, 1, 90);
! 699: case 31+4:
! 700: SQUARE_SINGLE_QUADRANT(-1, 0, 180);
! 701: case 31+8:
! 702: SQUARE_SINGLE_QUADRANT(0, -1, 270);
! 703: #undef SQUARE_SINGLE_QUADRANT
! 704:
! 705: #define SQUARE_TWO_NEIGHBOR_QUADRANTS(x, y, angle) \
! 706: SQUARE_SINGLE_PIESLICE(x, y, 2)
! 707: case 31+3:
! 708: SQUARE_TWO_NEIGHBOR_QUADRANTS(1, 0, 0);
! 709: case 31+6:
! 710: SQUARE_TWO_NEIGHBOR_QUADRANTS(0, 1, 90);
! 711: case 31+12:
! 712: SQUARE_TWO_NEIGHBOR_QUADRANTS(-1, 0, 180);
! 713: case 31+9:
! 714: SQUARE_TWO_NEIGHBOR_QUADRANTS(0, -1, 270);
! 715: #undef SQUARE_TWO_NEIGHBOR_QUADRANTS
! 716:
! 717: case 31+5:
! 718: SQUARE_TWO_OPPOSING_QUADRANTS(1, 0, 0);
! 719: case 31+10:
! 720: SQUARE_TWO_OPPOSING_QUADRANTS(0, 1, 90);
! 721:
! 722: #define SQUARE_THREE_QUADRANTS(x, y, angle) \
! 723: SQUARE_SINGLE_PIESLICE(x, y, 3)
! 724: case 31+7:
! 725: SQUARE_THREE_QUADRANTS(1, 0, 0);
! 726: case 31+14:
! 727: SQUARE_THREE_QUADRANTS(0, 1, 90);
! 728: case 31+13:
! 729: SQUARE_THREE_QUADRANTS(-1, 0, 180);
! 730: case 31+11:
! 731: SQUARE_THREE_QUADRANTS(0, -1, 270);
! 732: #undef SQUARE_THREE_QUADRANTS
! 733:
! 734: #define DIAMOND_SINGLE_QUADRANT(x, y, angle) \
! 735: DIAMOND_SINGLE_PIESLICE(x, y, 1)
! 736: case 47+1:
! 737: DIAMOND_SINGLE_QUADRANT(1, 0, 0);
! 738: case 47+2:
! 739: DIAMOND_SINGLE_QUADRANT(0, 1, 90);
! 740: case 47+4:
! 741: DIAMOND_SINGLE_QUADRANT(-1, 0, 180);
! 742: case 47+8:
! 743: DIAMOND_SINGLE_QUADRANT(0, -1, 270);
! 744: #undef DIAMOND_SINGLE_QUADRANT
! 745:
! 746: #define DIAMOND_TWO_NEIGHBOR_QUADRANTS(x, y, angle) \
! 747: DIAMOND_SINGLE_PIESLICE(x, y, 2)
! 748: case 47+3:
! 749: DIAMOND_TWO_NEIGHBOR_QUADRANTS(1, 0, 0);
! 750: case 47+6:
! 751: DIAMOND_TWO_NEIGHBOR_QUADRANTS(0, 1, 90);
! 752: case 47+12:
! 753: DIAMOND_TWO_NEIGHBOR_QUADRANTS(-1, 0, 180);
! 754: case 47+9:
! 755: DIAMOND_TWO_NEIGHBOR_QUADRANTS(0, -1, 270);
! 756: #undef DIAMOND_TWO_NEIGHBOR_QUADRANTS
! 757:
! 758:
! 759: case 47+5:
! 760: DIAMOND_TWO_OPPOSING_QUADRANTS(1, 0, 0);
! 761: case 47+10:
! 762: DIAMOND_TWO_OPPOSING_QUADRANTS(0, 1, 90);
! 763: #undef DIAMOND_TWO_OPPOSING_QUADRANTS
! 764: #undef SQUARE_TWO_OPPOSING_QUADRANTS
! 765:
! 766: #define DIAMOND_THREE_QUADRANTS(x, y, angle) \
! 767: DIAMOND_SINGLE_PIESLICE(x, y, 3)
! 768: case 47+7:
! 769: DIAMOND_THREE_QUADRANTS(1, 0, 0);
! 770: case 47+14:
! 771: DIAMOND_THREE_QUADRANTS(0, 1, 90);
! 772: case 47+13:
! 773: DIAMOND_THREE_QUADRANTS(-1, 0, 180);
! 774: case 47+11:
! 775: DIAMOND_THREE_QUADRANTS(0, -1, 270);
! 776: #undef DIAMOND_THREE_QUADRANTS
! 777: #undef DIAMOND_SINGLE_PIESLICE
! 778: #undef SQUARE_SINGLE_PIESLICE
! 779:
! 780: default:
! 781: {
! 782: char temp[64];
! 783: sprintf(temp, "PDF: unknown point type number %d", number);
! 784: int_warn(temp,NO_CARET);
! 785: }
! 786: }
! 787: }
! 788:
! 789: PDF_restore(myPDF);
! 790: PDF_xLast = x;
! 791: PDF_yLast = y;
! 792: }
! 793:
! 794:
! 795: TERM_PUBLIC int
! 796: PDF_justify_text (enum JUSTIFY mode)
! 797: {
! 798: PDF_TextJust = mode;
! 799: return (TRUE);
! 800: }
! 801:
! 802:
! 803: TERM_PUBLIC int
! 804: PDF_text_angle (int ang)
! 805: {
! 806: if (ang == 0 || ang == 1) {
! 807: /* FIXME: need to do this in a different way? */
! 808: PDF_TextAngle = ang;
! 809: return (TRUE);
! 810: }
! 811:
! 812: return (FALSE);
! 813: }
! 814:
! 815:
! 816: TERM_PUBLIC void
! 817: PDF_put_text (unsigned int x, unsigned int y, char *str)
! 818: {
! 819: char *alignment = NULL;
! 820: double h = x, v = y;
! 821:
! 822: PDF_PathClose ();
! 823:
! 824: /* horizontal justification*/
! 825: switch (PDF_TextJust) {
! 826: case LEFT:
! 827: alignment = "left";
! 828: break;
! 829: case CENTRE:
! 830: alignment = "center";
! 831: break;
! 832: case RIGHT:
! 833: alignment = "right";
! 834: break;
! 835: }
! 836:
! 837: /* vertical justification*/
! 838: switch (PDF_TextAngle) {
! 839: case 1:
! 840: h += (PDF_fontAscent - PDF_fontDescent) / 2;
! 841: break; /* vertical text*/
! 842: default:
! 843: v -= (PDF_fontAscent - PDF_fontDescent) / 2;
! 844: break; /* horizontal text*/
! 845: }
! 846:
! 847: if (PDF_TextAngle) {
! 848: PDF_save(myPDF);
! 849: PDF_rotate(myPDF, 90);
! 850: PDF_show_boxed(myPDF, str, v , -h, 0, 0, alignment, NULL);
! 851: PDF_restore(myPDF);
! 852: } else {
! 853: PDF_show_boxed(myPDF, str, h , v, 0, 0, alignment, NULL);
! 854: }
! 855:
! 856: }
! 857:
! 858:
! 859: TERM_PUBLIC int
! 860: PDF_set_font (char *font)
! 861: {
! 862: if (strlen (font) > 0) { /* if available, parse the font specification ("fontname,fontsize")*/
! 863: short index;
! 864: char *token,
! 865: seps[] = ",", *buffer = (char *) malloc (strlen (font) + 1);
! 866:
! 867: if (buffer == NULL)
! 868: return (FALSE);
! 869: strcpy (buffer, font);
! 870:
! 871: for (token = strtok (buffer, seps), index = 1;
! 872: token != NULL; token = strtok (NULL, seps), index++
! 873: ) {
! 874: switch (index) {
! 875: case 1:
! 876: strcpy (PDF_fontNameCur, token);
! 877: break; /* font name*/
! 878: case 2:
! 879: PDF_fontSizeCur = atoi (token);
! 880: break; /* font size*/
! 881: default:
! 882: break;
! 883: }
! 884: }
! 885:
! 886: free (buffer);
! 887: } else { /* otherwise simply reset the default font*/
! 888: strcpy (PDF_fontNameCur, PDF_fontNameDef);
! 889: PDF_fontSizeCur = PDF_fontSizeDef;
! 890: }
! 891:
! 892:
! 893: PDF_PathClose();
! 894: PDF_SetFont();
! 895: return (TRUE);
! 896: }
! 897:
! 898: TERM_PUBLIC void
! 899: PDF_boxfill(int style, unsigned int x1, unsigned int y1,
! 900: unsigned int width, unsigned int height)
! 901: {
! 902: (void) style; /* unused */
! 903: PDF_PathClose();
! 904: PDF_save(myPDF);
! 905: PDF_setgray(myPDF, 1);
! 906: PDF_moveto(myPDF, x1, y1);
! 907: PDF_lineto(myPDF, x1+width, y1);
! 908: PDF_lineto(myPDF, x1+width, y1+height);
! 909: PDF_lineto(myPDF, x1, y1+height);
! 910: PDF_fill(myPDF);
! 911: PDF_restore(myPDF);
! 912: }
! 913:
! 914: #endif /* TERM_BODY */
! 915:
! 916: #ifdef TERM_TABLE
! 917: TERM_TABLE_START (pdf_driver)
! 918: "pdf", "PDF (Portable Document File) file driver",
! 919: 0 /* xmax */ , 0 /* ymax */ , 0 /* vchar */ , 0 /* hchar */ ,
! 920: 0 /* vtic */ , 0 /* htic */ ,
! 921: PDF_options, PDF_init, PDF_reset, PDF_text, null_scale, PDF_graphics,
! 922: PDF_move, PDF_vector, PDF_linetype, PDF_put_text, PDF_text_angle,
! 923: PDF_justify_text, PDF_point, do_arrow, PDF_set_font, do_pointsize,
! 924: TERM_BINARY,
! 925: 0 /* suspend */, 0 /* resume */ , PDF_boxfill, PDF_linewidth
! 926: TERM_TABLE_END (pdf_driver)
! 927: #undef LAST_TERM
! 928: #define LAST_TERM pdf_driver
! 929: #endif /* TERM_TABLE */
! 930:
! 931: #endif /* TERM_PROTO_ONLY */
! 932:
! 933: #ifdef TERM_HELP
! 934: START_HELP (pdf)
! 935: "1 pdf",
! 936: "?commands set terminal pdf",
! 937: "?set terminal pdf",
! 938: "?set term pdf",
! 939: "?terminal pdf",
! 940: "?term pdf",
! 941: "?pdf",
! 942: " This terminal produces files in the Adobe Portable Document Format",
! 943: " (PDF), useable for printing or display with tools like Acrobat Reader",
! 944: "",
! 945: " Syntax:",
! 946: " set terminal pdf {fname \"<font>\"} {fsize <fontsize>}",
! 947: "",
! 948: " where <font> is the name of the default font to use (default Helvetica)",
! 949: " and <fontsize> is the font size (in points, default 12)"
! 950: END_HELP (pdf)
! 951: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>