1/* Hello, Emacs, this is -*-C-*- */ 2 3/*------------------------------ 4 GNUPLOT - pdf.trm 5 6 This file is included by ../term.c. 7 8 This driver uses PDFlib from www.pdflib.com 9 10 Author: 11 12 Hans-Bernhard Br"oker 13 broeker@physik.rwth-aachen.de 14 15 Licence: see the gnuplot copyright (to be merged into here...) 16 17 Options: can #define PDF_DONT_COMPRESS to avoid PDF output 18 generated being compressed (by the 'deflate' algorithm as used 19 in 'zip' or 'gzip'). That helps in debugging. 20 21------------------------------*/ 22 23/* CODEME: Add patterned lines (?). */ 24 25/* PM3D support by Johannes Zellner <johannes@zellner.org>, May-15-2002 */ 26/* set_color fixes by Petr Mikulik <mikulik@physics.muni.cz>, June-10-2002 */ 27/* image support by Ethan A Merritt <merritt@u.washington.edu>, March 2003 */ 28 29/* Text rotation 24-Jul-2002 Ethan A Merritt <merritt@u.washington.edu> */ 30/* Revised fill patterns 02-Apr-2003 Ethan A Merritt */ 31/* Enhanced text mode support November 2003 Ethan A Merritt */ 32 33#include "driver.h" 34 35#ifdef TERM_REGISTER 36register_term(pdf) 37#endif 38 39#ifdef TERM_PROTO 40TERM_PUBLIC void PDF_options(void); 41TERM_PUBLIC void PDF_init(void); 42TERM_PUBLIC void PDF_graphics(void); 43TERM_PUBLIC void PDF_text(void); 44TERM_PUBLIC void PDF_linetype(int linetype); 45TERM_PUBLIC void PDF_move(unsigned int x, unsigned int y); 46TERM_PUBLIC void PDF_vector(unsigned int x, unsigned int y); 47TERM_PUBLIC void PDF_put_text(unsigned int x, unsigned int y, const char *str); 48TERM_PUBLIC void PDF_reset(void); 49TERM_PUBLIC int PDF_justify_text(enum JUSTIFY mode); 50TERM_PUBLIC int PDF_text_angle(int ang); 51TERM_PUBLIC void PDF_point(unsigned int x, unsigned int y, int pointstyle); 52TERM_PUBLIC int PDF_set_font(const char *font); 53TERM_PUBLIC void PDF_boxfill(int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height); 54TERM_PUBLIC void PDF_linewidth(double linewidth); 55TERM_PUBLIC int PDF_make_palette(t_sm_palette *); 56TERM_PUBLIC void PDF_previous_palette(void); 57TERM_PUBLIC void PDF_set_color(t_colorspec *); 58TERM_PUBLIC void PDF_image(unsigned int, unsigned int, coordval *, gpiPoint *, t_imagecolor); 59 60TERM_PUBLIC void PDF_filled_polygon(int, gpiPoint *); 61 62/* To support "set term png enhanced" */ 63TERM_PUBLIC void ENHPDF_put_text(unsigned int x, unsigned int y, const char *str); 64TERM_PUBLIC void ENHPDF_OPEN(char * fontname, double fontsize, 65 double base, TBOOLEAN widthflag, TBOOLEAN showflag, 66 int overprint); 67TERM_PUBLIC void ENHPDF_FLUSH(void); 68 69#define PDF_NUM_POINTTYPES 75 /* number of point symbol types not counting the dot */ 70 71#define PDF_RESOLUTION (20) /* number of terminal pixels per pt */ 72#define PDF_XMAX (5*72*PDF_RESOLUTION) /* 5 inches, 72 pt/inch */ 73#define PDF_YMAX (3*72*PDF_RESOLUTION) /* 3 inches, 72 pt/inch */ 74 75static TBOOLEAN pdf_explicit_size = FALSE; 76static size_units pdf_explicit_units = INCHES; 77 78#endif /* TERM_PROTO */ 79 80#ifndef TERM_PROTO_ONLY 81#ifdef TERM_BODY 82 83#include <pdflib.h> 84 85static PDF *myPDF = NULL; 86 87static unsigned int PDF_xLast = UINT_MAX; /* current pen horizontal position*/ 88static unsigned int PDF_yLast = UINT_MAX; /* current pen vertical position*/ 89 90static int PDF_LineType = LT_UNDEFINED; /* current line type*/ 91static int PDF_LineCap = 0; /* Butt ends */ 92static double PDF_LineWidth = 1.0; /* current line width*/ 93static int PDF_TextAngle = 0; /* current text orientation*/ 94static enum JUSTIFY PDF_TextJust = LEFT; /* current text justification*/ 95static double PDF_linewidth_factor = 1.0; /* multiplier for line width */ 96static double PDF_dashlength_factor = 1.0; /* multiplier for dash length */ 97static TBOOLEAN PDF_monochrome = FALSE; /* default all linetypes to black */ 98static rgb_color PDF_current_rgb = {0.,0.,0.}; /* Last color set */ 99static double PDF_current_gray = 0.0; /* Last color set (mono version) */ 100 101#ifdef HAVE_NODASH_LIBPDF 102static TBOOLEAN PDF_dashedlines = FALSE; /* solid or dashed? */ 103#else 104static TBOOLEAN PDF_dashedlines = TRUE; /* solid or dashed? */ 105#endif 106 107/* default text font family: */ 108static char PDF_fontNameDef[MAX_ID_LEN + 1] = "Helvetica"; 109static double PDF_fontSizeDef = 6; /* default text size*/ 110/* current text font family: */ 111static char PDF_fontNameCur[MAX_ID_LEN + 1] = "Helvetica"; 112static double PDF_fontSizeCur = 6; /* current text size*/ 113static double PDF_fontscale = 1.0; 114 115static TBOOLEAN PDF_pageIsOpen = FALSE; /* already started a page ?? */ 116static TBOOLEAN PDF_pathIsOpen = FALSE; /* open path flag*/ 117 118static int PDF_fontAscent = 0; /* estimated current font ascent*/ 119static int PDF_fontDescent = 0; /* estimated current font descent*/ 120static int PDF_fontLeading = 0; /* estimated current font leading*/ 121static int PDF_fontAvWidth = 0; /* estimated current font char average width*/ 122static int PDF_currentFontHandle; /* Needed for exhanced text mode */ 123 124static short PDF_Pen_RealID(int); 125static void PDF_PathOpen(void); 126static void PDF_PathClose(void); 127static void PDF_SetFont(void); 128static void PDF_DefinePatterns(void); 129enum { PDF_patterns = 7 }; 130static int PDF_patternHandles[PDF_patterns]; 131 132#ifndef HAVE_NODASH_LIBPDF 133/* Description of dash patterns (same as those in post.trm) */ 134static int dash1[] = {8, 8}; 135static int dash2[] = {4, 6}; 136static int dash3[] = {2, 3}; 137static int dash4[] = {12, 4, 2, 4}; 138static int dash5[] = {6, 6, 2, 6}; 139static int dash6[] = {4, 4, 4, 12}; 140static int dash7[] = {1, 4, 12, 4, 1, 4}; 141#endif 142 143/*------------------------ helper functions -------------------*/ 144 145static short 146PDF_Pen_RealID (int inPenCode) 147{ 148 if (inPenCode >= 12) 149 inPenCode %= 12; /* normalize pen code*/ 150 if (inPenCode <= LT_NODRAW) 151 inPenCode = LT_NODRAW; 152 153 return (inPenCode + 2); 154} 155 156/* Functions to ensure that as many move() and vector() calls as 157 * possible get converted into a single long 'path', before closing it 158 * with a stroke or similar command. */ 159static void 160PDF_PathOpen () 161{ 162 PDF_pathIsOpen = TRUE; 163} 164 165static void 166PDF_PathClose () 167{ 168 if (PDF_pathIsOpen) { 169 PDF_stroke(myPDF); 170 171 PDF_pathIsOpen = FALSE; 172 } 173} 174 175/* Helper function to deal with switching over to a newly selected font. 176 * For now, this does not try to embed fonts into the PDF file. 177 * We would like to allow UTF-8 fonts via 178 font_handle = PDF_findfont(myPDF, PDF_fontNameCur, "unicode", 0); 179 * but this is not supported by the free-as-in-beer PDFlib Lite. 180 */ 181static void 182PDF_SetFont () 183{ 184 int font_handle; 185 const char *pdfenc = "host"; 186 187 /* Allow graceful failure */ 188 PDF_set_parameter(myPDF, "fontwarning", "false"); 189 190 /* LCB : Symbol and ZapfDingbats should use "builtin" encoding */ 191 if ( (strcmp(PDF_fontNameCur,"Symbol") == 0) || 192 (strcmp(PDF_fontNameCur,"ZapfDingbats") == 0) ) { 193 pdfenc = "builtin"; 194 } else if (encoding == S_ENC_ISO8859_1) { 195 pdfenc = "iso8859-1"; 196 } else if (encoding == S_ENC_ISO8859_2) { 197 pdfenc = "iso8859-2"; 198 } else if (encoding == S_ENC_ISO8859_9) { 199 pdfenc = "iso8859-9"; 200 } else if (encoding == S_ENC_ISO8859_15) { 201 pdfenc = "iso8859-15"; 202 } else if (encoding == S_ENC_CP1250) { 203 pdfenc = "cp1250"; 204 } else if (encoding == S_ENC_CP1252) { 205 pdfenc = "cp1252"; 206 } 207 208 font_handle = PDF_findfont(myPDF, PDF_fontNameCur, pdfenc, 0); 209 210 if (font_handle == -1 && strcmp(pdfenc, "host")) { 211 fprintf(stderr,"Couldn't find font %s in encoding %s, trying \"host\"\n", 212 PDF_fontNameCur, pdfenc); 213 font_handle = PDF_findfont(myPDF, PDF_fontNameCur, "host", 0); 214 } 215 216 if (font_handle == -1) { 217 font_handle = PDF_findfont(myPDF, "Times-Roman", "host", 0); 218 fprintf(stderr,"Couldn't find font %s, falling back to Times-Roman\n", PDF_fontNameCur); 219 } 220 221 PDF_setfont(myPDF, font_handle, PDF_fontSizeCur * PDF_RESOLUTION * PDF_fontscale); 222 223 /* Ask PDFlib for the actual numbers */ 224 PDF_fontAscent = (int) (PDF_RESOLUTION * PDF_fontSizeCur * PDF_fontscale * PDF_get_value(myPDF, "ascender", 0)); 225 PDF_fontDescent = (int) (- PDF_RESOLUTION * PDF_fontSizeCur * PDF_fontscale * PDF_get_value(myPDF, "descender", 0)); 226 PDF_fontLeading = (int) (PDF_RESOLUTION * PDF_fontSizeCur * PDF_fontscale * 0.25); 227 228 /* Assume this particular string is a somewhat reasonable typical 229 * output, for getting at the average character width */ 230 PDF_fontAvWidth = (int) 231 (PDF_RESOLUTION * PDF_stringwidth(myPDF, "01234567890123456789", 232 font_handle, PDF_fontSizeCur * PDF_fontscale ) 233 / 20.0); 234 PDF_currentFontHandle = font_handle; 235 236} 237 238#if !HAVE_OLD_LIBPDF 239static void 240PDF_DefinePatterns() 241{ 242 int i; 243 244 /* EAM April 2003 - Rearrange patterns to maximize contrast in mono. 245 * Because of the finite linewidth, each pattern must include line 246 * fragments at the "empty" corners. 247 */ 248 for (i=0; i<PDF_patterns; i++) { 249 PDF_patternHandles[i] = PDF_begin_pattern(myPDF, 8, 8, 8, 8, 2); 250 PDF_setlinewidth(myPDF, 0.25); 251 PDF_setlinecap(myPDF, 2); /* square ends */ 252 switch (i) { 253 case 0: PDF_moveto(myPDF, 0, 8); 254 PDF_lineto(myPDF, 8, 0); 255 PDF_moveto(myPDF, 0, 0); 256 PDF_lineto(myPDF, 8, 8); 257 PDF_stroke(myPDF); 258 break; 259 case 1: PDF_moveto(myPDF, 0, 8); 260 PDF_lineto(myPDF, 8, 0); 261 PDF_moveto(myPDF, 0, 0); 262 PDF_lineto(myPDF, 8, 8); 263 PDF_moveto(myPDF, 4, 0); 264 PDF_lineto(myPDF, 8, 4); 265 PDF_lineto(myPDF, 4, 8); 266 PDF_lineto(myPDF, 0, 4); 267 PDF_lineto(myPDF, 4, 0); 268 PDF_stroke(myPDF); 269 break; 270 case 2: PDF_moveto(myPDF, 0, 0); 271 PDF_lineto(myPDF, 0, 8); 272 PDF_lineto(myPDF, 8, 8); 273 PDF_lineto(myPDF, 8, 0); 274 PDF_lineto(myPDF, 0, 0); 275 PDF_fill(myPDF); 276 break; 277 case 3: PDF_moveto(myPDF, 0, 4); 278 PDF_lineto(myPDF, 4, 0); 279 PDF_moveto(myPDF, 4, 8); 280 PDF_lineto(myPDF, 8, 4); 281 PDF_stroke(myPDF); 282 break; 283 case 4: PDF_moveto(myPDF, 0, 4); 284 PDF_lineto(myPDF, 4, 8); 285 PDF_moveto(myPDF, 4, 0); 286 PDF_lineto(myPDF, 8, 4); 287 PDF_stroke(myPDF); 288 break; 289 case 5: PDF_moveto(myPDF, 0, 4); 290 PDF_lineto(myPDF, 2, 0); 291 PDF_moveto(myPDF, 2, 8); 292 PDF_lineto(myPDF, 6, 0); 293 PDF_moveto(myPDF, 6, 8); 294 PDF_lineto(myPDF, 8, 4); 295 PDF_stroke(myPDF); 296 break; 297 case 6: PDF_moveto(myPDF, 0, 4); 298 PDF_lineto(myPDF, 2, 8); 299 PDF_moveto(myPDF, 2, 0); 300 PDF_lineto(myPDF, 6, 8); 301 PDF_moveto(myPDF, 6, 0); 302 PDF_lineto(myPDF, 8, 4); 303 PDF_stroke(myPDF); 304 break; 305 case 7: /* not used */ 306 PDF_moveto(myPDF, 4, 0); 307 PDF_lineto(myPDF, 0, 2); 308 PDF_moveto(myPDF, 8, 2); 309 PDF_lineto(myPDF, 0, 6); 310 PDF_moveto(myPDF, 8, 6); 311 PDF_lineto(myPDF, 4, 8); 312 PDF_stroke(myPDF); 313 break; 314 case 8: /* not used */ 315 PDF_moveto(myPDF, 4, 0); 316 PDF_lineto(myPDF, 8, 2); 317 PDF_moveto(myPDF, 0, 2); 318 PDF_lineto(myPDF, 8, 6); 319 PDF_moveto(myPDF, 0, 6); 320 PDF_lineto(myPDF, 4, 8); 321 PDF_stroke(myPDF); 322 break; 323 } 324 PDF_end_pattern(myPDF); 325 } 326} 327#endif 328 329/*------------------- the terminal entry functions --------------------*/ 330 331 332TERM_PUBLIC void 333PDF_options () 334{ 335 /* Annoying hack to handle the case of 'set termoption' after */ 336 /* we have already initialized the terminal. */ 337 if (!almost_equals(c_token-1, "termopt$ion")) { 338 pdf_explicit_size = FALSE; 339 /* Default to enhanced text */ 340 term->put_text = ENHPDF_put_text; 341 term->flags |= TERM_ENHANCED_TEXT; 342 } 343 344 while (!END_OF_COMMAND) { 345 346 if (almost_equals(c_token, "enh$anced")) { 347 c_token++; 348 term->put_text = ENHPDF_put_text; 349 term->flags |= TERM_ENHANCED_TEXT; 350 continue; 351 } else if (almost_equals(c_token, "noenh$anced")) { 352 c_token++; 353 term->put_text = PDF_put_text; 354 term->flags &= ~TERM_ENHANCED_TEXT; 355 continue; 356 } 357 358 if (almost_equals(c_token, "fn$ame") || almost_equals(c_token, "font")) { 359 char *s, *comma; 360 c_token++; 361 362 if (!(s = try_to_get_string())) 363 int_error(c_token,"fname: expecting font name"); 364 comma = strrchr(s,','); 365 if (comma && (1 == sscanf(comma+1,"%lf",&PDF_fontSizeDef))) 366 *comma = '\0'; 367 if (*s) 368 strncpy(PDF_fontNameDef, s, sizeof(PDF_fontNameDef)); 369 free(s); 370 continue; 371 } 372 373 if (almost_equals(c_token, "fs$ize")) { 374 c_token++; 375 376 if (END_OF_COMMAND) 377 int_error(c_token,"fsize: expecting font size"); 378 PDF_fontSizeDef = real_expression(); 379 continue; 380 } 381 382 if (equals(c_token, "lw") || almost_equals(c_token, "linew$idth")) { 383 c_token++; 384 385 if (END_OF_COMMAND) 386 int_error(c_token, "expecting line width"); 387 PDF_linewidth_factor = real_expression(); 388 if (PDF_linewidth_factor <= 0) 389 PDF_linewidth_factor = 0.1; 390 continue; 391 } 392 393 if (almost_equals(c_token, "rou$nded")) { 394 c_token++; 395 PDF_LineCap = 1; 396 continue; 397 } 398 399 if (equals(c_token, "butt")) { 400 PDF_LineCap = 0; 401 continue; 402 } 403 404 if (equals(c_token, "color") || almost_equals(c_token, "col$our")) { 405 c_token++; 406 PDF_monochrome = FALSE; 407 term->flags &= ~TERM_MONOCHROME; 408 continue; 409 } 410 411 if (almost_equals(c_token, "mono$chrome")) { 412 c_token++; 413 PDF_monochrome = TRUE; 414 term->flags |= TERM_MONOCHROME; 415 continue; 416 } 417 418 if (equals(c_token, "dl") || almost_equals(c_token, "dashl$ength")) { 419 c_token++; 420 if (END_OF_COMMAND) 421 int_error(c_token, "expecting dashlength multiplier"); 422 PDF_dashlength_factor = real_expression(); 423 if (PDF_dashlength_factor < 0.0) 424 PDF_dashlength_factor = 1.0; 425 continue; 426 } 427 428 if (almost_equals(c_token, "dash$ed") || equals(c_token, "solid")) { 429 /* Version 5 always enables dashed lines */ 430 c_token++; 431 continue; 432 } 433 434 if (equals(c_token, "size")) { 435 float xmax_t, ymax_t; 436 c_token++; 437 pdf_explicit_size = TRUE; 438 pdf_explicit_units = parse_term_size(&xmax_t, &ymax_t, INCHES); 439 term->xmax = xmax_t*PDF_RESOLUTION*72./gp_resolution; 440 term->ymax = ymax_t*PDF_RESOLUTION*72./gp_resolution; 441 continue; 442 } 443 444 if (equals(c_token, "fontscale")) { 445 c_token++; 446 PDF_fontscale = END_OF_COMMAND ? -1 : real_expression(); 447 if (PDF_fontscale < 0) 448 PDF_fontscale = 1.0; 449 continue; 450 } 451 452 int_error(c_token, "unexpected text at end of command"); 453 } 454 455 /* Save options back into options string in normalized format */ 456 sprintf(term_options, "%s%s fname '%s' fsize %g fontscale %3.1f linewidth %3.1f %s ", 457 PDF_monochrome ? "monochrome " : " ", 458 term->put_text == ENHPDF_put_text ? "enhanced" : "noenhanced", 459 PDF_fontNameDef, PDF_fontSizeDef, PDF_fontscale, PDF_linewidth_factor, 460 PDF_LineCap == 1 ? "rounded" : ""); 461 if (PDF_dashedlines) 462 sprintf(&(term_options[strlen(term_options)]), "dl %3.1f", 463 PDF_dashlength_factor); 464 if (pdf_explicit_size) { 465 if (pdf_explicit_units == CM) 466 sprintf(&(term_options[strlen(term_options)]), "size %.2fcm, %.2fcm ", 467 2.54*(float)term->xmax/(72.*PDF_RESOLUTION), 468 2.54*(float)term->ymax/(72.*PDF_RESOLUTION)); 469 else 470 sprintf(&(term_options[strlen(term_options)]), "size %.2fin, %.2fin ", 471 (float)term->xmax/(72.*PDF_RESOLUTION), 472 (float)term->ymax/(72.*PDF_RESOLUTION)); 473 } 474} 475 476 477TERM_PUBLIC void 478PDF_init () 479{ 480 static TBOOLEAN PDFlib_booted = FALSE; 481 char *gpversionstring; 482 char *username; 483 char *timedate; 484 time_t now; 485 486 if (!PDFlib_booted) { 487 PDF_boot(); 488 PDFlib_booted = TRUE; 489 } 490 491 if (!myPDF) 492 myPDF = PDF_new(); 493 494 /*open new PDF file */ 495#ifdef HAVE_LIBPDF_OPEN_FILE 496 if (PDF_open_file(myPDF, outstr) == -1) 497#else 498 if (PDF_begin_document(myPDF, outstr?outstr:"-", 0, 499 "compatibility=1.4") == -1) 500#endif /* HAVE_LIBPDF_OPEN_FILE */ 501 int_error(NO_CARET, "Error:cannot open PDF file .\n"); 502 503#ifdef PDF_DONT_COMPRESS 504 /* for easier debugging of the output, turn off PDF stream 505 * compression */ 506 PDF_set_value(myPDF, "compress", 0); 507#endif 508 509 gpversionstring = gp_alloc(20 + strlen(gnuplot_version) + 510 strlen(gnuplot_patchlevel) + 1, "PDF_init"); 511 sprintf(gpversionstring,"gnuplot %s patchlevel %s", 512 gnuplot_version, gnuplot_patchlevel); 513 514 time(&now); 515 timedate=asctime(localtime(&now)); 516 timedate[strlen(timedate)-1]='\0'; 517 518 PDF_set_info(myPDF,"Creator",gpversionstring); 519 520 username=getusername(); 521 if (username) { 522 PDF_set_info(myPDF,"Author",username); 523 free(username); 524 } 525 526 if (outstr) 527 PDF_set_info(myPDF,"Title",outstr); /* FIXME: use 'set title', if any? */ 528 PDF_set_info(myPDF,"Subject","gnuplot plot"); 529 530 if (gpversionstring) 531 free(gpversionstring); 532 533 PDF_LineType = LT_UNDEFINED; 534 535 /* set current font to default */ 536 strcpy(PDF_fontNameCur, PDF_fontNameDef); 537 PDF_fontSizeCur = PDF_fontSizeDef; 538 539#if !HAVE_OLD_LIBPDF 540 PDF_DefinePatterns(); 541#endif 542 543 /* Have to start the first page now, in order to know the actual 544 * size of the selected font */ 545 PDF_graphics(); 546 547 /* set h_char, v_char*/ 548 term->h_char = PDF_fontAvWidth; 549 term->v_char = (PDF_fontAscent + PDF_fontDescent + PDF_fontLeading); 550 551 /* set h_tic, v_tic*/ 552 term->h_tic = term->v_tic = 3 * PDF_RESOLUTION; 553 554 /* initialize terminal's pointsize from "set pointsize" value */ 555 term_pointsize = pointsize; 556 557 /* Initialize other default settings */ 558 PDF_setlinecap(myPDF, PDF_LineCap); 559 PDF_setlinejoin(myPDF, PDF_LineCap); /* round+round or butt+mitre */ 560} 561 562 563TERM_PUBLIC void 564PDF_graphics () 565{ 566 if (PDF_pageIsOpen) 567 return; /* already open --> nothing to do */ 568 569 PDF_pathIsOpen = FALSE; 570 PDF_xLast = PDF_yLast = UINT_MAX; 571 572 /* set size of canvas */ 573 if (!pdf_explicit_size) { 574 term->xmax = PDF_XMAX; 575 term->ymax = PDF_YMAX; 576 } 577 578 PDF_begin_page(myPDF, (double)term->xmax / PDF_RESOLUTION, 579 (double)term->ymax / PDF_RESOLUTION); 580 PDF_scale(myPDF, 1.0/PDF_RESOLUTION, 1.0/PDF_RESOLUTION); 581 if (title.text && title.text[0]) 582 /* a title has been set --> use it as the bookmark name, too */ 583 PDF_add_bookmark(myPDF, title.text, 0, 1); 584 PDF_pageIsOpen = TRUE; 585 586 PDF_SetFont(); 587} 588 589 590TERM_PUBLIC void 591PDF_text () 592{ 593 PDF_PathClose(); 594 PDF_end_page(myPDF); 595 PDF_pageIsOpen = FALSE; 596} 597 598 599TERM_PUBLIC void 600PDF_reset () 601{ 602 assert(PDF_pageIsOpen == FALSE); 603#ifdef HAVE_LIBPDF_OPEN_FILE 604 PDF_close(myPDF); 605#else 606 PDF_end_document(myPDF, ""); 607#endif /* HAVE_LIBPDF_OPEN_FILE */ 608 PDF_delete(myPDF); 609 myPDF = NULL; 610} 611 612 613TERM_PUBLIC void 614PDF_linetype (int linetype) 615{ 616 int dash = linetype % 8; 617 618 linetype = PDF_Pen_RealID(linetype); 619 if (linetype == PDF_LineType) 620 return; 621 622 PDF_PathClose (); 623 PDF_LineType = linetype; 624 625 if (PDF_monochrome) { 626 PDF_current_gray = 0.0; 627 PDF_setgray(myPDF, PDF_current_gray); 628 } else { 629 unsigned int irgb = pm3d_color_names_tbl[1+linetype].value; 630 PDF_current_rgb.r = (double)((irgb >> 16) & 0xff) / 255.; 631 PDF_current_rgb.g = (double)((irgb >> 8) & 0xff) / 255.; 632 PDF_current_rgb.b = (double)((irgb ) & 0xff) / 255.; 633 PDF_setrgbcolor(myPDF, PDF_current_rgb.r, PDF_current_rgb.g, PDF_current_rgb.b); 634 } 635 636#ifndef HAVE_NODASH_LIBPDF 637 if (PDF_dashedlines) { 638 char dashtype[64]; 639 float dl = 8.0 * PDF_dashlength_factor; 640 641 switch (dash) { 642 default: 643 case 0: PDF_setdash(myPDF, 0.0, 0.0); 644 return; 645 case 1: sprintf(dashtype,"dasharray={%4.1f %4.1f}", 646 dl*dash1[0],dl*dash1[1]); 647 break; 648 case 2: sprintf(dashtype,"dasharray={%4.1f %4.1f}", 649 dl*dash2[0],dl*dash2[1]); 650 break; 651 case 3: sprintf(dashtype,"dasharray={%4.1f %4.1f}", 652 dl*dash3[0],dl*dash3[1]); 653 break; 654 case 4: sprintf(dashtype,"dasharray={%4.1f %4.1f %4.1f %4.1f}", 655 dl*dash4[0],dl*dash4[1],dl*dash4[2],dl*dash4[3]); 656 break; 657 case 5: sprintf(dashtype,"dasharray={%4.1f %4.1f %4.1f %4.1f}", 658 dl*dash5[0],dl*dash5[1],dl*dash5[2],dl*dash5[3]); 659 break; 660 case 6: sprintf(dashtype,"dasharray={%4.1f %4.1f %4.1f %4.1f}", 661 dl*dash6[0],dl*dash6[1],dl*dash6[2],dl*dash6[3]); 662 break; 663 case 7: sprintf(dashtype,"dasharray={%4.1f %4.1f %4.1f %4.1f %4.1f %4.1f}", 664 dl*dash7[0],dl*dash7[1],dl*dash7[2],dl*dash7[3],dl*dash7[4],dl*dash7[5]); 665 break; 666 } 667 PDF_setdashpattern(myPDF,dashtype); 668 } 669#endif 670 671} 672 673 674TERM_PUBLIC void 675PDF_linewidth (double linewidth) 676{ 677 PDF_PathClose(); 678 PDF_LineWidth = PDF_RESOLUTION * PDF_linewidth_factor * linewidth / 4.0; 679 if (PDF_LineWidth < 0.1) 680 PDF_LineWidth = 0.1; 681 PDF_setlinewidth(myPDF, PDF_LineWidth); 682} 683 684 685TERM_PUBLIC void 686PDF_move (unsigned int x, unsigned int y) 687{ 688 if (PDF_pathIsOpen && x == PDF_xLast && y == PDF_yLast) 689 return; 690 691 PDF_PathOpen (); 692 PDF_moveto(myPDF, x, y); 693 694 PDF_xLast = x; 695 PDF_yLast = y; 696} 697 698 699TERM_PUBLIC void 700PDF_vector (unsigned int x, unsigned int y) 701{ 702 if (PDF_pathIsOpen && x == PDF_xLast && y == PDF_yLast) 703 return; 704 705 if (!PDF_pathIsOpen) { 706 PDF_PathOpen (); 707 PDF_moveto(myPDF, PDF_xLast, PDF_yLast); 708 } 709 710 PDF_lineto(myPDF, x, y); 711 712 PDF_xLast = x; 713 PDF_yLast = y; 714} 715 716/* Helper function. Many symbols have an additional dot in their 717 * center, so isolate its drawing into a separate function. */ 718static GP_INLINE void 719PDF_dot (unsigned int x, unsigned int y) 720{ 721 /* Imitate PS's way of creating a small dot by a zero-length line 722 * segment with rounded endpoints */ 723 PDF_setlinecap(myPDF, 1); /* rounded ends */ 724 PDF_moveto(myPDF, x, y); 725 PDF_lineto(myPDF, x, y); 726 PDF_stroke(myPDF); 727 PDF_setlinecap(myPDF, PDF_LineCap); /* restore ends */ 728} 729 730 731TERM_PUBLIC void 732PDF_point (unsigned int x, unsigned int y, int number) 733{ 734 PDF_PathClose (); 735 PDF_save(myPDF); 736 737 if (number < 0 || term_pointsize <= 0) { 738 /* Treat all negative point sizes as dots */ 739 PDF_dot(x, y); 740 } else { 741 /* Change coordinate system so the point symbols themselves 742 * can be drawn without depending on position or size (--> 743 * better compression and less coding for gnuplot) */ 744 /* NB: I use the do_pointsize() default implementation, which 745 * just stores the last set pointsize into `term_pointsize', 746 * to avoid introducing another static driver-local variable 747 * */ 748 PDF_translate(myPDF, x, y); 749 PDF_scale(myPDF, term->h_tic / 2.0 * term_pointsize, 750 term->v_tic / 2.0 * term_pointsize); 751 /* Correct linewidth to counter the scaling effect --- assume 752 * h_tic is usable, to avoid having to average h_ and v_tic */ 753 PDF_setlinewidth(myPDF, 754 PDF_LineWidth / (term->h_tic / 2.0 * term_pointsize)); 755 switch (number %= PDF_NUM_POINTTYPES) { 756 case 0: /* Plus */ 757 PDF_moveto(myPDF, -1, 0); 758 PDF_lineto(myPDF, 1, 0); 759 PDF_moveto(myPDF, 0, -1); 760 PDF_lineto(myPDF, 0, 1); 761 PDF_stroke(myPDF); 762 break; 763 case 2: /* Star */ 764 PDF_moveto(myPDF, -1, 0); 765 PDF_lineto(myPDF, 1, 0); 766 PDF_moveto(myPDF, 0, -1); 767 PDF_lineto(myPDF, 0, 1); 768 /* FALLTHROUGH */ 769 case 1: /* Cross */ 770 PDF_moveto(myPDF, -1, -1); 771 PDF_lineto(myPDF, 1, 1); 772 PDF_moveto(myPDF, 1, -1); 773 PDF_lineto(myPDF, -1, 1); 774 PDF_stroke(myPDF); 775 break; 776 777/* For each x = 0..5, 4 shapes are defined: 778 * 3 + 2*x --> hollow symbol with a dot at its center 779 * 4 + 2*x --> solid symbol filled in linetype's color 780 * 63 + x --> hollow symbol without the center dot 781 * 69 + x --> symbol filled with white --> opaque symbol */ 782 783 case 63+0: /* BoxEmpty */ 784 case 3+2*0: /* Box */ 785 PDF_moveto(myPDF, -1, -1); 786 PDF_lineto(myPDF, 1, -1); 787 PDF_lineto(myPDF, 1, 1); 788 PDF_lineto(myPDF, -1, 1); 789 PDF_closepath_stroke(myPDF); 790 if (number == 3) PDF_dot(0,0); 791 break; 792 case 69+0: /* BoxWhitefilled */ 793 PDF_setgray_fill(myPDF, 1); 794 /* FALLTHROUGH */ 795 case 4+2*0: /* BoxFilled */ 796 PDF_moveto(myPDF, -1, -1); 797 PDF_lineto(myPDF, 1, -1); 798 PDF_lineto(myPDF, 1, 1); 799 PDF_lineto(myPDF, -1, 1); 800 PDF_closepath_fill_stroke(myPDF); 801 break; 802 803 case 63+1: /* CircleEmpty */ 804 case 3+2*1: /* Circle */ 805 PDF_circle(myPDF, 0, 0, 1); 806 PDF_stroke(myPDF); 807 if (number == 5) PDF_dot(0,0); 808 break; 809 case 69+1: /* CircleWhitefilled */ 810 PDF_setgray_fill(myPDF, 1); 811 /* FALLTHROUGH */ 812 case 4+2*1: /* CircleFilled */ 813 PDF_circle(myPDF, 0, 0, 1); 814 PDF_fill_stroke(myPDF); 815 break; 816 817 case 63+2: /* TriangleUpEmpty */ 818 case 3+2*2: /* TriangleUp */ 819 PDF_moveto(myPDF, 0, 1.12); 820 PDF_lineto(myPDF, -1, -0.5); 821 PDF_lineto(myPDF, 1, -0.5); 822 PDF_closepath_stroke(myPDF); 823 if (number == 7) PDF_dot(0,0); 824 break; 825 case 69+2: /* TriangleUpWhitefilled */ 826 PDF_setgray_fill(myPDF, 1); 827 /* FALLTHROUGH */ 828 case 4+2*2: /* TriangleUpFilled */ 829 PDF_moveto(myPDF, 0, 1.12); 830 PDF_lineto(myPDF, -1, -0.5); 831 PDF_lineto(myPDF, 1, -0.5); 832 PDF_closepath_fill_stroke(myPDF); 833 break; 834 835 case 63+3: /* TriangleDownEmpty */ 836 case 3+2*3: /* TriangleDown */ 837 PDF_moveto(myPDF, 0, -1.12); 838 PDF_lineto(myPDF, -1, 0.5); 839 PDF_lineto(myPDF, 1, 0.5); 840 PDF_closepath_stroke(myPDF); 841 if (number == 9) PDF_dot(0,0); 842 break; 843 case 69+3: /* TriangleDownWhitefilled */ 844 PDF_setgray_fill(myPDF, 1); 845 /* FALLTHROUGH */ 846 case 4+2*3: /* TriangleDownFilled */ 847 PDF_moveto(myPDF, 0, -1.12); 848 PDF_lineto(myPDF, -1, 0.5); 849 PDF_lineto(myPDF, 1, 0.5); 850 PDF_closepath_fill_stroke(myPDF); 851 break; 852 853 case 63+4: /* DiamondEmpty */ 854 case 3+2*4: /* Diamond */ 855 PDF_moveto(myPDF, 0, -1); 856 PDF_lineto(myPDF, 1, 0); 857 PDF_lineto(myPDF, 0, 1); 858 PDF_lineto(myPDF, -1, 0); 859 PDF_closepath_stroke(myPDF); 860 if (number == 11) PDF_dot(0,0); 861 break; 862 case 69+4: /* DiamondWhitefilled */ 863 PDF_setgray_fill(myPDF, 1); 864 /* FALLTHROUGH */ 865 case 4+2*4: /* DiamondFilled */ 866 PDF_moveto(myPDF, 0, -1); 867 PDF_lineto(myPDF, 1, 0); 868 PDF_lineto(myPDF, 0, 1); 869 PDF_lineto(myPDF, -1, 0); 870 PDF_closepath_fill_stroke(myPDF); 871 break; 872 873 case 63+5: /* PentagonEmpty */ 874 case 3+2*5: /* Pentagon */ 875 PDF_moveto(myPDF, 0, 1); 876 PDF_lineto(myPDF, -0.95, 0.31); 877 PDF_lineto(myPDF, -0.58, -0.81); 878 PDF_lineto(myPDF, +0.58, -0.81); 879 PDF_lineto(myPDF, +0.95, 0.31); 880 PDF_closepath_stroke(myPDF); 881 if (number == 13) PDF_dot(0,0); 882 break; 883 case 69+5: /* PentagonWhitefilled */ 884 PDF_setgray_fill(myPDF, 1); 885 /* FALLTHROUGH */ 886 case 4+2*5: /* PentagonFilled */ 887 PDF_moveto(myPDF, 0, 1); 888 PDF_lineto(myPDF, -0.95, 0.31); 889 PDF_lineto(myPDF, -0.58, -0.81); 890 PDF_lineto(myPDF, +0.58, -0.81); 891 PDF_lineto(myPDF, +0.95, 0.31); 892 PDF_closepath_fill_stroke(myPDF); 893 break; 894 895/* 15 + (0..15): circles with varying parts of'em filled. The added 896 * number is a bit-pattern of the 4 quadrants: 1 signals a quadrant 897 * filled */ 898 case 15+0: 899 PDF_moveto(myPDF, 0, 0); 900 PDF_lineto(myPDF, 0, 1); 901 PDF_arc(myPDF, 0, 0, 1, 90, 360+90); 902 PDF_closepath_stroke(myPDF); 903 break; 904 905/* Generalize common code into a macro... */ 906#define CIRCLE_SINGLE_PIESLICE(x, y, angle1, angle2) \ 907 PDF_moveto(myPDF, 0, 0); \ 908 PDF_lineto(myPDF, (x), (y)); \ 909 PDF_arc(myPDF, 0, 0, 1, (angle1), (angle2)); \ 910 PDF_lineto(myPDF, 0, 0); \ 911 PDF_closepath(myPDF); \ 912 PDF_fill_stroke(myPDF); \ 913 PDF_arc(myPDF, 0, 0, 1, (angle2), (angle1) + 360); \ 914 PDF_stroke(myPDF); \ 915 break; 916 917#define CIRCLE_SINGLE_QUADRANT(x, y, angle) \ 918 CIRCLE_SINGLE_PIESLICE(x, y, angle, angle+90); 919 case 15+1: 920 CIRCLE_SINGLE_QUADRANT(1, 0, 0); 921 case 15+2: 922 CIRCLE_SINGLE_QUADRANT(0, 1, 90); 923 case 15+4: 924 CIRCLE_SINGLE_QUADRANT(-1, 0, 180); 925 case 15+8: 926 CIRCLE_SINGLE_QUADRANT(0, -1, 270); 927#undef CIRCLE_SINGLE_QUADRANT 928 929#define CIRCLE_TWO_NEIGHBOR_QUADRANTS(x, y, angle) \ 930 CIRCLE_SINGLE_PIESLICE(x, y, angle, angle+180) 931 case 15+3: 932 CIRCLE_TWO_NEIGHBOR_QUADRANTS(1, 0, 0); 933 case 15+6: 934 CIRCLE_TWO_NEIGHBOR_QUADRANTS(0, 1, 90); 935 case 15+12: 936 CIRCLE_TWO_NEIGHBOR_QUADRANTS(-1, 0, 180); 937 case 15+9: 938 CIRCLE_TWO_NEIGHBOR_QUADRANTS(0, -1, 270); 939#undef CIRCLE_TWO_NEIGHBOR_QUADRANTS 940 941#define CIRCLE_TWO_OPPOSING_QUADRANTS(x, y, angle) \ 942 PDF_moveto(myPDF, 0, 0); \ 943 PDF_lineto(myPDF, x, y); \ 944 PDF_arc(myPDF, 0, 0, 1, angle, angle + 90); \ 945 PDF_lineto(myPDF, 0, 0); \ 946 PDF_fill_stroke(myPDF); \ 947 PDF_moveto(myPDF, 0, 0); \ 948 PDF_lineto(myPDF, -x, -y); \ 949 PDF_arc(myPDF, 0, 0, 1, angle + 180, angle + 270); \ 950 PDF_lineto(myPDF, 0, 0); \ 951 PDF_fill_stroke(myPDF); \ 952 PDF_arc(myPDF, 0, 0, 1, angle + 90, angle + 360); \ 953 PDF_stroke(myPDF); \ 954 break; 955 case 15+5: 956 CIRCLE_TWO_OPPOSING_QUADRANTS(1, 0, 0); 957 case 15+10: 958 CIRCLE_TWO_OPPOSING_QUADRANTS(0, 1, 90); 959#undef CIRCLE_TWO_OPPOSING_QUADRANTS 960 961#define CIRCLE_THREE_QUADRANTS(x, y, angle) \ 962 CIRCLE_SINGLE_PIESLICE(x, y, angle, angle+270) 963 case 15+7: 964 CIRCLE_THREE_QUADRANTS(1, 0, 0); 965 case 15+14: 966 CIRCLE_THREE_QUADRANTS(0, 1, 90); 967 case 15+13: 968 CIRCLE_THREE_QUADRANTS(-1, 0, 180); 969 case 15+11: 970 CIRCLE_THREE_QUADRANTS(0, -1, 270); 971#undef CIRCLE_THREE_QUADRANTS 972#undef CIRCLE_SINGLE_PIESLICE 973 974 case 15+15: 975 PDF_circle(myPDF, 0, 0, 1); 976 PDF_closepath_fill_stroke(myPDF); 977 break; 978 979 980/*************************************************************************/ 981/* 31 + (0..15): squares with different quadrants of them filled in. */ 982/*************************************************************************/ 983/*************************************************************************/ 984/* 47 + (0..15): diamonds with filled quadrants as given by bit pattern */ 985/* Diamonds are drawn as squares rotated by 45 degrees, so can use 986 * fall-through from diamond to squares, and re-use some macros. */ 987/*************************************************************************/ 988 case 47+0: 989 PDF_rotate(myPDF, 45); 990 /* FALLTHROUGH */ 991 case 31+0: 992 PDF_moveto(myPDF, 0, 0); 993 PDF_lineto(myPDF, 0, 1); 994 PDF_lineto(myPDF, -1, 1); 995 PDF_lineto(myPDF, -1, -1); 996 PDF_lineto(myPDF, 1, -1); 997 PDF_lineto(myPDF, 1, 1); 998 PDF_lineto(myPDF, 0, 1); 999 PDF_stroke(myPDF); 1000 break; 1001 1002 case 47+15: 1003 PDF_rotate(myPDF, 45); 1004 /* FALLTHROUGH */ 1005 case 31+15: 1006 PDF_moveto(myPDF, -1, 1); 1007 PDF_lineto(myPDF, -1, -1); 1008 PDF_lineto(myPDF, 1, -1); 1009 PDF_lineto(myPDF, 1, 1); 1010 PDF_closepath_fill_stroke(myPDF); 1011 break; 1012 1013/* macros defining shapes of the partly filled symbols. Done by 1014 * rotating the starting point (x0, y0) by 90 degrees or 45 degrees 1015 * (with length adjustment). The rotations can be done without 1016 * trigonometric function calls, since their values are known: 1017 * cos(90)=0, sin(90)=1, cos(45)=sin(45)=1/sqrt(2). A good compiler 1018 * should be able to optimize away all the local variables and 1019 * loops... */ 1020 1021#define SQUARE_SINGLE_PIESLICE(x0, y0, quadrants) \ 1022 { \ 1023 int quadrant = 0; \ 1024 int x= x0, y=y0; \ 1025 PDF_moveto(myPDF, 0, 0); \ 1026 PDF_lineto(myPDF, x, y); \ 1027 /* poor man's rotation by 45 and 90 degrees around the \ 1028 * square's outline. */ \ 1029 while (quadrant++ < quadrants) { \ 1030 int dummy; \ 1031 PDF_lineto(myPDF, x-y, x+y); \ 1032 dummy = x; x = -y; y = dummy; \ 1033 } \ 1034 PDF_lineto(myPDF, x, y); \ 1035 PDF_closepath_fill_stroke(myPDF); \ 1036 PDF_moveto(myPDF, x, y); \ 1037 while (quadrant++ <= 4) { \ 1038 int dummy; \ 1039 PDF_lineto(myPDF, x-y, x+y); \ 1040 dummy = x; x = -y; y = dummy; \ 1041 } \ 1042 PDF_lineto(myPDF, x, y); \ 1043 PDF_stroke(myPDF); \ 1044 } \ 1045 break; 1046 1047#define SQUARE_TWO_OPPOSING_QUADRANTS(x0, y0, angle) \ 1048 { \ 1049 int x = x0, y = y0, dummy; \ 1050 int counter = 0; \ 1051 \ 1052 while (counter++ < 2) { \ 1053 PDF_moveto(myPDF, 0, 0); \ 1054 PDF_lineto(myPDF, x, y); \ 1055 PDF_lineto(myPDF, x-y, x+y); \ 1056 dummy = x; x = -y; y = dummy; \ 1057 PDF_lineto(myPDF, x, y); \ 1058 PDF_closepath_fill_stroke(myPDF); \ 1059 \ 1060 PDF_moveto(myPDF, x, y); \ 1061 PDF_lineto(myPDF, x-y, x+y); \ 1062 dummy = x; x = -y; y = dummy; \ 1063 PDF_lineto(myPDF, x, y); \ 1064 PDF_stroke(myPDF); \ 1065 } \ 1066 break; \ 1067 } 1068 1069/* Macros for diamonds just prepend the rotation and then call those 1070 * for squares: */ 1071#define DIAMOND_SINGLE_PIESLICE(x, y, quadrants) \ 1072 PDF_rotate(myPDF, 45); \ 1073 SQUARE_SINGLE_PIESLICE(x, y, quadrants); 1074#define DIAMOND_TWO_OPPOSING_QUADRANTS(x, y, angle) \ 1075 PDF_rotate(myPDF, 45); \ 1076 SQUARE_TWO_OPPOSING_QUADRANTS(x, y, angle); 1077 1078/* ... and now all the individual cases. The 'angle' arguments' are 1079 * purely for the sake of easing cut'n'paste with the circle case */ 1080#define SQUARE_SINGLE_QUADRANT(x, y, angle) \ 1081 SQUARE_SINGLE_PIESLICE(x, y, 1); 1082 case 31+1: 1083 SQUARE_SINGLE_QUADRANT(1, 0, 0); 1084 case 31+2: 1085 SQUARE_SINGLE_QUADRANT(0, 1, 90); 1086 case 31+4: 1087 SQUARE_SINGLE_QUADRANT(-1, 0, 180); 1088 case 31+8: 1089 SQUARE_SINGLE_QUADRANT(0, -1, 270); 1090#undef SQUARE_SINGLE_QUADRANT 1091 1092#define SQUARE_TWO_NEIGHBOR_QUADRANTS(x, y, angle) \ 1093 SQUARE_SINGLE_PIESLICE(x, y, 2) 1094 case 31+3: 1095 SQUARE_TWO_NEIGHBOR_QUADRANTS(1, 0, 0); 1096 case 31+6: 1097 SQUARE_TWO_NEIGHBOR_QUADRANTS(0, 1, 90); 1098 case 31+12: 1099 SQUARE_TWO_NEIGHBOR_QUADRANTS(-1, 0, 180); 1100 case 31+9: 1101 SQUARE_TWO_NEIGHBOR_QUADRANTS(0, -1, 270); 1102#undef SQUARE_TWO_NEIGHBOR_QUADRANTS 1103 1104 case 31+5: 1105 SQUARE_TWO_OPPOSING_QUADRANTS(1, 0, 0); 1106 case 31+10: 1107 SQUARE_TWO_OPPOSING_QUADRANTS(0, 1, 90); 1108 1109#define SQUARE_THREE_QUADRANTS(x, y, angle) \ 1110 SQUARE_SINGLE_PIESLICE(x, y, 3) 1111 case 31+7: 1112 SQUARE_THREE_QUADRANTS(1, 0, 0); 1113 case 31+14: 1114 SQUARE_THREE_QUADRANTS(0, 1, 90); 1115 case 31+13: 1116 SQUARE_THREE_QUADRANTS(-1, 0, 180); 1117 case 31+11: 1118 SQUARE_THREE_QUADRANTS(0, -1, 270); 1119#undef SQUARE_THREE_QUADRANTS 1120 1121#define DIAMOND_SINGLE_QUADRANT(x, y, angle) \ 1122 DIAMOND_SINGLE_PIESLICE(x, y, 1) 1123 case 47+1: 1124 DIAMOND_SINGLE_QUADRANT(1, 0, 0); 1125 case 47+2: 1126 DIAMOND_SINGLE_QUADRANT(0, 1, 90); 1127 case 47+4: 1128 DIAMOND_SINGLE_QUADRANT(-1, 0, 180); 1129 case 47+8: 1130 DIAMOND_SINGLE_QUADRANT(0, -1, 270); 1131#undef DIAMOND_SINGLE_QUADRANT 1132 1133#define DIAMOND_TWO_NEIGHBOR_QUADRANTS(x, y, angle) \ 1134 DIAMOND_SINGLE_PIESLICE(x, y, 2) 1135 case 47+3: 1136 DIAMOND_TWO_NEIGHBOR_QUADRANTS(1, 0, 0); 1137 case 47+6: 1138 DIAMOND_TWO_NEIGHBOR_QUADRANTS(0, 1, 90); 1139 case 47+12: 1140 DIAMOND_TWO_NEIGHBOR_QUADRANTS(-1, 0, 180); 1141 case 47+9: 1142 DIAMOND_TWO_NEIGHBOR_QUADRANTS(0, -1, 270); 1143#undef DIAMOND_TWO_NEIGHBOR_QUADRANTS 1144 1145 1146 case 47+5: 1147 DIAMOND_TWO_OPPOSING_QUADRANTS(1, 0, 0); 1148 case 47+10: 1149 DIAMOND_TWO_OPPOSING_QUADRANTS(0, 1, 90); 1150#undef DIAMOND_TWO_OPPOSING_QUADRANTS 1151#undef SQUARE_TWO_OPPOSING_QUADRANTS 1152 1153#define DIAMOND_THREE_QUADRANTS(x, y, angle) \ 1154 DIAMOND_SINGLE_PIESLICE(x, y, 3) 1155 case 47+7: 1156 DIAMOND_THREE_QUADRANTS(1, 0, 0); 1157 case 47+14: 1158 DIAMOND_THREE_QUADRANTS(0, 1, 90); 1159 case 47+13: 1160 DIAMOND_THREE_QUADRANTS(-1, 0, 180); 1161 case 47+11: 1162 DIAMOND_THREE_QUADRANTS(0, -1, 270); 1163#undef DIAMOND_THREE_QUADRANTS 1164#undef DIAMOND_SINGLE_PIESLICE 1165#undef SQUARE_SINGLE_PIESLICE 1166 1167 default: 1168 int_warn(NO_CARET, "PDF: unknown point type number %d", number); 1169 } 1170 } 1171 1172 PDF_restore(myPDF); 1173 PDF_xLast = x; 1174 PDF_yLast = y; 1175} 1176 1177 1178TERM_PUBLIC int 1179PDF_justify_text (enum JUSTIFY mode) 1180{ 1181 PDF_TextJust = mode; 1182 return (TRUE); 1183} 1184 1185 1186TERM_PUBLIC int 1187PDF_text_angle (int ang) 1188{ 1189 PDF_TextAngle = ang; 1190 return (TRUE); 1191} 1192 1193 1194TERM_PUBLIC void 1195PDF_put_text (unsigned int x, unsigned int y, const char *str) 1196{ 1197 char *alignment = NULL; 1198 double h = x, v = y; 1199 1200 PDF_PathClose (); 1201 1202 /* horizontal justification*/ 1203 switch (PDF_TextJust) { 1204 case LEFT: 1205 alignment = "left"; 1206 break; 1207 case CENTRE: 1208 alignment = "center"; 1209 break; 1210 case RIGHT: 1211 alignment = "right"; 1212 break; 1213 } 1214 1215 if (PDF_TextAngle) { 1216 PDF_save(myPDF); 1217 PDF_translate(myPDF, h, v); 1218 PDF_rotate(myPDF, PDF_TextAngle); 1219 /* vertical justification*/ 1220 PDF_translate(myPDF, 0, -(PDF_fontAscent-PDF_fontDescent)/2); 1221 PDF_show_boxed(myPDF, str, 0,0, 0, 0, alignment, NULL); 1222 PDF_restore(myPDF); 1223 } else { 1224 /* vertical justification*/ 1225 v -= (PDF_fontAscent - PDF_fontDescent) / 2; 1226 PDF_show_boxed(myPDF, str, h , v, 0, 0, alignment, NULL); 1227 } 1228 1229} 1230 1231 1232TERM_PUBLIC int 1233PDF_set_font (const char *font) 1234{ 1235 /* FIXME: This condition is somehow triggered by enhanced_recursion */ 1236 if (font == PDF_fontNameCur) 1237 ; 1238 1239 else if (!font || !(*font)) { 1240 strcpy (PDF_fontNameCur, PDF_fontNameDef); 1241 PDF_fontSizeCur = PDF_fontSizeDef; 1242 } else { 1243 int sep = strcspn(font,","); 1244 if (sep > 0) { 1245 strncpy(PDF_fontNameCur,font,sep); 1246 PDF_fontNameCur[sep] = NUL; 1247 } 1248 if (font[sep] == ',') 1249 sscanf(&(font[sep+1]), "%lf", &PDF_fontSizeCur); 1250 } 1251 1252 PDF_PathClose(); 1253 PDF_SetFont(); 1254 1255 term->h_char = PDF_fontAvWidth; 1256 term->v_char = (PDF_fontAscent + PDF_fontDescent + PDF_fontLeading); 1257 1258 return (TRUE); 1259} 1260 1261TERM_PUBLIC void 1262PDF_boxfill(int style, unsigned int x1, unsigned int y1, 1263 unsigned int width, unsigned int height) 1264{ 1265 gpiPoint corner[4]; 1266 1267 corner[0].x = x1; corner[0].y = y1; 1268 corner[1].x = x1+width; corner[1].y = y1; 1269 corner[2].x = x1+width; corner[2].y = y1+height; 1270 corner[3].x = x1; corner[3].y = y1+height; 1271 1272 corner->style = style; 1273 PDF_filled_polygon(4, corner); 1274} 1275 1276TERM_PUBLIC void 1277PDF_filled_polygon(int points, gpiPoint* corners) 1278{ 1279 int i; 1280 int fillpar = corners->style >> 4; 1281 int style = corners->style &= 0xf; 1282 1283 PDF_PathClose(); 1284 PDF_save(myPDF); 1285 1286 switch (style) { 1287 case FS_EMPTY: /* fill with white */ 1288 PDF_setgray(myPDF, 1); 1289 break; 1290 case FS_TRANSPARENT_SOLID: 1291#if !HAVE_OLD_LIBPDF 1292 { 1293 /* FIXME: This attribute will be in effect until the end of */ 1294 /* the current page. We should explicitly reset it to restore */ 1295 /* opaque fill areas as the default. But when should it be? */ 1296 char density[18]; 1297 double red = PDF_current_rgb.r; 1298 double green = PDF_current_rgb.g; 1299 double blue = PDF_current_rgb.b; 1300 sprintf(density,"opacityfill=%4.2f", (double)fillpar*0.01); 1301 i = PDF_create_gstate(myPDF, density); 1302 PDF_set_gstate(myPDF, i); 1303 if (PDF_monochrome) 1304 PDF_setgray_fill(myPDF, PDF_current_gray); 1305 else 1306 PDF_setrgbcolor_fill(myPDF, red, green, blue); 1307 break; 1308 } 1309#endif 1310 case FS_SOLID: 1311 { 1312 double fact = (double)fillpar * 0.01; 1313 double _fact = (double)(100-fillpar) * 0.01; 1314 double red = PDF_current_rgb.r * fact + _fact; 1315 double green = PDF_current_rgb.g * fact + _fact; 1316 double blue = PDF_current_rgb.b * fact + _fact; 1317 if (PDF_monochrome) 1318 PDF_setgray_fill(myPDF, PDF_current_gray); 1319 else 1320 PDF_setrgbcolor_fill(myPDF, red, green, blue); 1321 } 1322 break; 1323 1324#if !HAVE_OLD_LIBPDF 1325 case FS_PATTERN: 1326 fillpar = fillpar % (PDF_patterns + 1) /* 0 == white */; 1327 /* Fill in solid background before drawing pattern */ 1328 /* NOTE: kpdf/xpdf would accept this as part of the pattern definition */ 1329 /* but acroread does not. So for compatibility we do the fill in */ 1330 /* a separate step, despite its inefficiency. */ 1331 if (fillpar != 0) { 1332 PDF_setcolor(myPDF, "fill", "rgb", 1, 1, 1, 0 /* unused */); 1333 PDF_moveto(myPDF, corners[0].x, corners[0].y); 1334 for (i=1; i<points; i++) 1335 PDF_lineto(myPDF, corners[i].x, corners[i].y); 1336 PDF_lineto(myPDF, corners[0].x, corners[0].y); 1337 PDF_fill(myPDF); 1338 PDF_restore(myPDF); 1339 PDF_save(myPDF); 1340 } 1341 /* NOTE: Fall through to the actual pattern code */ 1342 case FS_TRANSPARENT_PATTERN: 1343 fillpar = fillpar % (PDF_patterns + 1) /* 0 == white */; 1344 switch (fillpar) { 1345 case 0: 1346 /* fill with white */ 1347 PDF_setcolor(myPDF, "fill", "rgb", 1, 1, 1, 0 /* unused */); 1348 break; 1349 default: 1350 PDF_setcolor(myPDF, "fill", "pattern", PDF_patternHandles[fillpar - 1], 0, 0, 0); 1351 } 1352 break; 1353#endif 1354 1355 default: 1356 break; 1357 } 1358 1359 PDF_moveto(myPDF, corners[0].x, corners[0].y); 1360 for (i=1; i<points; i++) 1361 PDF_lineto(myPDF, corners[i].x, corners[i].y); 1362 PDF_lineto(myPDF, corners[0].x, corners[0].y); 1363 PDF_fill(myPDF); 1364 PDF_restore(myPDF); 1365} 1366 1367TERM_PUBLIC int 1368PDF_make_palette(t_sm_palette *palette) 1369{ 1370 if (palette == NULL) { 1371 /* pdf can do continuous colors */ 1372 return 0; 1373 } 1374 1375 return 0; 1376} 1377 1378TERM_PUBLIC void 1379PDF_set_color(t_colorspec *colorspec) 1380{ 1381 if (colorspec->type == TC_LT) { 1382 unsigned int irgb = pm3d_color_names_tbl[ 1 + PDF_Pen_RealID(colorspec->lt) ].value; 1383 PDF_current_rgb.r = (double)((irgb >> 16) & 0xff) / 255.; 1384 PDF_current_rgb.g = (double)((irgb >> 8) & 0xff) / 255.; 1385 PDF_current_rgb.b = (double)((irgb ) & 0xff) / 255.; 1386 PDF_current_gray = 0.0; /* monochrome mode only */ 1387 } else if (colorspec->type == TC_FRAC) { 1388 rgb1maxcolors_from_gray( colorspec->value, &PDF_current_rgb); 1389 PDF_current_gray = colorspec->value; /* monochrome mode only */ 1390 } else if (colorspec->type == TC_RGB) { 1391 PDF_current_rgb.r = (double)((colorspec->lt >> 16 ) & 255) / 255.; 1392 PDF_current_rgb.g = (double)((colorspec->lt >> 8 ) & 255) / 255.; 1393 PDF_current_rgb.b = (double)(colorspec->lt & 255) / 255.; 1394 } else 1395 return; 1396 1397 /* make sure that the path is stroked with the current color 1398 * before changing the color */ 1399 PDF_PathClose(); 1400 1401 if (PDF_monochrome && colorspec->type != TC_RGB) 1402 PDF_setgray(myPDF, PDF_current_gray); /* FIXME - Should this be NTSC(current_rgb)? */ 1403 else 1404 PDF_setrgbcolor(myPDF, PDF_current_rgb.r, PDF_current_rgb.g, PDF_current_rgb.b); 1405 1406 /* mark linetype invalid so that the color will be 1407 * set when PDF_linetype() is called next */ 1408 PDF_LineType = LT_UNDEFINED; 1409} 1410 1411TERM_PUBLIC void 1412PDF_previous_palette() 1413{ 1414} 1415 1416TERM_PUBLIC void 1417PDF_image (unsigned int M, unsigned int N, coordval * image, gpiPoint * corner, t_imagecolor color_mode) 1418{ 1419 unsigned char *pixel; 1420 float xscale, yscale; 1421 int i, im; 1422 1423 /* Allocate memory to hold a copy of the entire image in raw RGB format */ 1424 unsigned char *rawrgb = gp_alloc( M*N*3, "Raw RGB image"); 1425 1426 /* Convert the input image into raw RGB 24-bit color representation */ 1427 if (color_mode == IC_RGB) { 1428 for (i=0, pixel=rawrgb; i<N*M*3;) { 1429 rgb_color rgb1; 1430 rgb255_color rgb255; 1431 rgb1.r = image[i++]; 1432 rgb1.g = image[i++]; 1433 rgb1.b = image[i++]; 1434 rgb255_from_rgb1( rgb1, &rgb255 ); 1435 *pixel++ = rgb255.r; 1436 *pixel++ = rgb255.g; 1437 *pixel++ = rgb255.b; 1438 } 1439 } else { 1440 for (i=0, pixel=rawrgb; i< N*M; i++) { 1441 if (isnan(image[i])) { 1442 /* Transparent would be better! */ 1443 *pixel++ = 255; 1444 *pixel++ = 255; 1445 *pixel++ = 255; 1446 } else { 1447 rgb255_color rgb; 1448 rgb255maxcolors_from_gray(image[i], &rgb); 1449 *pixel++ = rgb.r; 1450 *pixel++ = rgb.g; 1451 *pixel++ = rgb.b; 1452 } 1453 } 1454 } 1455 1456 /* Describe this image to PDF library */ 1457 im = PDF_open_image( myPDF, "raw", "memory", (char *)rawrgb, 1458 (long)(M*N*3), (int)M, (int)N, 1459 3, 8, /* 3 colors, 8 bits each */ 1460 ""); 1461 1462 /* Clip to bounding box requested */ 1463 PDF_save(myPDF); 1464 PDF_moveto(myPDF, corner[2].x, corner[2].y); 1465 PDF_lineto(myPDF, corner[2].x, corner[3].y); 1466 PDF_lineto(myPDF, corner[3].x, corner[3].y); 1467 PDF_lineto(myPDF, corner[3].x, corner[2].y); 1468 PDF_closepath(myPDF); 1469 PDF_clip(myPDF); 1470 1471/* Scale and copy into the main PDF image */ 1472 xscale = fabs((float)corner[1].x - (float)corner[0].x) / (float)M; 1473 yscale = fabs((float)corner[1].y - (float)corner[0].y) / (float)N; 1474 PDF_translate(myPDF, corner[0].x, corner[0].y); 1475 PDF_scale(myPDF, xscale, yscale); 1476 PDF_translate(myPDF, 0, -(float)N); 1477 PDF_place_image(myPDF, im, 0.0, 0.0, 1.0 ); 1478 PDF_restore(myPDF); 1479 1480 /* Clean up */ 1481 PDF_close_image(myPDF, im); 1482 free(rawrgb); 1483 1484} 1485 1486/* 1487 * Ethan A Merritt November 2003 1488 * - support for enhanced text mode 1489 * BUGS: 1490 * - The baseline is not consistent if font size changes within a string. 1491 * - Placement of overprinted characters is not correct. 1492 * - libpdf exits if the requested font is not recognized. 1493 * - I implement text-rotation by hand, but it may be possible to use 1494 * a gsave/translate/rotate/.../grestore sequence instead. 1495 */ 1496 1497static TBOOLEAN ENHpdf_opened_string; 1498 1499/* used in determining height of processed text */ 1500static float ENHpdf_base; 1501 1502/* use these so that we don't over-write the current font settings in pdf_state */ 1503static double ENHpdf_fontsize; 1504static char *ENHpdf_font; 1505 1506/* A global flag that tells us this run is just to determine text size */ 1507static TBOOLEAN ENHpdf_sizeonly = FALSE; 1508 1509static TBOOLEAN ENHpdf_show = TRUE; 1510static int ENHpdf_overprint = 0; 1511static TBOOLEAN ENHpdf_widthflag = FALSE; 1512static unsigned int ENHpdf_xsave, ENHpdf_ysave; 1513 1514/* Start a new string fragment */ 1515TERM_PUBLIC void 1516ENHPDF_OPEN( 1517 char *fontname, 1518 double fontsize, double base, 1519 TBOOLEAN widthflag, TBOOLEAN showflag, 1520 int overprint) 1521{ 1522 /* If the overprint code requests a save or request, that's all we do */ 1523 if (overprint == 3) { 1524 ENHpdf_xsave = PDF_xLast; 1525 ENHpdf_ysave = PDF_yLast; 1526 return; 1527 } else if (overprint == 4) { 1528 PDF_move(ENHpdf_xsave, ENHpdf_ysave); 1529 return; 1530 } 1531 1532 if (!ENHpdf_opened_string) { 1533 ENHpdf_opened_string = TRUE; 1534 enhanced_cur_text = &enhanced_text[0]; 1535 ENHpdf_font = fontname; 1536 ENHpdf_fontsize = fontsize; 1537 ENHpdf_base = base * PDF_RESOLUTION; 1538 ENHpdf_show = showflag; 1539 ENHpdf_overprint = overprint; 1540 ENHpdf_widthflag = widthflag; 1541 } 1542} 1543 1544/* Write a string fragment and update the current position */ 1545TERM_PUBLIC void 1546ENHPDF_FLUSH() 1547{ 1548 int x, y; 1549 float stringlength; 1550 1551 if (ENHpdf_opened_string) { 1552 ENHpdf_opened_string = FALSE; 1553 *enhanced_cur_text = '\0'; 1554 x = PDF_xLast; 1555 y = PDF_yLast; 1556 x -= sin((double)PDF_TextAngle * M_PI_2/90.) * ENHpdf_base; 1557 y += cos((double)PDF_TextAngle * M_PI_2/90.) * ENHpdf_base; 1558 x += sin((double)PDF_TextAngle * M_PI_2/90.) * (double)PDF_fontAvWidth/2.; 1559 y -= cos((double)PDF_TextAngle * M_PI_2/90.) * (double)PDF_fontAvWidth/2.; 1560 1561 /* Select current font for enhanced text fragment, then restore context */ 1562 if (1) { 1563 char save_fontname[MAX_ID_LEN + 1]; 1564 double save_fontsize = PDF_fontSizeCur; 1565 strcpy(save_fontname,PDF_fontNameCur); 1566 PDF_fontSizeCur = ENHpdf_fontsize / PDF_fontscale; 1567 PDF_set_font(ENHpdf_font); 1568 strcpy(PDF_fontNameCur,save_fontname); 1569 PDF_fontSizeCur = save_fontsize; 1570 } 1571 1572 /* Find length of string in current font */ 1573 stringlength = PDF_stringwidth(myPDF, enhanced_text, 1574 PDF_currentFontHandle, ENHpdf_fontsize); 1575 stringlength *= PDF_RESOLUTION; 1576 1577 if (ENHpdf_show && !ENHpdf_sizeonly) { 1578 if (PDF_TextAngle == 0 ) { 1579 /* PDF_show(myPDF, enhanced_text); */ 1580 PDF_show_boxed(myPDF, enhanced_text, x, y, 0, 0, "left", NULL); 1581 } else { 1582 PDF_save(myPDF); 1583 PDF_translate(myPDF, x, y); 1584 PDF_rotate(myPDF, PDF_TextAngle); 1585 /* vertical justification*/ 1586 PDF_translate(myPDF, 0, -(PDF_fontAscent-PDF_fontDescent)/2); 1587 PDF_show_boxed(myPDF, enhanced_text, 0, 0, 0, 0, "left", NULL); 1588 PDF_restore(myPDF); 1589 } 1590 } 1591 if (ENHpdf_overprint == 1) { 1592 PDF_xLast += stringlength * cos((double)PDF_TextAngle * M_PI_2/90.) / 2.; 1593 PDF_yLast += stringlength * sin((double)PDF_TextAngle * M_PI_2/90.); 1594 } else if (ENHpdf_widthflag) { 1595 PDF_xLast += stringlength * cos((double)PDF_TextAngle * M_PI_2/90.); 1596 PDF_yLast += stringlength * sin((double)PDF_TextAngle * M_PI_2/90.); 1597 } 1598 } 1599} 1600 1601TERM_PUBLIC void 1602ENHPDF_put_text(unsigned int x, unsigned int y, const char *str) 1603{ 1604 char *original_string = (char *)str; 1605 1606 if (ignore_enhanced_text) { 1607 PDF_put_text(x,y,str); 1608 return; 1609 } 1610 1611 if (!str || !strlen(str)) 1612 return; 1613 1614 /* if there are no magic characters, we should just be able 1615 * punt the string to PDF_put_text() 1616 */ 1617 if (!strpbrk(str, "{}^_@&~")) { 1618 /* do something to ensure default font is selected */ 1619 PDF_put_text(x,y,str); 1620 return; 1621 } 1622 1623 PDF_move(x, y); 1624 PDF_PathClose(); 1625 PDF_save(myPDF); 1626 1627 /* FIXME - Is this the way to do it????? 1628 if (PDF_TextAngle != 0) 1629 ENHPDF_DEBUG(("currentpoint gsave translate %d rotate 0 0 moveto\n", PDF_TextAngle)); 1630 */ 1631 1632 /* set up the global variables needed by enhanced_recursion() */ 1633 enhanced_fontscale = PDF_fontscale; 1634 strncpy(enhanced_escape_format,"%c",sizeof(enhanced_escape_format)); 1635 1636 ENHpdf_opened_string = FALSE; 1637 1638 /* EAM - Software text justification requires two passes */ 1639 if (PDF_TextJust == RIGHT || PDF_TextJust == CENTRE) 1640 ENHpdf_sizeonly = TRUE; 1641 1642 /* Set the recursion going. We say to keep going until a 1643 * closing brace, but we don't really expect to find one. 1644 * If the return value is not the nul-terminator of the 1645 * string, that can only mean that we did find an unmatched 1646 * closing brace in the string. We increment past it (else 1647 * we get stuck in an infinite loop) and try again. 1648 */ 1649 while (*(str = enhanced_recursion((char *)str, TRUE, 1650 PDF_fontNameCur, PDF_fontSizeCur * PDF_fontscale, 1651 0.0, TRUE, TRUE, 0))) { 1652 (term->enhanced_flush)(); 1653 1654 /* I think we can only get here if *str == '}' */ 1655 enh_err_check(str); 1656 1657 if (!*++str) 1658 break; /* end of string */ 1659 1660 /* else carry on and process the rest of the string */ 1661 } 1662 1663 PDF_restore(myPDF); 1664 1665 /* We can do text justification by running the entire top level string */ 1666 /* through 2 times, with the ENHpdf_sizeonly flag set the first time. */ 1667 /* After seeing where the final position is, we then offset the start */ 1668 /* point accordingly and run it again. */ 1669 if (PDF_TextJust == RIGHT || PDF_TextJust == CENTRE) { 1670 int justification = PDF_TextJust; 1671 int x_offset = PDF_xLast - x; 1672 int y_offset = 0; 1673 1674 if (PDF_TextAngle != 0) 1675 y_offset = PDF_yLast - y; 1676 PDF_TextJust = LEFT; 1677 ENHpdf_sizeonly = FALSE; 1678 1679 if (justification == RIGHT) { 1680 ENHPDF_put_text(x - x_offset, y - y_offset, original_string); 1681 } else if (justification == CENTRE) { 1682 ENHPDF_put_text(x - x_offset/2, y - y_offset/2, original_string); 1683 } 1684 PDF_TextJust = justification; 1685 } 1686 1687} 1688 1689#endif /* TERM_BODY */ 1690 1691#ifdef TERM_TABLE 1692TERM_TABLE_START (pdf_driver) 1693 "pdf", "PDF (Portable Document File) file driver", 1694 0 /* xmax */ , 0 /* ymax */ , 0 /* vchar */ , 0 /* hchar */ , 1695 0 /* vtic */ , 0 /* htic */ , 1696 PDF_options, PDF_init, PDF_reset, PDF_text, null_scale, PDF_graphics, 1697 PDF_move, PDF_vector, PDF_linetype, PDF_put_text, PDF_text_angle, 1698 PDF_justify_text, PDF_point, do_arrow, PDF_set_font, do_pointsize, 1699 TERM_BINARY|TERM_CAN_DASH|TERM_LINEWIDTH|TERM_FONTSCALE, 1700 0 /* suspend */, 0 /* resume */ , PDF_boxfill, PDF_linewidth 1701# ifdef USE_MOUSE 1702 , 0, 0, 0, 0, 0 /* no mouse support for pdf */ 1703# endif 1704 , PDF_make_palette, 1705 PDF_previous_palette, 1706 PDF_set_color, 1707 PDF_filled_polygon 1708 , PDF_image 1709 , ENHPDF_OPEN, ENHPDF_FLUSH, do_enh_writec 1710TERM_TABLE_END (pdf_driver) 1711#undef LAST_TERM 1712#define LAST_TERM pdf_driver 1713#endif /* TERM_TABLE */ 1714 1715#endif /* TERM_PROTO_ONLY */ 1716 1717#ifdef TERM_HELP 1718START_HELP(pdf) 1719"1 pdf", 1720"?commands set terminal pdf", 1721"?set terminal pdf", 1722"?set term pdf", 1723"?terminal pdf", 1724"?term pdf", 1725"?pdf", 1726" [DEPRECATED] This terminal uses the non-free library PDFlib (GmbH Munchen)" 1727" to produce files in Portable Document Format. Unless you have a commercial", 1728" license for PDFlib and need some special feature it provides you would do", 1729" better to use the cairo pdf terminal instead. Gnuplot can also export PDF", 1730" files from wxt or qt interactive terminal sessions.", 1731"", 1732" Syntax:", 1733" set terminal pdf {monochrome|color|colour}", 1734" {{no}enhanced}", 1735" {fname \"<font>\"} {fsize <fontsize>}", 1736" {font \"<fontname>{,<fontsize>}\"} {fontscale <scale>}", 1737" {linewidth <lw>} {rounded|butt}", 1738" {dl <dashlength>}}", 1739" {size <XX>{unit},<YY>{unit}}", 1740"", 1741" The default is to use a different color for each line type. Selecting", 1742" `monochome` will use black for all linetypes, Even in in mono mode", 1743" you can still use explicit colors for filled areas or linestyles.", 1744"", 1745" where <font> is the name of the default font to use (default Helvetica)", 1746" and <fontsize> is the font size (in points, default 12).", 1747" For help on which fonts are available or how to install new ones, please", 1748" see the documentation for your local installation of pdflib.", 1749"", 1750" The `enhanced` option enables enhanced text processing features", 1751" (subscripts, superscripts and mixed fonts). See `enhanced`.", 1752"", 1753" The width of all lines in the plot can be increased by the factor <n>", 1754" specified in `linewidth`. Similarly `dashlength` is a multiplier for the", 1755" default dash spacing.", 1756"", 1757" `rounded` sets line caps and line joins to be rounded; `butt` is the", 1758" default, butt caps and mitered joins.", 1759"", 1760" The default size for PDF output is 5 inches by 3 inches. The `size` option", 1761" changes this to whatever the user requests. By default the X and Y sizes", 1762" are taken to be in inches, but other units are possible (currently only cm).", 1763"" 1764END_HELP(pdf) 1765#endif 1766