1 /* Hello, Emacs: this is -*-C-*- !
2 * $Id: post.trm,v 1.203.2.17 2009/03/02 17:40:06 mikulik Exp $
5 /* GNUPLOT - post.trm */
8 * Copyright 1990 - 1993, 1998, 1999, 2000, 2001, 2004
10 * Permission to use, copy, and distribute this software and its
11 * documentation for any purpose with or without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and
13 * that both that copyright notice and this permission notice appear
14 * in supporting documentation.
16 * Permission to modify the software is granted, but not the right to
17 * distribute the complete modified source code. Modifications are to
18 * be distributed as patches to the released version. Permission to
19 * distribute binaries produced by compiling modified sources is granted,
21 * 1. distribute the corresponding source modifications from the
22 * released version in the form of a patch file along with the binaries,
23 * 2. add special version identification to distinguish your version
24 * in addition to the base release version number,
25 * 3. provide your name and address as the primary contact for the
26 * support of your modified version, and
27 * 4. retain our contact information in regard to use of the base
29 * Permission to distribute the released version of the source code along
30 * with corresponding source modifications in the form of a patch file is
31 * granted with same provisions 2 through 4 for binary distributions.
33 * This software is provided "as is" without express or implied warranty
34 * to the extent permitted by applicable law.
38 * This terminal driver supports:
42 * Russell Lang <rjl@monu1.cc.monash.edu.au>
44 * modified 10/5/95 by drd - put in support for other postscript drivers
45 * (enhpost, pslatex, ...) so they dont have to work quite so hard
47 * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
49 * The 'postscript' driver produces landscape output 10" wide and 7" high.
50 * To change font to Times-Roman and font size to 20pts use
51 * 'set term postscript "Times-Roman" 20'.
52 * To get a smaller (5" x 3.5") eps output use 'set term post eps'
53 * and make only one plot per file. Font size for eps will be half
56 * Erik Luijten 30/5/97: added %%CreationDate, made %%DocumentFonts conform
57 * to DSC, added version no. and patchl. to %%Creator
58 * Petr Mikulik, Jan 1999: terminal entries for PM3D functionality
60 * Dick Crawford 24/5/00: added 'a{}{}' syntax to allow for overprinting
62 * Dan Sebald, 7 March 2003: terminal entry for image functionality
64 * Harald Harders (h.harders@tu-bs.de), 2004-12-02:
65 * Moved all terminal settings into a single structure.
67 * Harald Harders (h.harders@tu-bs.de), 2005-02-08:
68 * Merged functionality of postscript, pslatex, pstex, and epslatex terminals.
70 * Ethan Merritt Mar 2006: Break out prolog and character encodings into
71 * separate files loaded at runtime
77 #include "variable.h" /* For loadpath_handler used in PS_dump_prologue_file */
85 TERM_PUBLIC void PS_options __PROTO((void));
86 TERM_PUBLIC void PS_common_init __PROTO((TBOOLEAN uses_fonts, unsigned int xoff, unsigned int yoff, unsigned int bb_xmin, unsigned int bb_ymin, unsigned int bb_xmax, unsigned int bb_ymax, const char **dict));
87 TERM_PUBLIC void PS_init __PROTO((void));
88 TERM_PUBLIC void PS_graphics __PROTO((void));
89 TERM_PUBLIC void PS_text __PROTO((void));
90 TERM_PUBLIC void PS_reset __PROTO((void));
91 TERM_PUBLIC void PS_linetype __PROTO((int linetype));
92 TERM_PUBLIC void PS_move __PROTO((unsigned int x, unsigned int y));
93 TERM_PUBLIC void PS_vector __PROTO((unsigned int x, unsigned int y));
94 TERM_PUBLIC void PS_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
95 TERM_PUBLIC int PS_text_angle __PROTO((int ang));
96 TERM_PUBLIC int PS_justify_text __PROTO((enum JUSTIFY mode));
97 TERM_PUBLIC void PS_point __PROTO((unsigned int x, unsigned int y, int number));
98 TERM_PUBLIC void PS_arrow __PROTO(( unsigned int sx, unsigned int sy,
99 unsigned int ex, unsigned int ey, int head));
100 TERM_PUBLIC int PS_set_font __PROTO((const char * font));
101 TERM_PUBLIC void PS_fillbox __PROTO((int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height));
102 TERM_PUBLIC void PS_linewidth __PROTO((double linewidth)); /* JFi [linewidth] */
103 TERM_PUBLIC void PS_pointsize __PROTO((double ptsize)); /* JFi [pointsize] */
104 TERM_PUBLIC int PS_make_palette (t_sm_palette *);
105 TERM_PUBLIC void PS_previous_palette (void);
106 TERM_PUBLIC void PS_set_color (t_colorspec *);
107 TERM_PUBLIC void PS_filled_polygon (int, gpiPoint *);
109 TERM_PUBLIC void PS_image __PROTO((unsigned, unsigned, coordval *, gpiPoint *, t_imagecolor));
112 /* To support "set term post enhanced" */
113 TERM_PUBLIC void ENHPS_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
114 TERM_PUBLIC int ENHPS_set_font __PROTO((const char * font));
115 TERM_PUBLIC void ENHPS_OPEN __PROTO((char * fontname, double fontsize,
116 double base, TBOOLEAN widthflag, TBOOLEAN showflag,
118 TERM_PUBLIC void ENHPS_FLUSH __PROTO((void));
119 TERM_PUBLIC void ENHPS_WRITEC __PROTO((int c));
120 TERM_PUBLIC char *PS_RememberFont __PROTO((char *fname, int reencode));
122 TERM_PUBLIC char *PS_escape_string __PROTO((char *origstr, char *escapelist));
124 TERM_PUBLIC void PS_path __PROTO((int p));
125 static TBOOLEAN PS_newpath = FALSE;
127 #endif /* TERM_PROTO */
129 #ifndef TERM_PROTO_ONLY
135 #define PS_FLUSH_PATH do { \
136 if (ps_path_count) { \
137 fputs("stroke\n", gppsfile); \
139 PS_relative_ok = FALSE; \
143 /* Datastructure implementing inclusion of font files */
144 struct ps_fontfile_def {
145 struct ps_fontfile_def *next;/* pointer to next fontfile in linked list */
147 char *fontfile_fullname;
150 /* Terminal type of postscript dialect */
151 enum PS_TERMINALTYPE {
152 PSTERM_PSTEX, PSTERM_PSLATEX, PSTERM_EPSLATEX, PSTERM_POSTSCRIPT
156 PSTERM_EPS, PSTERM_PORTRAIT, PSTERM_LANDSCAPE
159 /* One struct that takes all terminal parameters
160 * by Harald Harders <h.harders@tu-bs.de> */
161 typedef struct ps_params_t {
162 enum PS_TERMINALTYPE terminal;
165 enum PS_PSFORMAT psformat;
171 float linewidth_factor;
172 TBOOLEAN duplex_option; /* one of duplex or simplex specified? */
173 TBOOLEAN duplex_state;
174 TBOOLEAN rounded; /* rounded linecaps and linejoins */
175 struct ps_fontfile_def *first_fontfile;
176 char font[MAX_ID_LEN+1]; /* name of font */
177 float fontsize; /* size of font in pts */
178 TBOOLEAN useauxfile; /* only necessary for ps(la)tex */
179 TBOOLEAN rotate; /* only necessary for ps(la)tex */
180 int palfunc_samples; /* setable via "palf$uncparam" */
181 double palfunc_deviation; /* terminal option */
183 TBOOLEAN epslatex_standalone;
186 #define POST_PARAMS_DEFAULT { \
187 PSTERM_POSTSCRIPT, 50, 50, \
188 PSTERM_LANDSCAPE, FALSE, FALSE, FALSE, FALSE, 1.0, 1.0, FALSE, \
189 FALSE, FALSE, NULL, "Helvetica", 14, FALSE, FALSE, 2000, 0.003, \
193 static ps_params_t post_params = POST_PARAMS_DEFAULT;
194 static const ps_params_t post_params_default = POST_PARAMS_DEFAULT;
196 #define EPSLATEX_PARAMS_DEFAULT { \
197 PSTERM_EPSLATEX, 50, 50, \
198 PSTERM_EPS, FALSE, FALSE, TRUE, FALSE, 1.0, 1.0, FALSE, \
199 FALSE, FALSE, NULL, "", 11, TRUE, FALSE, 2000, 0.003, \
202 static ps_params_t epslatex_params = EPSLATEX_PARAMS_DEFAULT;
203 static const ps_params_t epslatex_params_default = EPSLATEX_PARAMS_DEFAULT;
205 #define PSLATEX_PARAMS_DEFAULT { \
206 PSTERM_PSLATEX, 0, 0, \
207 PSTERM_EPS, FALSE, FALSE, TRUE, FALSE, 1.0, 1.0, FALSE, \
208 FALSE, FALSE, NULL, "", 0, FALSE, TRUE, 2000, 0.003, \
211 static ps_params_t pslatex_params = PSLATEX_PARAMS_DEFAULT;
212 static const ps_params_t pslatex_params_default = PSLATEX_PARAMS_DEFAULT;
214 #define PSTEX_PARAMS_DEFAULT { \
215 PSTERM_PSTEX, 0, 0, \
216 PSTERM_EPS, FALSE, FALSE, TRUE, FALSE, 1.0, 1.0, FALSE, \
217 FALSE, FALSE, NULL, "", 0, FALSE, TRUE, 2000, 0.003, \
220 static ps_params_t pstex_params = PSTEX_PARAMS_DEFAULT;
221 static const ps_params_t pstex_params_default = PSTEX_PARAMS_DEFAULT;
223 static ps_params_t *ps_params = &post_params;
225 static void make_interpolation_code __PROTO((void));
226 static void make_color_model_code __PROTO((void));
227 static char * save_space __PROTO((double gray));
228 static void write_component_array __PROTO((const char *text, gradient_struct *grad, int cnt, int offset));
229 static void write_gradient_definition __PROTO((gradient_struct *gradient, int cnt));
230 static void write_color_space __PROTO((t_sm_palette *palette));
231 static void make_palette_formulae __PROTO((void));
232 static void PS_make_header __PROTO((t_sm_palette *palette));
234 static float ps_fontsize;
236 /* for enhanced mode, we keep a separate font name and size, which
237 * is restored to the default value on font of ""
239 static char ps_enh_font[MAX_ID_LEN+1];
240 static float ps_enh_fontsize;
241 static int ENHPS_initialized;
243 static int ps_page = 0; /* page count */
244 static int ps_path_count = 0; /* count of lines in path */
245 static int ps_ang = 0; /* text angle */
246 static enum JUSTIFY ps_justify = LEFT; /* text is flush left */
248 static void delete_ps_fontfile __PROTO((struct ps_fontfile_def *, struct ps_fontfile_def *));
250 TERM_PUBLIC void PS_load_fontfile __PROTO((struct ps_fontfile_def *,TBOOLEAN));
251 TERM_PUBLIC void PS_load_fontfiles __PROTO((TBOOLEAN));
253 static TBOOLEAN ps_explicit_size = FALSE;
254 static size_units ps_explicit_units = INCHES;
255 static int eps_explicit_x = 0;
256 static int eps_explicit_y = 0;
258 #define DOTS_PER_INCH (300) /* resolution of printer we expect to use */
260 /* name of auxiliary file */
261 static char *pslatex_auxname = NULL;
263 /* Routine to copy pre-existing prolog files into output stream */
264 static void PS_dump_prologue_file __PROTO((char *));
266 static const char GPFAR * GPFAR OldEPSL_linetypes[] = {
268 "% Redefine line types to match old epslatex driver\n",
269 "/LTw { PL [] 1 setgray } def\n", /* background (assumed white) */
270 "/LTb { BL [] 0 0 0 DL } def\n", /* border */
271 "/LTa { AL [1 udl mul 2 udl mul] 0 setdash 0 0 0 setrgbcolor } def\n", /* axes */
272 "/LT0 { PL [] 1 0 0 DL } def\n",
273 "/LT1 { PL [8 dl1 5 dl1] 0 0 1 DL } def\n",
274 "/LT2 { PL [4 dl1 4 dl1] 0 1 1 DL } def\n",
275 "/LT3 { PL [8 dl1 5 dl1 0.5 dl1 5 dl1] 1 0 1 DL } def\n",
279 static const char GPFAR * GPFAR ENHPS_header[] = {
280 /* For MFshow and MFwidth the tos is an array with the string and font info: */
281 /* [<fontname (a string)> <fontsize> <vertical offset> <width significant?> <printed?> <overprint> <text string>] */
282 /* EAM Mar 2004 - Add in a special case overprint 3 = save, overprint 4 = restore */
285 " { dup 5 get 3 ge\n", /* EAM test for overprint 3 or 4 */
286 " { 5 get 3 eq {gsave} {grestore} ifelse }\n", /* EAM */
287 " {dup dup 0 get findfont exch 1 get scalefont setfont\n",
288 " [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6\n",
289 " get exch 4 get {show} {stringwidth pop 0 R} ifelse }if dup 5 get 0 eq\n",
290 " {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5\n",
291 " get 1 eq {dup 2 get exch dup 3 get exch 6 get stringwidth pop -2 div\n",
292 " dup 0 R} {dup 6 get stringwidth pop -2 div 0 R 6 get\n",
293 " show 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop\n",
294 " pop aload pop M} ifelse }ifelse }ifelse }\n",
295 " ifelse }\n", /* EAM */
296 " forall} bind def\n",
298 /* get the width of the text */
299 /* HH 2005-07-24 - Add in a special case overprint 3 = save, 4 = restore
300 * also for estimation of string width. This is done by interposing an
301 * additional value on the stack. between XYsave and XYrestore,
302 * this number is increased by the strings. By pop'ing this number, all
303 * strings between XYsave and XYrestore are ignored. */
304 "/MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse }\n",
305 " {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont\n",
306 " 6 get stringwidth pop add} {pop} ifelse} ifelse} forall} bind def\n",
308 /* flush left show */
309 "/MLshow { currentpoint stroke M\n",
310 " 0 exch R\n Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def\n",
312 /* flush right show */
313 "/MRshow { currentpoint stroke M\n",
314 " exch dup MFwidth neg 3 -1 roll R\n Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def\n",
317 "/MCshow { currentpoint stroke M\n",
318 " exch dup MFwidth -2 div 3 -1 roll R\n Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def\n",
320 /* Save and restore for @-text (phantom box) */
321 "/XYsave { [( ) 1 2 true false 3 ()] } bind def\n",
322 "/XYrestore { [( ) 1 2 true false 4 ()] } bind def\n",
327 /* external/internal prologue files machinery */
328 #if defined(GNUPLOT_PS_DIR)
329 # if defined(_Windows)
330 # include "win/winmain.h"
332 # define INCL_DOSPROCESS
333 # define INCL_DOSMODULEMGR
335 # endif /* _Windows || OS2 */
336 #else /* GNUPLOT_PS_DIR */
337 # include "PostScript/prologues.h"
338 #endif /* GNUPLOT_PS_DIR */
340 /* added to enhpost by Matt Heffron <heffron@falstaff.css.beckman.com> */
341 /* moved to post.trm by drd */
343 static struct PS_FontName {
345 struct PS_FontName *next;
346 } *PS_DocFonts = NULL;
348 static char PS_default_font[MAX_ID_LEN+1] = {'H','e','l','v','e','t','i','c','a',',','1','4','\0'};
350 /* given a font, look in store to see if it is there already
351 * if so, return NULL. If not, reencode it if allowed to, otherwise
352 * return an appropriate re-encode string
356 PS_RememberFont(char *fname, int can_reencode)
358 struct PS_FontName *fnp;
360 char *myfname = "Symbol";
362 if (strcmp(fname, "Symbol-Oblique") != 0)
365 for (fnp = PS_DocFonts; fnp ; fnp = fnp->next)
366 if (strcmp(fnp->name, myfname) == 0)
369 /* we did not find the name */
371 fnp = (struct PS_FontName *)gp_alloc(sizeof(struct PS_FontName),
372 "PostScript Font record");
373 fnp->name = gp_strdup(myfname);
374 fnp->next = PS_DocFonts;
378 case S_ENC_ISO8859_1:
379 recode = "reencodeISO def\n";
381 case S_ENC_ISO8859_2:
382 recode = "reencodeISO2 def\n";
384 case S_ENC_ISO8859_15:
385 recode = "reencodeISO15 def\n";
388 recode = "reencodeCP437 def\n";
391 recode = "reencodeCP850 def\n";
394 recode = "reencodeCP852 def\n";
397 recode = "reencodeKOI8R def\n";
400 recode = "reencodeCP1250 def\n";
403 recode = "reencodeKOI8U def\n";
410 if (can_reencode && recode) {
411 fprintf(gppsfile,"/%s %s", myfname, recode);
418 PS_escape_string(char *origstr, char *escapelist)
423 if (!origstr || !*origstr)
426 newstr = gp_alloc(2*strlen(origstr)+1,"PS_escape_string");
427 for (n=newstr; *origstr; *n++ = *origstr++) {
428 if (strchr(escapelist,*origstr))
436 static int PS_pen_x, PS_pen_y;
438 static int PS_linetype_last;
439 static double PS_linewidth_last; /* HBB NEW 20031219 */
440 static TBOOLEAN PS_relative_ok;
442 /* HBB 990914: PS_SOLID is already used by the WIN32 API headers.
443 * Renamed to PS_SOLIDE, therefore... */
445 PS_PORTRAIT, PS_LANDSCAPE,
446 PS_EPSF, PS_DEFAULT, PS_ENHANCED, PS_NOENHANCED,
447 PS_LATEX, EPSLATEX_STANDALONE, EPSLATEX_INPUT,
448 PS_MONOCHROME, PS_COLOR, PS_BLACKTEXT, PS_COLORTEXT,
449 PS_SOLIDE, PS_DASHED, PS_DASHLENGTH, PS_LINEWIDTH,
450 PS_SIMPLEX, PS_DUPLEX, PS_DEFAULTPLEX,
451 PS_ROUNDED, PS_NOROUNDED, PS_FONTFILE, PS_NOFONTFILES,
453 PS_LEVEL1, PS_LEVELDEFAULT, PS_FONT,
454 PSLATEX_ROTATE, PSLATEX_NOROTATE, PSLATEX_AUXFILE, PSLATEX_NOAUXFILE,
455 PSLATEX_OLDSTYLE, PSLATEX_NEWSTYLE, EPSLATEX_HEADER, EPSLATEX_NOHEADER,
460 static struct gen_table PS_opts[] =
462 { "d$efault", PS_DEFAULT },
463 { "p$ortrait", PS_PORTRAIT },
464 { "l$andscape", PS_LANDSCAPE },
465 { "ep$sf", PS_EPSF },
466 { "enh$anced", PS_ENHANCED },
467 { "noenh$anced", PS_NOENHANCED },
468 { "m$onochrome", PS_MONOCHROME },
469 { "c$olor", PS_COLOR },
470 { "c$olour", PS_COLOR },
471 { "b$lacktext", PS_BLACKTEXT },
472 { "colort$ext", PS_COLORTEXT },
473 { "colourt$ext", PS_COLORTEXT },
474 { "so$lid", PS_SOLIDE },
475 { "da$shed", PS_DASHED },
476 { "dashl$ength", PS_DASHLENGTH },
477 { "dl", PS_DASHLENGTH },
478 { "linew$idth", PS_LINEWIDTH },
479 { "lw", PS_LINEWIDTH },
481 { "si$mplex", PS_SIMPLEX },
482 { "du$plex", PS_DUPLEX },
483 { "defaultp$lex", PS_DEFAULTPLEX },
484 { "butt", PS_NOROUNDED },
485 { "rou$nded", PS_ROUNDED },
486 { "fontf$ile", PS_FONTFILE },
487 { "nofontf$iles", PS_NOFONTFILES },
488 { "palf$uncparam", PS_PALFUNCPARAM },
489 { "level1", PS_LEVEL1 },
490 { "leveldefault", PS_LEVELDEFAULT },
492 { "stand$alone", EPSLATEX_STANDALONE },
493 { "inp$ut", EPSLATEX_INPUT },
494 { "header", EPSLATEX_HEADER },
495 { "noheader", EPSLATEX_NOHEADER },
496 { "r$otate", PSLATEX_ROTATE },
497 { "n$orotate", PSLATEX_NOROTATE },
498 { "a$uxfile", PSLATEX_AUXFILE },
499 { "noa$uxfile", PSLATEX_NOAUXFILE },
500 { "old$style", PSLATEX_OLDSTYLE },
501 { "new$style", PSLATEX_NEWSTYLE },
511 char *ps_fontfile_char = NULL;
512 char tmp_term_options[MAX_LINE_LEN+1] = "";
514 TBOOLEAN set_orientation = FALSE, set_enhanced = FALSE, set_plex = FALSE;
515 TBOOLEAN set_level = FALSE, set_color = FALSE, set_dashed = FALSE;
516 TBOOLEAN set_dashlen = FALSE, set_linewidth = FALSE, set_round = FALSE;
517 TBOOLEAN set_palfunc = FALSE, set_colortext = FALSE;
518 TBOOLEAN set_standalone = FALSE, set_epslheader = FALSE;
519 TBOOLEAN set_pslrotate = FALSE, set_pslauxfile = FALSE;
520 TBOOLEAN set_psloldstyle = FALSE, set_font = FALSE, set_fontsize = FALSE;
522 /* Annoying hack to handle the case of 'set termoption' after */
523 /* we have already initialized the terminal. */
525 ps_explicit_size = FALSE;
527 if (strcmp(term->name, "pstex") == 0)
528 ps_params = &pstex_params;
529 else if (strcmp(term->name, "pslatex") == 0)
530 ps_params = &pslatex_params;
531 else if (strcmp(term->name, "epslatex") == 0) {
532 ps_params = &epslatex_params;
534 ps_params = &post_params;
536 if (ps_params->terminal == PSTERM_POSTSCRIPT) {
538 free(pslatex_auxname);
539 pslatex_auxname = NULL;
541 term->set_font = PS_set_font;
544 if (!END_OF_COMMAND) {
545 if (lookup_table(&PS_opts[0],c_token) == PS_DEFAULT) {
546 switch (ps_params->terminal) {
547 case PSTERM_POSTSCRIPT:
548 while (ps_params->first_fontfile != NULL)
549 delete_ps_fontfile((struct ps_fontfile_def *) NULL,
550 ps_params->first_fontfile);
551 *ps_params = post_params_default;
553 case PSTERM_EPSLATEX:
554 *ps_params = epslatex_params_default;
557 *ps_params = pslatex_params_default;
560 *ps_params = pstex_params_default;
563 term->flags &= ~TERM_ENHANCED_TEXT;
567 "extraneous argument in set terminal %s",term->name);
571 while (!END_OF_COMMAND) {
572 switch(lookup_table(&PS_opts[0],c_token)) {
574 if (set_orientation || ps_params->terminal != PSTERM_POSTSCRIPT)
576 "extraneous argument in set terminal %s",term->name);
577 set_orientation = TRUE;
578 ps_params->psformat = PSTERM_PORTRAIT;
582 if (set_orientation || ps_params->terminal != PSTERM_POSTSCRIPT)
584 "extraneous argument in set terminal %s",term->name);
585 set_orientation = TRUE;
586 ps_params->psformat = PSTERM_LANDSCAPE;
590 if (set_orientation || ps_params->terminal != PSTERM_POSTSCRIPT)
592 "extraneous argument in set terminal %s",term->name);
593 set_orientation = TRUE;
594 ps_params->psformat = PSTERM_EPS;
600 "extraneous argument in set terminal %s",term->name);
602 ps_params->level1 = TRUE;
605 case PS_LEVELDEFAULT:
608 "extraneous argument in set terminal %s",term->name);
610 ps_params->level1 = FALSE;
615 "extraneous argument in set terminal %s",term->name);
619 if (set_enhanced || ps_params->terminal != PSTERM_POSTSCRIPT)
621 "extraneous argument in set terminal %s",term->name);
623 term->put_text = ENHPS_put_text;
624 term->set_font = ENHPS_set_font;
625 term->flags |= TERM_ENHANCED_TEXT;
629 if (set_enhanced || ps_params->terminal != PSTERM_POSTSCRIPT)
631 "extraneous argument in set terminal %s",term->name);
633 term->put_text = PS_put_text;
634 term->set_font = PS_set_font;
635 term->flags &= ~TERM_ENHANCED_TEXT;
638 #ifdef PSLATEX_DRIVER
639 case EPSLATEX_STANDALONE:
640 if (set_standalone || ps_params->terminal != PSTERM_EPSLATEX)
642 "extraneous argument in set terminal %s",term->name);
643 set_standalone = TRUE;
644 ps_params->epslatex_standalone = TRUE;
648 if (set_standalone || ps_params->terminal != PSTERM_EPSLATEX)
650 "extraneous argument in set terminal %s",term->name);
651 set_standalone = TRUE;
652 ps_params->epslatex_standalone = FALSE;
656 case EPSLATEX_HEADER:
657 if (set_epslheader || ps_params->terminal != PSTERM_EPSLATEX)
659 "extraneous argument in set terminal %s",term->name);
660 set_epslheader = TRUE;
662 free(epslatex_header);
663 /* Protect against int_error() bail from try_to_get_string() */
664 epslatex_header = NULL;
665 epslatex_header = try_to_get_string();
666 if (!epslatex_header)
667 int_error(c_token,"String containing header information expected");
670 case EPSLATEX_NOHEADER:
671 if (set_epslheader || ps_params->terminal != PSTERM_EPSLATEX)
673 "extraneous argument in set terminal %s",term->name);
674 set_epslheader = TRUE;
675 free(epslatex_header);
676 epslatex_header = NULL;
681 if (set_pslrotate || ((ps_params->terminal != PSTERM_PSLATEX) &&
682 (ps_params->terminal != PSTERM_PSTEX)))
684 "extraneous argument in set terminal %s",term->name);
685 set_pslrotate = TRUE;
686 ps_params->rotate = TRUE;
689 case PSLATEX_NOROTATE:
690 if (set_pslrotate || ((ps_params->terminal != PSTERM_PSLATEX) &&
691 (ps_params->terminal != PSTERM_PSTEX)))
693 "extraneous argument in set terminal %s",term->name);
694 set_pslrotate = TRUE;
695 ps_params->rotate = FALSE;
698 case PSLATEX_AUXFILE:
699 if (set_pslauxfile ||
700 ((ps_params->terminal == PSTERM_POSTSCRIPT) ||
701 (ps_params->terminal == PSTERM_EPSLATEX)))
703 "extraneous argument in set terminal %s",term->name);
704 set_pslauxfile = TRUE;
705 ps_params->useauxfile = TRUE;
708 case PSLATEX_NOAUXFILE:
709 if (set_pslauxfile ||
710 ((ps_params->terminal == PSTERM_POSTSCRIPT) ||
711 (ps_params->terminal == PSTERM_EPSLATEX)))
713 "extraneous argument in set terminal %s",term->name);
714 set_pslauxfile = TRUE;
715 ps_params->useauxfile = FALSE;
718 case PSLATEX_OLDSTYLE:
719 if (set_psloldstyle || ps_params->terminal == PSTERM_POSTSCRIPT)
721 "extraneous argument in set terminal %s",term->name);
722 set_psloldstyle = TRUE;
723 ps_params->oldstyle = TRUE;
724 if (ps_params->terminal == PSTERM_EPSLATEX)
725 ps_params->rounded = TRUE;
728 case PSLATEX_NEWSTYLE:
729 if (set_psloldstyle || ps_params->terminal == PSTERM_POSTSCRIPT)
731 "extraneous argument in set terminal %s",term->name);
732 set_psloldstyle = TRUE;
733 ps_params->oldstyle = FALSE;
740 "extraneous argument in set terminal %s",term->name);
742 ps_params->color = FALSE;
748 "extraneous argument in set terminal %s",term->name);
750 ps_params->color = TRUE;
754 if (set_colortext || ((ps_params->terminal != PSTERM_POSTSCRIPT) &&
755 (ps_params->terminal != PSTERM_EPSLATEX)))
757 "extraneous argument in set terminal %s",term->name);
758 set_colortext = TRUE;
759 ps_params->blacktext = TRUE;
763 if (set_colortext || ((ps_params->terminal != PSTERM_POSTSCRIPT) &&
764 (ps_params->terminal != PSTERM_EPSLATEX)))
766 "extraneous argument in set terminal %s",term->name);
767 set_colortext = TRUE;
768 ps_params->blacktext = FALSE;
774 "extraneous argument in set terminal %s",term->name);
776 ps_params->solid = TRUE;
782 "extraneous argument in set terminal %s",term->name);
784 ps_params->solid = FALSE;
790 "extraneous argument in set terminal %s",term->name);
793 ps_params->dash_length = real(const_express(&a));
794 if (ps_params->dash_length <= 0.0)
795 ps_params->dash_length = 1.0;
800 "extraneous argument in set terminal %s",term->name);
801 set_linewidth = TRUE;
803 ps_params->linewidth_factor = real(const_express(&a));
804 if (ps_params->linewidth_factor <= 0.0)
805 ps_params->linewidth_factor = 1.0;
808 if (set_plex || ps_params->terminal != PSTERM_POSTSCRIPT)
810 "extraneous argument in set terminal %s",term->name);
812 ps_params->duplex_state = FALSE;
813 ps_params->duplex_option = TRUE;
817 if (set_plex || ps_params->terminal != PSTERM_POSTSCRIPT)
819 "extraneous argument in set terminal %s",term->name);
821 ps_params->duplex_state = TRUE;
822 ps_params->duplex_option = TRUE;
826 if (set_plex || ps_params->terminal != PSTERM_POSTSCRIPT)
828 "extraneous argument in set terminal %s",term->name);
830 ps_params->duplex_option = FALSE;
836 "extraneous argument in set terminal %s",term->name);
838 ps_params->rounded = TRUE;
844 "extraneous argument in set terminal %s",term->name);
846 ps_params->rounded = FALSE;
850 TBOOLEAN deleteentry = FALSE;
852 if (ps_params->terminal != PSTERM_POSTSCRIPT)
854 "extraneous argument in set terminal %s",term->name);
856 if (!isstring(c_token)) {
857 if (equals(c_token, "add"))
859 else if (almost_equals(c_token, "del$ete")) {
863 int_error(c_token, "Font filename expected");
865 if (isstring(c_token)) {
866 TBOOLEAN filename_doubled = FALSE;
867 struct ps_fontfile_def *curr_ps_fontfile =
868 ps_params->first_fontfile;
869 struct ps_fontfile_def *prev_ps_fontfile = NULL;
870 struct ps_fontfile_def *new_ps_fontfile =
871 gp_alloc(sizeof(struct ps_fontfile_def),
874 new_ps_fontfile->fontfile_name =
875 gp_alloc (token_len(c_token),
876 "new_ps_fontfile->fontfile_name");
877 quote_str(new_ps_fontfile->fontfile_name,
878 c_token, token_len(c_token));
879 gp_expand_tilde(&(new_ps_fontfile->fontfile_name));
882 if (*(new_ps_fontfile->fontfile_name) != '<') {
884 new_ps_fontfile->fontfile_fullname =
885 fontpath_fullname(new_ps_fontfile->fontfile_name);
886 if (!new_ps_fontfile->fontfile_fullname)
887 int_error(c_token, "Font file '%s' not found",
888 new_ps_fontfile->fontfile_name);
891 new_ps_fontfile->fontfile_fullname = NULL;
895 new_ps_fontfile->next = NULL;
903 if ((lf && lf->interactive) || interactive)
904 /* if (interactive) { */
905 PS_load_fontfile(new_ps_fontfile,FALSE);
908 if (ps_params->first_fontfile) {
909 while (curr_ps_fontfile) {
910 if (strcmp(curr_ps_fontfile->fontfile_name,
911 new_ps_fontfile->fontfile_name) == 0) {
912 filename_doubled = TRUE;
914 delete_ps_fontfile(prev_ps_fontfile,
916 curr_ps_fontfile = NULL;
920 prev_ps_fontfile = curr_ps_fontfile;
921 curr_ps_fontfile = curr_ps_fontfile->next;
923 if (!filename_doubled) {
925 prev_ps_fontfile->next = new_ps_fontfile;
927 int_warn(c_token,"Can't delete Font filename '%s'",
928 new_ps_fontfile->fontfile_name);
932 ps_params->first_fontfile = new_ps_fontfile;
934 int_warn(c_token, "Can't delete Font filename '%s'",
935 new_ps_fontfile->fontfile_name);
939 int_error(c_token, "Font filename expected");
943 if (ps_params->terminal != PSTERM_POSTSCRIPT)
945 "extraneous argument in set terminal %s",term->name);
946 while (ps_params->first_fontfile != NULL)
947 delete_ps_fontfile((struct ps_fontfile_def *) NULL,
948 ps_params->first_fontfile);
951 case PS_PALFUNCPARAM:
954 "extraneous argument in set terminal %s",term->name);
957 ps_params->palfunc_samples = (int)real(const_express(&a));
958 if (ps_params->palfunc_samples < 2)
959 ps_params->palfunc_samples = 2;
960 if (!END_OF_COMMAND && equals(c_token, ",")) {
962 ps_params->palfunc_deviation = fabs(real(const_express(&a)));
963 if (ps_params->palfunc_deviation >= 1)
964 int_error(c_token-1,"allowed deviation must be < 1");
970 float xmax_t, ymax_t;
973 ps_explicit_size = TRUE;
974 ps_explicit_units = parse_term_size(&xmax_t, &ymax_t, INCHES);
976 /* PostScript *always* works in pts, not locally defined dpi */
977 term->xmax = xmax_t * PS_SC * 72./gp_resolution;
978 term->ymax = ymax_t * PS_SC * 72./gp_resolution;
979 eps_explicit_x = 2 * term->xmax;
980 eps_explicit_y = 2 * term->ymax;
986 /* Fall through to attempt to read font name */
989 if ((s = try_to_get_string())) {
992 "extraneous argument in set terminal %s",
995 if ((ps_params->terminal == PSTERM_POSTSCRIPT) ||
996 (ps_params->terminal == PSTERM_EPSLATEX)) {
997 char *comma = strrchr(s,',');
998 if (comma && (1 == sscanf(comma+1,"%f",&ps_params->fontsize))) {
1003 strncpy(ps_params->font, s, sizeof(ps_params->font));
1006 int_error(c_token-1,
1007 "terminal %s does not allow specification %s",
1008 term->name, "of font name");
1012 "extraneous argument in set terminal %s",
1014 set_fontsize = TRUE;
1015 /* We have font size specified */
1016 ps_params->fontsize = real(const_express(&a));
1022 switch (ps_params->terminal) {
1023 case PSTERM_POSTSCRIPT:
1024 ps_fontsize = ps_params->fontsize;
1026 case PSTERM_EPSLATEX:
1027 ps_fontsize = 2 * ps_params->fontsize;
1029 case PSTERM_PSLATEX:
1031 if (ps_params->fontsize > 0)
1032 ps_fontsize = 2 * ps_params->fontsize;
1034 ps_fontsize = 20; /* default: 10pt */
1037 term->v_char = (unsigned int)(ps_fontsize*PS_SC);
1038 if (ps_params->oldstyle)
1039 term->h_char = (unsigned int)(ps_fontsize*PS_SC*5/10);
1041 term->h_char = (unsigned int)(ps_fontsize*PS_SC*6/10);
1042 sprintf(PS_default_font,"%s,%g",ps_params->font,ps_fontsize);
1044 if (ps_params->terminal == PSTERM_POSTSCRIPT) {
1045 if (ps_params->first_fontfile) {
1046 struct ps_fontfile_def *curr_ps_fontfile =
1047 ps_params->first_fontfile;
1048 unsigned int totlength = 0;
1051 while (curr_ps_fontfile) {
1052 totlength += strlen(curr_ps_fontfile->fontfile_name) +
1053 strlen(" fontfile \"\"");
1054 curr_ps_fontfile = curr_ps_fontfile->next;
1056 curr_ps_fontfile = ps_params->first_fontfile;
1057 ps_fontfile_char = gp_alloc (totlength+1,"ps_fontfile_char");
1058 running = ps_fontfile_char;
1059 while (curr_ps_fontfile) {
1060 sprintf(running," fontfile \"%s\"",
1061 curr_ps_fontfile->fontfile_name);
1062 running += strlen(running);
1063 curr_ps_fontfile = curr_ps_fontfile->next;
1068 /* HBB 19990823: fixed the options string. It violated the 'save
1069 * loadable output' rule */
1070 if (ps_params->terminal == PSTERM_POSTSCRIPT)
1071 sprintf(term_options,"%s %s %s \\\n",
1072 ps_params->psformat==PSTERM_EPS ? "eps" :
1073 (ps_params->psformat==PSTERM_PORTRAIT ?
1074 "portrait" : "landscape"),
1075 term->put_text == ENHPS_put_text ? "enhanced" : "noenhanced",
1076 ps_params->duplex_option ? (ps_params->duplex_state ?
1077 "duplex" : "simplex")
1079 else if (ps_params->terminal != PSTERM_EPSLATEX)
1080 sprintf(term_options, "%s%s",
1081 ps_params->rotate ? "rotate" : "norotate",
1082 ps_params->useauxfile ? " auxfile" : "");
1084 term_options[0] = '\0';
1086 sprintf(tmp_term_options," %s %s %s \\\n\
1087 %s dashlength %.1f linewidth %.1f %s \\\n",
1088 ps_params->level1 ? "level1" : "leveldefault",
1089 ps_params->color ? "color" : "monochrome",
1090 ps_params->blacktext ? "blacktext" : "colortext",
1091 ps_params->solid ? "solid" : "dashed",
1092 ps_params->dash_length,
1093 ps_params->linewidth_factor,
1094 ps_params->rounded ? "rounded" : "butt");
1095 strcat(term_options,tmp_term_options);
1097 sprintf(tmp_term_options," palfuncparam %d,%g \\\n ",
1098 ps_params->palfunc_samples, ps_params->palfunc_deviation);
1099 strcat(term_options,tmp_term_options);
1101 #ifdef PSLATEX_DRIVER
1102 if ((ps_params->terminal == PSTERM_PSTEX) ||
1103 (ps_params->terminal == PSTERM_PSLATEX)) {
1104 sprintf(tmp_term_options, "%s %s ",
1105 ps_params->rotate ? "rotate" : "norotate",
1106 ps_params->useauxfile ? "auxfile" : "noauxfile");
1107 strcat(term_options,tmp_term_options);
1110 if (ps_params->terminal == PSTERM_EPSLATEX) {
1111 sprintf(tmp_term_options, "%s ",
1112 ps_params->epslatex_standalone ? "standalone" : "input");
1113 if (epslatex_header)
1114 sprintf(tmp_term_options, "header \"%s\" ", epslatex_header);
1116 sprintf(tmp_term_options, "noheader ");
1117 strcat(term_options,tmp_term_options);
1121 if (ps_explicit_size) {
1122 if (ps_explicit_units == CM)
1123 sprintf(tmp_term_options,"size %.2fcm, %.2fcm ",
1124 2.54*(float)term->xmax/(72.*PS_SC), 2.54*(float)term->ymax/(72.*PS_SC));
1126 sprintf(tmp_term_options,"size %.2fin, %.2fin ",
1127 (float)term->xmax/(72.*PS_SC), (float)term->ymax/(72.*PS_SC));
1128 strcat(term_options,tmp_term_options);
1131 if (ps_params->terminal == PSTERM_POSTSCRIPT)
1132 sprintf(tmp_term_options,"\"%s\" %g%s ",
1133 ps_params->font,ps_params->fontsize,
1134 ps_fontfile_char ? ps_fontfile_char : "");
1135 else if (ps_params->terminal == PSTERM_EPSLATEX)
1136 sprintf(tmp_term_options,"\"%s\" %g ",
1137 ps_params->font,ps_params->fontsize);
1138 else if (ps_params->fontsize)
1139 sprintf(tmp_term_options,"%g ",ps_params->fontsize);
1141 tmp_term_options[0]='\0';
1142 if (ps_fontfile_char)
1143 free(ps_fontfile_char);
1145 strcat(term_options,tmp_term_options);
1149 /* store settings passed to common_init() for use in PS_graphics()
1150 * ps_params->psformat, etc are reserved for storing the term options
1152 static TBOOLEAN ps_common_uses_fonts;
1153 static unsigned int ps_common_xoff, ps_common_yoff;
1157 PS_load_fontfile(struct ps_fontfile_def *current_ps_fontfile, TBOOLEAN doload)
1159 if (current_ps_fontfile) {
1160 unsigned int linesread = 0;
1165 char *fontname = NULL;
1167 char *envcmd = NULL;
1168 TBOOLEAN ispipe = FALSE;
1175 fprintf(gppsfile,"%%%%BeginProcSet: %s\n",
1176 current_ps_fontfile->fontfile_name);
1178 /* get filename extension if no pipe (if pipe *ext=='\0') */
1180 if (*(current_ps_fontfile->fontfile_name) != '<') {
1181 /* Filename is given */
1183 if (strlen(current_ps_fontfile->fontfile_name) > 3)
1184 strcpy(ext, current_ps_fontfile->fontfile_name +
1185 strlen(current_ps_fontfile->fontfile_name) - 3);
1187 strcpy(ext, current_ps_fontfile->fontfile_name);
1189 /* make extension lowercase for comparison */
1192 if (!current_ps_fontfile->fontfile_fullname)
1193 int_error(NO_CARET, "Font file '%s' not found",
1194 current_ps_fontfile->fontfile_name);
1198 if (strlen(ext) == 0) {
1202 strcpy(cmd,current_ps_fontfile->fontfile_name + 1);
1203 ffont = popen(cmd, "r");
1205 int_error(NO_CARET, "Could not execute pipe '%s'",
1206 current_ps_fontfile->fontfile_name + 1);
1209 else if (strcmp(ext,"ttf") == 0) {
1213 envcmd = getenv("GNUPLOT_TTFTOPFA");
1215 sprintf(cmd,envcmd,current_ps_fontfile->fontfile_fullname);
1217 sprintf(cmd,"ttf2pt1 -a -e -W 0 %s -",
1218 current_ps_fontfile->fontfile_fullname);
1219 if (strlen(cmd) == 0)
1221 "No command for automatic font conversion ttf->pfa defined");
1223 ffont = popen(cmd,"r");
1225 int_error(NO_CARET,"Could not execute command '%s'", cmd);
1229 "Automatic font conversion ttf->pfa not supported");
1231 } else if (strcmp(ext,"pfb") == 0) {
1235 envcmd = getenv("GNUPLOT_PFBTOPFA");
1237 sprintf(cmd,envcmd,current_ps_fontfile->fontfile_fullname);
1239 sprintf(cmd,"pfbtops %s",
1240 current_ps_fontfile->fontfile_fullname);
1241 if (strlen(cmd) == 0)
1243 "No command for automatic font conversion pfb->pfa defined");
1245 ffont = popen(cmd,"r");
1247 int_error(NO_CARET,"Could not execute command '%s'", cmd);
1251 "Automatic font conversion pfb->pfa not supported");
1255 if (strcmp(ext,"pfa") != 0)
1257 "Font file '%s' has unknown extension. Assume it is a pfa file",
1258 current_ps_fontfile->fontfile_name);
1259 ffont = fopen(current_ps_fontfile->fontfile_fullname, "r");
1261 int_error(NO_CARET, "Font file '%s' not found",
1262 current_ps_fontfile->fontfile_name);
1265 while (fgets(line,255,ffont)) {
1266 /* test file format */
1267 if ((linesread == 0) &&
1268 (strstr(line,"%!PS-AdobeFont") != line) &&
1269 (strstr(line,"%!FontType1") != line)) {
1273 "Command '%s' seems not to generate PFA data",
1278 "Font file '%s' seems not to be a PFA file",
1279 current_ps_fontfile->fontfile_name);
1282 if (strstr(line,"/FontName") == line) {
1283 char *fnende = NULL;
1284 fontname = gp_alloc(strlen(line)-9,"load_fontfiles");
1285 strcpy(fontname,strstr(line+1,"/")+1);
1286 fnende = strstr(fontname," ");
1288 /* Print font name */
1290 if (current_ps_fontfile->fontfile_fullname)
1292 "Font file '%s' contains the font '%s'. Location:\n %s\n",
1293 current_ps_fontfile->fontfile_name,
1295 current_ps_fontfile->fontfile_fullname);
1298 "Pipe '%s' contains the font '%s'.\n",
1299 current_ps_fontfile->fontfile_name,
1302 /* Stop reading font file in order to save time */
1303 /* This does not work for pipes because they give the */
1304 /* error message 'broken pipe' */
1312 fputs(line, gppsfile);
1319 if ((exitcode = pclose(ffont)) != 0)
1321 "Command '%s' generated error, exitcode is %d",
1328 if (linesread == 0) {
1332 "Command '%s' generates empty output",
1336 int_error(NO_CARET, "Font file '%s' is empty",
1337 current_ps_fontfile->fontfile_name);
1340 fputs("%%EndProcSet\n", gppsfile);
1342 /* Computer Modern Symbol font with corrected baseline if the
1343 * font CMEX10 is embedded */
1344 if (doload && fontname && (strcmp(fontname,"CMEX10") == 0)) {
1345 fputs("%%BeginProcSet: CMEX10-Baseline\n", gppsfile);
1346 fputs("/CMEX10-Baseline /CMEX10 findfont [1 0 0 1 0 1] makefont\n",
1348 fputs("dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall\n", gppsfile);
1349 fputs("currentdict end definefont pop\n", gppsfile);
1350 fputs("%%EndProcSet\n",gppsfile);
1362 PS_load_fontfiles(TBOOLEAN doload)
1364 struct ps_fontfile_def *current_ps_fontfile=ps_params->first_fontfile;
1366 while (current_ps_fontfile) {
1367 PS_load_fontfile(current_ps_fontfile,doload);
1368 current_ps_fontfile = current_ps_fontfile->next;
1375 TBOOLEAN uses_fonts, /* FALSE for (e)ps(la)tex */
1376 unsigned int xoff, unsigned int yoff, /* how much to translate by */
1377 unsigned int bb_xmin, unsigned int bb_ymin,
1378 unsigned int bb_xmax, unsigned int bb_ymax, /* bounding box */
1379 const char **dict) /* extra entries for the dictionary */
1381 static const char GPFAR psi1[] = "\
1382 %%%%Creator: gnuplot %s patchlevel %s\n\
1383 %%%%CreationDate: %s\n\
1384 %%%%DocumentFonts: %s\n";
1386 static const char GPFAR psi2[] = "\
1389 /gnudict 256 dict def\ngnudict begin\n\
1391 %% The following 6 true/false flags may be edited by hand if required\n\
1392 %% The unit line width may also be changed\n\
1395 /Blacktext %s def\n\
1397 /Dashlength %g def\n\
1398 /Landscape %s def\n\
1401 /TransparentPatterns false def\n\
1402 /gnulinewidth %.3f def\n\
1403 /userlinewidth gnulinewidth def\n\
1407 %.1f Dashlength mul mul\n\
1408 Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if\n\
1411 %.1f Dashlength mul mul\n\
1412 Rounded { currentlinewidth 0.75 mul add } if\n\
1419 static const char GPFAR psi3[] = "\
1421 /SDict 10 dict def\n\
1422 systemdict /pdfmark known not {\n\
1423 userdict /pdfmark systemdict /cleartomark get put\n\
1427 /Subject (gnuplot plot)\n\
1428 /Creator (gnuplot %s patchlevel %s)\n\
1430 %% /Producer (gnuplot)\n\
1432 /CreationDate (%s)\n\
1438 struct termentry *t = term;
1443 ps_common_uses_fonts = uses_fonts;
1444 ps_common_xoff = xoff;
1445 ps_common_yoff = yoff;
1450 timedate=asctime(localtime(&now));
1451 timedate[strlen(timedate)-1]='\0';
1453 #ifdef PSLATEX_DRIVER
1454 /* Set files for (e)ps(la)tex terminals */
1455 switch (ps_params->terminal) {
1456 case PSTERM_EPSLATEX:
1457 EPSLATEX_common_init();
1459 case PSTERM_PSLATEX:
1461 PSTEX_common_init();
1463 default:; /* do nothing, just avoid a compiler warning */
1467 if (ps_params->psformat == PSTERM_EPS)
1468 fputs("%!PS-Adobe-2.0 EPSF-2.0\n", gppsfile);
1470 fputs("%!PS-Adobe-2.0\n", gppsfile);
1473 fprintf(gppsfile, "%%%%Title: %s\n", outstr); /* JFi */
1474 fprintf(gppsfile, psi1, gnuplot_version, gnuplot_patchlevel,
1475 timedate, uses_fonts ? "(atend)" : "");
1477 fprintf(gppsfile,"%%%%BoundingBox: %d %d %d %d\n",
1478 xoff + bb_xmin, yoff + bb_ymin, xoff + bb_xmax, yoff + bb_ymax);
1480 if ((ps_params->terminal == PSTERM_POSTSCRIPT) &&
1481 (ps_params->psformat != PSTERM_EPS))
1482 fprintf(gppsfile,"%%%%Orientation: %s\n",
1483 ps_params->psformat == PSTERM_LANDSCAPE ?
1484 "Landscape" : "Portrait");
1486 if (ps_params->psformat != PSTERM_EPS)
1487 fputs("%%Pages: (atend)\n", gppsfile);
1488 fprintf(gppsfile, psi2,
1489 ps_params->color ? "true" : "false",
1490 ps_params->blacktext ? "true" : "false",
1491 ps_params->solid ? "true" : "false",
1492 ps_params->dash_length, /* dash length */
1493 ps_params->psformat == PSTERM_LANDSCAPE ? "true" : "false",
1494 ps_params->level1 ? "true" : "false",
1495 ps_params->rounded ? "true" : "false",
1496 PS_LW*ps_params->linewidth_factor, /* line width */
1497 (int)(t->v_char)/(-3), /* shift for vertical centring */
1498 PS_SC*1.0, /* dash length */
1499 PS_SC*1.0, /* dash length */
1500 PS_HTIC/2.0, /* half point width */
1501 PS_VTIC/2.0); /* half point height */
1503 /* HH: print pdf information interpreted by ghostscript/acrobat */
1505 char *username=getusername();
1506 char *username2=PS_escape_string(username,"()\\");
1507 char *outstr2=PS_escape_string(outstr,"()\\");
1508 fprintf(gppsfile, psi3,
1510 gnuplot_version, gnuplot_patchlevel,
1511 username2?username2:"",
1521 /* insert font encoding vector */
1524 case S_ENC_ISO8859_1: PS_dump_prologue_file("8859-1.ps"); break;
1525 case S_ENC_ISO8859_2: PS_dump_prologue_file("8859-2.ps"); break;
1526 case S_ENC_ISO8859_15: PS_dump_prologue_file("8859-15.ps"); break;
1527 case S_ENC_CP437: PS_dump_prologue_file("cp437.ps"); break;
1528 case S_ENC_CP850: PS_dump_prologue_file("cp850.ps"); break;
1529 case S_ENC_CP852: PS_dump_prologue_file("cp852.ps"); break;
1530 case S_ENC_CP1250: PS_dump_prologue_file("cp1250.ps"); break;
1531 case S_ENC_KOI8_R: PS_dump_prologue_file("koi8r.ps"); break;
1532 case S_ENC_KOI8_U: PS_dump_prologue_file("koi8u.ps"); break;
1538 /* Dump the body of the prologue */
1539 PS_dump_prologue_file("prologue.ps");
1541 /* Redefine old epslatex linetypes if requested */
1542 if ((ps_params->terminal == PSTERM_EPSLATEX) && ps_params->oldstyle) {
1543 for (i = 0; OldEPSL_linetypes[i] != NULL; i++)
1544 fprintf(gppsfile,"%s",OldEPSL_linetypes[i]);
1547 if (ps_params->duplex_option)
1548 fprintf(gppsfile, "statusdict begin %s setduplexmode end\n",
1549 ps_params->duplex_state ? "true" : "false");
1553 fputs(*(dict++), gppsfile);
1556 PS_load_fontfiles(TRUE);
1557 PS_RememberFont(ps_params->font, 1);
1560 fputs("end\n%%EndProlog\n", gppsfile);
1563 /* the init fn for the postscript driver */
1567 unsigned int xmin_t = 0, ymin_t = 0, xmax_t = 0, ymax_t = 0;
1569 switch (ps_params->psformat) {
1571 if (ps_explicit_size) {
1572 term->xmax = eps_explicit_x;
1573 term->ymax = eps_explicit_y;
1575 term->xmax = PS_XMAX;
1576 if (ps_params->oldstyle)
1577 term->ymax = PS_YMAX_OLDSTYLE;
1579 term->ymax = PS_YMAX;
1581 xmin_t = term->xmax * xoffset / (2*PS_SC);
1582 xmax_t = term->xmax * (xsize + xoffset) / (2*PS_SC);
1583 ymin_t = term->ymax * yoffset / (2*PS_SC);
1584 ymax_t = term->ymax * (ysize + yoffset) / (2*PS_SC);
1586 case PSTERM_PORTRAIT:
1587 if (!ps_explicit_size) {
1588 term->xmax = PS_YMAX;
1589 term->ymax = PS_XMAX;
1591 xmin_t = term->xmax * xoffset / PS_SC;
1592 xmax_t = term->xmax * (xsize + xoffset) / PS_SC;
1593 ymin_t = term->ymax * yoffset / PS_SC;
1594 ymax_t = term->ymax * (ysize + yoffset) / PS_SC;
1596 case PSTERM_LANDSCAPE:
1597 if (!ps_explicit_size) {
1598 term->xmax = PS_XMAX;
1599 term->ymax = PS_YMAX;
1601 ymin_t = term->xmax * xoffset / PS_SC;
1602 ymax_t = term->xmax * (xsize+xoffset) / PS_SC;
1603 xmin_t = term->ymax * (1-ysize-yoffset) / PS_SC;
1604 xmax_t = term->ymax * (1-yoffset) / PS_SC;
1607 int_error(NO_CARET, "invalid postscript format used");
1610 /* for enhanced postscript, copy ps_params->font to ps_enh_font
1611 * does no harm for non-enhanced
1613 strcpy(ps_enh_font, ps_params->font);
1614 ps_enh_fontsize = ps_fontsize;
1616 switch (ps_params->terminal) {
1617 case PSTERM_POSTSCRIPT:
1618 gppsfile = gpoutfile;
1621 #ifdef PSLATEX_DRIVER
1622 PSTEX_reopen_output();
1624 case PSTERM_EPSLATEX:
1625 EPSLATEX_reopen_output();
1630 PS_common_init(ps_params->terminal == PSTERM_POSTSCRIPT,
1631 ps_params->xoff, ps_params->yoff,
1632 xmin_t, ymin_t, xmax_t, ymax_t,
1633 (term->put_text == ENHPS_put_text) ? ENHPS_header : NULL);
1635 /* Keep track of whether we have written the enhanced text dictionary yet */
1636 ENHPS_initialized = (term->put_text == ENHPS_put_text) ? 2 : 1;
1643 static char GPFAR psg1[] = "0 setgray\nnewpath\n";
1644 struct termentry *t = term;
1646 if (ps_params->psformat != PSTERM_EPS)
1647 fprintf(gppsfile,"%%%%Page: %d %d\n",ps_page,ps_page);
1649 /* If we are about to use enhanced text mode for the first time in a plot that */
1650 /* was initialized previously without it, we need to write out the macros now */
1651 if (term->put_text == ENHPS_put_text && ENHPS_initialized == 1) {
1652 const char **dict = ENHPS_header;
1654 fputs(*(dict++), gppsfile);
1655 fprintf(stderr,"Writing out PostScript macros for enhanced text mode\n");
1656 ENHPS_initialized = 2;
1660 gnudict begin\ngsave\n\
1663 ps_common_xoff, ps_common_yoff,
1664 (ps_params->psformat == PSTERM_EPS ? 0.5 : 1.0)/PS_SC,
1665 (ps_params->psformat == PSTERM_EPS ? 0.5 : 1.0)/PS_SC);
1666 if (ps_params->psformat == PSTERM_LANDSCAPE)
1667 fprintf(gppsfile,"90 rotate\n0 %d translate\n", -(int)(term->ymax));
1668 fprintf(gppsfile, psg1);
1669 if (ps_common_uses_fonts)
1670 fprintf(gppsfile, "(%s) findfont %d scalefont setfont\n",
1671 ps_params->font, (t->v_char));
1673 PS_relative_ok = FALSE;
1674 PS_pen_x = PS_pen_y = -4000;
1676 PS_linewidth_last = PS_linetype_last = LT_UNDEFINED;
1684 fputs("stroke\ngrestore\nend\nshowpage\n", gppsfile);
1685 /* fprintf(stderr,"taken %d times\n",PS_taken); */
1686 /* informational: tells how many times it was "cheaper"
1687 * to do a relative moveto or lineto rather than an
1695 fputs("%%Trailer\n", gppsfile);
1697 /* I think the following commands should be executed
1698 `if (ps_common_uses_fonts)`. So I changed the next line.
1699 Please see "PS_RememberFont", too. */ /* JFi */
1701 /* if (!ps_common_uses_fonts) { */ /* JFi */
1702 if (ps_common_uses_fonts) {
1703 fputs("%%DocumentFonts: ", gppsfile);
1704 while (PS_DocFonts) {
1705 struct PS_FontName *fnp;
1706 fnp = PS_DocFonts->next;
1707 fprintf(gppsfile, "%s%s", PS_DocFonts->name, fnp ? " " : "\n");
1708 free(PS_DocFonts->name);
1713 if (ps_params->psformat != PSTERM_EPS)
1714 fprintf(gppsfile,"%%%%Pages: %d\n",ps_page);
1718 PS_linetype(int linetype)
1720 if ((ps_params->terminal == PSTERM_EPSLATEX) && ps_params->oldstyle)
1721 linetype = (linetype % 4) + 3;
1723 linetype = (linetype % 9) + 3;
1724 if (linetype < 0) /* LT_NODRAW, LT_BACKGROUND, LT_UNDEFINED */
1727 if (PS_linetype_last == linetype) return;
1729 PS_relative_ok = FALSE;
1732 PS_linetype_last = linetype;
1733 fprintf(gppsfile, "LT%c\n", "wba012345678"[linetype]);
1739 PS_linewidth (double linewidth)
1741 /* HBB NEW 20031219: don't do anything if nothing changed */
1742 if (ps_path_count != 0 && PS_linewidth_last == linewidth)
1744 PS_linewidth_last = linewidth;
1745 PS_linetype_last = -1; /* disable cache for next linetype change */
1748 fprintf(gppsfile, "%.3f UL\n", linewidth);
1751 Documentation of the 'change linewidth' strategy of the postscript terminal:
1753 1. define a new postscript variable with a default value:
1754 /userlinewidth gnulinewidth def
1756 2. define a new postscript command to change the contents of that variable:
1757 /UL { gnulinewidth mul /userlinewidth exch def } def
1758 usage: multiplication_factor UL
1760 3. modify the already known postscript command /PL for the plot lines:
1761 /PL { stroke userlinewidth setlinewidth } def
1763 4. issue the new command before every change of the plot linestyle:
1768 Linetype 0 is drawn four times as thick as defined by the contents
1769 of the postscript variable 'gnulinewidth'.
1775 PS_pointsize (double ptsize)
1777 fprintf(gppsfile, "%.3f UP\n", ptsize);
1780 * Documentation of the 'change pointsize' strategy of the postscript
1783 * 1. define two new postscript variables to hold the overall pointsize:
1786 * 2. define a new postscript command to use the contents of these variables:
1787 * /UP { cf. definition above } def
1788 * usage: multiplication_factor UP
1790 * [3.] [doesn't exist, skip to next number]
1792 * 4. issue the new command whereever you change the symbols (and linetype):
1795 * 4.0 UL % optionally change linewidth, too
1798 * Next symbols will be drawn 2.5 times as big as defined by the
1799 * GNUPLOT `set pointsize` command (= overall pointsize).
1805 PS_move(unsigned int x, unsigned int y)
1807 /* Make this semi-dynamic and independent of architecture */
1808 char abso[5+2*INT_STR_LEN], rel[5+2*INT_STR_LEN];
1809 int dx = x - PS_pen_x;
1810 int dy = y - PS_pen_y;
1812 /* can't cancel all null moves--need a move after stroke'ing */
1813 if (dx==0 && dy==0 && PS_relative_ok)
1816 sprintf(abso, "%d %d M\n", x, y);
1817 sprintf(rel, "%d %d R\n", dx, dy);
1820 fprintf(gppsfile, "%d %d N\n", x, y);
1823 if (strlen(rel) < strlen(abso) && PS_relative_ok) {
1824 fputs(rel, gppsfile);
1827 fputs(abso, gppsfile);
1828 PS_relative_ok = TRUE;
1836 PS_vector(unsigned int x, unsigned int y)
1838 char abso[5+2*INT_STR_LEN], rel[5+2*INT_STR_LEN];
1839 int dx = x - PS_pen_x;
1840 int dy = y - PS_pen_y;
1845 sprintf(abso, "%d %d L\n", x, y);
1846 sprintf(rel, "%d %d V\n", dx, dy);
1848 /* The following PS_move() is executed only when the limit of ps_path_count
1849 * has been reached below: then PS_FLUSH_PATH has been called which has not
1850 * moved to currentpoint after the stroke. */
1851 if (!PS_relative_ok)
1852 PS_move(PS_pen_x, PS_pen_y);
1854 if (strlen(rel) < strlen(abso)) {
1855 fputs(rel, gppsfile);
1856 PS_taken++; /* only used for debug info */
1859 fputs(abso, gppsfile);
1860 ps_path_count = 1; /* If we set it to zero, it may never get flushed */
1862 /* Ghostscript has a "pile-up of rounding errors" bug: a sequence of many
1863 * rmove's or rlineto's does not yield the same line as move's or lineto's.
1864 * Therefore, we periodically force an update of the absolute position.
1865 * There was a case when 400 rlineto's were too much, so let's go a little
1866 * bit higher than the default function sampling rate in gnuplot.
1867 * This runs into a second ghostscript bug, that mixing relative and absolute
1868 * lineto with no intervening 'stroke' is ridiculously slow to render.
1869 * So we stroke the partial line, update the position in absolute terms,
1870 * then continue. This whole section can go away if ghostscript/gv is fixed.
1872 #define MAX_REL_PATHLEN 105
1873 if (ps_path_count >= MAX_REL_PATHLEN) {
1874 fprintf(gppsfile, "stroke %d %d M\n", x, y);
1878 PS_relative_ok = TRUE;
1885 PS_put_text(unsigned int x, unsigned int y, const char *str)
1889 if (!str && !strlen(str))
1893 fprintf(gppsfile,"currentpoint gsave translate %d rotate 0 0 M\n",
1898 if ((ch=='(') || (ch==')') || (ch=='\\'))
1899 putc('\\', gppsfile);
1904 switch(ps_justify) {
1906 fputs(") Lshow\n", gppsfile);
1909 fputs(") Cshow\n", gppsfile);
1912 fputs(") Rshow\n", gppsfile);
1916 fputs("grestore\n", gppsfile);
1918 PS_relative_ok = FALSE;
1923 PS_text_angle(int ang)
1931 PS_justify_text(enum JUSTIFY mode)
1939 PS_set_font(const char *font)
1946 if (!font || !(*font))
1947 font = PS_default_font;
1948 sep = strcspn(font,",");
1949 name = gp_strdup(font);
1951 for (i=0; i<sep; i++)
1952 if (name[i] == ' ') name[i] = '-';
1954 if (font[sep] == ',')
1955 sscanf (&(font[sep+1]),"%f",&size);
1957 /* If TeX is doing the font handling, we don't need to */
1958 /* write anything into the postscript stream */
1959 if (ps_params->terminal == PSTERM_POSTSCRIPT) {
1960 PS_RememberFont(name,1);
1961 fprintf(gppsfile, "/%s findfont %g scalefont setfont\n",
1966 term->v_char = (unsigned int)(size*PS_SC);
1967 term->h_char = (unsigned int)(size*PS_SC*6/10);
1972 /* postscript point routines */
1976 PS_point(unsigned int x, unsigned int y, int number)
1978 static const char GPFAR * GPFAR pointFNS[] = {
1979 "Pnt", "Pls", "Crs", "Star",
1980 "Box", "BoxF", "Circle", "CircleF",
1981 "TriU", "TriUF", "TriD", "TriDF",
1982 "Dia", "DiaF", "Pent", "PentF",
1983 "C0", "C1", "C2", "C3",
1984 "C4", "C5", "C6", "C7",
1985 "C8", "C9", "C10", "C11",
1986 "C12", "C13", "C14", "C15",
1987 "S0", "S1", "S2", "S3",
1988 "S4", "S5", "S6", "S7",
1989 "S8", "S9", "S10", "S11",
1990 "S12", "S13", "S14", "S15",
1991 "D0", "D1", "D2", "D3",
1992 "D4", "D5", "D6", "D7",
1993 "D8", "D9", "D10", "D11",
1994 "D12", "D13", "D14", "D15",
1995 "BoxE", "CircE", "TriUE", "TriDE",
1996 "DiaE", "PentE", "BoxW", "CircW",
1997 "TriUW","TriDW", "DiaW", "PentW"
1999 static const char GPFAR * GPFAR pointFNS_OldEPSL[] = {
2000 "Pnt", "Dia", "Circle", "Pls",
2001 "Crs", "Box", "DiaF", "CircleF",
2004 if ((ps_params->terminal == PSTERM_EPSLATEX) && ps_params->oldstyle) {
2006 number = -1; /* negative types are all 'dot' */
2008 number %= sizeof(pointFNS_OldEPSL)/sizeof(pointFNS_OldEPSL[0]) -1;
2009 fprintf(gppsfile, "%d %d %s\n", x, y, pointFNS_OldEPSL[number+1]);
2012 number = -1; /* negative types are all 'dot' */
2014 number %= sizeof(pointFNS)/sizeof(pointFNS[0]) -1;
2015 fprintf(gppsfile, "%d %d %s\n", x, y, pointFNS[number+1]);
2018 PS_relative_ok = FALSE;
2020 PS_linewidth_last = PS_linetype_last = -1; /* force next linetype change */
2026 unsigned int x1, unsigned int y1,
2027 unsigned int width, unsigned int height)
2034 switch(style & 0xf) {
2037 /* style == 1 --> fill with intensity according to filldensity */
2038 filldens = (style >> 4) / 100.0;
2043 fprintf(gppsfile, "%.3f %d %d %d %d BoxColFill\n",
2044 filldens, x1,y1, width,height);
2048 /* style == 2 --> fill with pattern according to fillpattern */
2049 /* the upper 3 nibbles of 'style' contain pattern number */
2050 pattern = (style >> 4) % 8;
2055 fprintf(gppsfile, "%d %d %d %d BoxFill\n",
2056 x1, y1, width, height);
2059 fprintf(gppsfile, "%d %d %d %d %d %d 1 PatternFill\n",
2060 x1, y1, width, height, 80, -45);
2063 fprintf(gppsfile, "%d %d %d %d %d %d 2 PatternFill\n",
2064 x1, y1, width, height, 40, 45);
2067 fprintf(gppsfile, "1 %d %d %d %d BoxColFill\n",
2068 x1, y1, width, height);
2071 fprintf(gppsfile, "%d %d %d %d %d %d 0 PatternFill\n",
2072 x1, y1, width, height, 80, 45);
2075 fprintf(gppsfile, "%d %d %d %d %d %d 0 PatternFill\n",
2076 x1, y1, width, height, 80, -45);
2079 fprintf(gppsfile, "%d %d %d %d %d %d 0 PatternFill\n",
2080 x1, y1, width, height, 40, 30);
2083 fprintf(gppsfile, "%d %d %d %d %d %d 0 PatternFill\n",
2084 x1, y1, width, height, 40, -30);
2087 break; /* end of pattern filling part */
2089 default: /* style == 0 or unknown --> fill with background color */
2090 fprintf(gppsfile, "%d %d %d %d BoxFill\n", x1, y1, width, height);
2093 PS_relative_ok = FALSE;
2094 PS_linewidth_last = PS_linetype_last = -1;
2100 static TBOOLEAN ENHps_opened_string; /* try to cut out empty ()'s */
2103 * close a postscript string if it has been opened
2108 if (ENHps_opened_string) {
2109 fputs(")]\n", gppsfile);
2110 ENHps_opened_string = FALSE;
2115 * open a postscript string
2120 double fontsize, double base,
2121 TBOOLEAN widthflag, TBOOLEAN showflag,
2124 /* overprint 3 means save current position; 4 means restore saved position */
2125 /* EAM FIXME - I couldn't figure out how to use less than the 7 parameters */
2126 /* that the normal case macro wants. Somebody more familiar with PostScript*/
2127 /* than I am please clean it up! */
2128 if (overprint == 3) {
2129 fputs("XYsave\n", gppsfile);
2131 } else if (overprint == 4) {
2132 fputs("XYrestore\n", gppsfile);
2136 if (!ENHps_opened_string) {
2137 fprintf(gppsfile, "[(%s) %.1f %.1f %s %s %d (",
2138 fontname, fontsize, base,
2139 widthflag ? "true" : "false",
2140 showflag ? "true" : "false",
2142 ENHps_opened_string = TRUE;
2147 * write one or more characters from inside enhanced text processing
2155 /* a set-font routine for enhanced post : simply copies
2156 * the font into a global, or restores the globals
2157 * to the ps_params->font default
2161 ENHPS_set_font(const char *font)
2163 if (ignore_enhanced_text)
2164 return PS_set_font(font);
2167 size_t sep = strcspn(font,",");
2169 strncpy(ps_enh_font,font,sep);
2170 ps_enh_font[sep] = NUL;
2171 PS_RememberFont(ps_enh_font, 1);
2173 ps_enh_fontsize = ps_fontsize;
2174 sscanf (font+sep+1,"%f",&ps_enh_fontsize);
2176 /* return to defaults */
2177 strcpy(ps_enh_font, ps_params->font);
2178 ps_enh_fontsize = ps_fontsize;
2180 term->v_char = (unsigned int)(ps_enh_fontsize*PS_SC);
2181 term->h_char = (unsigned int)(ps_enh_fontsize*PS_SC*6/10);
2187 ENHPS_put_text(unsigned int x, unsigned int y, const char *str)
2189 if (ignore_enhanced_text) {
2190 PS_put_text(x,y,str);
2194 /* flush any pending graphics (all the XShow routines do this...) */
2201 /* if there are no magic characters, we should just be able
2202 * punt the string to PS_put_text(), which will give shorter
2203 * ps output [eg tics and stuff rarely need extra processing],
2204 * but we need to make sure that the current font is the
2205 * default one before we can do that. {ie I tried it and it
2206 * used the wrong font !}
2207 * if (!strpbrk(str, "{}^_@&~"))
2209 * - do something to ensure default font is selected
2210 * PS_put_text(x,y,str);
2218 fprintf(gppsfile,"currentpoint gsave translate %d rotate 0 0 moveto\n",
2221 fputs("[ ", gppsfile);
2223 /* set up the global variables needed by enhanced_recursion() */
2224 enhanced_max_height = -1000;
2225 enhanced_min_height = 1000;
2226 enhanced_fontscale = PS_SC;
2227 strncpy(enhanced_escape_format,"\\%o",sizeof(enhanced_escape_format));
2229 ENHps_opened_string = FALSE;
2231 /* Set the recursion going. We say to keep going until a
2232 * closing brace, but we don't really expect to find one.
2233 * If the return value is not the nul-terminator of the
2234 * string, that can only mean that we did find an unmatched
2235 * closing brace in the string. We increment past it (else
2236 * we get stuck in an infinite loop) and try again.
2238 * ps_enh_font and ps_enh_fontsize are either set to the
2239 * the defaults set on option line, or have been set to
2240 * "font,size". That is to say, ps_params->font is used only
2241 * at startup and by ENHPS_set_font
2243 while (*(str = enhanced_recursion((char *)str, TRUE, ps_enh_font,
2244 (double)(ps_enh_fontsize*PS_SC), 0.0, TRUE, TRUE, 0))) {
2247 /* I think we can only get here if *str == '}' */
2251 break; /* end of string */
2253 /* else carry on and process the rest of the string */
2256 enhanced_max_height += enhanced_min_height;
2258 fprintf(gppsfile, "] %.1f ", -enhanced_max_height/3);
2260 switch(ps_justify) {
2262 fputs("MLshow\n", gppsfile);
2265 fputs("MCshow\n", gppsfile);
2268 fputs("MRshow\n", gppsfile);
2273 fputs("grestore\n", gppsfile);
2275 PS_relative_ok = FALSE;
2279 make_palette_formulae()
2281 #define R sm_palette.formulaR
2282 #define G sm_palette.formulaG
2283 #define B sm_palette.formulaB
2284 /* print the definition of R,G,B formulae */
2285 fputs("/InterpolatedColor false def\n", gppsfile);
2286 if (sm_palette.ps_allcF == 0) { /* print only those 3 used formulae */
2287 fprintf(gppsfile, "/cF%i {%s} bind def\t%% %s\n",
2288 abs(R), ps_math_color_formulae[ 2*abs(R) ],
2289 ps_math_color_formulae[ 2*abs(R)+1 ]);
2290 if (abs(G) != abs(R))
2291 fprintf(gppsfile, "/cF%i {%s} bind def\t%% %s\n",
2292 abs(G), ps_math_color_formulae[ 2*abs(G) ],
2293 ps_math_color_formulae[ 2*abs(G)+1 ]);
2294 if ((abs(B) != abs(R)) && (abs(B) != abs(G)))
2295 fprintf(gppsfile, "/cF%i {%s} bind def\t%% %s\n",
2296 abs(B), ps_math_color_formulae[ 2*abs(B) ],
2297 ps_math_color_formulae[ 2*abs(B)+1 ]);
2299 else { /* all color formulae are written into the output PostScript file */
2301 while (*(ps_math_color_formulae[2*i])) {
2302 fprintf(gppsfile, "/cF%i {%s} bind def\t%% %s\n",
2303 i, ps_math_color_formulae[ 2*i ],
2304 ps_math_color_formulae[ 2*i+1 ]);
2316 make_interpolation_code()
2318 static const char *header[] = {
2319 "/grayindex {/gidx 0 def\n",
2320 " {GrayA gidx get grayv ge {exit} if /gidx gidx 1 add def} loop} def\n",
2321 "/dgdx {grayv GrayA gidx get sub GrayA gidx 1 sub get\n",
2322 " GrayA gidx get sub div} def \n",
2323 "/redvalue {RedA gidx get RedA gidx 1 sub get\n",
2324 " RedA gidx get sub dgdxval mul add} def\n",
2325 "/greenvalue {GreenA gidx get GreenA gidx 1 sub get\n",
2326 " GreenA gidx get sub dgdxval mul add} def\n",
2327 "/bluevalue {BlueA gidx get BlueA gidx 1 sub get\n",
2328 " BlueA gidx get sub dgdxval mul add} def\n",
2330 " grayindex grayv GrayA gidx get sub abs 1e-5 le\n",
2331 " {RedA gidx get GreenA gidx get BlueA gidx get}\n",
2332 " {/dgdxval dgdx def redvalue greenvalue bluevalue} ifelse} def\n",
2337 for(i=0; header[i]!=NULL; ++i) {
2338 fputs(header[i], gppsfile);
2344 make_color_model_code()
2346 /* Postscript version of the color space transformations in getcolor.c */
2347 static const char *header[] = {
2349 " exch dup 0.0 eq {pop exch pop dup dup} % achromatic gray\n",
2350 " { /HSVs exch def /HSVv exch def 6.0 mul dup floor dup 3 1 roll sub\n ",
2351 " /HSVf exch def /HSVi exch cvi def /HSVp HSVv 1.0 HSVs sub mul def\n",
2352 " /HSVq HSVv 1.0 HSVs HSVf mul sub mul def \n",
2353 " /HSVt HSVv 1.0 HSVs 1.0 HSVf sub mul sub mul def\n",
2354 " /HSVi HSVi 6 mod def 0 HSVi eq {HSVv HSVt HSVp}\n",
2355 " {1 HSVi eq {HSVq HSVv HSVp}{2 HSVi eq {HSVp HSVv HSVt}\n",
2356 " {3 HSVi eq {HSVp HSVq HSVv}{4 HSVi eq {HSVt HSVp HSVv}\n",
2357 " {HSVv HSVp HSVq} ifelse} ifelse} ifelse} ifelse} ifelse\n",
2360 " dup 0 lt {0 exch pop}{dup 1 gt {1 exch pop} if} ifelse} def\n",
2362 " 3 copy -1.702 mul exch -1.105 mul add add Constrain 4 1 roll\n",
2363 " 3 copy -0.647 mul exch -0.272 mul add add Constrain 5 1 roll\n",
2364 " 0.621 mul exch -0.956 mul add add Constrain 3 1 roll } def\n",
2366 " 1 exch sub exch 1 exch sub 3 2 roll 1 exch sub 3 1 roll exch } def\n",
2368 " 3 copy -0.9017 mul exch -0.1187 mul add exch 0.0585 mul exch add\n",
2369 " Constrain 4 1 roll 3 copy -0.0279 mul exch 1.999 mul add exch\n",
2370 " -0.9844 mul add Constrain 5 1 roll -0.2891 mul exch -0.5338 mul add\n",
2371 " exch 1.91 mul exch add Constrain 3 1 roll} def\n",
2372 "/SelectSpace {ColorSpace (HSV) eq {HSV2RGB}{ColorSpace (XYZ) eq {\n",
2373 " XYZ2RGB}{ColorSpace (CMY) eq {CMY2RGB}{ColorSpace (YIQ) eq {YIQ2RGB}\n",
2374 " if} ifelse} ifelse} ifelse} def\n",
2379 for(i=0; header[i]!=NULL; ++i) {
2380 fputs(header[i], gppsfile);
2386 *save_space(double gray)
2388 /* printing the gray with 4 digits and without the leading 0
2389 * ... saving space */
2392 gray = 0.0001*(int)(gray*10000+0.5); /* round it to 4 digits */
2393 sprintf(s, "%.4g", gray);
2394 if (s[0] == '0' && s[1] == '.')
2395 return &(s[1]); /* strip leading 0 */
2402 write_color_space(t_sm_palette *palette)
2404 /* write something like
2405 * /ColorSpace (HSV) def
2406 * depending on the selected cmodel in palette */
2407 fputs("/ColorSpace ", gppsfile);
2408 switch(palette->cmodel) {
2410 fputs("(RGB)", gppsfile);
2413 fputs("(HSV)", gppsfile);
2416 fputs("(CMY)", gppsfile);
2419 fputs("(YIQ)", gppsfile);
2422 fputs("(XYZ)", gppsfile);
2425 fprintf(stderr,"%s:%d ooops: Unkown color model '%c'. Will be RGB\n",
2426 __FILE__, __LINE__, (char)(palette->cmodel));
2427 fputs("(RGB)", gppsfile);
2430 fputs(" def\n", gppsfile);
2435 write_component_array(const char *text, gradient_struct *grad,
2436 int cnt, int offset)
2438 /* write someting like
2439 * /RedA [ 0 .1 .2 .3 .35 .3 .2 .1 0 0 0 ] def
2440 * nicely formated to gppsfile
2445 fprintf(gppsfile, "/%s [", text);
2446 len = strlen(text) + 4;
2447 for(i=0; i<cnt; ++i) {
2448 char *ref = (char*)(&(grad[i]));
2451 val = save_space(*((double*) (ref)));
2452 len += strlen(val) + 1;
2454 fputs("\n ",gppsfile);
2455 len = strlen(val) + 3;
2457 fprintf(gppsfile, "%s ", val);
2459 fputs("] def\n", gppsfile);
2464 write_gradient_definition(gradient_struct *gradient, int cnt)
2466 /* some strange pointer acrobatic here, but it seems to work... */
2467 char *ref = (char*) (gradient);
2468 int p = (char*) (&(gradient[0].pos)) - ref;
2469 int r = (char*) (&(gradient[0].col.r)) - ref;
2470 int g = (char*) (&(gradient[0].col.g)) - ref;
2471 int b = (char*) (&(gradient[0].col.b)) - ref;
2473 write_component_array("GrayA", gradient, cnt, p);
2474 write_component_array("RedA", gradient, cnt, r);
2475 write_component_array("GreenA", gradient, cnt, g);
2476 write_component_array("BlueA", gradient, cnt, b);
2481 PS_make_header(t_sm_palette *palette)
2483 /* write header for smooth colors */
2484 fputs("gsave % colour palette begin\n", gppsfile);
2485 fprintf(gppsfile, "/maxcolors %i def\n", sm_palette.use_maxcolors);
2486 make_color_model_code();
2488 switch(sm_palette.colorMode) {
2489 case SMPAL_COLOR_MODE_GRAY:
2490 fputs("/InterpolatedColor false def\n", gppsfile);
2491 break; /* nothing to do for gray */
2492 case SMPAL_COLOR_MODE_RGB:
2493 make_palette_formulae();
2495 case SMPAL_COLOR_MODE_FUNCTIONS: {
2497 gradient_struct *gradient;
2499 fputs("/InterpolatedColor true def\n", gppsfile);
2500 make_interpolation_code();
2501 gradient = approximate_palette(palette, ps_params->palfunc_samples,
2502 ps_params->palfunc_deviation, &cnt);
2503 write_gradient_definition(gradient, cnt);
2507 case SMPAL_COLOR_MODE_GRADIENT:
2508 fputs("/InterpolatedColor true def\n", gppsfile);
2509 make_interpolation_code();
2510 write_gradient_definition(palette->gradient, palette->gradient_num);
2513 fprintf(stderr, "%s:%d ooops: Unknown color mode '%c'\n",
2514 __FILE__, __LINE__, (char)(sm_palette.colorMode));
2516 fputs("/pm3dround {maxcolors 0 gt {dup 1 ge\n", gppsfile);
2517 fputs("\t{pop 1} {maxcolors mul floor maxcolors 1 sub div} ifelse} if} def\n",
2519 fprintf(gppsfile, "/pm3dGamma 1.0 %g div def\n", sm_palette.gamma);
2520 write_color_space(palette);
2522 /* Now print something like
2523 /g {dup cF7 exch dup cF5 exch cF15 setrgbcolor} bind def
2525 #define R sm_palette.formulaR
2526 #define G sm_palette.formulaG
2527 #define B sm_palette.formulaB
2529 /* 18.1.2009 Since the beginning of pm3d, the Color definition switched
2530 between gray and colour map. This led to ambiguities for custom colour
2531 palettes if they contain grays only. Thus let postscript choose always
2532 always colour palette for interpolated colours ('set palette defined',
2533 'set palette file') and colour/gray according to Color otherwise
2534 ('set palette gray', 'set palette rgb').
2537 fprintf(gppsfile, "Color %s and { %% COLOUR vs. GRAY map\n",
2538 (sm_palette.colorMode!=SMPAL_COLOR_MODE_GRAY) ? "true":"false");
2540 if (sm_palette.colorMode == SMPAL_COLOR_MODE_GRAY)
2541 fputs("false { % COLOUR vs. GRAY map\n", gppsfile);
2543 fputs("Color InterpolatedColor or { % COLOUR vs. GRAY map\n", gppsfile);
2546 fputs(" InterpolatedColor { %% Interpolation vs. RGB-Formula\n",
2548 fputs(" /g {stroke pm3dround /grayv exch def interpolate\n", gppsfile);
2549 fputs(" SelectSpace setrgbcolor} bind def\n", gppsfile);
2550 fputs(" }{\n", gppsfile);
2551 fputs(" /g {stroke pm3dround dup ", gppsfile);
2553 fputs("1 exch sub ", gppsfile); /* negate */
2554 fprintf(gppsfile,"cF%i Constrain exch dup ", abs(R));
2556 fputs("1 exch sub ", gppsfile); /* negate */
2557 fprintf(gppsfile,"cF%i Constrain exch ", abs(G));
2558 if (R<0 || G<0 || B<0)
2559 fputs("\n\t", gppsfile);
2561 fputs("1 exch sub ", gppsfile); /* negate */
2562 fprintf(gppsfile,"cF%i Constrain ", abs(B));
2563 fputs("\n SelectSpace setrgbcolor} bind def\n", gppsfile);
2564 fputs(" } ifelse\n", gppsfile);
2565 fputs("}{\n", gppsfile);
2566 fputs(" /g {stroke pm3dround pm3dGamma exp setgray} bind def\n", gppsfile);
2567 fputs("} ifelse\n", gppsfile);
2574 TERM_PUBLIC int PS_make_palette (t_sm_palette *palette)
2576 if (palette == NULL) {
2577 return 0; /* postscript can do continuous colors */
2580 PS_make_header(palette);
2585 TERM_PUBLIC void PS_set_color (t_colorspec *colorspec)
2589 PS_linetype_last = -1; /* Force next call to linetype to be honored */
2591 if (colorspec->type == TC_LT) {
2592 int linetype = colorspec->lt;
2594 if ((ps_params->terminal == PSTERM_EPSLATEX) && ps_params->oldstyle)
2595 linetype = (linetype % 4) + 3;
2597 linetype = (linetype % 9) + 3;
2598 if (linetype < 0) /* LT_NODRAW, LT_BACKGROUND, LT_UNDEFINED */
2600 fprintf(gppsfile, "LC%1c setrgbcolor\n","wba012345678"[linetype]);
2601 } else if (colorspec->type == TC_RGB) {
2602 double r = (double)((colorspec->lt >> 16 ) & 255) / 255.;
2603 double g = (double)((colorspec->lt >> 8 ) & 255) / 255.;
2604 double b = (double)(colorspec->lt & 255) / 255.;
2606 fprintf(gppsfile, "%3.2f %3.2f %3.2f C ",r,g,b);
2609 if (colorspec->type != TC_FRAC)
2612 /* map [0;1] to gray/colors */
2613 gray = colorspec->value;
2615 fputs("0 g ", gppsfile);
2618 fputs("1 g ", gppsfile);
2620 fprintf(gppsfile, "%s g ", save_space(gray));
2622 PS_relative_ok = FALSE; /* "M" required because "g" forces stroke (??) */
2626 TERM_PUBLIC void PS_filled_polygon (int points, gpiPoint *corners)
2629 float filldens = 1.0;
2631 int style = corners->style;
2633 /* Stroke the previous graphic element if required. */
2637 if (points == 4 && style == FS_OPAQUE) {
2638 /* Special case for pm3d surface quadrangles
2639 * <x0> <y0> ... <x4> <y4> h
2641 fprintf(gppsfile, "%i %i N", corners[0].x, corners[0].y);
2642 fprintf(gppsfile, " %i %i %i %i %i %i h\n",
2643 corners[3].x-corners[2].x, corners[3].y-corners[2].y,
2644 corners[2].x-corners[1].x, corners[2].y-corners[1].y,
2645 corners[1].x-corners[0].x, corners[1].y-corners[0].y);
2647 /* General case for solid or pattern-filled polygons
2648 * gsave <x0> <y0> N <x1> <y1> ... <xn> <yn> density PolyFill
2650 fprintf(gppsfile, "gsave ");
2651 fprintf(gppsfile, "%i %i N", corners[0].x, corners[0].y);
2652 for (i = 1; i < points; i++) {
2653 /* The rationale for mixing V and L is given in PS_vector */
2654 if (i % MAX_REL_PATHLEN)
2655 fprintf(gppsfile, " %i %i V", corners[i].x-corners[i-1].x,
2656 corners[i].y-corners[i-1].y);
2658 fprintf(gppsfile, " %i %i L", corners[i].x, corners[i].y);
2661 switch(style & 0xf) {
2664 filldens = (style >> 4) / 100.0;
2668 fprintf(gppsfile, " 1 PolyFill\n");
2670 fprintf(gppsfile, " %.2f PolyFill\n", filldens);
2674 pattern = (style >> 4) % 8;
2677 fprintf(gppsfile, " %.1f PolyFill\n", filldens);
2679 fprintf(gppsfile," Pattern%d fill grestore\n", pattern);
2684 fputs(" 1 PolyFill\n", gppsfile);
2690 PS_relative_ok = FALSE;
2693 #undef MAX_REL_PATHLEN
2695 TERM_PUBLIC void PS_previous_palette()
2697 /* Needed to stroke the previous graphic element. */
2699 fputs("grestore % colour palette end\n", gppsfile);
2704 * The reason for having a PostScript-specific wrapper for do_arrow
2705 * is that post.trm draws dotted lines for monochrome output, and
2706 * dotted arrowheads are ugly. So in that case we call do_arrow twice,
2707 * the second time to retrace the head with the line style forced to solid.
2709 TERM_PUBLIC void PS_arrow (
2710 unsigned int sx, unsigned int sy,
2711 unsigned int ex, unsigned int ey,
2714 do_arrow( sx, sy, ex, ey, head );
2715 if (!ps_params->solid && head != 0) {
2717 fputs("gsave [] 0 setdash\n", gppsfile);
2718 do_arrow( sx, sy, ex, ey, -head );
2720 fputs("grestore\n", gppsfile);
2725 delete_ps_fontfile(struct ps_fontfile_def *prev, struct ps_fontfile_def *this)
2727 if (this != NULL) { /* there really is something to delete */
2728 FPRINTF((stderr, "Remove font/kerning file `%s'\n",
2729 this->fontfile_name));
2730 if (prev != NULL) /* there is a previous ps_fontfile */
2731 prev->next = this->next;
2732 else /* this = ps_params->first_fontfile */
2733 /* so change ps_params->first_fontfile */
2734 ps_params->first_fontfile = this->next;
2735 free(this->fontfile_name);
2736 free(this->fontfile_fullname);
2746 PS_encode85(unsigned long tuple4, unsigned char *tuple5)
2748 /* The compiler should know to carry out the powers of
2749 * 85 computation at compilation time.
2751 tuple5[0] = tuple4/(85*85*85*85);
2752 tuple4 -= ((unsigned long)tuple5[0])*(85*85*85*85);
2753 tuple5[1] = tuple4/(85*85*85);
2754 tuple4 -= ((unsigned long)tuple5[1])*(85*85*85);
2755 tuple5[2] = tuple4/(85*85);
2756 tuple4 -= ((unsigned long)tuple5[2])*(85*85);
2757 tuple5[3] = tuple4/(85);
2758 tuple4 -= ((unsigned long)tuple5[3])*(85);
2767 /* Returns pointer to encoded image, allocated on heap that the
2768 * caller must free. Can error to command line so make sure all
2769 * heap memory is recorded in static pointers when calling this
2773 PS_encode_image(unsigned M, unsigned N, coordval *image, t_imagecolor color_mode,
2774 int bits_per_component, int max_colors, double cscale,
2775 enum PS_ENCODING encoding, int *return_num_bytes)
2777 unsigned coord_remaining;
2778 coordval *coord_ptr;
2779 unsigned short i_line;
2781 unsigned end_of_line;
2782 unsigned short bits_remaining, bits_start;
2784 unsigned long tuple4;
2785 unsigned char tuple5[5];
2786 int max_encoded_bytes;
2787 char *encoded_image, *encoded_image_ptr;
2788 unsigned long total_bits;
2790 #define ASCII_PER_LINE 78
2792 /* 18.1.2009 RGB images ("plot ... with rgbimage") are drawn always in color,
2793 * i.e. for both "set term post color" and "set term post mono".
2795 total_bits = bits_per_component*M*N*((color_mode == IC_RGB /* && ps_params->color */) ? 3 : 1);
2797 /* At the end of each image line, data is aligned to the nearest 8 bits,
2798 * which means potentially adding 7 bits per line.
2803 /* Compute max number of ascii characters encoding will require.
2805 if (encoding == PS_ASCII_HEX) {
2806 /* Straight hex encoding */
2807 max_encoded_bytes = (total_bits/4 + 1);
2808 max_encoded_bytes += max_encoded_bytes / ASCII_PER_LINE; /* newline characters */
2810 /* ASCII85 encoding */
2811 max_encoded_bytes = (total_bits/32 + 1)*5 + 2; /* 5 tuples and additional ~> */
2812 max_encoded_bytes += max_encoded_bytes / ASCII_PER_LINE; /* newline characters */
2815 /* Reserve enough memory. */
2816 if (!(encoded_image = gp_alloc(max_encoded_bytes, "encoded image")))
2817 int_error(NO_CARET, "GNUPLOT (post.trm): Error allocating memory.\n");
2818 encoded_image_ptr = encoded_image;
2821 i_line = ASCII_PER_LINE;
2823 coord_remaining = M*N;
2824 if (color_mode == IC_RGB /* && ps_params->color */) {
2826 coord_remaining *= 3;
2828 bits_remaining = 32;
2832 while (coord_remaining) {
2833 unsigned short us_tmp;
2834 if (0 /* color_mode == IC_RGB && !ps_params->color */) {
2836 c_tmp = *coord_ptr++;
2837 c_tmp += *coord_ptr++;
2838 c_tmp += *coord_ptr++;
2839 us_tmp = (unsigned short) (c_tmp*(max_colors-1)/3.0 + 0.5);
2841 us_tmp = (unsigned short) ((*coord_ptr++) * max_colors);
2843 if (us_tmp > (max_colors-1)) us_tmp = max_colors-1;
2845 /* Rescale to accommodate a mismatch between max_colors and # of bits */
2848 if (bits_remaining < bits_per_component) {
2849 tuple4 <<= bits_remaining;
2850 bits_start = bits_per_component - bits_remaining;
2852 tuple4 |= (us_tmp >> bits_start);
2854 tuple4 <<= bits_per_component;
2856 bits_remaining -= bits_per_component;
2859 /* If this is last pixel in line, pad to nearest 8 bits. */
2861 if (i_element == end_of_line) {
2862 register unsigned short bit_align = (bits_remaining & 0x7);
2863 tuple4 <<= bit_align;
2864 bits_remaining -= bit_align;
2868 /* Check if another 4-tuple is complete. */
2869 if (!bits_remaining) {
2870 if (ps_params->level1) {
2871 /* A straight hex encoding for every 4 bits. */
2872 unsigned char tuple8[8];
2874 for (i=7; i >= 0; i--) {
2875 tuple8[i] = tuple4 & 0xf;
2878 for (i=0; i < 8; i++) {
2879 sprintf(encoded_image_ptr++, "%1x", tuple8[i]);
2881 if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
2884 /* Convert to ASCII85 representation. */
2887 PS_encode85(tuple4, tuple5);
2889 for (i=0; i < 5; i++) {
2890 sprintf(encoded_image_ptr++, "%c", tuple5[i]+'!');
2892 if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
2895 *encoded_image_ptr++ = 'z';
2897 if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
2901 /* Now pick up any bits that may have not made it into the 4-tuple. */
2902 if (bits_start) {tuple4 = us_tmp - ((us_tmp>>bits_start)<<bits_start);}
2903 bits_remaining = 32 - bits_start;
2912 if (bits_remaining < 32) {
2914 int n = 4 - bits_remaining/8;
2915 if (ps_params->level1) {
2916 /* A straight hex encoding for every 4 bits. */
2917 unsigned char tuple8[8];
2918 for (i=2*n-1; i >= 0; i--) {
2919 tuple8[i] = tuple4 & 0xf;
2922 for (i=0; i < 2*n; i++) {
2923 sprintf(encoded_image_ptr++, "%1x", tuple8[i]);
2925 if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
2928 /* Convert to ASCII85 representation.
2930 * The case where not all bytes in a tuple are used is slightly different.
2931 * There is no use of 'z' as a special character and the remaining bytes
2932 * need to be filled. Then use only a portion of the final 5-tuple.
2934 tuple4 <<= bits_remaining;
2935 PS_encode85(tuple4, tuple5);
2936 /* Write first n+1 bytes. */
2937 for (i=0; i <= n; i++) {
2938 sprintf(encoded_image_ptr++, "%c", tuple5[i]+'!');
2940 if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
2945 if (!ps_params->level1) {
2946 sprintf(encoded_image_ptr, "~>");
2947 encoded_image_ptr += 2;
2950 *return_num_bytes = (encoded_image_ptr - encoded_image);
2951 assert(*return_num_bytes <= max_encoded_bytes);
2952 return encoded_image;
2957 print_five_operand_image(unsigned M, unsigned N, gpiPoint *corner, t_imagecolor color_mode, unsigned short bits_per_component)
2959 char *space = ps_params->level1 ? "" : " ";
2961 fprintf(gppsfile, "%sgsave\n", space);
2962 if (sm_palette.colorMode == SMPAL_COLOR_MODE_GRAY)
2963 fprintf(gppsfile, "%s{pm3dGamma exp} settransfer\n", space);
2964 fprintf(gppsfile, "%s%d %d translate\n", space, corner[0].x, corner[0].y);
2965 fprintf(gppsfile, "%s%d %d scale\n", space, (corner[1].x - corner[0].x), (corner[1].y - corner[0].y));
2966 fprintf(gppsfile, "%s%d %d %d\n", space, M, N, bits_per_component);
2967 fprintf(gppsfile, "%s[ %d 0 0 %d 0 0 ]\n", space, M, N);
2968 if (ps_params->level1) {
2969 fprintf(gppsfile, "/imagebuf %d string def\n",
2970 (M*N*bits_per_component*((color_mode == IC_RGB /* && ps_params->color */) ? 3 : 1) + 7)/8);
2971 fputs("{currentfile imagebuf readhexstring pop}\n", gppsfile);
2973 fprintf(gppsfile, " currentfile /ASCII85Decode filter\n");
2974 if (color_mode == IC_RGB /* && ps_params->color */) {
2975 fprintf(gppsfile, "%sfalse 3\n"
2976 "%scolorimage\n", space, space);
2978 fprintf(gppsfile, "%simage\n", space);
2983 PS_image (unsigned M, unsigned N, coordval *image, gpiPoint *corner, t_imagecolor color_mode)
2985 char *encoded_image;
2986 int num_encoded_bytes;
2987 unsigned short bits_per_component = 0;
2988 int max_colors, i_tmp;
2989 TBOOLEAN five_operand_image;
2992 #define DEFAULT_BITS_PER_COMPONENT 8
2993 #define DEFAULT_COMPONENT_MAX (1<<DEFAULT_BITS_PER_COMPONENT)
2995 if (sm_palette.use_maxcolors > 0)
2996 max_colors = sm_palette.use_maxcolors;
2998 max_colors = DEFAULT_COMPONENT_MAX;
3001 while (i_tmp < max_colors) {
3002 bits_per_component++;
3006 if (bits_per_component < 1 || bits_per_component > 12) {
3007 fprintf(stderr, "GNUPLOT (post.trm): Component bits (%d) out of range.\n", bits_per_component);
3011 if (bits_per_component > 8)
3012 bits_per_component = 12;
3013 else if (bits_per_component > 4)
3014 bits_per_component = 8;
3015 else if (bits_per_component > 2)
3016 bits_per_component = 4;
3018 /* Color and gray scale images do not need a palette and can use
3019 * the 5 operand form of the image routine.
3022 /* 18.1.2009 It was decided to use the custom palette (i.e. colours) also
3023 for the monochrome postscript output.
3025 if ((color_mode == IC_RGB) || (sm_palette.colorMode == SMPAL_COLOR_MODE_GRAY) || !ps_params->color)
3027 if ((color_mode == IC_RGB) || (sm_palette.colorMode == SMPAL_COLOR_MODE_RGB && !ps_params->color) || (sm_palette.colorMode == SMPAL_COLOR_MODE_GRAY))
3029 five_operand_image = TRUE;
3031 five_operand_image = FALSE;
3033 /* The five operand image doesn't have a palette and the values are
3034 * such that 0 maps to 0.0 and 2^bits_per_component - 1 maps to 1.0
3035 * in the PostScript driver. Without any other knowledge, we scale
3036 * things so that our max colors corresponds to 1.0.
3038 if (five_operand_image)
3039 cscale = (float)((1 << bits_per_component)-1) / (float)(max_colors-1);
3043 encoded_image = PS_encode_image(M, N, image, color_mode,
3044 bits_per_component, max_colors, cscale,
3045 (ps_params->level1 ? PS_ASCII_HEX : PS_ASCII85), &num_encoded_bytes);
3047 fputs("%%%%BeginImage\n", gppsfile);
3049 /* Clip image to requested bounding box */
3050 fprintf(gppsfile,"gsave %d %d N %d %d L %d %d L %d %d L Z clip\n",
3051 corner[2].x, corner[2].y, corner[2].x, corner[3].y, corner[3].x, corner[3].y, corner[3].x, corner[2].y);
3053 /* Color and gray scale images do not need a palette and can use
3054 * the 5 operand form of the image routine. For other types of
3055 * palettes, the 1 operand form of the image routine must be used
3056 * and an indexed palette needs to be constructed.
3058 if (five_operand_image) {
3060 if (ps_params->level1) {
3061 print_five_operand_image(M, N, corner, color_mode, bits_per_component);
3063 fputs("InterpretLevel1 {\n"
3064 " %% Construct a box instead of image\n"
3065 " LTb\n", gppsfile);
3066 fprintf(gppsfile, " %d %d M\n", corner[0].x, corner[0].y);
3067 fprintf(gppsfile, " %d 0 V\n", (corner[1].x - corner[0].x));
3068 fprintf(gppsfile, " 0 %d V\n", (corner[1].y - corner[0].y));
3069 fprintf(gppsfile, " %d 0 V\n", -(corner[1].x - corner[0].x));
3070 fprintf(gppsfile, " %d %d L\n", corner[0].x, corner[0].y);
3071 fputs(" 40 -110 R\n"
3072 " (PS level 2 image) Lshow\n"
3073 " % Read data but ignore it\n", gppsfile);
3074 fprintf(gppsfile, " /imagebuf %d string def\n", num_encoded_bytes);
3075 fputs(" currentfile imagebuf readstring\n"
3077 print_five_operand_image(M, N, corner, color_mode, bits_per_component);
3078 fputs("} ifelse\n", gppsfile);
3085 unsigned short i_tuple;
3086 double fact = 1.0 / (double)(max_colors-1);
3087 if (!ps_params->level1) {
3088 fputs("InterpretLevel1 {\n"
3089 " %% Construct a box instead of image\n"
3090 " LTb\n", gppsfile);
3091 fprintf(gppsfile, " %d %d M\n", corner[0].x, corner[0].y);
3092 fprintf(gppsfile, " %d 0 V\n", (corner[1].x - corner[0].x));
3093 fprintf(gppsfile, " 0 %d V\n", (corner[1].y - corner[0].y));
3094 fprintf(gppsfile, " %d 0 V\n", -(corner[1].x - corner[0].x));
3095 fprintf(gppsfile, " %d %d L\n", corner[0].x, corner[0].y);
3096 fprintf(gppsfile, " 40 -110 R\n"
3097 " (PS level 2 image) Lshow\n"
3098 " %% Read data but ignore it\n"
3099 " /imagebuf %d string def\n"
3100 " currentfile imagebuf readstring\n", num_encoded_bytes);
3101 fputs("} {\n", gppsfile);
3103 fputs("gsave\n", gppsfile);
3104 fprintf(gppsfile, "%d %d translate\n", corner[0].x, corner[0].y);
3105 fprintf(gppsfile, "%d %d scale\n", (corner[1].x - corner[0].x), (corner[1].y - corner[0].y));
3106 fputs("%%%%BeginPalette\n", gppsfile);
3107 fprintf(gppsfile, "[ /Indexed\n /DeviceRGB %d\n <", (max_colors-1));
3109 #define TUPLES_PER_LINE 8
3111 for (allocated = 0, i_tuple = 0; allocated < max_colors; allocated++, i_tuple--) {
3112 double gray = (double) allocated * fact;
3114 rgb255maxcolors_from_gray( gray, &color );
3115 if (!i_tuple) { fprintf(gppsfile,"\n "); i_tuple = TUPLES_PER_LINE; }
3116 fprintf(gppsfile," %2.2x%2.2x%2.2x", (int)color.r, (int)color.g, (int)color.b);
3119 fputs("\n >\n] setcolorspace\n", gppsfile);
3120 fputs("%%%%EndPalette\n", gppsfile);
3121 fprintf(gppsfile, "<<\n /ImageType 1\n /Width %d\n /Height %d\n", M, N);
3122 fprintf(gppsfile, " /BitsPerComponent %d\n /ImageMatrix [ %d 0 0 %d 0 0 ]\n", bits_per_component, M, N);
3123 fprintf(gppsfile, " /Decode [ 0 %d ]\n", ((1<<bits_per_component)-1));
3124 if (ps_params->level1) {
3125 fprintf(gppsfile, " /imagebuf %d string def\n", (M*N*bits_per_component + 7)/8);
3126 fputs(" /DataSource {currentfile imagebuf readhexstring pop}\n", gppsfile);
3128 fputs(" /DataSource currentfile /ASCII85Decode filter\n", gppsfile);
3130 fputs(" /MultipleDataSources false\n", gppsfile);
3131 fputs(" /Interpolate false\n"
3133 "image\n", gppsfile);
3134 if (!ps_params->level1)
3135 fputs("} ifelse\n", gppsfile);
3139 /* Send encoded image to file. */
3141 char *encoded_image_ptr;
3142 for (i_tmp=0, encoded_image_ptr = encoded_image; i_tmp < num_encoded_bytes; i_tmp++)
3143 fputc(*encoded_image_ptr++, gppsfile);
3146 if (ps_params->level1)
3147 fputs("\ngrestore\n", gppsfile);
3149 fputs("\nInterpretLevel1 not {\n"
3151 "} if\n", gppsfile);
3152 fputs("grestore\n", gppsfile);
3153 fputs("%%%%EndImage\n", gppsfile);
3155 free(encoded_image);
3160 #endif /* WITH_IMAGE */
3162 /* First look for the GNUPLOT_PS_DIR environment variable
3163 * If unsuccessful, look for hardcoded absolute path on UNIX,
3164 * or hardcoded relative path on Windows and OS2,
3165 * or files included at compile time. */
3167 PS_dump_prologue_file(char *name)
3170 char *ps_prologue_dir;
3174 if ((ps_prologue_dir = getenv("GNUPLOT_PS_DIR")) == NULL) {
3175 #ifdef GNUPLOT_PS_DIR
3176 # if defined(_Windows)
3177 /* retrieve prologues path relatively to gnuplot executable,
3178 * whose path is in szModuleName (winmain.c) */
3179 ps_prologue_dir = gp_alloc(strlen((char*) szModuleName)
3180 + strlen(GNUPLOT_PS_DIR) + 2, "Prolog path");
3181 strcpy(ps_prologue_dir, (char*) szModuleName);
3182 strcat(ps_prologue_dir, "\\");
3183 /* GNUPLOT_PS_DIR is _relative_ path */
3184 strcat(ps_prologue_dir, GNUPLOT_PS_DIR);
3186 const ULONG bufsiz = 1024;
3187 CHAR exepath[bufsiz];
3191 rc = DosGetInfoBlocks(NULL, &ppib);
3193 rc = DosQueryModuleName(ppib->pib_hmte, bufsiz, (PCHAR) &exepath);
3195 char *p = strrchr(exepath, '\\');
3197 ps_prologue_dir = gp_alloc(strlen(exepath) + strlen(GNUPLOT_PS_DIR) + 2,
3199 strcpy(ps_prologue_dir, exepath);
3200 strcat(ps_prologue_dir, "\\");
3201 /* GNUPLOT_PS_DIR is _relative_ path */
3202 strcat(ps_prologue_dir, GNUPLOT_PS_DIR);
3205 ps_prologue_dir = gp_alloc(1, "Prolog path");
3206 /* unsucessful to retrieve executable path */
3207 strcpy(ps_prologue_dir,"");
3209 # else /* !_Windows && !OS2 */
3210 /* use hardcoded _absolute_ path */
3211 ps_prologue_dir = GNUPLOT_PS_DIR;
3213 #else /* using headers included at compile time */
3214 const char **dump = NULL;
3217 /* load from included header */
3218 if (!strcmp(name,"8859-15.ps"))
3219 dump = prologue_8859_15_ps;
3220 else if (!strcmp(name,"8859-1.ps"))
3221 dump = prologue_8859_1_ps;
3222 else if (!strcmp(name,"8859-2.ps"))
3223 dump = prologue_8859_2_ps;
3224 else if (!strcmp(name,"cp1250.ps"))
3225 dump = prologue_cp1250_ps;
3226 else if (!strcmp(name,"cp437.ps"))
3227 dump = prologue_cp437_ps;
3228 else if (!strcmp(name,"cp850.ps"))
3229 dump = prologue_cp850_ps;
3230 else if (!strcmp(name,"cp852.ps"))
3231 dump = prologue_cp852_ps;
3232 else if (!strcmp(name,"koi8r.ps"))
3233 dump = prologue_koi8r_ps;
3234 else if (!strcmp(name,"koi8u.ps"))
3235 dump = prologue_koi8u_ps;
3236 else if (!strcmp(name,"prologue.ps"))
3237 dump = prologue_prologue_ps;
3239 int_error(NO_CARET,"Requested Postscript prologue is not included");
3242 for (i = 0; dump[i] != NULL; ++i)
3243 fprintf(gppsfile, "%s", dump[i]);
3246 #endif /* GNUPLOT_PS_DIR */
3249 fullname = gp_alloc(strlen(ps_prologue_dir) + strlen(name) + 4,"Prolog name");
3250 strcpy(fullname,ps_prologue_dir);
3251 #if defined(_Windows) || defined(OS2)
3252 if (fullname[strlen(fullname)-1] != '\\')
3253 strcat(fullname,"\\");
3255 if (fullname[strlen(fullname)-1] != '/')
3256 strcat(fullname,"/");
3258 strcat(fullname,name);
3259 prologue_fd = fopen(fullname,"r");
3260 #if defined(_Windows) || defined(OS2)
3261 if (getenv("GNUPLOT_PS_DIR") == NULL)
3262 free(ps_prologue_dir);
3265 prologue_fd = loadpath_fopen(name,"r");
3267 fprintf(stderr,"Can't find PostScript prologue file %s\n", fullname);
3268 loadpath_handler(ACTION_SHOW,NULL);
3270 fprintf(stderr,"Please copy %s to one of the above directories\n",name);
3271 fprintf(stderr,"or set the loadpath appropriately\n");
3272 fprintf(stderr,"or set the environmental variable GNUPLOT_PS_DIR\n");
3273 int_error(NO_CARET,"Plot failed!");
3276 while (fgets(buf, sizeof(buf), prologue_fd))
3277 fputs(buf, gppsfile);
3278 fclose(prologue_fd);
3285 case 0: /* Start new path */
3290 case 1: /* Close path */
3291 fprintf(gppsfile, "Z ");
3298 #endif /* TERM_BODY */
3302 TERM_TABLE_START(post_driver)
3304 "PostScript graphics, including EPSF embedded files (*.eps)",
3305 PS_XMAX, PS_YMAX, PS_VCHAR, PS_HCHAR,
3306 PS_VTIC, PS_HTIC, PS_options, PS_init, PS_reset,
3307 PS_text, null_scale, PS_graphics, PS_move, PS_vector,
3308 PS_linetype, PS_put_text, PS_text_angle,
3309 PS_justify_text, PS_point, PS_arrow, PS_set_font, PS_pointsize,
3310 TERM_BINARY|TERM_IS_POSTSCRIPT|TERM_CAN_CLIP /*flags*/,
3311 0 /*suspend*/, 0 /*resume*/, PS_fillbox, PS_linewidth
3313 , 0, 0, 0, 0, 0 /* no mouse support for postscript */
3316 PS_previous_palette, /* write grestore */
3322 , ENHPS_OPEN, ENHPS_FLUSH, ENHPS_WRITEC
3323 , 0 /* layer control */
3325 TERM_TABLE_END(post_driver)
3328 #define LAST_TERM post_driver
3330 #endif /* TERM_TABLE */
3332 #endif /* TERM_PROTO_ONLY */
3335 /* This is a pseudo help section that is labeled with 00psglobal to be
3336 * sure that it is sorted in before `post', `epslatex', and `pslatex'.
3337 * This section just defines commonly used text snippets for all three
3338 * help sections defined in this file. Defining PS_COMMON_OPTS1,
3339 * PS_COMMON_OPTS2, and PS_COMMON_DOC1 outside START_HELP()...END_HELP()
3341 * The last line before the END_HELP(00psglobal) contains one single line
3342 * of "text" that is necessary to avoid errors.
3344 START_HELP(00psglobal)
3345 #define PS_COMMON_OPTS1 \
3346 " {level1 | leveldefault}",\
3347 " {color | colour | monochrome}",\
3348 " {solid | dashed}",\
3349 " {dashlength | dl <DL>}",\
3350 " {linewidth | lw <LW>}",\
3351 " {rounded | butt}",\
3352 " {palfuncparam <samples>{,<maxdeviation>}}",\
3353 " {size <XX>{unit},<YY>{unit}}",
3354 #define PS_COMMON_OPTS2 \
3355 " {blacktext | colortext | colourtext}",\
3356 " {{font} \"fontname{,fontsize}\" {<fontsize>}}",
3357 #define PS_COMMON_PROLOG_INFO \
3358 " If you see the error message",\
3359 " \"Can't find PostScript prologue file ... \"",\
3360 " Please see and follow the instructions in `postscript prologue`.",\
3362 #define PS_COMMON_DOC1 \
3363 " The option `color` enables color, while `monochrome` prefers black and white",\
3364 " drawing elements. Further, `monochrome` uses gray `palette` but it does not",\
3365 " change color of objects specified with an explicit `colorspec`."\
3367 " `solid` draws all plots with solid lines, overriding any dashed patterns.",\
3368 " `dashlength` or `dl` scales the length of the dashed-line segments by <DL>,",\
3369 " which is a floating-point number greater than zero.",\
3370 " `linewidth` or `lw` scales all linewidths by <LW>.",\
3372 " By default the generated PostScript code uses language features that were",\
3373 " introduced in PostScript Level 2, notably filters and pattern-fill of",\
3374 " irregular objects such as filledcurves. PostScript Level 2 features are",\
3375 " conditionally protected so that PostScript Level 1 interpreters do not issue",\
3376 " errors but, rather, display a message or a PostScript Level 1 approximation.",\
3377 " The `level1` option substitutes PostScript Level 1 approximations of these",\
3378 " features and uses no PostScript Level 2 code. This may be required by some",\
3379 " old printers and old versions of Adobe Illustrator. The flag `level1` can be", \
3380 " toggled later by editing a single line in the PostScript output file to force",\
3381 " PostScript Level 1 interpretation. In the case of files containing level 2",\
3382 " code, the above features will not appear or will be replaced by a note when",\
3383 " this flag is set or when the interpreting program does not indicate that it",\
3384 " understands level 2 PostScript or higher.",\
3386 " `rounded` sets line caps and line joins to be rounded; `butt` is the",\
3387 " default, butt caps and mitered joins;",\
3389 " `palfuncparam` controls how `set palette functions` are encoded as gradients",\
3390 " in the output. Analytic color component functions (set via",\
3391 " `set palette functions`) are encoded as linear interpolated gradients in the",\
3392 " postscript output: The color component functions are sampled at <samples>",\
3393 " points and all points are removed from this gradient which can be removed",\
3394 " without changing the resulting colors by more than <maxdeviation>. For",\
3395 " almost every useful palette you may savely leave the defaults of",\
3396 " <samples>=2000 and <maxdeviation>=0.003 untouched.",\
3398 " The default size for postscript output is 10 inches x 7 inches. The default",\
3399 " for eps output is 5 x 3.5 inches. The `size` option changes this to",\
3400 " whatever the user requests. By default the X and Y sizes are taken to be in",\
3401 " inches, but other units are possibly (currently only cm). The BoundingBox",\
3402 " of the plot is correctly adjusted to contain the resized image.",\
3403 " Screen coordinates always run from 0.0 to 1.0 along the full length of the",\
3404 " plot edges as specified by the `size` option.",\
3405 " NB: `this is a change from the previously recommended method of using the",\
3406 " set size command prior to setting the terminal type`. The old method left",\
3407 " the BoundingBox unchanged and screen coordinates did not correspond to the",\
3408 " actual limits of the plot.",\
3411 END_HELP(00psglobal)
3413 START_HELP(epslatex)
3415 "?commands set terminal epslatex",
3416 "?set terminal epslatex",
3417 "?set term epslatex",
3418 "?terminal epslatex",
3421 " The `epslatex` driver generates output for further processing by LaTeX.",
3424 " set terminal epslatex {default}",
3425 " set terminal epslatex {standalone | input}",
3426 " {oldstyle | newstyle}",
3428 " {header <header> | noheader}",
3431 " The epslatex terminal prints a plot as `terminal postscript eps`",
3432 " but transfers the texts to LaTeX instead of including in the PostScript",
3433 " code. Thus, many options are the same as in the `postscript terminal`.",
3435 " From version 4.0 to 4.2, some changes have been invoked into the default ",
3436 " appearance of the epslatex terminal to reach better consistency with the",
3437 " postscript terminal: The plot size has been changed from 5 x 3 inches to",
3438 " 5 x 3.5 inches; the character width is now estimated to be 60% of the font",
3439 " size while the old epslatex terminal used 50%; now, the larger number of",
3440 " postscript linetypes and symbols are used. To reach an appearance that is",
3441 " nearly identical to the old one specify the option `oldstyle`. (In fact",
3442 " some small differences remain: the symbol sizes are slightly different, the",
3443 " tics are half as large as in the old terminal which can be changed using",
3444 " `set tics scale`, and the arrows have all features as in the postscript",
3447 PS_COMMON_PROLOG_INFO
3449 " `blacktext` forces all text to be written in black even in color mode;",
3451 " The epslatex driver offers a special way of controlling text positioning:",
3452 " (a) If any text string begins with '{', you also need to include a '}' at the",
3453 " end of the text, and the whole text will be centered both horizontally",
3454 " and vertically by LaTeX. (b) If the text string begins with '[', you need",
3455 " to continue it with: a position specification (up to two out of t,b,l,r,c),",
3456 " ']{', the text itself, and finally, '}'. The text itself may be anything",
3457 " LaTeX can typeset as an LR-box. \\rule{}{}'s may help for best positioning.",
3458 " See also the documentation for the `pslatex` terminal driver.",
3459 " To create multiline labels, use \\shortstack, for example",
3460 " set ylabel '[r]{\\shortstack{first line \\\\ second line}}' ",
3462 " The `back` option of `set label` commands is handled slightly different",
3463 " than in other terminals. Labels using 'back' are printed behind all other",
3464 " elements of the plot while labels using 'front' are printed above ",
3465 " everything else.",
3467 " The driver produces two different files, one for the eps part of the figure",
3468 " and one for the LaTeX part. The name of the LaTeX file is taken from the",
3469 " `set output` command. The name of the eps file is derived by replacing",
3470 " the file extension (normally `.tex`) with `.eps` instead. There is no",
3471 " LaTeX output if no output file is given! Remember to close the",
3472 " `output file` before next plot unless in `multiplot` mode.",
3474 " In your LaTeX documents use '\\input{filename}' to include the figure.",
3475 " The `.eps` file is included by the command \\includegraphics{...}, so you",
3476 " must also include \\usepackage{graphicx} in the LaTeX preamble. If you",
3477 " want to use coloured text (option `textcolour`) you also have to include",
3478 " \\usepackage{color} in the LaTeX preamble.",
3480 " Pdf files can be made from the eps file using 'epstopdf'. If the graphics",
3481 " package is properly configured, the LaTeX files can also be processed by",
3482 " pdflatex without changes, using the pdf files instead of the eps files."
3484 " The behaviour concerning font selection depends on the header mode.",
3485 " In all cases, the given font size is used for the calculation of proper",
3486 " spacing. When not using the `standalone` mode the actual LaTeX font and",
3487 " font size at the point of inclusion is taken, so use LaTeX commands for",
3488 " changing fonts. If you use e.g. 12pt as font size for your LaTeX",
3489 " document, use '\"\" 12' as options. The font name is ignored. If using",
3490 " `standalone` the given font and font size are used, see below for a",
3491 " detailed description.",
3493 " If text is printed coloured is controlled by the TeX booleans \\ifGPcolor",
3494 " and \\ifGPblacktext. Only if \\ifGPcolor is true and \\ifGPblacktext is",
3495 " false, text is printed coloured. You may either change them in the",
3496 " generated TeX file or provide them globally in your TeX file, for example",
3498 " \\newif\\ifGPblacktext",
3499 " \\GPblacktexttrue",
3500 " in the preamble of your document. The local assignment is only done if no",
3501 " global value is given.",
3503 " When using the epslatex terminal give the name of the TeX file in the",
3504 " `set output` command including the file extension (normally \".tex\").",
3505 " The eps filename is generated by replacing the extension by \".eps\".",
3507 " If using the `standalone` mode a complete LaTeX header is added to the",
3508 " LaTeX file; and \"-inc\" is added to the filename of the eps file.",
3509 " The `standalone` mode generates a TeX file that produces",
3510 " output with the correct size when using dvips, pdfTeX, or VTeX.",
3511 " The default, `input`, generates a file that has to be included into a",
3512 " LaTeX document using the \\input command.",
3514 " If a font other than \"\" or \"default\" is given it is interpreted as",
3515 " LaTeX font name. It contains up to three parts, separated by a comma:",
3516 " 'fontname,fontseries,fontshape'. If the default fontshape or fontseries",
3517 " are requested, they can be omitted. Thus, the real syntax for the fontname",
3518 " is '[fontname][,fontseries][,fontshape]'. The naming convention for all",
3519 " parts is given by the LaTeX font scheme. The fontname is 3 to 4 characters",
3520 " long and is built as follows: One character for the font vendor, two",
3521 " characters for the name of the font, and optionally one additional",
3522 " character for special fonts, e.g., 'j' for fonts with old-style numerals",
3523 " or 'x' for expert fonts. The names of many fonts is described in",
3524 "^ <a href=\"http://www.tug.org/fontname/fontname.pdf\">",
3525 " http://www.tug.org/fontname/fontname.pdf",
3527 " For example, 'cmr' stands for Computer Modern Roman, 'ptm' for Times-Roman,",
3528 " and 'phv' for Helvetica. The font series denotes the thickness of the",
3529 " glyphs, in most cases 'm' for normal (\"medium\") and 'bx' or 'b' for bold",
3530 " fonts. The font shape is 'n' for upright, 'it' for italics, 'sl' for",
3531 " slanted, or 'sc' for small caps, in general. Some fonts may provide",
3532 " different font series or shapes.",
3536 " Use Times-Roman boldface (with the same shape as in the surrounding text):",
3537 " set terminal epslatex 'ptm,bx'",
3538 " Use Helvetica, boldface, italics:",
3539 " set terminal epslatex 'phv,bx,it'",
3540 " Continue to use the surrounding font in slanted shape:",
3541 " set terminal epslatex ',,sl'",
3542 " Use small capitals:",
3543 " set terminal epslatex ',,sc'",
3545 " By this method, only text fonts are changed. If you also want to change",
3546 " the math fonts you have to use the \"gnuplot.cfg\" file or the `header`",
3547 " option, described below.",
3549 " In standalone mode, the font size is taken from the given font size in the",
3550 " `set terminal` command. To be able to use a specified font size, a file",
3551 " \"size<size>.clo\" has to reside in the LaTeX search path. By default,",
3552 " 10pt, 11pt, and 12pt are supported. If the package \"extsizes\" is",
3553 " installed, 8pt, 9pt, 14pt, 17pt, and 20pt are added.",
3555 " The `header` option takes a string as argument. This string is written",
3556 " into the generated LaTeX file. If using the `standalone` mode, it is ",
3557 " written into the preamble, directly before the \\begin{document} command.",
3558 " In the `input` mode, it is placed directly after the \\begingroup command",
3559 " to ensure that all settings are local to the plot.",
3563 " Use T1 fontencoding, change the text and math font to Times-Roman as well",
3564 " as the sans-serif font to Helvetica:",
3565 " set terminal epslatex standalone header \\",
3566 " \"\\\\usepackage[T1]{fontenc}\\n\\\\usepackage{mathptmx}\\n\\\\usepackage{helvet}\"",
3567 " Use a boldface font in the plot, not influencing the text outside the plot:",
3568 " set terminal epslatex input header \"\\\\bfseries\"",
3570 " If the file \"gnuplot.cfg\" is found by LaTeX it is input in the preamble",
3571 " the LaTeX document, when using `standalone` mode. It can be used for",
3572 " further settings, e.g., changing the document font to Times-Roman,",
3573 " Helvetica, and Courier, including math fonts (handled by \"mathptmx.sty\"):",
3574 " \\usepackage{mathptmx}",
3575 " \\usepackage[scaled=0.92]{helvet}",
3576 " \\usepackage{courier}",
3577 " The file \"gnuplot.cfg\" is loaded before the header information given",
3578 " by the `header` command. Thus, you can use `header` to overwrite some of",
3579 " settings performed using \"gnuplot.cfg\"",
3584 "1 pslatex and pstex",
3585 "?commands set terminal pslatex",
3586 "?set terminal pslatex",
3587 "?set term pslatex",
3588 "?terminal pslatex",
3591 "?commands set terminal pstex",
3592 "?set terminal pstex",
3597 " The `pslatex` driver generates output for further processing by LaTeX,",
3598 " while the `pstex` driver generates output for further processing by",
3599 " TeX. `pslatex` uses \\specials understandable by dvips and xdvi. Figures",
3600 " generated by `pstex` can be included in any plain-based format (including",
3604 " set terminal [pslatex | pstex] {default}",
3605 " set terminal [pslatex | pstex]",
3606 " {rotate | norotate}",
3607 " {oldstyle | newstyle}",
3608 " {auxfile | noauxfile}",
3612 PS_COMMON_PROLOG_INFO
3614 " if `rotate` is specified, the y-axis label is rotated.",
3615 " <font_size> is the size (in pts) of the desired font.",
3617 " If `auxfile` is specified, it directs the driver to put the PostScript",
3618 " commands into an auxiliary file instead of directly into the LaTeX file.",
3619 " This is useful if your pictures are large enough that dvips cannot handle",
3620 " them. The name of the auxiliary PostScript file is derived from the name of",
3621 " the TeX file given on the `set output` command; it is determined by replacing",
3622 " the trailing `.tex` (actually just the final extent in the file name) with",
3623 " `.ps` in the output file name, or, if the TeX file has no extension, `.ps`",
3624 " is appended. The `.ps` is included into the `.tex` file by a",
3625 " \\special{psfile=...} command. Remember to close the `output file` before",
3626 " next plot unless in `multiplot` mode.",
3628 " Gnuplot versions prior version 4.2 have generated plots of the size",
3629 " 5 x 3 inches using the ps(la)tex terminal while the current version generates",
3630 " 5 x 3.5 inches to be consistent with the postscript eps terminal. In",
3631 " addition, the character width is now estimated to be 60% of the font size",
3632 " while the old epslatex terminal used 50%. To reach the old format specify",
3633 " the option `oldstyle`.",
3635 " The pslatex driver offers a special way of controlling text positioning: ",
3636 " (a) If any text string begins with '{', you also need to include a '}' at the",
3637 " end of the text, and the whole text will be centered both horizontally",
3638 " and vertically by LaTeX. (b) If the text string begins with '[', you need",
3639 " to continue it with: a position specification (up to two out of t,b,l,r),",
3640 " ']{', the text itself, and finally, '}'. The text itself may be anything",
3641 " LaTeX can typeset as an LR-box. \\rule{}{}'s may help for best positioning.",
3643 " The options not described here are identical to the `Postscript terminal`.",
3644 " Look there if you want to know what they do.",
3647 " set term pslatex monochrome dashed rotate # set to defaults",
3648 " To write the PostScript commands into the file \"foo.ps\":",
3649 " set term pslatex auxfile",
3650 " set output \"foo.tex\"; plot ...; set output",
3651 " About label positioning:",
3652 " Use gnuplot defaults (mostly sensible, but sometimes not really best):",
3653 " set title '\\LaTeX\\ -- $ \\gamma $'",
3654 " Force centering both horizontally and vertically:",
3655 " set label '{\\LaTeX\\ -- $ \\gamma $}' at 0,0",
3656 " Specify own positioning (top here):",
3657 " set xlabel '[t]{\\LaTeX\\ -- $ \\gamma $}'",
3658 " The other label -- account for long ticlabels:",
3659 " set ylabel '[r]{\\LaTeX\\ -- $ \\gamma $\\rule{7mm}{0pt}}'",
3661 " Linewidths and pointsizes may be changed with `set style line`."
3667 "?commands set terminal postscript",
3668 "?set terminal postscript",
3669 "?set term postscript",
3670 "?terminal postscript",
3673 " Several options may be set in the `postscript` driver.",
3676 " set terminal postscript {default}",
3677 " set terminal postscript {landscape | portrait | eps}",
3678 " {enhanced | noenhanced}",
3679 " {defaultplex | simplex | duplex}",
3680 " {fontfile [add | delete] \"<filename>\"",
3684 PS_COMMON_PROLOG_INFO
3686 " `landscape` and `portrait` choose the plot orientation.",
3687 " `eps` mode generates EPS (Encapsulated PostScript) output, which is just",
3688 " regular PostScript with some additional lines that allow the file to be",
3689 " imported into a variety of other applications. (The added lines are",
3690 " PostScript comment lines, so the file may still be printed by itself.) To",
3691 " get EPS output, use the `eps` mode and make only one plot per file. In `eps`",
3692 " mode the whole plot, including the fonts, is reduced to half of the default",
3695 " `enhanced` enables enhanced text mode features (subscripts,",
3696 " superscripts and mixed fonts). See `enhanced` for more information.",
3697 " `blacktext` forces all text to be written in black even in color mode;",
3699 " Duplexing in PostScript is the ability of the printer to print on both",
3700 " sides of the same sheet of paper. With `defaultplex`, the default setting",
3701 " of the printer is used; with `simplex` only one side is printed; `duplex`",
3702 " prints on both sides (ignored if your printer can't do it).",
3704 " `\"<fontname>\"` is the name of a valid PostScript font; and `<fontsize>` is",
3705 " the size of the font in PostScript points.",
3706 " In addition to the standard postscript fonts, an oblique version of the",
3707 " Symbol font, useful for mathematics, is defined. It is called",
3708 " \"Symbol-Oblique\".",
3710 " `default` sets all options to their defaults: `landscape`, `monochrome`,",
3711 " `dashed`, `dl 1.0`, `lw 1.0`, `defaultplex`, `noenhanced`, \"Helvetica\" and",
3712 " 14pt. Default size of a PostScript plot is 10 inches wide and 7 inches high.",
3714 " Fonts listed by `fontfile` or `fontfile add` encapsulate the font",
3715 " definitions of the listed font from a postscript Type 1 or TrueType font",
3716 " file directly into the gnuplot output postscript file. Thus, the enclosed",
3717 " font can be used in labels, titles, etc. See the section",
3718 " `postscript fontfile` for more details. With `fontfile delete`, a fontfile",
3719 " is deleted from the list of embedded files. `nofontfiles` cleans the list",
3720 " of embedded fonts.",
3723 " set terminal postscript default # old postscript",
3724 " set terminal postscript enhanced # old enhpost",
3725 " set terminal postscript landscape 22 # old psbig",
3726 " set terminal postscript eps 14 # old epsf1",
3727 " set terminal postscript eps 22 # old epsf2",
3728 " set size 0.7,1.4; set term post portrait color \"Times-Roman\" 14",
3729 " set term post \"VAGRoundedBT_Regular\" 14 fontfile \"bvrr8a.pfa\"",
3731 " Linewidths and pointsizes may be changed with `set style line`.",
3733 " The `postscript` driver supports about 70 distinct pointtypes, selectable",
3734 " through the `pointtype` option on `plot` and `set style line`.",
3736 " Several possibly useful files about `gnuplot`'s PostScript are included",
3737 " in the /docs/psdoc subdirectory of the `gnuplot` distribution and at the",
3738 " distribution sites. These are \"ps_symbols.gpi\" (a `gnuplot` command file",
3739 " that, when executed, creates the file \"ps_symbols.ps\" which shows all the",
3740 " symbols available through the `postscript` terminal), \"ps_guide.ps\" (a",
3741 " PostScript file that contains a summary of the enhanced syntax and a page",
3742 " showing what the octal codes produce with text and symbol fonts),",
3743 " \"ps_file.doc\" (a text file that contains a discussion of the organization",
3744 " of a PostScript file written by `gnuplot`), and \"ps_fontfile_doc.tex\"",
3745 " (a LaTeX file which contains a short documentation concerning the",
3746 " encapsulation of LaTeX fonts with a glyph table of the math fonts).",
3748 " A PostScript file is editable, so once `gnuplot` has created one, you are",
3749 " free to modify it to your heart's desire. See the `editing postscript`",
3750 " section for some hints.",
3751 "2 enhanced postscript",
3752 "?commands set terminal postscript enhanced",
3753 "?set terminal postscript enhanced",
3754 "?set term postscript enhanced",
3755 "?terminal postscript enhanced",
3756 "?term postscript enhanced",
3757 "?enhanced_postscript",
3758 "?enhanced postscript",
3759 "?Enhanced postscript",
3763 " Several terminal types support an enhanced text mode in which ",
3764 " additional formatting information is embedded in the text string.",
3766 "@start table - first is interactive cleartext form",
3767 " Control Examples Explanation",
3768 " ^ a^x superscript",
3770 " @ @x or a@^b_c phantom box (occupies no width)",
3771 " & &{space} inserts space of specified length",
3772 " ~ ~a{.8-} overprints '-' on 'a', raised by .8",
3773 " times the current fontsize",
3774 "#\\begin{tabular}{|ccl|} \\hline",
3775 "#\\multicolumn{3}{|c|}{Enhanced Text Control Codes} \\\\ \\hline",
3776 "#Control & Examples & Explanation \\\\ \\hline",
3777 "#\\verb~^~ & \\verb~a^x~ & superscript\\\\",
3778 "#\\verb~_~ & \\verb~a_x~ & subscript\\\\",
3779 "#\\verb~@~ & \\verb~@x or a@^b_c~ & phantom box (occupies no width)\\\\",
3780 "#\\verb~&~ & \\verb~&{space}~ & inserts space of specified length\\\\",
3781 "#\\verb|~| & \\verb|~a{.8-}| & overprints '-' on 'a', raised by .8\\\\",
3782 "#\\verb~ ~ & \\verb~ ~ & times the current fontsize\\\\",
3784 "%.TE", /* ugly - doc2ms uses @ for column separator, but here we */
3785 "%.TS", /* need @ in table, so end and restart the table ! */
3786 "%center box tab ($) ;",
3788 "%Control$Examples$Explanation",
3790 "%^$a^x$superscript",
3791 "%\\&_$a\\&_x$subscript",
3792 "% @ $ @x or a\\&@^b\\&_c$phantom box (occupies no width)",
3793 "% & $ &{space}$inserts space of specified length",
3794 "% ~ $ ~a{.8-}$overprints '-' on 'a', raised by .8",
3795 "% $ $times the current fontsize",
3798 " Braces can be used to place multiple-character text where a single character",
3799 " is expected (e.g., 2^{10}). To change the font and/or size, use the full",
3800 " form: {/[fontname][=fontsize | *fontscale] text}. Thus {/Symbol=20 G} is a",
3801 " 20-point GAMMA and {/*0.75 K} is a K at three-quarters of whatever fontsize",
3802 " is currently in effect. (The '/' character MUST be the first character after",
3805 " If the encoding vector has been changed by `set encoding`, the default",
3806 " encoding vector can be used instead by following the slash with a dash. This",
3807 " is unnecessary if you use the Symbol font, however---since /Symbol uses its",
3808 " own encoding vector, `gnuplot` will not apply any other encoding vector to",
3811 " The phantom box is useful for a@^b_c to align superscripts and subscripts",
3812 " but does not work well for overwriting an accent on a letter. (To do the",
3813 " latter, it is much better to use 'set encoding iso_8859_1' to change to the",
3814 " ISO Latin-1 encoding vector, which contains a large variety of letters with",
3815 " accents or other diacritical marks.) Since the box is non-spacing, it is",
3816 " sensible to put the shorter of the subscript or superscript in the box (that",
3817 " is, after the @).",
3819 " Space equal in length to a string can be inserted using the '&' character.",
3825 " The '~' character causes the next character or bracketed text to be",
3826 " overprinted by the following character or bracketed text. The second text",
3827 " will be horizontally centered on the first. Thus '~a/' will result in an 'a'",
3828 " with a slash through it. You can also shift the second text vertically by",
3829 " preceding the second text with a number, which will define the fraction of the",
3830 " current fontsize by which the text will be raised or lowered. In this case",
3831 " the number and text must be enclosed in brackets because more than one",
3832 " character is necessary. If the overprinted text begins with a number, put a",
3833 " space between the vertical offset and the text ('~{abc}{.5 000}'); otherwise",
3834 " no space is needed ('~{abc}{.5---}'). You can change the font for one or",
3835 " both strings ('~a{.5 /*.2 o}'---an 'a' with a one-fifth-size 'o' on top---and",
3836 " the space between the number and the slash is necessary), but you can't",
3837 " change it after the beginning of the string. Neither can you use any other",
3838 " special syntax within either string. You can, of course, use control",
3839 " characters by escaping them (see below), such as '~a{\\^}'",
3841 " You can access special symbols numerically by specifying \\character-code (in",
3842 " octal), e.g., {/Symbol \\245} is the symbol for infinity.",
3844 " You can escape control characters using \\, e.g., \\\\, \\{, and so on.",
3846 " But be aware that strings in double-quotes are parsed differently than those",
3847 " enclosed in single-quotes. The major difference is that backslashes may need",
3848 " to be doubled when in double-quoted strings.",
3850 " Examples (these are hard to describe in words---try them!):",
3851 " set xlabel 'Time (10^6 {/Symbol m}s)'",
3852 " set title '{/Symbol=18 \\362@_{/=9.6 0}^{/=12 x}} \\",
3853 " {/Helvetica e^{-{/Symbol m}^2/2} d}{/Symbol m}'",
3855 " The file \"ps_guide.ps\" in the /docs/psdoc subdirectory of the `gnuplot` source",
3856 " distribution contains more examples of the enhanced syntax.",
3857 "2 editing postscript",
3858 "?commands set terminal postscript editing",
3859 "?set terminal postscript editing",
3860 "?set term postscript editing",
3861 "?terminal postscript editing",
3862 "?term postscript editing",
3863 "?editing_postscript",
3864 "?editing postscript",
3865 " The PostScript language is a very complex language---far too complex to",
3866 " describe in any detail in this document. Nevertheless there are some things",
3867 " in a PostScript file written by `gnuplot` that can be changed without risk of",
3868 " introducing fatal errors into the file.",
3870 " For example, the PostScript statement \"/Color true def\" (written into the",
3871 " file in response to the command `set terminal postscript color`), may be",
3872 " altered in an obvious way to generate a black-and-white version of a plot.",
3873 " Similarly line colors, text colors, line weights and symbol sizes can also be",
3874 " altered in straight-forward ways. Text (titles and labels) can be edited to",
3875 " correct misspellings or to change fonts. Anything can be repositioned, and",
3876 " of course anything can be added or deleted, but modifications such as these",
3877 " may require deeper knowledge of the PostScript language.",
3879 " The organization of a PostScript file written by `gnuplot` is discussed in",
3880 " the text file \"ps_file.doc\" in the docs/ps subdirectory of the gnuplot",
3881 " source distribution.",
3882 "2 postscript fontfile",
3883 "?commands set terminal postscript fontfile",
3884 "?set terminal postscript fontfile",
3885 "?set term postscript fontfile",
3886 "?terminal postscript fontfile",
3887 "?term postscript fontfile",
3888 "?postscript fontfile",
3890 " The `fontfile` or `fontfile add` option takes one file name as argument",
3891 " and encapsulates this file into the postscript output in order to make",
3892 " this font available for text elements (labels, tic marks, titles, etc.).",
3893 " The `fontfile delete` option also takes one file name as argument. It",
3894 " deletes this file name from the list of encapsulated files.",
3896 " The postscript terminal understands some",
3897 " font file formats: Type 1 fonts in ASCII file format (extension \".pfa\"),",
3898 " Type 1 fonts in binary file format (extension \".pfb\"), and TrueType",
3899 " fonts (extension \".ttf\"). Pfa files are understood directly, pfb and ttf",
3900 " files are converted on the fly if appropriate conversion tools are",
3901 " installed (see below). You have to specify the full filename including the",
3902 " extension. Each `fontfile` option takes exact one font file name. This",
3903 " option can be used multiple times in order to include more than one font",
3906 " The font file is searched in the working directory and in all directories",
3907 " listed in the fontpath which is determined by `set fontpath`.",
3908 " In addition, the fontpath can be set using the environment variable",
3909 " GNUPLOT_FONTPATH. If this is not set a system dependent default search",
3910 " list is used. See `set fontpath` for more details.",
3912 " For using the encapsulated font file you have to specify the font name",
3913 " (which normally is not the same as the file name). When embedding a",
3914 " font file by using the `fontfile` option in interactive mode, the ",
3915 " font name is printed on the screen. E.g.",
3916 " Font file 'p052004l.pfb' contains the font 'URWPalladioL-Bold'. Location:",
3917 " /usr/lib/X11/fonts/URW/p052004l.pfb",
3919 " When using pfa or pfb fonts, you can also find it out by looking into the",
3920 " font file. There is a line similar to \"/FontName /URWPalladioL-Bold def\".",
3921 " The middle string without the slash is the fontname, here",
3922 " \"URWPalladioL-Bold\".",
3923 " For TrueType fonts, this is not so easy since the font name is stored in a",
3924 " binary format. In addition, they often have spaces in the font names which",
3925 " is not supported by Type 1 fonts (in which a TrueType is converted on the",
3926 " fly). The font names are changed in order to eliminate the spaces in the",
3927 " fontnames. The easiest way to find out which font name is generated for",
3928 " use with gnuplot, start gnuplot in interactive mode and type in",
3929 " \"set terminal postscript fontfile '<filename.ttf>'\".",
3931 " For converting font files (either ttf or pfb) to pfa format, the conversion",
3932 " tool has to read the font from a file and write it to standard output. If",
3933 " the output cannot be written to standard output, on-the-fly conversion is",
3936 " For pfb files \"pfbtops\" is a tool which can do this. If this program",
3937 " is installed on your system the on the fly conversion should work.",
3938 " Just try to encapsulate a pfb file. If the compiled in program call does",
3939 " not work correctly you can specify how this program is called by",
3940 " defining the environment variable GNUPLOT_PFBTOPFA e.g. to",
3941 " \"pfbtops %s\". The `%s` will be replaced by the font file name and thus",
3942 " has to exist in the string.",
3944 " If you don't want to do the conversion on the fly but get a pfa file of",
3945 " the font you can use the tool \"pfb2pfa\" which is written in simple c",
3946 " and should compile with any c compiler.",
3947 " It is available from many ftp servers, e.g.",
3948 "^ <a href=\"ftp://ftp.dante.de/tex-archive/fonts/utilities/ps2mf/\">",
3949 " ftp://ftp.dante.de/tex-archive/fonts/utilities/ps2mf/",
3951 " In fact, \"pfbtopfa\" and \"pfb2ps\" do the same job. \"pfbtopfa\" puts",
3952 " the resulting pfa code into a file, whereas \"pfbtops\" writes it to",
3953 " standard output.",
3955 " TrueType fonts are converted into Type 1 pfa format, e.g.",
3956 " by using the tool \"ttf2pt1\" which is available from",
3957 "^ <a href=\"http://ttf2pt1.sourceforge.net/\">",
3958 " http://ttf2pt1.sourceforge.net/",
3960 " If the builtin conversion does not",
3961 " work, the conversion command can be changed by the environment variable",
3962 " GNUPLOT_TTFTOPFA. For usage with ttf2pt1 it may be set to",
3963 " \"ttf2pt1 -a -e -W 0 %s - \". Here again, `%s` stands for the",
3966 " For special purposes you also can use a pipe (if available for your",
3967 " operating system). Therefore you start the file name definition with ",
3968 " the character \"<\" and append a program call. This program has ",
3969 " to write pfa data to standard output. Thus, a pfa file may be accessed",
3970 " by `set fontfile \"< cat garamond.pfa\"`.",
3972 " For example, including Type 1 font files can be used for including the",
3973 " postscript output in LaTeX documents. The \"european computer modern\"",
3974 " font (which is a variant of the \"computer modern\" font) is available",
3975 " in pfb format from any CTAN server, e.g.",
3976 "^ <a href=\"ftp://ftp.dante.de/tex-archive/fonts/ps-type1/cm-super/\">",
3977 " ftp://ftp.dante.de/tex-archive/fonts/ps-type1/cm-super/",
3979 " For example, the file \"sfrm1000.pfb\" contains the normal upright fonts",
3980 " with serifs in the design size 10pt (font name \"SFRM1000\").",
3981 " The computer modern fonts, which are still necessary for mathematics,",
3982 " are available from",
3983 "^ <a href=\"ftp://ftp.dante.de/tex-archive/fonts/cm/ps-type1/bluesky\">",
3984 " ftp://ftp.dante.de/tex-archive/fonts/cm/ps-type1/bluesky",
3986 " With these you can use any character available in TeX. However, the",
3987 " computer modern fonts have a strange encoding. (This is why you should not",
3988 " use cmr10.pfb for text, but sfrm1000.pfb instead.)",
3989 " The usage of TeX fonts is shown in one of the demos.",
3990 " The file \"ps_fontfile_doc.tex\" in the /docs/psdoc subdirectory of the",
3991 " `gnuplot` source distribution contains a table with glyphs of the TeX",
3994 " If the font \"CMEX10\" is embedded (file \"cmex10.pfb\") gnuplot defines",
3995 " the additional font \"CMEX10-Baseline\". It is shifted vertically in order",
3996 " to fit better to the other glyphs (CMEX10 has its baseline at the top of",
3998 "2 postscript prologue",
3999 "?commands set terminal postscript prologue",
4000 "?set terminal postscript prologue",
4001 "?terminal postscript prologue",
4002 "?postscript prologue",
4004 " Each PostScript output file includes a %%Prolog section and possibly some",
4005 " additional user-defined sections containing, for example, character",
4006 " encodings. These sections are copied from a set of PostScript prologue files",
4007 " which are either compiled in the gnuplot executable or stored elsewhere on your",
4008 " computer. This behaviour and the default directory where these files live are",
4009 " controlled at the time gnuplot is built. However, you can control this",
4010 " either by defining an environment variable GNUPLOT_PS_DIR or by using the",
4011 " gnuplot command `set loadpath`. See `set loadpath`.",
4015 #endif /* TERM_HELP */