Initial release of Maemo 5 port of gnuplot
[gnuplot] / term / pbm.trm
1 /* Hello, Emacs, this is -*-C-*-
2  * $Id: pbm.trm,v 1.26.2.1 2006/11/23 05:36:01 sfeam Exp $
3  *
4  */
5
6 /* GNUPLOT - pbm.trm */
7
8 /*[
9  * Copyright 1990 - 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  *  pbm
43  *
44  * AUTHORS
45  *  Russell Lang
46  *
47  * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
48  *
49  */
50
51 /* The following pbmplus drivers use the generic bit mapped graphics
52    routines from bitmap.c to build up a bit map in memory.  The driver
53    interchanges colomns and lines in order to access entire lines
54    easily and returns the lines to get bits in the right order :
55    (x,y) -> (y,XMAX-1-x). */
56 /* This interchange is done by calling b_makebitmap() with reversed
57    xmax and ymax, and then setting b_rastermode to TRUE.  b_setpixel()
58    will then perform the interchange before each pixel is plotted */
59 /* See Jef Poskanzer's excellent PBMplus package for more details of
60    the Portable BitMap format and for programs to convert PBM files
61    to other bitmap formats. */
62
63 #include "driver.h"
64
65 #ifdef TERM_REGISTER
66 register_term(pbm_driver)
67 #endif
68
69 #ifdef TERM_PROTO
70 TERM_PUBLIC void PBM_options __PROTO((void));
71 TERM_PUBLIC void PBM_init __PROTO((void));
72 TERM_PUBLIC void PBM_reset __PROTO((void));
73 TERM_PUBLIC void PBM_setfont __PROTO((void));
74 TERM_PUBLIC void PBM_graphics __PROTO((void));
75 TERM_PUBLIC void PBM_monotext __PROTO((void));
76 TERM_PUBLIC void PBM_graytext __PROTO((void));
77 TERM_PUBLIC void PBM_colortext __PROTO((void));
78 TERM_PUBLIC void PBM_text __PROTO((void));
79 TERM_PUBLIC void PBM_linetype __PROTO((int linetype));
80 TERM_PUBLIC void PBM_point __PROTO((unsigned int x, unsigned int y, int point));
81 #endif /* TERM_PROTO */
82
83 /* make XMAX and YMAX a multiple of 8 */
84 #define PBM_XMAX (640)
85 #define PBM_YMAX (480)
86 #define PBM_VCHAR (FNT5X9_VCHAR)
87 #define PBM_HCHAR (FNT5X9_VCHAR)
88 #define PBM_VTIC FNT5X9_HBITS
89 #define PBM_HTIC FNT5X9_HBITS
90
91 #ifdef TERM_BODY
92
93 static int pbm_font = 1;        /* small font */
94 static int pbm_mode = 0;        /* 0:monochrome 1:gray 2:color */
95
96 /* Only needed for dubious backwards compatibility with 'set size'
97  * in pre-4.2 versions that didn't support 'set term size'
98  */
99 static TBOOLEAN PBM_explicit_size = FALSE;
100
101 /* 7=black, 0=white */
102 static int pgm_gray[] = { 7, 1, 6, 5, 4, 3, 2, 1, 7 };  /* grays  */
103 /* bit3=!intensify, bit2=!red, bit1=!green, bit0=!blue */
104 static int ppm_color[] ={ 15, 8, 3, 5, 6, 2, 4, 1, 11, 13, 14 };  /* colors */
105
106 enum PBM_id {
107     PBM_SMALL, PBM_MEDIUM, PBM_LARGE,
108     PBM_MONOCHROME, PBM_GRAY, PBM_COLOR, PBM_SIZE,
109     PBM_OTHER
110 };
111
112 static struct gen_table PBM_opts[] =
113 {
114     { "s$mall", PBM_SMALL },
115     { "me$dium", PBM_MEDIUM },
116     { "l$arge", PBM_LARGE },
117     { "mo$nochrome", PBM_MONOCHROME },
118     { "g$ray", PBM_GRAY },
119     { "c$olor", PBM_COLOR },
120     { "c$olour", PBM_COLOR },
121     { "size", PBM_SIZE },
122     { NULL, PBM_OTHER }
123 };
124
125 TERM_PUBLIC void
126 PBM_options()
127 {
128     int xpixels = PBM_XMAX;
129     int ypixels = PBM_YMAX;
130     struct value a;
131     pbm_font = 1;
132     pbm_mode = 0;
133
134     term_options[0] = NUL;
135
136     while (!END_OF_COMMAND) {
137         switch(lookup_table(&PBM_opts[0],c_token)) {
138         case PBM_SMALL:
139             pbm_font = 1;
140             c_token++;
141             break;
142         case PBM_MEDIUM:
143             pbm_font = 2;
144             c_token++;
145             break;
146         case PBM_LARGE:
147             pbm_font = 3;
148             c_token++;
149             break;
150         case PBM_MONOCHROME:
151             pbm_mode = 0;
152             c_token++;
153             break;
154         case PBM_GRAY:
155             pbm_mode = 1;
156             c_token++;
157             break;
158         case PBM_COLOR:
159             pbm_mode = 2;
160             c_token++;
161             break;
162         case PBM_SIZE:
163             c_token++;
164             if (END_OF_COMMAND) {
165                 term->xmax = PBM_XMAX;
166                 term->ymax = PBM_YMAX;
167                 PBM_explicit_size = FALSE;
168             } else {
169                 xpixels = real(const_express(&a));
170                 if (equals(c_token, ",")) {
171                     c_token++;
172                     ypixels = real(const_express(&a));
173                 }
174                 PBM_explicit_size = TRUE;
175             }
176             if (xpixels > 0)
177                 term->xmax = xpixels;
178             if (ypixels > 0)
179                 term->ymax = ypixels;
180             break;
181         case PBM_OTHER:
182         default:
183             /* reset to default, since term is already set */
184             pbm_font = 1;
185             pbm_mode = 0;
186             int_error(c_token, "expecting: {small, medium, large} and {monochrome, gray, color}");
187             break;
188         }
189     }
190
191     /* setup options string */
192
193     switch (pbm_font) {
194     case 1:
195         strcat(term_options, "small");
196         break;
197     case 2:
198         strcat(term_options, "medium");
199         break;
200     case 3:
201         strcat(term_options, "large");
202         break;
203     }
204
205     switch (pbm_mode) {
206     case 0:
207         strcat(term_options, " monochrome");
208         break;
209     case 1:
210         strcat(term_options, " gray");
211         break;
212     case 2:
213         strcat(term_options, " color");
214         break;
215     }
216
217     if (PBM_explicit_size)
218         sprintf(term_options + strlen(term_options), " size %d,%d",
219             term->xmax, term->ymax);
220 }
221
222
223 TERM_PUBLIC void
224 PBM_init()
225 {
226     PBM_setfont();              /* HBB 980226: call it here! */
227 }
228
229
230 TERM_PUBLIC void
231 PBM_reset()
232 {
233 #ifdef VMS
234     fflush_binary();
235 #endif /* VMS */
236 }
237
238
239 TERM_PUBLIC void
240 PBM_setfont()
241 {
242     switch (pbm_font) {
243     case 1:
244         b_charsize(FNT5X9);
245         term->v_char = FNT5X9_VCHAR;
246         term->h_char = FNT5X9_HCHAR;
247         term->v_tic = FNT5X9_HBITS;
248         term->h_tic = FNT5X9_HBITS;
249         break;
250     case 2:
251         b_charsize(FNT9X17);
252         term->v_char = FNT9X17_VCHAR;
253         term->h_char = FNT9X17_HCHAR;
254         term->v_tic = FNT9X17_HBITS;
255         term->h_tic = FNT9X17_HBITS;
256         break;
257     case 3:
258         b_charsize(FNT13X25);
259         term->v_char = FNT13X25_VCHAR;
260         term->h_char = FNT13X25_HCHAR;
261         term->v_tic = FNT13X25_HBITS;
262         term->h_tic = FNT13X25_HBITS;
263         break;
264     }
265 }
266
267
268 TERM_PUBLIC void
269 PBM_graphics()
270 {
271     int numplanes = 1;
272     unsigned int xpixels = term->xmax;
273     unsigned int ypixels = term->ymax;
274
275     /* 'set size' should not affect the size of the canvas in pixels,
276      * but versions prior to 4.2 did not have a separate 'set term size'
277      */
278     if (!PBM_explicit_size) {
279         xpixels *= xsize;
280         ypixels *= ysize;
281     }
282
283     switch (pbm_mode) {
284     case 1:
285         numplanes = 3;
286         break;
287     case 2:
288         numplanes = 4;
289         break;
290     }
291
292     /* HBB 980226: this is not the right place to do this: setfont() influences
293      * fields of the termtable entry, and therefore must be called by init()
294      * already. */
295     /* PBMsetfont(); */
296     /* rotate plot -90 degrees by reversing XMAX and YMAX and by
297        setting b_rastermode to TRUE */
298     b_makebitmap(ypixels, xpixels, numplanes);
299     b_rastermode = TRUE;
300
301     if (pbm_mode != 0)
302         b_setlinetype(0);       /* solid lines */
303 }
304
305
306 static void
307 PBM_monotext()
308 {
309     register int x, j, row;
310
311     fputs("P4\n", gpoutfile);
312     fprintf(gpoutfile, "%u %u\n", b_ysize, b_xsize);
313
314     /* dump bitmap in raster mode */
315     for (x = b_xsize - 1; x >= 0; x--) {
316         row = (b_ysize / 8) - 1;
317         for (j = row; j >= 0; j--) {
318             (void) fputc((char) (*((*b_p)[j] + x)), gpoutfile);
319         }
320     }
321
322     b_freebitmap();
323 }
324
325 static void
326 PBM_graytext()
327 {
328     register int x, j, row;
329     register int i, value;
330     int mask, plane1, plane2, plane3;
331
332     fprintf(gpoutfile, "\
333 P5\n\
334 %u %u\n\
335 %u\n",
336             b_ysize, b_xsize,
337             255);
338
339     /* dump bitmap in raster mode */
340     for (x = b_xsize - 1; x >= 0; x--) {
341         row = (b_ysize / 8) - 1;
342         for (j = row; j >= 0; j--) {
343             mask = 0x80;
344             plane1 = (*((*b_p)[j] + x));
345             plane2 = (*((*b_p)[j + b_psize] + x));
346             plane3 = (*((*b_p)[j + b_psize + b_psize] + x));
347             for (i = 0; i < 8; i++) {
348                 /* HBB: The values below are set to span the full range
349                  * from 0 up to 255 in 7 steps: */
350                 value = 255;
351                 if (plane1 & mask)
352                     value -= 36;
353                 if (plane2 & mask)
354                     value -= 73;
355                 if (plane3 & mask)
356                     value -= 146;
357                 (void) fputc((char) (value), gpoutfile);
358                 mask >>= 1;
359             }
360         }
361     }
362
363     b_freebitmap();
364 }
365
366 static void
367 PBM_colortext()
368 {
369     register int x, j, row;
370     register int i;
371     int mask, plane1, plane2, plane3, plane4;
372     int red, green, blue;
373
374     fprintf(gpoutfile, "P6\n\
375 %u %u\n\
376 %u\n",
377             b_ysize, b_xsize,
378             255);
379
380     /* dump bitmap in raster mode */
381     for (x = b_xsize - 1; x >= 0; x--) {
382         row = (b_ysize / 8) - 1;
383         for (j = row; j >= 0; j--) {
384             mask = 0x80;
385             plane1 = (*((*b_p)[j] + x));
386             plane2 = (*((*b_p)[j + b_psize] + x));
387             plane3 = (*((*b_p)[j + b_psize + b_psize] + x));
388             plane4 = (*((*b_p)[j + b_psize + b_psize + b_psize] + x));
389             for (i = 0; i < 8; i++) {
390                 red = (plane3 & mask) ? 1 : 3;
391                 green = (plane2 & mask) ? 1 : 3;
392                 blue = (plane1 & mask) ? 1 : 3;
393                 if (plane4 & mask) {
394                     red--;
395                     green--;
396                     blue--;
397                 }
398                 /* HBB: '85' is exactly 255/3, so this spans the full
399                  * range of colors in three steps: */
400                 (void) fputc((char) (red * 85), gpoutfile);
401                 (void) fputc((char) (green * 85), gpoutfile);
402                 (void) fputc((char) (blue * 85), gpoutfile);
403                 mask >>= 1;
404             }
405         }
406     }
407
408     b_freebitmap();
409 }
410
411 TERM_PUBLIC void
412 PBM_text()
413 {
414     switch (pbm_mode) {
415     case 0:
416         PBM_monotext();
417         break;
418     case 1:
419         PBM_graytext();
420         break;
421     case 2:
422         PBM_colortext();
423         break;
424     }
425 }
426
427
428 TERM_PUBLIC void
429 PBM_linetype(int linetype)
430 {
431     if (linetype < -2)
432         linetype = LT_BLACK;
433
434     switch (pbm_mode) {
435     case 0:
436         b_setlinetype(linetype);
437         break;
438     case 1:
439         if (linetype >= 7)
440             linetype %= 7;
441         b_setvalue(pgm_gray[linetype + 2]);
442         break;
443     case 2:
444         if (linetype >= 9)
445             linetype %= 9;
446         b_setvalue(ppm_color[linetype + 2]);
447         break;
448     }
449 }
450
451 TERM_PUBLIC void
452 PBM_point(unsigned int x, unsigned int y, int point)
453 {
454     if (pbm_mode == 0)
455         line_and_point(x, y, point);
456     else
457         do_point(x, y, point);
458 }
459
460 #endif /* TERM_BODY */
461
462 #ifdef TERM_TABLE
463
464 TERM_TABLE_START(pbm_driver)
465     "pbm", "Portable bitmap [small medium large] [monochrome gray color]",
466     PBM_XMAX, PBM_YMAX, PBM_VCHAR,
467     PBM_HCHAR, PBM_VTIC, PBM_HTIC, PBM_options,
468     PBM_init, PBM_reset, PBM_text, null_scale,
469     PBM_graphics, b_move, b_vector, PBM_linetype,
470     b_put_text, b_text_angle, null_justify_text, PBM_point,
471     do_arrow, set_font_null,
472     0,                          /* pointsize */
473     TERM_CAN_MULTIPLOT | TERM_BINARY,
474     0, 0, b_boxfill
475 TERM_TABLE_END(pbm_driver)
476
477 #undef LAST_TERM
478 #define LAST_TERM pbm_driver
479
480 #endif /* TERM_TABLE */
481
482
483 #ifdef TERM_HELP
484 START_HELP(pbm)
485 "1 pbm",
486 "?commands set terminal pbm",
487 "?set terminal pbm",
488 "?set term pbm",
489 "?terminal pbm",
490 "?term pbm",
491 "?pbm",
492 " Several options may be set in the `pbm` terminal---the driver for PBMplus.",
493 "",
494 " Syntax:",
495 "       set terminal pbm {<fontsize>} {<mode>} {size <x>,<y>}",
496 "",
497 " where <fontsize> is `small`, `medium`, or `large` and <mode> is `monochrome`,",
498 " `gray` or `color`.  The default plot size is 640 pixels wide and 480 pixels",
499 " high.",
500 "",
501 " The output of the `pbm` driver depends upon <mode>: `monochrome` produces a",
502 " portable bitmap (one bit per pixel), `gray` a portable graymap (three bits",
503 " per pixel) and `color` a portable pixmap (color, four bits per pixel).",
504 "",
505 " The output of this driver can be used with various image conversion and",
506 " manipulation utilities provided by NETPBM.  Based on Jef Poskanzer's",
507 " PBMPLUS package, NETPBM provides programs to convert the above PBM formats",
508 " to GIF, TIFF, MacPaint, Macintosh PICT, PCX, X11 bitmap and many others.",
509 " Complete information is available at http://netpbm.sourceforge.net/.",
510 "",
511 " Examples:",
512 "       set terminal pbm small monochrome                # defaults",
513 "       set terminal pbm color medium size 800,600",
514 "       set output '| pnmrotate 45 | pnmtopng > tilted.png'  # uses NETPBM"
515 END_HELP(pbm)
516 #endif /* TERM_HELP */