Annotation of OpenXM_contrib/gnuplot/term/gif.trm, Revision 1.1.1.2
1.1 maekawa 1: /*
1.1.1.2 ! maekawa 2: * $Id: gif.trm,v 1.12.2.3 1999/09/29 13:53:53 lhecking Exp $
1.1 maekawa 3: */
4:
5: /* GNUPLOT -- gif.trm */
6:
7: /*[
8: * Copyright 1998
9: *
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.
15: *
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,
20: * provided you
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
28: * software.
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.
32: *
33: * This software is provided "as is" without express or implied warranty
34: * to the extent permitted by applicable law.
35: ]*/
36:
37: /*
38: * This file is included by ../term.c.
39: *
40: * This terminal driver supports:
41: * GD GIF library 1.2 & 1.3
42: *
43: * To Use:
44: *
45: * set terminal gif ?options ...?
46: *
47: * Where an option is:
48: *
49: * transparent - generate transparent GIFs. The first color will
50: * be the transparent one.
51: *
52: * interlace - generate interlaced GIFs.
53: *
54: * size (in pixels)
55: *
1.1.1.2 ! maekawa 56: * font (tiny,small,medium,large,giant)
1.1 maekawa 57: *
58: * xrrggbb - sets the next color. x is the literal character 'x',
59: * rrggbb are the red green and blue components in hex. For example
60: * x00ff00 is green. The background color is set first, then the
61: * color borders, then the X & Y axis, then the plotting colors.
62: * (The wierd color spec is in order to get around limitations
63: * in gnuplot's scanner.)
64: *
65: * This driver is modeled after the PBM driver pbm.trm.
66: *
67: * AUTHORS
68: * Sam Shen <sls@mh1.lbl.gov>
69: * Alex Woo <woo@playfair.stanford.edu>
70: *
71: * CONTRIBUTORS
1.1.1.2 ! maekawa 72: * Alfred Reibenschuh <alfred.reibenschuh@it-austria.com> or <fredo@blackbox.at>
! 73: * Ben Laurie <ben@algroup.co.uk>
1.1 maekawa 74: *
75: * send your comments or suggestions to:
76: * info-gnuplot@cs.dartmouth.edu
77: *
78: * This version outputs either color or monochrome GIFs. The default
79: * is 640x480 pixels.
80: *
81: * link with -Lterm/gd -lgd if your directory structure is gnuplot/term/gd
82: *
83: * gd is not distributed with gnuplot, because of the UNISYS license thing.
84: *
85: * find out about gd from http://www.boutell.com/gd/
86: *
1.1.1.2 ! maekawa 87: * Gd library versions before 1.3, and gd library 1.5 are subject to
! 88: * the Unisys license. Use at your own risk. From version 1.6 on, gd
! 89: * library creates png files instead of gif.
1.1 maekawa 90: *
91: */
92:
93: #include "driver.h"
94:
95: #ifdef TERM_REGISTER
96: register_term(gif)
97: #endif
98:
99: #ifdef TERM_PROTO
100: TERM_PUBLIC void GIF_options __PROTO((void));
101: TERM_PUBLIC void GIF_init __PROTO((void));
102: TERM_PUBLIC void GIF_graphics __PROTO((void));
103: TERM_PUBLIC void GIF_text __PROTO((void));
104: TERM_PUBLIC void GIF_linetype __PROTO((int linetype));
105: TERM_PUBLIC void GIF_move __PROTO((unsigned int x, unsigned int y));
106: TERM_PUBLIC void GIF_vector __PROTO((unsigned int x, unsigned int y));
107: TERM_PUBLIC void GIF_put_text __PROTO((unsigned int x, unsigned int y, char str[]));
108: TERM_PUBLIC int GIF_text_angle __PROTO((int ang));
109: TERM_PUBLIC void GIF_reset __PROTO((void));
110:
111: #include "gd.h"
1.1.1.2 ! maekawa 112:
1.1 maekawa 113: extern gdFontPtr gdFontSmall; /* 6x12 */
114: extern gdFontPtr gdFontLarge; /* 8x16 */
115: extern gdFontPtr gdFontMediumBold; /* 7x13 */
1.1.1.2 ! maekawa 116: extern gdFontPtr gdFontGiant; /* 9x15 */
! 117: extern gdFontPtr gdFontTiny; /* 5x8 */
1.1 maekawa 118:
119:
120: #define GREG_XMAX 640
121: #define GREG_YMAX 480
122:
123:
1.1.1.2 ! maekawa 124: static int GIF_XMAX = GREG_XMAX;
! 125: static int GIF_YMAX = GREG_YMAX;
1.1 maekawa 126:
127:
128: #define GIF_FONT_SMALL 1
129: #ifdef GIF_FONT_SMALL
130: # define gdfont gdFontSmall
131: # define GIF_VCHAR 12
132: # define GIF_HCHAR 6
133: #else
134: # define gdfont gdFontMediumBold
135: # define GIF_VCHAR 13
136: # define GIF_HCHAR 7
137: #endif
138:
139: static gdFontPtr GIF_font;
140:
141: #define GIF_VTIC (GREG_YMAX/100)
142: #define GIF_HTIC (GREG_XMAX/150)
143:
144: #define GIF_MAX_COLORS 256
145: #define GOT_NEXT_PROTO
146: #endif
147:
148: #ifndef TERM_PROTO_ONLY
149: #ifdef TERM_BODY
150:
151: static struct {
152: gdImagePtr image;
153: gdFontPtr font;
154: unsigned int x, y;
155: int height;
156: int charh, charw;
157: int color;
158: int n_colors;
159: int color_table[GIF_MAX_COLORS];
160: int rgb_table[GIF_MAX_COLORS];
161: int angle;
162: int flags;
163: int linetype;
164: } gif_state;
165:
166: #define GIF_USE_TRANSPARENT 1
167: #define GIF_USE_INTERLACE 2
168:
169: /*
170: * _options() Called when terminal type is selected.
171: * This procedure should parse options on the command line. A list of the
172: * currently selected options should be stored in term_options[] in a form
173: * suitable for use with the set term command. term_options[] is used by
174: * the save command. Use options_null() if no options are available.
175: */
1.1.1.2 ! maekawa 176: TERM_PUBLIC void
! 177: GIF_options()
1.1 maekawa 178: {
1.1.1.2 ! maekawa 179: struct value s;
1.1 maekawa 180: int gif_font, i;
1.1.1.2 ! maekawa 181: char *string;
! 182: unsigned long color;
! 183:
1.1 maekawa 184: term_options[0] = NUL;
185: gif_state.n_colors = 0;
186: gif_state.flags = 0;
187: gif_font = 1;
188: GIF_font = gdfont;
189:
190: while (!END_OF_COMMAND) {
191: if (almost_equals(c_token, "t$ransparent")) {
192: gif_state.flags |= GIF_USE_TRANSPARENT;
193: ++c_token;
194: } else if (almost_equals(c_token, "i$nterlace")) {
195: gif_state.flags |= GIF_USE_INTERLACE;
196: ++c_token;
1.1.1.2 ! maekawa 197: } else if (almost_equals(c_token, "ti$ny")) {
! 198: GIF_font=gdFontTiny;
! 199: gif_font = 0;
! 200: term->v_char = (unsigned int)(8);
! 201: term->h_char = (unsigned int)(5);
! 202: ++c_token;
1.1 maekawa 203: } else if (almost_equals(c_token, "s$mall")) {
204: GIF_font = gdFontSmall;
205: gif_font = 1;
206: term->v_char = (unsigned int) (12);
207: term->h_char = (unsigned int) (6);
208: ++c_token;
209: } else if (almost_equals(c_token, "m$edium")) {
210: GIF_font = gdFontMediumBold;
211: gif_font = 2;
212: term->v_char = (unsigned int) (13);
213: term->h_char = (unsigned int) (7);
214: ++c_token;
215: } else if (almost_equals(c_token, "l$arge")) {
216: GIF_font = gdFontLarge;
217: gif_font = 3;
218: term->v_char = (unsigned int) (16);
219: term->h_char = (unsigned int) (8);
220: ++c_token;
1.1.1.2 ! maekawa 221: } else if (almost_equals(c_token, "l$arge")) {
! 222: GIF_font=gdFontGiant;
! 223: gif_font = 4;
! 224: term->v_char = (unsigned int)(15);
! 225: term->h_char = (unsigned int)(9);
! 226: ++c_token;
1.1 maekawa 227: } else if (almost_equals(c_token, "si$ze")) {
228: c_token++;
229: if (END_OF_COMMAND) {
230: GIF_XMAX = GREG_XMAX;
231: GIF_YMAX = GREG_YMAX;
232: term->v_tic = GIF_YMAX / 80;
233: term->h_tic = GIF_XMAX / 80;
234: } else {
235: GIF_XMAX = real(const_express(&s));
236: if (equals(c_token, ",")) {
237: c_token++;
238: GIF_YMAX = real(const_express(&s));
239: term->v_tic = GIF_YMAX / 80;
240: term->h_tic = GIF_XMAX / 80;
241: term->ymax = GIF_YMAX;
242: term->xmax = GIF_XMAX;
243: }
244: }
1.1.1.2 ! maekawa 245: } else { /* not "size" */
! 246: string = input_line + token[c_token].start_index;
1.1 maekawa 247: if (sscanf(string, "x%lx", &color) != 1) {
1.1.1.2 ! maekawa 248: int_error("invalid color spec, must be xRRGGBB",c_token);
1.1 maekawa 249: } else if (gif_state.n_colors == GIF_MAX_COLORS) {
1.1.1.2 ! maekawa 250: int_warn("too many colors, ingoring",c_token);
1.1 maekawa 251: ++c_token;
252: } else {
253: gif_state.rgb_table[gif_state.n_colors++] = color;
254: ++c_token;
255: }
256: }
257: }
258:
259:
260: /* now generate options string */
261:
262: if (gif_state.flags & GIF_USE_TRANSPARENT) {
263: strcat(term_options, "transparent ");
264: }
265: if (gif_state.flags & GIF_USE_INTERLACE) {
266: strcat(term_options, "interlace ");
267: }
268: switch (gif_font) {
1.1.1.2 ! maekawa 269: case 0:
! 270: strcat(term_options,"tiny ");
! 271: break;
1.1 maekawa 272: case 1:
273: strcat(term_options, "small ");
274: break;
275: case 2:
276: strcat(term_options, "medium ");
277: break;
278: case 3:
279: strcat(term_options, "large ");
280: break;
1.1.1.2 ! maekawa 281: case 4:
! 282: strcat(term_options,"giant ");
! 283: break;
1.1 maekawa 284: }
285: sprintf(term_options + strlen(term_options),
286: "size %d,%d ", GIF_XMAX, GIF_YMAX);
287:
288: for (i = 0; i < gif_state.n_colors; i++) {
289: sprintf(term_options + strlen(term_options),
290: "x%06x ", gif_state.rgb_table[i]);
291: }
292: }
293:
294:
295: /*
296: * _init() Called once, when the device is first selected. This procedure
297: * should set up things that only need to be set once, like handshaking and
298: * character sets etc...
299: */
1.1.1.2 ! maekawa 300: TERM_PUBLIC void
! 301: GIF_init()
1.1 maekawa 302: {
303: gif_state.linetype = 0;
304: }
305:
306: /*
307: * _reset() Called when gnuplot is exited, the output device changed or
308: * the terminal type changed. This procedure should reset the device,
309: * possibly flushing a buffer somewhere or generating a form feed.
310: */
1.1.1.2 ! maekawa 311: TERM_PUBLIC void
! 312: GIF_reset()
1.1 maekawa 313: {
314: }
315:
316: /*
317: * _graphics() Called just before a plot is going to be displayed. This
318: * procedure should set the device into graphics mode. Devices which can't
319: * be used as terminals (like plotters) will probably be in graphics mode
320: * always and therefore won't need this.
321: */
1.1.1.2 ! maekawa 322: TERM_PUBLIC void
! 323: GIF_graphics()
1.1 maekawa 324: {
325: int i;
326: unsigned int rgb;
327: gif_state.font = GIF_font;
328: gif_state.color = 0;
329: gif_state.image = gdImageCreate((int) (xsize * GIF_XMAX),
330: (int) (ysize * GIF_YMAX));
1.1.1.2 ! maekawa 331: gif_state.height = (int) (ysize * GIF_YMAX - 1);
1.1 maekawa 332: gif_state.charw = term->h_char; /* gif_state.font->w; */
333: gif_state.charh = term->v_char; /* gif_state.font->h; */
1.1.1.2 ! maekawa 334: for (i = gif_state.n_colors; i < WEB_N_COLORS; i++)
! 335: gif_state.rgb_table[i] =
! 336: (web_color_rgbs[i].r << 16) |
! 337: (web_color_rgbs[i].g << 8) |
! 338: web_color_rgbs[i].b;
! 339: if (gif_state.n_colors < WEB_N_COLORS)
! 340: gif_state.n_colors = WEB_N_COLORS;
1.1 maekawa 341: for (i = 0; i < gif_state.n_colors; i++) {
342: rgb = gif_state.rgb_table[i];
343: gif_state.color_table[i] =
344: gdImageColorAllocate(gif_state.image, (rgb >> 16) & 0xff,
345: (rgb >> 8) & 0xff, rgb & 0xff);
346: }
347: if (gif_state.flags & GIF_USE_TRANSPARENT)
348: gdImageColorTransparent(gif_state.image,
349: gif_state.color_table[0]);
350: else
351: gdImageColorTransparent(gif_state.image, -1);
352: }
353:
354: /*
355: * _text() Called immediately after a plot is displayed. This procedure
356: * should set the device back into text mode if it is also a terminal, so
357: * that commands can be seen as they're typed. Again, this will probably
358: * do nothing if the device can't be used as a terminal.
359: */
1.1.1.2 ! maekawa 360: TERM_PUBLIC void
! 361: GIF_text()
1.1 maekawa 362: {
363: if (gif_state.flags & GIF_USE_INTERLACE)
364: gdImageInterlace(gif_state.image, 1);
365: gdImageGif(gif_state.image, gpoutfile);
366: gdImageDestroy(gif_state.image);
367: }
368:
369: /* _move(x,y) Called at the start of a line. The cursor should move to the
370: * (x,y) position without drawing.
371: */
1.1.1.2 ! maekawa 372: TERM_PUBLIC void
! 373: GIF_move(unsigned int x, unsigned int y)
1.1 maekawa 374: {
375: gif_state.x = x;
376: gif_state.y = y;
377: }
378:
379: /* _vector(x,y) Called when a line is to be drawn. This should display a line
380: * from the last (x,y) position given by _move() or _vector() to this new (x,y)
381: * position.
382: */
1.1.1.2 ! maekawa 383: TERM_PUBLIC void
! 384: GIF_vector(unsigned int x, unsigned int y)
1.1 maekawa 385: {
386: int gif_linetype_dotted[5];
387:
388: if (gif_state.linetype == -1) {
389: gif_linetype_dotted[0] = gif_state.color_table[2];
390: gif_linetype_dotted[1] = gif_state.color_table[2];
391: gif_linetype_dotted[2] = gif_state.color_table[0];
392: gif_linetype_dotted[3] = gif_state.color_table[0];
393: gif_linetype_dotted[4] = gif_state.color_table[0];
394:
395: gdImageSetStyle(gif_state.image, gif_linetype_dotted, 5);
396: gdImageLine(gif_state.image, gif_state.x, gif_state.height - gif_state.y,
397: x, gif_state.height - y, gdStyled);
398: } else {
399: gdImageLine(gif_state.image, gif_state.x, gif_state.height - gif_state.y,
400: x, gif_state.height - y, gif_state.color);
401: }
402: gif_state.x = x;
403: gif_state.y = y;
404: }
405:
406: /* _linetype(lt) Called to set the line type before text is displayed or
407: * line(s) plotted. This procedure should select a pen color or line
408: * style if the device has these capabilities.
409: * lt is an integer from -2 to 0 or greater.
410: * An lt of -2 is used for the border of the plot.
411: * An lt of -1 is used for the X and Y axes.
412: * lt 0 and upwards are used for plots 0 and upwards.
413: * If _linetype() is called with lt greater than the available line types,
414: * it should map it to one of the available line types.
415: * Most drivers provide 9 different linetypes (lt is 0 to 8).
416: */
1.1.1.2 ! maekawa 417: TERM_PUBLIC void
! 418: GIF_linetype(int type)
1.1 maekawa 419: {
420: if (type >= (gif_state.n_colors - 3))
421: type %= (gif_state.n_colors - 3);
422:
423: gif_state.color = gif_state.color_table[type + 3];
424: gif_state.linetype = type;
425: }
426:
427: /* _put_text(x,y,str) Called to display text at the (x,y) position,
428: * while in graphics mode. The text should be vertically (with respect
429: * to the text) justified about (x,y). The text is rotated according
430: * to _text_angle and then horizontally (with respect to the text)
431: * justified according to _justify_text.
432: */
1.1.1.2 ! maekawa 433: TERM_PUBLIC void
! 434: GIF_put_text(unsigned int x, unsigned int y, char *string)
1.1 maekawa 435: {
436: if (gif_state.angle == 1) {
437: x -= gif_state.charh / 2;
438: gdImageStringUp(gif_state.image, gif_state.font,
439: x, gif_state.height - y,
440: string, gif_state.color);
441: } else {
442: y += gif_state.charh / 2;
443: gdImageString(gif_state.image, gif_state.font,
444: x, gif_state.height - y,
445: string, gif_state.color);
446: }
447: }
448:
449: /* _text_angle(ang) Called to rotate the text angle when placing the y label.
450: * If ang = 0 then text is horizontal. If ang = 1 then text is vertically
451: * upwards. Returns TRUE if text can be rotated, FALSE otherwise.
452: */
1.1.1.2 ! maekawa 453: TERM_PUBLIC int
! 454: GIF_text_angle(int ang)
1.1 maekawa 455: {
456: gif_state.angle = ang;
457: return TRUE;
458: }
459:
1.1.1.2 ! maekawa 460: TERM_PUBLIC int
! 461: GIF_set_font(char *fontname)
! 462: {
! 463: char name[32];
! 464: int sep;
! 465: gdFontPtr font;
! 466:
! 467: sep = strcspn(fontname,",");
! 468: strncpy(name,fontname,sep);
! 469: name[sep] = NUL;
! 470:
! 471: if (!strcmp(fontname,"small"))
! 472: font = gdFontSmall;
! 473: else if (!strcmp(fontname,"medium"))
! 474: font = gdFontMediumBold;
! 475: else if(!strcmp(fontname,"large"))
! 476: font = gdFontLarge;
! 477: else if(!strcmp(fontname,"giant"))
! 478: font = gdFontGiant;
! 479: else if(!strcmp(fontname,"tiny"))
! 480: font = gdFontTiny;
! 481: else
! 482: font = GIF_font;
! 483:
! 484: gif_state.charw = font->w;
! 485: gif_state.charh = font->h;
! 486:
! 487: gif_state.font = font;
! 488:
! 489: return TRUE;
! 490: }
1.1 maekawa 491:
492: #endif /* TERM_BODY */
493: #ifdef TERM_TABLE
494:
495: TERM_TABLE_START(gif_driver)
496: "gif", "GIF format [mode] [fontsize] [size] [colors]",
497: GREG_XMAX, GREG_YMAX, GIF_VCHAR, GIF_HCHAR,
498: GIF_VTIC, GIF_HTIC, GIF_options, GIF_init, GIF_reset,
499: GIF_text, null_scale, GIF_graphics, GIF_move, GIF_vector,
500: GIF_linetype, GIF_put_text, GIF_text_angle,
1.1.1.2 ! maekawa 501: null_justify_text, do_point, do_arrow, GIF_set_font,
1.1 maekawa 502: 0, /* pointsize */
503: TERM_CAN_MULTIPLOT | TERM_BINARY
504: TERM_TABLE_END(gif_driver)
505:
506: #undef LAST_TERM
507: #define LAST_TERM gif_driver
508:
509: #endif /* TERM_TABLE */
510: #endif /* TERM_PROTO_ONLY */
511:
512: #ifdef TERM_HELP
513: START_HELP(gif)
514: "1 gif",
515: "?commands set terminal gif",
516: "?set terminal gif",
517: "?set term gif",
518: "?terminal gif",
519: "?term gif",
520: "?gif",
521: " The `gif` terminal driver generates output in GIF format. It uses Thomas",
522: " Boutell's gd library, which is available from http://www.boutell.com/gd/",
523: "",
1.1.1.2 ! maekawa 524: " By default, the `gif` terminal driver uses a shared Web-friendy palette."
! 525: "",
1.1 maekawa 526: " Syntax:",
527: " set terminal gif {transparent} {interlace}",
1.1.1.2 ! maekawa 528: " {tiny | small | medium | large | giant}",
1.1 maekawa 529: " {size <x>,<y>}",
530: " {<color0> <color1> <color2> ...}",
531: "",
532: " `transparent` instructs the driver to generate transparent GIFs. The first",
533: " color will be the transparent one.",
534: "",
535: " `interlace` instructs the driver to generate interlaced GIFs.",
536: "",
1.1.1.2 ! maekawa 537: " The choice of fonts is `tiny` (5x8 pixels), `small` (6x12 pixels), `medium`",
! 538: " (7x13 Bold), `large` (8x16) or `giant` (9x15 pixels)",
1.1 maekawa 539: "",
540: " The size <x,y> is given in pixels---it defaults to 640x480. The number of",
541: " pixels can be also modified by scaling with the `set size` command.",
542: "",
543: " Each color must be of the form 'xrrggbb', where x is the literal character",
544: " 'x' and 'rrggbb' are the red, green and blue components in hex. For example,",
545: " 'x00ff00' is green. The background color is set first, then the border",
546: " colors, then the X & Y axis colors, then the plotting colors. The maximum",
547: " number of colors that can be set is 256.",
548: "",
549: " Examples:",
550: " set terminal gif small size 640,480 \\",
551: " xffffff x000000 x404040 \\",
552: " xff0000 xffa500 x66cdaa xcdb5cd \\",
553: " xadd8e6 x0000ff xdda0dd x9500d3 # defaults",
554: "",
555: " which uses white for the non-transparent background, black for borders, gray",
556: " for the axes, and red, orange, medium aquamarine, thistle 3, light blue, blue,",
557: " plum and dark violet for eight plotting colors.",
558: "",
559: " set terminal gif transparent xffffff \\",
560: " x000000 x202020 x404040 x606060 \\",
561: " x808080 xA0A0A0 xC0C0C0 xE0E0E0 \\",
562: " which uses white for the transparent background, black for borders, dark",
563: " gray for axes, and a gray-scale for the six plotting colors.",
564: "",
565: " The page size is 640x480 pixels. The `gif` driver can create either color",
566: " or monochromatic output, but you have no control over which is produced.",
567: "",
568: " The current version of the `gif` driver does not support animated GIFs."
569: END_HELP(gif)
570: #endif /* TERM_HELP */
1.1.1.2 ! maekawa 571:
! 572: /*
! 573: * Local Variables:
! 574: * mode:C
! 575: * End:
! 576: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>