- Optification is done by auto builder now
[gnuplot] / term / ai.trm
1 /* Hello, Emacs, this is -*-C-*-
2  * $Id: ai.trm,v 1.21 2006/07/29 22:35:43 tlecomte Exp $
3  *
4  */
5
6 /* GNUPLOT - ai.trm */
7
8 /*[
9  * Copyright 1991, 1992, 1993, 1998, 2004
10  *
11  * Permission to use, copy, and distribute this software and its
12  * documentation for any purpose with or without fee is hereby granted,
13  * provided that the above copyright notice appear in all copies and
14  * that both that copyright notice and this permission notice appear
15  * in supporting documentation.
16  *
17  * Permission to modify the software is granted, but not the right to
18  * distribute the complete modified source code.  Modifications are to
19  * be distributed as patches to the released version.  Permission to
20  * distribute binaries produced by compiling modified sources is granted,
21  * provided you
22  *   1. distribute the corresponding source modifications from the
23  *    released version in the form of a patch file along with the binaries,
24  *   2. add special version identification to distinguish your version
25  *    in addition to the base release version number,
26  *   3. provide your name and address as the primary contact for the
27  *    support of your modified version, and
28  *   4. retain our contact information in regard to use of the base
29  *    software.
30  * Permission to distribute the released version of the source code along
31  * with corresponding source modifications in the form of a patch file is
32  * granted with same provisions 2 through 4 for binary distributions.
33  *
34  * This software is provided "as is" without express or implied warranty
35  * to the extent permitted by applicable law.
36 ]*/
37
38 /*
39  * This file is included by ../term.c.
40  *
41  * This terminal driver supports:
42  *     aifm
43  *
44  * AUTHORS
45  *  Ray Ghanbari
46  *
47  * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
48  *
49  * The 'aifm' driver produces files editable by Adobe Illustrator 3.0
50  * To change font to Courier and font size to 20pts use
51  * 'set term aifm "Courier" 20'.
52  * To switch to color output use
53  * 'set term aifm color'.
54  */
55
56  /* AIFM driver by Ray Ghanbari, ray@mtl.mit.edu,
57   *   based on PostScript driver by Russell Lang, rjl@monu1.cc.monash.edu.au */
58
59 /* Changed to 3.6 terminal format, David C. Schooley, 9/29/95 */
60 /* Improved multiple plot support, David C. Schooley, 6/5/95 */
61 /* Compatiblity with Illustrator 7.0, David C. Schooley, 6/5/95 */
62 /* Font and size support for labels, David C. Schooley, 6/5/95 */
63
64 #include "driver.h"
65
66 #ifdef TERM_REGISTER
67 register_term(aifm)
68 #endif
69
70 #ifdef TERM_PROTO
71 TERM_PUBLIC void AI_init __PROTO((void));
72 TERM_PUBLIC void AI_graphics __PROTO((void));
73 TERM_PUBLIC void AI_text __PROTO((void));
74 TERM_PUBLIC void AI_linetype __PROTO((int linetype));
75 TERM_PUBLIC void AI_move __PROTO((unsigned int x, unsigned int y));
76 TERM_PUBLIC void AI_vector __PROTO((unsigned int x, unsigned int y));
77 TERM_PUBLIC void AI_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
78 TERM_PUBLIC int AI_text_angle __PROTO((int ang));
79 TERM_PUBLIC void AI_reset __PROTO((void));
80 TERM_PUBLIC void AI_options __PROTO((void));
81 TERM_PUBLIC int AI_justify_text __PROTO((enum JUSTIFY mode));
82 TERM_PUBLIC void AI_suspend __PROTO((void));
83 TERM_PUBLIC void AI_resume __PROTO((void));
84 TERM_PUBLIC int AI_set_font __PROTO((const char *font));
85
86 #define AI_XOFF 50              /* page offset in pts */
87 #define AI_YOFF 50
88
89 #define AI_XMAX 5000
90 #define AI_YMAX 3500
91
92 #define AI_XLAST (AI_XMAX - 1)
93 #define AI_YLAST (AI_YMAX - 1)
94
95 #define AI_VTIC (AI_YMAX/80)
96 #define AI_HTIC (AI_YMAX/80)
97
98 #define AI_SC (10.0)            /* scale is 1pt = 10 units */
99 #define AI_LW (0.5*AI_SC)       /* linewidth = 0.5 pts */
100
101 #define AI_VCHAR (14*AI_SC)     /* default is 14 point characters */
102 #define AI_HCHAR (14*AI_SC*6/10)
103
104 #endif /* TERM_PROTO */
105
106
107 #ifndef TERM_PROTO_ONLY
108 #ifdef TERM_BODY
109
110 enum AI_id { AI_DEFAULT, AI_MONOCHROME, AI_COLOUR, AI_OTHER };
111
112 static struct gen_table AI_opts[] =
113 {
114     { "d$efault", AI_DEFAULT },
115     { "m$onochrome", AI_MONOCHROME },
116     { "c$olor", AI_COLOUR },
117     { "c$olour", AI_COLOUR },
118     { NULL, AI_OTHER }
119 };
120
121 #define DEFAULT_FONT "Times-Roman"
122
123 /* name of font */
124 static char ai_font[MAX_ID_LEN + 1] = DEFAULT_FONT;
125
126 /* size of font in pts */
127 static int ai_fontsize = 14;
128
129 /* name of font */
130 static char ai_oldfont[MAX_ID_LEN + 1] = DEFAULT_FONT;
131
132 /* size of font in pts */
133 static int ai_oldfontsize = 14;
134
135 static TBOOLEAN ai_color = FALSE;
136 static TBOOLEAN ai_stroke = FALSE;
137 static int ai_page = 0;         /* page count */
138 static int ai_path_count = 0;           /* count of lines in path */
139 static int ai_ang = 0;                  /* text angle */
140 static int ai_subgroup_level = 0;       /* depth of sub-groups */
141 static int ai_multiplot_group = 0;      /* group for multiplot */
142 static enum JUSTIFY ai_justify = LEFT;  /* text is flush left */
143
144
145 TERM_PUBLIC void
146 AI_options()
147 {
148     while (!END_OF_COMMAND) {
149         switch(lookup_table(&AI_opts[0],c_token)) {
150         case AI_DEFAULT:
151             c_token++;
152             ai_color = FALSE;
153             strncpy(ai_font,DEFAULT_FONT,sizeof(ai_font));
154             ai_fontsize = 14;
155             strncpy(ai_oldfont,DEFAULT_FONT,sizeof(ai_oldfont));
156             ai_oldfontsize = 14;
157             break;
158         case AI_MONOCHROME:
159             c_token++;
160             ai_color = FALSE;
161             break;
162         case AI_COLOUR:
163             c_token++;
164             ai_color = TRUE;
165             break;
166         case AI_OTHER:
167         default:
168             if (isstring(c_token)) {
169                 quote_str(ai_font, c_token, MAX_ID_LEN);
170                 strcpy(ai_oldfont, ai_font);
171                 c_token++;
172             } else { /* is a number */
173                 /* We have font size specified */
174                 struct value a;
175                 ai_fontsize = (int) real(const_express(&a));
176                 ai_oldfontsize = ai_fontsize;
177                 term->v_char = (unsigned int) (ai_fontsize * AI_SC);
178                 term->h_char = (unsigned int) (ai_fontsize * AI_SC * 6 / 10);
179             }
180             break;
181         }
182     }
183
184     sprintf(term_options, "%s \"%s\" %d",
185             ai_color ? "color" : "monochrome", ai_font, ai_fontsize);
186 }
187
188
189 TERM_PUBLIC
190 void AI_init()
191 {
192     ai_page = 0;
193
194     fprintf(gpoutfile, "%%!PS-Adobe-2.0 EPSF-1.2\n\
195 %%%%Creator: Adobe Illustrator(TM) 3.2\n\
196 %%%%TrueCreator: gnuplot %s patchlevel %s ai terminal\n\
197 %%%%BoundingBox: %d %d %d %d\n\
198 %%%%Template:\n\
199 %%%%EndComments\n\
200 %%%%EndProlog\n",
201             gnuplot_version, gnuplot_patchlevel,
202             AI_XOFF, AI_YOFF,
203             (int) ((AI_XMAX) / AI_SC + 0.5 + AI_XOFF),
204             (int) ((AI_YMAX) / AI_SC + 0.5 + AI_YOFF));
205 }
206
207
208 TERM_PUBLIC void
209 AI_graphics()
210 {
211     ai_page++;
212 /*      fprintf(gpoutfile,"%%%%Page: %d %d\n",ai_page,ai_page);*/
213     fputs("\
214 0 G\n\
215 1 j\n\
216 1 J\n\
217 u\n", gpoutfile);
218     ai_path_count = 0;
219     ai_stroke = FALSE;
220 }
221
222
223 TERM_PUBLIC void
224 AI_text()
225 {
226     if (ai_stroke) {
227         fputs("S\n", gpoutfile);
228         ai_stroke = FALSE;
229     }
230     while (ai_subgroup_level) {
231         fputs("U\n", gpoutfile);
232         ai_subgroup_level--;
233     }
234     fputs("U\n", gpoutfile);
235     ai_path_count = 0;
236     ai_multiplot_group = 0;
237 }
238
239
240 TERM_PUBLIC void
241 AI_reset()
242 {
243     fputs("%%Trailer\n", gpoutfile);
244 /*      fprintf(gpoutfile,"%%%%Pages: %d\n",ai_page);*/
245 }
246
247
248 TERM_PUBLIC void
249 AI_linetype(int linetype)
250 {
251     if (ai_stroke) {
252         fputs("S\n", gpoutfile);
253         ai_stroke = FALSE;
254     }
255     if (ai_subgroup_level) {
256         fputs("U\n", gpoutfile);
257         ai_subgroup_level--;
258     }
259     if (linetype == LT_BLACK && multiplot) {
260         /* for each new plot, line_type gets called twice with a value of LT_BLACK.
261            It gets called once for the border and again for the tics.
262            This code will need to be changed if gnuplot's behavior changes.
263          */
264         switch (ai_multiplot_group) {
265         case 0:
266             fputs("u\n", gpoutfile);
267             ai_subgroup_level++;
268             ai_multiplot_group = 1;
269             break;
270         case 1:
271             ai_multiplot_group = 2;
272             break;
273         case 2:
274             ai_multiplot_group = 1;
275             fputs("U\nu\n", gpoutfile);
276             break;
277         }
278     }
279     if (linetype == LT_BLACK && !multiplot) {
280         if (ai_multiplot_group) {
281             fputs("U\n", gpoutfile);
282             ai_subgroup_level--;
283             ai_multiplot_group = 0;
284         }
285     }
286     fputs("u\n", gpoutfile);
287     ai_subgroup_level++;
288
289     switch (linetype) {
290     case LT_BLACK:
291         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC * 2.0);
292         if (ai_color) {
293             fputs("0 0 0 1 K\n", gpoutfile);
294         } else {
295             fputs("[] 0 d\n", gpoutfile);
296         }
297         break;
298
299     case LT_AXIS:
300         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC / 2.0);
301         if (ai_color) {
302             fputs("0 0 0 1 K\n", gpoutfile);
303         } else {
304             fputs("[1 2] 0 d\n", gpoutfile);
305         }
306         break;
307
308     case 0:
309         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC);
310         if (ai_color) {
311             fputs("1 0 1 0 K\n", gpoutfile);
312         } else {
313             fputs("[] 0 d\n", gpoutfile);
314         }
315         break;
316
317     case 1:
318         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC);
319         if (ai_color) {
320             fputs("1 1 0 0 K\n", gpoutfile);
321         } else {
322             fputs("[4 2] 0 d\n", gpoutfile);
323         }
324         break;
325
326     case 2:
327         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC);
328         if (ai_color) {
329             fputs("0 1 1 0 K\n", gpoutfile);
330         } else {
331             fputs("[2 3] 0 d\n", gpoutfile);
332         }
333         break;
334
335     case 3:
336         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC);
337         if (ai_color) {
338             fputs("0 1 0 0 K\n", gpoutfile);
339         } else {
340             fputs("[1 1.5] 0 d\n", gpoutfile);
341         }
342         break;
343
344     case 4:
345         fprintf(gpoutfile, "%f w\n", AI_LW / AI_SC);
346         if (ai_color) {
347             fputs("1 0 0 0 K\n", gpoutfile);
348         } else {
349             fputs("[5 2 1 2] 0 d\n", gpoutfile);
350         }
351         break;
352
353     case 5:
354         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC);
355         if (ai_color) {
356             fputs("0 0 1 0 K\n", gpoutfile);
357         } else {
358             fputs("[4 3 1 3] 0 d\n", gpoutfile);
359         }
360         break;
361
362     case 6:
363         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC);
364         if (ai_color) {
365             fputs("0 0 0 1 K\n", gpoutfile);
366         } else {
367             fputs("[2 2 2 4] 0 d\n", gpoutfile);
368         }
369         break;
370
371     case 7:
372         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC);
373         if (ai_color) {
374             fputs("0 0.7 1 0 K\n", gpoutfile);
375         } else {
376             fputs("[2 2 2 2 2 4] 0 d\n", gpoutfile);
377         }
378         break;
379
380     case 8:
381         fprintf(gpoutfile, "%.2f w\n", AI_LW / AI_SC);
382         if (ai_color) {
383             fputs("0.5 0.5 0.5 0 K\n", gpoutfile);
384         } else {
385             fputs("[2 2 2 2 2 2 2 4] 0 d\n", gpoutfile);
386         }
387         break;
388     }
389
390     ai_path_count = 0;
391 }
392
393
394 TERM_PUBLIC void
395 AI_move(unsigned int x, unsigned int y)
396 {
397     if (ai_stroke)
398         fputs("S\n", gpoutfile);
399     fprintf(gpoutfile, "%.2f %.2f m\n", x / AI_SC, y / AI_SC);
400     ai_path_count += 1;
401     ai_stroke = TRUE;
402 }
403
404
405 TERM_PUBLIC void
406 AI_vector(unsigned int x, unsigned int y)
407 {
408     fprintf(gpoutfile, "%.2f %.2f l\n", x / AI_SC, y / AI_SC);
409     ai_path_count += 1;
410     ai_stroke = TRUE;
411     if (ai_path_count >= 400) {
412         fprintf(gpoutfile, "S\n%.2f %.2f m\n", x / AI_SC, y / AI_SC);
413         ai_path_count = 0;
414     }
415 }
416
417
418 TERM_PUBLIC void
419 AI_put_text(unsigned int x, unsigned int y, const char *str)
420 {
421     char ch;
422     if (ai_stroke) {
423         fputs("S\n", gpoutfile);
424         ai_stroke = FALSE;
425     }
426     switch (ai_justify) {
427     case LEFT:
428         fprintf(gpoutfile, "/_%s %d 0 0 0 z\n", ai_font, ai_fontsize);
429         break;
430     case CENTRE:
431         fprintf(gpoutfile, "/_%s %d 0 0 1 z\n", ai_font, ai_fontsize);
432         break;
433     case RIGHT:
434         fprintf(gpoutfile, "/_%s %d 0 0 2 z\n", ai_font, ai_fontsize);
435         break;
436     }
437     if (ai_ang == 0) {
438         fprintf(gpoutfile, "[ 1 0 0 1 %.2f %.2f] e\n",
439                 x / AI_SC, y / AI_SC - ai_fontsize / 3.0);
440     } else {
441         fprintf(gpoutfile, "[ 0 1 -1 0 %.2f %.2f] e\n",
442                 x / AI_SC - ai_fontsize / 3.0, y / AI_SC);
443     }
444
445     putc('(', gpoutfile);
446     ch = *str++;
447     while (ch != '\0') {
448         if ((ch == '(') || (ch == ')') || (ch == '\\'))
449             putc('\\', gpoutfile);
450         putc(ch, gpoutfile);
451         ch = *str++;
452     }
453     fputs(") t\nT\n", gpoutfile);
454     ai_path_count = 0;
455 }
456
457 TERM_PUBLIC int
458 AI_text_angle(int ang)
459 {
460     ai_ang = ang;
461     return TRUE;
462 }
463
464 TERM_PUBLIC int
465 AI_justify_text(enum JUSTIFY mode)
466 {
467     ai_justify = mode;
468     return TRUE;
469 }
470
471 TERM_PUBLIC int
472 AI_set_font(const char *font)
473 {
474     char name[32];
475     size_t sep;
476     int size;
477
478     if (font && *font) {
479         sep = strcspn(font, ",");
480         assert(sep < sizeof(name));
481         strncpy(name, font, sep);
482         name[sep] = '\0';
483         size = ai_fontsize;
484         sscanf(&(font[sep + 1]), "%d", &size);
485         if (*name)
486             strcpy(ai_font, name);
487         if (size)
488             ai_fontsize = size;
489     } else {
490         ai_fontsize = ai_oldfontsize;
491         strcpy(ai_font, ai_oldfont);
492     }
493     return TRUE;
494 }
495
496
497 TERM_PUBLIC void
498 AI_suspend()
499 {
500 }
501
502 TERM_PUBLIC void
503 AI_resume()
504 {
505 }
506
507
508 #endif
509
510
511 #ifdef TERM_TABLE
512
513 TERM_TABLE_START(aifm_driver)
514     "aifm", "Adobe Illustrator 3.0 Format",
515     AI_XMAX, AI_YMAX, AI_VCHAR, AI_HCHAR,
516     AI_VTIC, AI_HTIC, AI_options, AI_init, AI_reset,
517     AI_text, null_scale, AI_graphics, AI_move, AI_vector,
518     AI_linetype, AI_put_text, AI_text_angle,
519     AI_justify_text, do_point, do_arrow, AI_set_font,
520     NULL, 0, AI_suspend, AI_resume
521 TERM_TABLE_END(aifm_driver)
522
523 #undef LAST_TERM
524 #define LAST_TERM aifm_driver
525
526 #endif /* TERM_TABLE */
527 #endif /* TERM_PROTO_ONLY */
528
529 #ifdef TERM_HELP
530 START_HELP(aifm)
531 "1 aifm",
532 "?commands set terminal aifm",
533 "?set terminal aifm",
534 "?set term aifm",
535 "?terminal aifm",
536 "?term aifm",
537 "?aifm",
538 "",
539 " NOTE: this terminal driver is outdated. Since Adobe Illustrator understands",
540 " PostScript level 1 directly, you should use `set terminal post level1`",
541 " instead.",
542 "",
543 " Several options may be set in `aifm`---the Adobe Illustrator 3.0+ driver.",
544 "",
545 " Syntax:",
546 "       set terminal aifm {<color>} {\"<fontname>\"} {<fontsize>}",
547 "",
548 " <color> is either `color` or `monochrome`; \"<fontname>\" is the name of a",
549 " valid PostScript font; <fontsize> is the size of the font in PostScript",
550 " points, before scaling by the `set size` command.  Selecting `default` sets",
551 " all options to their default values: `monochrome`, \"Times-Roman\", and 14pt.",
552 "",
553 " Since AI does not really support multiple pages, multiple graphs will be",
554 " drawn directly on top of one another.  However, each graph will be grouped",
555 " individually, making it easy to separate them inside AI (just pick them up",
556 " and move them).",
557 "",
558 " Examples:",
559 "       set term aifm",
560 "       set term aifm 22",
561 "       set size 0.7,1.4; set term aifm color \"Times-Roman\" 14"
562 END_HELP(ai)
563 #endif /* TERM_HELP */