1 /* Hello, Emacs, this is -*-C-*-
2 * $Id: imagen.trm,v 1.20 2006/07/21 02:35:47 sfeam Exp $
5 /* GNUPLOT - imagen.trm */
8 * Copyright 1990 - 1993, 1998, 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 file is included by ../term.c.
40 * This terminal driver supports:
41 * Imagen laser printers
44 * Paul E. McKenney, David Kotz
45 * Rewritten/extended by:
47 * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
52 * Original for direct Imagen output (but retaining many of the
53 * LaTeX extensions) by Paul E. McKenney, 1989.
54 * Further modified by David Kotz to fit into gnuplot 2.0.
55 * Information Science and Technology Division, SRI International,
56 * 333 Ravenswood Ave, Menlo Park, CA 94025.
57 * Mail to mckenney@sri.com.
60 * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
70 TERM_PUBLIC void IMAGEN_init __PROTO((void));
71 TERM_PUBLIC void IMAGEN_graphics __PROTO((void));
72 TERM_PUBLIC void IMAGEN_options __PROTO((void));
73 TERM_PUBLIC void IMAGEN_text __PROTO((void));
74 TERM_PUBLIC void IMAGEN_linetype __PROTO((int lt));
75 TERM_PUBLIC void IMAGEN_move __PROTO((unsigned int x, unsigned int y));
76 TERM_PUBLIC void IMAGEN_vector __PROTO((unsigned int ux, unsigned int uy));
77 TERM_PUBLIC int IMAGEN_text_angle __PROTO((int ang));
78 TERM_PUBLIC int IMAGEN_justify_text __PROTO((enum JUSTIFY mode));
79 TERM_PUBLIC void IMAGEN_put_text __PROTO((unsigned int x, unsigned int y, const char str[]));
80 TERM_PUBLIC void IMAGEN_reset __PROTO((void));
81 #define IMAGEN_PTS_PER_INCH (300)
82 #define IMAGEN_XMAX (IMAGEN_PTS_PER_INCH * 11) /* 10.0 inches */
83 #define IMAGEN_YMAX (IMAGEN_PTS_PER_INCH * 78 / 10) /* 7.5 inches */
84 #define IMAGEN_HTIC (20)
85 #define IMAGEN_VTIC (20)
86 #define IMAGEN_VCHAR (IMAGEN_FONTSIZE*5)
87 #define IMAGEN_HCHAR (IMAGEN_VCHAR/2)
88 #endif /* TERM_PROTO */
90 #ifndef TERM_PROTO_ONLY
93 static void IM_page __PROTO((void));
94 static void IMAGEN_draw_path __PROTO((void));
95 static void IMAGEN_setpos __PROTO((int ux, int uy));
96 static unsigned char *IMAGEN_cvts __PROTO((unsigned char *str, int *width, int *height));
97 static void IMAGEN_putwd __PROTO((unsigned int w));
98 static void IMAGEN_createfamily __PROTO((char *c, int sz));
99 static void IMAGEN_setfont __PROTO((int sz));
100 static void IMP_set_draw_pattern __PROTO((int pattern, int sz));
101 static void IMAGEN_mapsinit __PROTO((void));
102 static void IMAGEN_createmap __PROTO((int name, unsigned short *map));
110 #include "impcodes.h"
112 /* default is landscape */
113 #define IMAGEN_A4_H (IMAGEN_PTS_PER_INCH * 83 / 10)
114 #define IMAGEN_A4_W (IMAGEN_PTS_PER_INCH * 116 / 10)
116 /* width in current orientation */
117 static int IMAGEN_Xmax = IMAGEN_XMAX;
118 static int IMAGEN_Ymax = IMAGEN_YMAX;
120 #define IMAGEN_FONTSIZE 12
121 #define IMAGEN_FONT "cour"
124 static unsigned short IMP_gmap[128];
125 static unsigned char IMP_chmap[256];
127 static int IMAGEN_page_h = IMAGEN_A4_H;
128 static int IMAGEN_page_w = IMAGEN_A4_W;
129 static int IM_win_horiz = 1;
130 static int IM_win_verti = 1;
131 static int IM_plot_nr = 0;
133 static int IMAGEN_fontsize = IMAGEN_FONTSIZE;
134 static int IMAGEN_familytable[36];
135 static int IMAGEN_orgX; /* absolute-pixel-ORIgin of graph page. */
136 static int IMAGEN_orgY;
137 static int IMAGEN_orgx; /* absolute-pixel-ORIgin of current graph. */
138 static int IMAGEN_orgy;
139 static int IMAGEN_posx; /* current drawing position (lines). */
140 static int IMAGEN_posy;
141 /* static int IMAGEN_inplot; */
142 static int IMAGEN_xmax = IMAGEN_XMAX; /* width of graph in pixels. */
143 static int IMAGEN_ymax = IMAGEN_YMAX; /* height of graph in pixels. */
144 static int IMAGEN_winx = IMAGEN_XMAX; /* width of window in pixels. */
145 static int IMAGEN_winy = IMAGEN_YMAX; /* height of window in pixels. */
146 static int IMAGEN_hchar; /* Height of CHAR in current font. */
147 static int IMAGEN_wchar; /* Width of CHAR in current font. */
148 static int IMAGEN_blofs; /* BaseLine OFfSet from bounding box. */
149 static int IMAGEN_angle = -1; /* 0 for horizontal text, 1 for vertical */
150 static int IMAGEN_portrait; /* 0 for landscape */
151 static enum JUSTIFY IMAGEN_justify = LEFT; /* left/center/right */
153 #define STOREPATH 100
154 static unsigned int IM_xvector[STOREPATH]; /* draw path vector of x values */
155 static unsigned int IM_yvector[STOREPATH]; /* draw path vector of y values */
156 static unsigned int IM_veclen; /* length of allocated path vector */
157 static unsigned int IM_vecpos = 0; /* current pos in vector */
159 /* char IMPdrpattern[10][10] = { {0}, {30,10,0}, {0}, {10,30,0}, {2,20,0},
160 {20,10,0}, {30,20,10,20,0}, {30,20,4,10,10,10,4,20,0}, {40,20,0}, {30,15,4,15,0}
164 static char IMPdrpattern[10][10] =
172 /* 4 */ {16, 6, 3, 6, 0},
173 /* 5 */ {16, 6, 8, 6, 0},
174 /* 6 */ {16, 4, 1, 4, 8, 4, 1, 4, 0},
175 /* 7 */ {16, 4, 1, 8, 1, 4, 0}
178 enum IMAGEN_id { IMAGEN_PORTRAIT, IMAGEN_LANDSCAPE, IMAGEN_OTHER };
180 static struct gen_table IMAGEN_opts[] =
182 { "p$ortrait", IMAGEN_PORTRAIT },
183 { "l$andscape", IMAGEN_LANDSCAPE },
184 { NULL, IMAGEN_OTHER }
192 while (!END_OF_COMMAND) {
193 switch(lookup_table(&IMAGEN_opts[0],c_token)) {
194 case IMAGEN_PORTRAIT:
195 IMAGEN_portrait = TRUE;
196 IMAGEN_page_h = IMAGEN_A4_W;
197 IMAGEN_page_w = IMAGEN_A4_H;
198 IMAGEN_Xmax = IMAGEN_YMAX;
199 IMAGEN_Ymax = IMAGEN_XMAX;
202 case IMAGEN_LANDSCAPE:
203 IMAGEN_portrait = FALSE;
208 if (equals(c_token, "[")) { /* windows spesified */
210 /* if (IM_plot_nr>1) */
211 if (equals(c_token, "]")) {
216 if (END_OF_COMMAND) {
217 int_error(c_token, "no. windows: [horizontal,vertical] expected");
218 } else if (!equals(c_token, ",")) {
219 IM_win_horiz = (int) real(const_express(&a));
221 if (!equals(c_token, ","))
222 int_error(c_token, "',' expected");
224 if (!equals(c_token, "]")) {
225 IM_win_verti = (int) real(const_express(&a));
227 if (!equals(c_token, "]"))
228 int_error(c_token, "expecting ']'");
231 /* We have font size specified */
232 IMAGEN_fontsize = (int) real(const_express(&a));
233 if (IMAGEN_fontsize < 8)
235 if (IMAGEN_fontsize > 15)
236 IMAGEN_fontsize = 15;
240 sprintf(term_options, "%d %s [%1d,%1d]", IMAGEN_fontsize, (IMAGEN_portrait) ? "portrait" :
241 "landscape", IM_win_horiz, IM_win_verti);
248 register struct termentry *t = term;
249 /* char font[10]; */ /* font name */
251 IMAGEN_posx = IMAGEN_posy = 0;
253 IMAGEN_orgX = (IMAGEN_page_w - IMAGEN_Xmax) / 2;
254 IMAGEN_orgY = (IMAGEN_page_h - IMAGEN_Ymax) / 2;
256 IMAGEN_xmax = IMAGEN_winx = (int) (IMAGEN_Xmax / IM_win_horiz);
257 IMAGEN_ymax = IMAGEN_winy = (int) (IMAGEN_Ymax / IM_win_verti);
259 t->xmax = (unsigned int) (IMAGEN_xmax);
260 t->ymax = (unsigned int) (IMAGEN_ymax);
262 fputs("@document(language impress, paper a4)", gpoutfile);
264 if (IMAGEN_portrait) {
265 putc(imP_SET_ABS_V, gpoutfile);
268 putc(imP_SET_HV_SYSTEM, gpoutfile);
269 putc(((IMAGEN_portrait ? 3 : 0) << 5) | (3 << 3) | (IMAGEN_portrait ? 0 : 5), gpoutfile);
271 /* sprintf(font, "cour%02d", IMAGEN_FONTSIZE); */
273 IMAGEN_createmap(1, IMP_gmap);
274 /* IMAGEN_createfamily(font, IMAGEN_FONTSIZE); */
275 IMAGEN_setfont(IMAGEN_fontsize);
277 IMAGEN_text_angle(0);
279 putc(imP_SET_ABS_H, gpoutfile);
281 putc(imP_SET_ABS_V, gpoutfile);
284 IMAGEN_linetype(LT_AXIS);
286 if ((IM_xvector = (unsigned int *) malloc(STOREPATH*sizeof(int))) == NULL) {
287 fputs("Imagendriver: Unable to allocate memory for draw path\n", stderr);
290 if ((IM_yvector = (unsigned int *) malloc(STOREPATH*sizeof(int))) == NULL) {
291 fputs("Imagendriver: Unable to allocate memory for draw path\n", stderr);
295 IM_veclen = STOREPATH;
303 /* fprintf(stderr,"graphics, draw path\n"); */
306 putc(imP_ENDPAGE, gpoutfile);
313 /* int xoff, yoff; */
316 /* fprintf(stderr,"graphics, draw path\n"); */
319 if (IM_plot_nr >= (IM_win_horiz * IM_win_verti)) {
324 tmpx = IMAGEN_orgX + ((IM_plot_nr - 1) % IM_win_horiz) * IMAGEN_winx;
325 tmpy = IMAGEN_orgY + ((IM_win_verti - 1) - (int) ((IM_plot_nr - 1) / IM_win_horiz)) * IMAGEN_winy;
326 IMAGEN_orgx = tmpx + (int) ((IMAGEN_winx - IMAGEN_xmax) / 2);
327 IMAGEN_orgy = tmpy + (int) ((IMAGEN_winy - IMAGEN_ymax) / 2);
337 #define DRAW_PATTERNS 6
341 IMAGEN_linetype(int lt)
343 static int lastlinetype = -10;
344 int pen /*, pattern */ ;
347 /* fprintf(stderr,"move, draw path\n"); */
354 if (lt == LT_BLACK) {
357 pen = (int) (lt / 8) * 2;
363 if (lastlinetype == lt)
368 putc(imP_SET_PEN, gpoutfile);
369 putc(pen, gpoutfile);
370 IMP_set_draw_pattern(lt, pen);
375 IMAGEN_move(unsigned int x, unsigned int y)
378 /* fprintf(stderr,"move, draw path\n"); */
381 IM_xvector[0] = x + IMAGEN_orgx;
382 IM_yvector[0] = y + IMAGEN_orgy;
383 /* fprintf(stderr,"Ny vector: startpos: %1d %1d\n",IM_xvector[0],IM_yvector[0]); */
392 IMAGEN_vector(unsigned int ux, unsigned int uy)
394 /* void IMAGEN_draw_path(); */
397 IM_xvector[IM_vecpos] = ux + IMAGEN_orgx;
398 IM_yvector[IM_vecpos] = uy + IMAGEN_orgy;
399 /* fprintf(stderr,"Ny node: nr: %1d; %1d %1d\n",IM_vecpos,IM_xvector[IM_vecpos],IM_yvector[IM_vecpos]); */
401 if (IM_vecpos >= IM_veclen) {
403 IM_xvector[0] = ux + IMAGEN_orgx;
404 IM_yvector[0] = uy + IMAGEN_orgy;
412 /* unsigned int pos; */
415 putc(imP_CREATE_PATH, gpoutfile);
416 IMAGEN_putwd(IM_vecpos);
417 for (i = 0; i < IM_vecpos; i++) {
419 IMAGEN_putwd(IM_xvector[i] + IMAGEN_orgx);
420 IMAGEN_putwd(IM_yvector[i] + IMAGEN_orgy);
422 IMAGEN_putwd(IM_xvector[i]);
423 IMAGEN_putwd(IM_yvector[i]);
426 /* Draw path with black pen. */
428 putc(imP_DRAW_PATH, gpoutfile);
431 /* Set current position to end of line. */
433 /* IMAGEN_move(ux, uy); */
437 IMAGEN_setpos(int ux, int uy)
439 /* Set x and y position (for text), also set beginning-of-line. */
441 putc(imP_SET_ABS_H, gpoutfile);
442 IMAGEN_putwd(ux + IMAGEN_orgx);
443 putc(imP_SET_ABS_V, gpoutfile);
444 IMAGEN_putwd(uy + IMAGEN_orgy);
445 putc(imP_SET_BOL, gpoutfile);
446 if (IMAGEN_angle == 1)
447 IMAGEN_putwd(uy + IMAGEN_orgx); /* vertical */
449 IMAGEN_putwd(ux + IMAGEN_orgx); /* horizontal */
453 IMAGEN_text_angle(int ang)
456 /* fprintf(stderr,"text_angle, draw path\n"); */
459 if (IMAGEN_angle != ang) {
460 IMAGEN_angle = ang; /* record for later use */
461 putc(imP_SET_ADV_DIRS, gpoutfile);
462 putc(ang == 0 ? 0 : 7, gpoutfile); /* 0=>horiz : 7=>vert */
468 IMAGEN_justify_text(enum JUSTIFY mode)
471 /* fprintf(stderr,"justify_text, draw path\n"); */
474 IMAGEN_justify = mode;
478 static unsigned char *
479 IMAGEN_cvts(unsigned char *str, int *width, int *height)
483 static unsigned char *buf = NULL;
488 /* Free up old buffer, if there is one, get a new one. Since */
489 /* all transformations shorten the string, get a buffer that is */
490 /* the same size as the input string. */
494 buf = (unsigned char *) gp_alloc(strlen((char *) str)+2, "converted label string");
496 /* Do the transformations. */
503 while (strlen((char *) cp1) > 0) {
505 case ' ': /* Space character. */
510 case '\\': /* Escape sequence. */
511 if (*++cp1 == '\\') {
512 /* Begin new line. */
518 /* *cp2++ = imP_CRLF; */
521 /* Fall through to just copy next char out. */
525 *cp2++ = IMP_chmap[*cp1];
538 *height = IMAGEN_angle ?
539 IMAGEN_wchar * maxw :
542 *width = IMAGEN_angle ?
549 IMAGEN_put_text(unsigned int x, unsigned int y, const char str[])
551 unsigned char *cvstr, *p;
557 /* fprintf(stderr,"put_text, draw path\n"); */
560 cvstr = IMAGEN_cvts((unsigned char *) str, &width, &height);
562 if (IMAGEN_angle) { /* vertical */
563 /* x += IMAGEN_hchar; */
564 x -= width / 2 - IMAGEN_hchar;
566 } else /* horizontal */
567 y += height / 2 - IMAGEN_hchar;
569 while ((p = (unsigned char *) strchr((char *) cvstr, '\n'))) {
574 sx = x - IMAGEN_blofs;
576 sy = y + IMAGEN_blofs;
578 width = strlen((char *) cvstr) * IMAGEN_wchar;
580 switch (IMAGEN_justify) {
590 /*x -= width/2; break; */
598 /* x -= width; break; */
601 IMAGEN_setpos(sx, sy);
602 fputs((char *) cvstr, gpoutfile);
604 if (IMAGEN_angle) { /* vertical */
617 /* fprintf(stderr,"reset, draw path\n"); */
620 putc(imP_EOF, gpoutfile);
624 IMAGEN_putwd(unsigned int w)
626 /* fprintf(stderr,"%1u\n",w); */
627 putc(w >> 8, gpoutfile);
632 IMAGEN_createfamily(char *c, int sz)
635 putc(imP_CREATE_FAMILY_TABLE, gpoutfile);
639 /* putc(0, gpoutfile); */
645 IMAGEN_setfont(int sz)
649 if (!IMAGEN_familytable[sz]) {
650 sprintf(font, "%s%02d", IMAGEN_FONT, sz);
651 IMAGEN_createfamily(font, sz);
652 IMAGEN_familytable[sz] = sz;
654 IMAGEN_hchar = sz * 5;
655 IMAGEN_wchar = IMAGEN_hchar / 2;
656 IMAGEN_blofs = IMAGEN_hchar / 3;
657 term->v_char = IMAGEN_hchar;
658 term->h_char = IMAGEN_wchar;
659 putc(imP_SET_FAMILY, gpoutfile);
661 putc(imP_SET_SP, gpoutfile);
662 IMAGEN_putwd(IMAGEN_wchar);
663 putc(imP_SET_IL, gpoutfile);
664 IMAGEN_putwd(IMAGEN_hchar);
668 IMP_set_draw_pattern(int pattern, int sz)
671 putc(imP_SET_DRAW_PATTERN, gpoutfile);
673 putc(imP_SET_DRAW_PATTERN, gpoutfile);
674 /* if ( strlen(IMPdrpattern[pattern]) == 1 ) {
675 putc(type,gpoutfile);
678 putc(strlen(IMPdrpattern[pattern]), gpoutfile);
679 for (i = 0; i < strlen(IMPdrpattern[pattern]); i++) {
680 IMAGEN_putwd(IMPdrpattern[pattern][i] * sz);
689 register int i /*, j */ ;
691 for (i = 32; i < 127; i++) {
707 IMP_gmap[14] = 61346;
716 IMP_gmap[23] = 61232;
724 IMP_gmap[31] = 61249;
729 IMP_gmap[127] = 61286;
731 /* for (i=1;i<127;i++) fprintf(stderr,"%d -> %d\n",i,IMP_gmap[i]); */
733 for (i = 32; i <= 127; i++) {
736 for (i = 128; i <= 255; i++) {
737 IMP_chmap[i] = 128; /* first map all non printable chars to SPACE */
743 IMP_chmap[164] = 120;
745 IMP_chmap[166] = 124;
754 IMP_chmap[175] = 126;
811 IMP_chmap[232] = 101;
812 IMP_chmap[233] = 101;
813 IMP_chmap[234] = 101;
814 IMP_chmap[235] = 101;
815 IMP_chmap[236] = 105;
816 IMP_chmap[237] = 105;
817 IMP_chmap[238] = 105;
818 IMP_chmap[239] = 105;
819 IMP_chmap[240] = 100;
820 IMP_chmap[241] = 110;
821 IMP_chmap[242] = 111;
822 IMP_chmap[243] = 111;
823 IMP_chmap[244] = 111;
824 IMP_chmap[245] = 111;
825 IMP_chmap[246] = 111;
828 IMP_chmap[249] = 117;
829 IMP_chmap[250] = 117;
830 IMP_chmap[251] = 117;
831 IMP_chmap[252] = 117;
832 IMP_chmap[253] = 121;
834 IMP_chmap[255] = 121;
838 IMAGEN_createmap(int name, unsigned short *map)
841 unsigned char s[4], *p;
844 *p++ = imP_CREATE_MAP;
847 for (i = 0; i < 127; i++) {
852 for (i = 0; i < 3; i++)
853 putc(s[i], gpoutfile);
856 for (j = 0; j < 127; j++) {
862 for (i = 0; i < 4; i++)
863 putc(s[i], gpoutfile);
868 #endif /* TERM_BODY */
872 TERM_TABLE_START(imagen_driver)
873 "imagen", "Imagen laser printer",
874 IMAGEN_XMAX, IMAGEN_YMAX, IMAGEN_VCHAR, IMAGEN_HCHAR,
875 IMAGEN_VTIC, IMAGEN_HTIC, IMAGEN_options, IMAGEN_init, IMAGEN_reset,
876 IMAGEN_text, null_scale, IMAGEN_graphics, IMAGEN_move,
877 IMAGEN_vector, IMAGEN_linetype, IMAGEN_put_text, IMAGEN_text_angle,
878 IMAGEN_justify_text, line_and_point, do_arrow, set_font_null
879 TERM_TABLE_END(imagen_driver)
882 #define LAST_TERM imagen_driver
884 #endif /* TERM_TABLE */
885 #endif /* TERM_PROTO_ONLY */
890 "?commands set terminal imagen",
891 "?set terminal imagen",
896 " The `imagen` terminal driver supports Imagen laser printers. It is capable",
897 " of placing multiple graphs on a single page.",
900 " set terminal imagen {<fontsize>} {portrait | landscape}",
901 " {[<horiz>,<vert>]}",
903 " where `fontsize` defaults to 12 points and the layout defaults to `landscape`.",
904 " `<horiz>` and `<vert>` are the number of graphs in the horizontal and",
905 " vertical directions; these default to unity.",
908 " set terminal imagen portrait [2,3]",
910 " puts six graphs on the page in three rows of two in portrait orientation."