1 /*
2  *  This file is part of the XForms library package.
3  *
4  *  XForms is free software; you can redistribute it and/or modify it
5  *  under the terms of the GNU Lesser General Public License as
6  *  published by the Free Software Foundation; either version 2.1, or
7  *  (at your option) any later version.
8  *
9  *  XForms is distributed in the hope that it will be useful, but
10  *  WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public License
15  *  along with XForms. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 
19 /*
20  *  This file is part of the XForms library package.
21  *  Copyright (c) 1997-2002  by T.C. Zhao
22  *  All rights reserved.
23  *
24  * Some primitive drawing routines is PS
25  *
26  *  (x,y) (w,h) passed to all drawing functions are relative
27  *  to PS coordinate system and the unit is pixel/point.
28  */
29 
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #include "include/forms.h"
35 #include "flinternal.h"
36 #include "private/pflps.h"
37 #include <ctype.h>
38 #include <math.h>
39 
40 FLPSInfo *flps;
41 
42 
43 /***************************************
44  ***************************************/
45 
46 FLPS_CONTROL *
flps_init(void)47 flps_init( void )
48 {
49     static FLPSInfo *local_flps;
50 
51     if ( ! local_flps )
52     {
53         local_flps = fl_calloc( 1, sizeof *flps );
54         local_flps->ps_color    = FLPS_COLOR;
55         local_flps->orientation = FLPS_AUTO;
56         local_flps->paper_w     = 8.5;
57         local_flps->paper_h     = 11.0;
58         local_flps->auto_fit    = 1;
59         local_flps->xscale = local_flps->yscale = 1.0;
60 
61         /* driver will fill-in appropriate vals for minus */
62 
63         local_flps->drawbox = -1;
64         local_flps->xdpi    = local_flps->ydpi = fl_dpi;
65         local_flps->pack    = 1;
66 
67         /* Cache */
68 
69         local_flps->cur_color = FL_NoColor;
70         local_flps->cur_style = local_flps->cur_size = -1;
71         local_flps->cur_lw    = -1;
72     }
73 
74     return  ( FLPS_CONTROL * ) ( flps = local_flps );
75 }
76 
77 
78 /***************************************
79  ***************************************/
80 
81 void
flps_switch_flps(FLPSInfo * info)82 flps_switch_flps( FLPSInfo * info )
83 {
84     flps = info;
85 }
86 
87 
88 /***************************************
89  ***************************************/
90 
91 void
flps_restore_flps(void)92 flps_restore_flps( void )
93 {
94     flps_init( );
95 }
96 
97 
98 /***************************************
99  ***************************************/
100 
101 void
flps_reset_cache(void)102 flps_reset_cache( void )
103 {
104     flps_invalidate_font_cache( );
105     flps_invalidate_color_cache( );
106     flps_invalidate_symbol_cache( );
107     flps_invalidate_linewidth_cache( );
108 }
109 
110 
111 /***************************************
112  * write some arbitary text into the output stream
113  ***************************************/
114 
115 void
flps_log(const char * s)116 flps_log( const char * s )
117 {
118     fprintf( flps->fp, "%%%s", s );
119 }
120 
121 
122 #include <stdarg.h>
123 
124 #define LEFT    '('
125 #define RIGHT   ')'
126 
127 
128 /***************************************
129  ***************************************/
130 
131 void
flps_output(const char * fmt,...)132 flps_output( const char * fmt,
133              ... )
134 {
135     va_list args;
136     char buf[ 2048 ],
137          *q;
138     int lastc = flps->lastc;
139 
140     /* Flush */
141 
142     if ( ! fmt )
143     {
144         if ( flps->pack && flps->len )
145         {
146             putc( '\n', flps->fp );
147             flps->len = 0;
148         }
149         return;
150     }
151 
152     va_start( args, fmt );
153     vsprintf( buf, fmt, args );
154     va_end( args );
155 
156     if ( ! flps->pack )
157         fprintf( flps->fp, "%s", buf );
158     else
159     {
160         for ( q = buf; *q; q++ )
161         {
162             if ( *q == '\n' )
163                 *q = ' ';
164 
165             /* this is less than robust */
166 
167             if ( *q == LEFT )
168                 flps->literal = 1;
169             else if ( *q == RIGHT )
170                 flps->literal = 0;
171 
172             if ( lastc == ' ' && *q == ' ' && ! flps->literal )
173                 continue;
174 
175             if ( *q == ' ' && flps->len == 0 )
176                 continue;
177 
178             if ( *q == ' ' && flps->len >= 70 )
179             {
180                 putc( '\n', flps->fp );
181                 flps->len = 0;
182             }
183             else
184             {
185                 lastc = *q;
186                 flps->len++;
187                 putc( *q, flps->fp );
188             }
189         }
190 
191         flps->lastc = lastc;
192     }
193 }
194 
195 
196 /***************************************
197  * flps_linewidth() and flps_reset_linewidth() must be used in pairs
198  ***************************************/
199 
200 void
flps_linewidth(int lw)201 flps_linewidth( int lw )
202 {
203     float flw;
204 
205     if ( lw == flps->cur_lw )
206         return;
207 
208     flps->last_lw = flps->cur_lw;
209     flps->cur_lw = lw;
210 
211     flw = 0.9 * lw;
212     if ( flps->final_xscale + flps->final_yscale > 2 )
213         flw = 0.9 * lw;
214 
215     if ( flw < 0.4 )
216         flw = 0.4;
217 
218     flps_output( " %.1f %.1f LW\n", flw, flw );
219 }
220 
221 
222 /***************************************
223  ***************************************/
224 
225 int
flps_get_linewidth(void)226 flps_get_linewidth( void )
227 {
228     return flps->cur_lw;
229 }
230 
231 
232 /***************************************
233  ***************************************/
234 
235 void
flps_reset_linewidth(void)236 flps_reset_linewidth( void )
237 {
238     flps_linewidth( flps->last_lw );
239     flps_log( "resetline" );
240 }
241 
242 
243 /***************************************
244  ***************************************/
245 
246 void
flps_invalidate_linewidth_cache(void)247 flps_invalidate_linewidth_cache( void )
248 {
249     flps->cur_lw = -1;
250 }
251 
252 
253 static int ps_ls = FL_SOLID;
254 
255 
256 /***************************************
257  ***************************************/
258 
259 void
flps_linestyle(int n)260 flps_linestyle( int n )
261 {
262     if ( ps_ls == n )
263         return;
264 
265     switch ( n )
266     {
267         case FL_DOT :
268             flps_output( "DT " );
269             break;
270 
271         case FL_DOTDASH :
272             flps_output( "DTD " );
273             break;
274 
275         case FL_DASH :
276             flps_output( "D " );
277             break;
278 
279         case FL_LONGDASH :
280             flps_output( "LD " );
281             break;
282 
283         case FL_SOLID :
284         case FL_USERDASH :
285         case FL_USERDOUBLEDASH :
286         case -1:
287             flps_output( "SL " );
288             ps_ls = FL_SOLID;
289             break;
290 
291         default:
292             fprintf( stderr, "Unknown dashstyle: %d\n", n );
293             return;
294     }
295 
296     ps_ls = n;
297 }
298 
299 
300 /***************************************
301  ***************************************/
302 
303 int
flps_get_linestyle(void)304 flps_get_linestyle( void )
305 {
306     return ps_ls;
307 }
308 
309 
310 /***************************************
311  * Draw a line in abs coordinate system
312  ***************************************/
313 
314 void
flps_line(int xi,int yi,int xf,int yf,FL_COLOR col)315 flps_line( int      xi,
316            int      yi,
317            int      xf,
318            int      yf,
319            FL_COLOR col )
320 {
321     flps_color( col );
322     flps_output( "%d %d %d %d L S\n", xf, yf, xi, yi );
323 }
324 
325 
326 /***************************************
327  * ghostview and some printers have problems with too many
328  * points on the stack. We break the points into batches of
329  * PSMAXP pairs
330  ***************************************/
331 
332 #define PSMAXP    350
333 
334 static void
small_flps_lines(FL_POINT * xp,int n,FL_COLOR col)335 small_flps_lines( FL_POINT * xp,
336                   int        n,
337                   FL_COLOR   col )
338 {
339     FL_POINT *xps = xp + n;
340     int cnt = 1;
341 
342     flps_color( col );
343 
344     for ( ; xp < xps; xp++, cnt++ )
345     {
346         flps_output( "%d %d ", ( int ) xp->x, ( int ) xp->y );
347         if ( cnt % 6 == 0 )
348             flps_output( "\n" );
349     }
350 
351     if ( n )
352         flps_output( "%d lines\n", n );
353 }
354 
355 
356 /***************************************
357  ***************************************/
358 
359 void
flps_lines(FL_POINT * xp,int n,FL_COLOR col)360 flps_lines( FL_POINT * xp,
361             int        n,
362             FL_COLOR   col )
363 {
364     int k = n / PSMAXP,
365         r = n % PSMAXP;
366     int b;
367 
368     /* need to backup one point if broken up the batch */
369 
370     for ( b = 0; b < k; b++ )
371         small_flps_lines( xp + b * PSMAXP - ( b > 0 ),
372                           PSMAXP + ( b > 0 ), col );
373 
374     if ( r )
375         small_flps_lines( xp + k * PSMAXP - ( k > 0 ), r + ( k > 0 ), col );
376 }
377 
378 
379 /***************************************
380  ***************************************/
381 
382 void
flps_poly(int fill,FL_POINT * xp,int n,FL_COLOR col)383 flps_poly( int        fill,
384            FL_POINT * xp,
385            int        n,
386            FL_COLOR   col )
387 {
388     FL_POINT *xps = xp + n;
389     int cnt = 1;
390 
391     flps_color( col );
392 
393     for ( ; xp < xps; xp++, cnt++ )
394     {
395         flps_output( "%d %d ", ( int ) xp->x, ( int ) xp->y );
396         if ( cnt % 6 == 0 )
397             flps_output( "\n" );
398     }
399 
400     flps_output( "%d P %c\n", n, "SF"[ fill ] );
401 }
402 
403 
404 /***************************************
405  ***************************************/
406 
407 void
flps_rectangle(int fill,int x,int y,int w,int h,FL_COLOR col)408 flps_rectangle( int      fill,
409                 int      x,
410                 int      y,
411                 int      w,
412                 int      h,
413                 FL_COLOR col)
414 {
415     flps_color( col );
416     flps_output( "%d %d %d %d %d %d %d %d 4 P",
417                  x, y, x, y + h - 1, x + w - 1, y + h - 1, x + w - 1, y );
418     flps_output( " %c\n", "SF"[ fill ] );
419 }
420 
421 
422 /***************************************
423  ***************************************/
424 
425 void
flps_oval(int fill,int x,int y,int w,int h,FL_COLOR col)426 flps_oval( int      fill,
427            int      x,
428            int      y,
429            int      w,
430            int      h,
431            FL_COLOR col )
432 {
433     flps_pieslice( fill, x, y, w, h, 0.0, 3600.0, col );
434 }
435 
436 
437 /***************************************
438  ***************************************/
439 
440 void
flps_circ(int fill,int x,int y,int r,FL_COLOR col)441 flps_circ( int      fill,
442            int      x,
443            int      y,
444            int      r,
445            FL_COLOR col )
446 {
447     flps_color( col );
448     flps_output( "newpath %d %d %d 0 360 arc %c\n", x, y, r, "SF"[ fill ] );
449 }
450 
451 
452 /***************************************
453  * Draw an circular arc, optionally filled. Angle t1 and t2 are in one-tenth of
454  * a degree
455  ***************************************/
456 
457 void
flps_arc(int fill,int x,int y,int r,int t1,int t2,FL_COLOR col)458 flps_arc( int      fill,
459           int      x,
460           int      y,
461           int      r,
462           int      t1,
463           int      t2,
464           FL_COLOR col )
465 {
466     flps_color( col );
467     flps_output( "newpath %d %d %d %.1f %.1f arc %c\n",
468                  x, y, r, t1 * 0.1, t2 * 0.1, "SF"[ fill ] );
469 }
470 
471 
472 /***************************************
473  * Only fill does a pie slice
474  ***************************************/
475 
476 void
flps_pieslice(int fill,int x,int y,int w,int h,int t1,int t2,FL_COLOR col)477 flps_pieslice( int      fill,
478                int      x,
479                int      y,
480                int      w,
481                int      h,
482                int      t1,
483                int      t2,
484                FL_COLOR col )
485 {
486     float sx = 1.0,
487           sy = ( float ) h / w;
488 
489     flps_color( col );
490     flps_output( "gsave newpath %.1f %.1f translate %.1f %.1f scale\n",
491                  x + 0.5f * w, y + 0.5f * h, sx, sy );
492     if ( ! fill )
493         flps_output( "0 0 %.1f %.1f %.1f arc S grestore\n",
494                      w * 0.5, t1 * 0.1, t2 * 0.1 );
495     else
496         flps_output( "0 0 M 0 0 %.1f %.1f %.1f arc C F grestore\n",
497                      w * 0.5, t1 * 0.1, t2 * 0.1 );
498 
499     flps_invalidate_color_cache( );
500 }
501 
502 
503 /**************************************************************
504  * basic color routines
505  **************************************************************/
506 
507 #define VN( a )    a,#a
508 #define NV( a )    #a,a
509 
510 
511 /* slightly different from XForms' built-in due to the difference
512  * between  printer and screen
513  */
514 
515 #define PREVIEW
516 
517 static FLI_IMAP fl_imap[ ] =
518 {
519     { NV( FL_BLACK                ),   0,   0,   0, 0, 0 },
520     { NV( FL_WHITE                ), 255, 255, 255, 0, 0 },
521     { NV( FL_COL1                 ), 161, 161, 161, 0, 0 },
522     { NV( FL_BOTTOM_BCOL          ),  89,  89,  89, 0, 0 },
523     { NV( FL_RIGHT_BCOL           ),  41,  41,  41, 0, 0 },
524     { NV( FL_MCOL                 ), 191, 191, 191, 0, 0 },
525     { NV( FL_LEFT_BCOL            ), 222, 222, 222, 0, 0 },
526     { NV( FL_SLATEBLUE            ), 113, 113, 198, 0, 0 },
527     { NV( FL_INDIANRED            ), 198, 113, 113, 0, 0 },
528     { NV( FL_RED                  ), 255,   0,   0, 0, 0 },
529     { NV( FL_BLUE                 ),   0,   0, 255, 0, 0 },
530     { NV( FL_GREEN                ),   0, 255,   0, 0, 0 },
531     { NV( FL_YELLOW               ), 255, 255,   0, 0, 0 },
532     { NV( FL_MAGENTA              ), 255,   0, 255, 0, 0 },
533     { NV( FL_CYAN                 ),   0, 255, 255, 0, 0 },
534     { NV( FL_TOMATO               ), 255,  99,  71, 0, 0 },
535     { NV(FL_INACTIVE              ), 110, 110, 110, 0, 0 },
536     { NV(FL_TOP_BCOL              ), 204, 204, 204, 0, 0 },
537     { NV( FL_PALEGREEN            ), 113, 198, 113, 0, 0 },
538     { NV( FL_DARKGOLD             ), 205, 149,  10, 0, 0 },
539     { NV( FL_ORCHID               ), 205, 105, 201, 0, 0 },
540     { NV( FL_DARKCYAN             ),  40, 170, 175, 0, 0 },
541     { NV( FL_DARKTOMATO           ), 139,  54,  38, 0, 0 },
542     { NV( FL_WHEAT                ), 255, 231, 155, 0, 0 },
543     { NV( FL_DARKORANGE           ), 255, 128,   0, 0, 0 },
544     { NV( FL_DEEPPINK             ), 255,   0, 128, 0, 0 },
545     { NV( FL_CHARTREUSE           ), 128, 255,   0, 0, 0 },
546     { NV( FL_DARKVIOLET           ), 128,   0, 255, 0, 0 },
547     { NV( FL_SPRINGGREEN          ),   0, 255, 128, 0, 0 },
548     { NV( FL_DODGERBLUE           ),   0, 128, 255, 0, 0 },
549     { NV( FL_DOGERBLUE            ),   0, 128, 255, 0, 0 },
550 	{ NV( FL_LIGHTER_COL1         ), 204, 204, 204, 0, 0 },
551 	{ NV( FL_DARKER_COL1          ), 161, 161, 161, 0, 0 },
552 	{ NV( FL_ALICEBLUE            ), 240, 248, 255, 0, 0 },
553 	{ NV( FL_ANTIQUEWHITE         ), 250, 235, 215, 0, 0 },
554 	{ NV( FL_AQUA                 ),   0, 255, 255, 0, 0 },
555 	{ NV( FL_AQUAMARINE           ), 127, 255, 212, 0, 0 },
556 	{ NV( FL_AZURE                ), 240, 255, 255, 0, 0 },
557 	{ NV( FL_BEIGE                ), 245, 245, 220, 0, 0 },
558 	{ NV( FL_BISQUE               ), 255, 228, 196, 0, 0 },
559 	{ NV( FL_BLANCHEDALMOND       ), 255, 235, 205, 0, 0 },
560 	{ NV( FL_BLUEVIOLET           ), 138,  43, 226, 0, 0 },
561 	{ NV( FL_BROWN                ), 165,  42,  42, 0, 0 },
562 	{ NV( FL_BURLYWOOD            ), 222, 184, 135, 0, 0 },
563 	{ NV( FL_CADETBLUE            ),  95, 158, 160, 0, 0 },
564 	{ NV( FL_CHOCOLATE            ), 210, 105,  30, 0, 0 },
565 	{ NV( FL_CORAL                ), 255, 127,  80, 0, 0 },
566 	{ NV( FL_CORNFLOWERBLUE       ), 100, 149, 237, 0, 0 },
567 	{ NV( FL_CORNSILK             ), 255, 248, 220, 0, 0 },
568 	{ NV( FL_CRIMSON              ), 220,  20,  60, 0, 0 },
569 	{ NV( FL_DARKBLUE             ),   0,   0, 139, 0, 0 },
570 	{ NV( FL_DARKGOLDENROD        ), 184, 134,  11, 0, 0 },
571 	{ NV( FL_DARKGRAY             ), 169, 169, 169, 0, 0 },
572 	{ NV( FL_DARKGREEN            ),   0, 100,   0, 0, 0 },
573 	{ NV( FL_DARKGREY             ), 169, 169, 169, 0, 0 },
574 	{ NV( FL_DARKKHAKI            ), 189, 183, 107, 0, 0 },
575 	{ NV( FL_DARKMAGENTA          ), 139,   0, 139, 0, 0 },
576 	{ NV( FL_DARKOLIVEGREEN       ),  85, 107,  47, 0, 0 },
577 	{ NV( FL_DARKORCHID           ), 153,  50, 204, 0, 0 },
578 	{ NV( FL_DARKRED              ), 139,   0,   0, 0, 0 },
579 	{ NV( FL_DARKSALMON           ), 233, 150, 122, 0, 0 },
580 	{ NV( FL_DARKSEAGREEN         ), 143, 188, 143, 0, 0 },
581 	{ NV( FL_DARKSLATEBLUE        ),  72,  61, 139, 0, 0 },
582 	{ NV( FL_DARKSLATEGRAY        ),  47,  79,  79, 0, 0 },
583 	{ NV( FL_DARKSLATEGREY        ),  47,  79,  79, 0, 0 },
584 	{ NV( FL_DARKTURQUOISE        ),   0, 206, 209, 0, 0 },
585 	{ NV( FL_DEEPSKYBLUE          ),   0, 191, 255, 0, 0 },
586 	{ NV( FL_DIMGRAY              ), 105, 105, 105, 0, 0 },
587 	{ NV( FL_DIMGREY              ), 105, 105, 105, 0, 0 },
588 	{ NV( FL_FIREBRICK            ), 178,  34,  34, 0, 0 },
589 	{ NV( FL_FLORALWHITE          ), 255, 250, 240, 0, 0 },
590 	{ NV( FL_FORESTGREEN          ),  34, 139,  34, 0, 0 },
591 	{ NV( FL_FUCHSIA              ), 255,   0, 255, 0, 0 },
592 	{ NV( FL_GAINSBORO            ), 220, 220, 220, 0, 0 },
593 	{ NV( FL_GHOSTWHITE           ), 248, 248, 255, 0, 0 },
594 	{ NV( FL_GOLD                 ), 255, 215,   0, 0, 0 },
595 	{ NV( FL_GOLDENROD            ), 218, 165,  32, 0, 0 },
596 	{ NV( FL_GRAY                 ), 128, 128, 128, 0, 0 },
597 	{ NV( FL_GREENYELLOW          ), 173, 255,  47, 0, 0 },
598 	{ NV( FL_GREY                 ), 128, 128, 128, 0, 0 },
599 	{ NV( FL_HONEYDEW             ), 240, 255, 240, 0, 0 },
600 	{ NV( FL_HOTPINK              ), 255, 105, 180, 0, 0 },
601 	{ NV( FL_INDIGO               ),  75,   0, 130, 0, 0 },
602 	{ NV( FL_IVORY                ), 255, 255, 240, 0, 0 },
603 	{ NV( FL_KHAKI                ), 240, 230, 140, 0, 0 },
604 	{ NV( FL_LAVENDER             ), 230, 230, 250, 0, 0 },
605 	{ NV( FL_LAVENDERBLUSH        ), 255, 240, 245, 0, 0 },
606 	{ NV( FL_LAWNGREEN            ), 124, 252,   0, 0, 0 },
607 	{ NV( FL_LEMONCHIFFON         ), 255, 250, 205, 0, 0 },
608 	{ NV( FL_LIGHTBLUE            ), 173, 216, 230, 0, 0 },
609 	{ NV( FL_LIGHTCORAL           ), 240, 128, 128, 0, 0 },
610 	{ NV( FL_LIGHTCYAN            ), 224, 255, 255, 0, 0 },
611 	{ NV( FL_LIGHTGOLDENRODYELLOW ), 250, 250, 210, 0, 0 },
612 	{ NV( FL_LIGHTGRAY            ), 211, 211, 211, 0, 0 },
613 	{ NV( FL_LIGHTGREEN           ), 144, 238, 144, 0, 0 },
614 	{ NV( FL_LIGHTGREY            ), 211, 211, 211, 0, 0 },
615 	{ NV( FL_LIGHTPINK            ), 255, 182, 193, 0, 0 },
616 	{ NV( FL_LIGHTSALMON          ), 255, 160, 122, 0, 0 },
617 	{ NV( FL_LIGHTSEAGREEN        ),  32, 178, 170, 0, 0 },
618 	{ NV( FL_LIGHTSKYBLUE         ), 135, 206, 250, 0, 0 },
619 	{ NV( FL_LIGHTSLATEGRAY       ), 119, 136, 153, 0, 0 },
620 	{ NV( FL_LIGHTSLATEGREY       ), 119, 136, 153, 0, 0 },
621 	{ NV( FL_LIGHTSTEELBLUE       ), 176, 196, 222, 0, 0 },
622 	{ NV( FL_LIGHTYELLOW          ), 255, 255, 224, 0, 0 },
623 	{ NV( FL_LIME                 ),   0, 255,   0, 0, 0 },
624 	{ NV( FL_LIMEGREEN            ),  50, 205,  50, 0, 0 },
625 	{ NV( FL_LINEN                ), 250, 240, 230, 0, 0 },
626 	{ NV( FL_MAROON               ), 128,   0,   0, 0, 0 },
627 	{ NV( FL_MEDIUMAQUAMARINE     ), 102, 205, 170, 0, 0 },
628 	{ NV( FL_MEDIUMBLUE           ),   0,   0, 205, 0, 0 },
629 	{ NV( FL_MEDIUMORCHID         ), 186,  85, 211, 0, 0 },
630 	{ NV( FL_MEDIUMPURPLE         ), 147, 112, 219, 0, 0 },
631 	{ NV( FL_MEDIUMSEAGREEN       ),  60, 179, 113, 0, 0 },
632 	{ NV( FL_MEDIUMSLATEBLUE      ), 123, 104, 238, 0, 0 },
633 	{ NV( FL_MEDIUMSPRINGGREEN    ),   0, 250, 154, 0, 0 },
634 	{ NV( FL_MEDIUMTURQUOISE      ),  72, 209, 204, 0, 0 },
635 	{ NV( FL_MEDIUMVIOLETRED      ), 199,  21, 133, 0, 0 },
636 	{ NV( FL_MIDNIGHTBLUE         ),  25,  25, 112, 0, 0 },
637 	{ NV( FL_MINTCREAM            ), 245, 255, 250, 0, 0 },
638 	{ NV( FL_MISTYROSE            ), 255, 228, 225, 0, 0 },
639 	{ NV( FL_MOCCASIN             ), 255, 228, 181, 0, 0 },
640 	{ NV( FL_NAVAJOWHITE          ), 255, 222, 173, 0, 0 },
641 	{ NV( FL_NAVY                 ),   0,   0, 128, 0, 0 },
642 	{ NV( FL_OLDLACE              ), 253, 245, 230, 0, 0 },
643 	{ NV( FL_OLIVE                ), 128, 128,   0, 0, 0 },
644 	{ NV( FL_OLIVEDRAB            ), 107, 142,  35, 0, 0 },
645 	{ NV( FL_ORANGE               ), 255, 165,   0, 0, 0 },
646 	{ NV( FL_ORANGERED            ), 255,  69,   0, 0, 0 },
647 	{ NV( FL_PALEGOLDENROD        ), 238, 232, 170, 0, 0 },
648 	{ NV( FL_PALETURQUOISE        ), 175, 238, 238, 0, 0 },
649 	{ NV( FL_PALEVIOLETRED        ), 219, 112, 147, 0, 0 },
650 	{ NV( FL_PAPAYAWHIP           ), 255, 239, 213, 0, 0 },
651 	{ NV( FL_PEACHPUFF            ), 255, 218, 185, 0, 0 },
652 	{ NV( FL_PERU                 ), 205, 133,  63, 0, 0 },
653 	{ NV( FL_PINK                 ), 255, 192, 203, 0, 0 },
654 	{ NV( FL_PLUM                 ), 221, 160, 221, 0, 0 },
655 	{ NV( FL_POWDERBLUE           ), 176, 224, 230, 0, 0 },
656 	{ NV( FL_PURPLE               ), 128,   0, 128, 0, 0 },
657 	{ NV( FL_ROSYBROWN            ), 188, 143, 143, 0, 0 },
658 	{ NV( FL_ROYALBLUE            ),  65, 105, 225, 0, 0 },
659 	{ NV( FL_SADDLEBROWN          ), 139,  69,  19, 0, 0 },
660 	{ NV( FL_SALMON               ), 250, 128, 114, 0, 0 },
661 	{ NV( FL_SANDYBROWN           ), 244, 164,  96, 0, 0 },
662 	{ NV( FL_SEAGREEN             ),  46, 139,  87, 0, 0 },
663 	{ NV( FL_SEASHELL             ), 255, 245, 238, 0, 0 },
664 	{ NV( FL_SIENNA               ), 160,  82,  45, 0, 0 },
665 	{ NV( FL_SILVER               ), 192, 192, 192, 0, 0 },
666 	{ NV( FL_SKYBLUE              ), 135, 206, 235, 0, 0 },
667 	{ NV( FL_SLATEGRAY            ), 112, 128, 144, 0, 0 },
668 	{ NV( FL_SLATEGREY            ), 112, 128, 144, 0, 0 },
669 	{ NV( FL_SNOW                 ), 255, 250, 250, 0, 0 },
670 	{ NV( FL_STEELBLUE            ),  70, 130, 180, 0, 0 },
671 	{ NV( FL_TAN                  ), 210, 180, 140, 0, 0 },
672 	{ NV( FL_TEAL                 ),   0, 128, 128, 0, 0 },
673 	{ NV( FL_THISTLE              ), 216, 191, 216, 0, 0 },
674 	{ NV( FL_TURQUOISE            ),  64, 224, 208, 0, 0 },
675 	{ NV( FL_VIOLET               ), 238, 130, 238, 0, 0 },
676 	{ NV( FL_WHITESMOKE           ), 245, 245, 245, 0, 0 },
677 	{ NV( FL_YELLOWGREEN          ), 154, 205,  50, 0, 0 }
678 };
679 
680 #define builtin  ( sizeof fl_imap / sizeof *fl_imap )
681 
682 
683 /***************************************
684  * do gamma adjustment
685  ***************************************/
686 
687 void
flps_apply_gamma(float gamma)688 flps_apply_gamma( float gamma )
689 {
690     FLI_IMAP *fm = fl_imap,
691              *fs;
692     float lastgamma = 1.0;
693 
694     if ( FL_abs(gamma) < 1.0e-3 )
695     {
696         fprintf( stderr, "fd2ps: Bad Gamma value %.2f\n", gamma );
697         return;
698     }
699 
700     for ( fs = fm + builtin; fm < fs; fm++ )
701     {
702         if ( flps->verbose )
703             fprintf( stderr, "fm->r=%d\n", fm->r );
704         fm->r = 0.4 + 255 * ( pow( fm->r / 255.0, lastgamma / gamma ) );
705         fm->g = 0.4 + 255 * ( pow( fm->g / 255.0, lastgamma / gamma ) );
706         fm->b = 0.4 + 255 * ( pow( fm->b / 255.0, lastgamma / gamma ) );
707         if ( flps->verbose )
708             fprintf( stderr, "fm->r=%d\n", fm->r );
709     }
710 }
711 
712 
713 /***************************************
714  ***************************************/
715 
716 static void
flps_query_imap(FL_COLOR col,int * r,int * g,int * b)717 flps_query_imap( FL_COLOR   col,
718                  int      * r,
719                  int      * g,
720                  int      * b )
721 {
722     FLI_IMAP *flmap = fl_imap,
723              *flmape = flmap + builtin;
724 
725     for ( ; flmap < flmape; flmap++ )
726         if ( col == flmap->index )
727         {
728             *r = flmap->r;
729             *g = flmap->g;
730             *b = flmap->b;
731             return;
732         }
733 }
734 
735 
736 #define  C2NC( c )            ( 1.0 / 255.0 * c )
737 #define  rgb2gray( r, g, b )  ( 0.299 * ( r ) + 0.587 * ( g ) + 0.114 * ( b ) )
738 
739 #ifndef FL_PACK
740 #define FL_PACK( r, g, b )        ( ( b ) << 16 | ( g ) << 8 | ( r ) )
741 #define FL_UNPACK( p, r, g, b )       \
742     do {                              \
743         r = ( ( p )       ) & 0xff;   \
744         g = ( ( p ) >>  8 ) &0xff;    \
745         b = ( ( p ) >> 16 ) &0xff;    \
746     } while ( 0 )
747 #endif
748 
749 
750 /***************************************
751  ***************************************/
752 
753 void
flps_invalidate_color_cache(void)754 flps_invalidate_color_cache( void )
755 {
756     flps->cur_color = FL_NoColor;
757 }
758 
759 
760 /***************************************
761  ***************************************/
762 
763 void
flps_color(FL_COLOR color)764 flps_color( FL_COLOR color )
765 {
766     int r = 0,
767         g = 0,
768         b = 0;
769 
770     if ( color == FL_NoColor )
771         return;
772 
773     if ( flps->isRGBColor )
774         FL_UNPACK( color, r, g, b );
775     else
776         flps_query_imap( color, &r, &g, &b );
777 
778     if ( ( FL_COLOR ) FL_PACK( r, g, b ) != flps->cur_color )
779         flps_rgbcolor( r, g, b );
780 }
781 
782 
783 /***************************************
784  ***************************************/
785 
786 void
flps_rgbcolor(int r,int g,int b)787 flps_rgbcolor( int r,
788                int g,
789                int b )
790 {
791     unsigned int packed = FL_PACK( r, g, b );
792 
793     if ( flps->cur_color == packed )
794         return;
795 
796     if ( flps->ps_color == FLPS_COLOR && ( r != g || r != b ) )
797         flps_output( "%.3g %.3g %.3g RGB ", C2NC( r ), C2NC( g ), C2NC( b ) );
798     else if ( flps->ps_color == FLPS_BW )
799         flps_output("%d G ", C2NC( rgb2gray( r, g, b ) ) > 0.62 );
800     else
801         flps_output( "%.3g G ", C2NC( rgb2gray( r, g, b ) ) );
802 
803     flps->cur_color = FL_PACK( r, g, b );
804 }
805 
806 
807 /***************************************
808  ***************************************/
809 
810 int
flps_get_gray255(FL_COLOR color)811 flps_get_gray255( FL_COLOR color )
812 {
813     int r = 0,
814         g = 0,
815         b = 0;
816 
817     if ( flps->isRGBColor )
818         FL_UNPACK( color, r, g, b );
819     else
820         flps_query_imap( color, &r, &g, &b );
821 
822     return rgb2gray( r, g, b ) + 0.1;
823 }
824 
825 
826 /***************************************
827  ***************************************/
828 
829 FL_COLOR
flps_get_namedcolor(const char * s)830 flps_get_namedcolor( const char * s )
831 {
832     FLI_IMAP *flmap = fl_imap,
833              *flmape = flmap + builtin;
834 
835     for ( ; s && flmap < flmape; flmap++ )
836         if ( strcmp( s, flmap->name ) == 0 )
837             return flmap->index;
838 
839     /* a wild shot */
840 
841     return atoi( s );
842 }
843 
844 /************** Handle built-in symbols. ****************{*/
845 
846 typedef void ( * PSdrawit )( int, int, int, int, int, FL_COLOR );
847 
848 typedef struct
849 {
850     const char * name;
851     const char * psname;
852     const char * draw;
853     int          otherdef;
854     PSdrawit     fdrawit;
855     int          abs_coordinate;       /* fdrawit uses abs coordinate system */
856     int          defined;              /* if def code emitted                */
857 } PS_draw;
858 
859 
860 /***************************************
861  ***************************************/
862 
863 static void
draw_dnline(int x FL_UNUSED_ARG,int y FL_UNUSED_ARG,int w,int h,int angle FL_UNUSED_ARG,FL_COLOR col FL_UNUSED_ARG)864 draw_dnline( int     x      FL_UNUSED_ARG,
865              int     y      FL_UNUSED_ARG,
866              int     w,
867              int     h,
868              int     angle  FL_UNUSED_ARG,
869              FL_COLOR col   FL_UNUSED_ARG )
870 {
871     float t = 0.2,
872           len;
873 
874     flps_output( "%.2f %.2f LW ", 3.5 / ( w + h ), 3.5 / ( w + h ) );
875     if ( w + h > 200 )
876         len = 0.99;
877     else if ( w + h > 150 )
878         len = 0.98;
879     else
880         len = 0.93;
881 
882     flps_color( FL_RIGHT_BCOL );
883     flps_output( "-%.3f %.2f M %.3f %.2f LT S\n", len, t, len, t );
884     flps_color( FL_LEFT_BCOL );
885     flps_output( "-%.3f -%.2f M %.3f -%.2f LT S\n", len, t, len, t );
886 }
887 
888 
889 /***************************************
890  ***************************************/
891 
892 static void
draw_upline(int x FL_UNUSED_ARG,int y FL_UNUSED_ARG,int w,int h,int angle FL_UNUSED_ARG,FL_COLOR col FL_UNUSED_ARG)893 draw_upline( int      x      FL_UNUSED_ARG,
894              int      y      FL_UNUSED_ARG,
895              int      w,
896              int      h,
897              int      angle  FL_UNUSED_ARG,
898              FL_COLOR col    FL_UNUSED_ARG )
899 {
900     float t = 0.033;
901 
902     flps_color( FL_LEFT_BCOL );
903     flps_output( "%.3f %.3f LW ", 3.7 / ( w + h ), 3.7 / ( w + h ) );
904     flps_output( "-0.9 %.3f M 0.9 %.3f LT S\n", t, t );
905     flps_color( FL_RIGHT_BCOL );
906     flps_output( "0.9 -%.3f M 0.9 %.3f LT S ", t, t );
907     flps_output( "-0.9 -%.3f M 0.9 -%.3f LT S\n", t, t );
908 }
909 
910 
911 /* Due to pixel precision problems, we have to draw uparrow, downarrow and
912  * ripple line in absolute unit with the origin at the center of the figure. */
913 
914 
915 /***************************************
916  ***************************************/
917 
918 static void
draw_uparrow(int x,int y,int w,int h,int angle,FL_COLOR col FL_UNUSED_ARG)919 draw_uparrow( int      x,
920               int      y,
921               int      w,
922               int      h,
923               int      angle,
924               FL_COLOR col  FL_UNUSED_ARG )
925 {
926     float yc = y + h * 0.5;
927     float xc = x + w * 0.5;
928     float dx,
929           dy;
930     int d = 3 + ( w + h ) * 0.06;
931 
932     dx = w / 2 - d;
933     dy = h / 2 - d;
934 
935     if ( angle == 90 )
936     {
937         flps_line( xc,      yc + dy, xc - dx, yc - dy, FL_LEFT_BCOL   );
938         flps_line( xc - dx, yc - dy, xc + dx, yc - dy, FL_BOTTOM_BCOL );
939         flps_line( xc + dx, yc - dy, xc,      yc + dy, FL_RIGHT_BCOL  );
940     }
941     else if ( angle == 180 )
942     {
943         flps_line( xc - dx, yc,      xc + dx, yc + dy, FL_TOP_BCOL    );
944         flps_line( xc + dx, yc + dy, xc + dx, yc - dy, FL_RIGHT_BCOL  );
945         flps_line( xc + dx, yc - dy, xc - dx, yc,      FL_BOTTOM_BCOL );
946     }
947     else if ( angle == 270 )
948     {
949         flps_line( xc - dx, yc + dy, xc,      yc - dy, FL_BOTTOM_BCOL );
950         flps_line( xc,      yc - dy, xc + dx, yc + dy, FL_RIGHT_BCOL  );
951         flps_line( xc + dx, yc + dy, xc - dx, yc + dy, FL_TOP_BCOL    );
952     }
953     else
954     {
955         flps_line( xc, yc - dy, xc + w, yc,      FL_BOTTOM_BCOL );
956         flps_line( xc, yc + dy, xc + w, yc,      FL_RIGHT_BCOL  );
957         flps_line( xc, yc - dy, xc,     yc + dy, FL_LEFT_BCOL   );
958     }
959 }
960 
961 
962 /***************************************
963  ***************************************/
964 
965 static void
draw_dnarrow(int x,int y,int w,int h,int angle,FL_COLOR col FL_UNUSED_ARG)966 draw_dnarrow( int      x,
967               int      y,
968               int      w,
969               int      h,
970               int      angle,
971               FL_COLOR col   FL_UNUSED_ARG )
972 {
973     float yc = y + h * 0.5;
974     float xc = x + w * 0.5;
975     float dx,
976           dy;
977     int d = 3 + ( w + h ) * 0.06;
978 
979     dx = w / 2 - d;
980     dy = h / 2 - d;
981 
982     if ( angle == 90 )
983     {
984         flps_line( xc,      yc + dy, xc - dx, yc - dy, FL_RIGHT_BCOL );
985         flps_line( xc - dx, yc - dy, xc + dx, yc - dy, FL_TOP_BCOL   );
986         flps_line( xc + dx, yc - dy, xc,      yc + dy, FL_TOP_BCOL   );
987     }
988     else if ( angle == 180 )
989     {
990         flps_line( xc - dx, yc, xc + dx, yc + dy,      FL_RIGHT_BCOL );
991         flps_line( xc + dx, yc + dy, xc + dx, yc - dy, FL_LEFT_BCOL  );
992         flps_line( xc + dx, yc - dy, xc - dx, yc,      FL_TOP_BCOL   );
993     }
994     else if ( angle == 270 )
995     {
996         flps_line( xc - dx, yc + dy, xc,      yc - dy, FL_RIGHT_BCOL  );
997         flps_line( xc,      yc - dy, xc + dx, yc + dy, FL_LEFT_BCOL   );
998         flps_line( xc + dx, yc + dy, xc - dx, yc + dy, FL_BOTTOM_BCOL );
999     }
1000     else
1001     {
1002         flps_line( xc - dx, yc - dy, xc - dx, yc + dy, FL_RIGHT_BCOL  );
1003         flps_line( xc - dx, yc - dy, xc + dx, yc,      FL_TOP_BCOL    );
1004         flps_line( xc - dx, yc + dy, xc + dx, yc,      FL_BOTTOM_BCOL );
1005     }
1006 }
1007 
1008 
1009 /***************************************
1010  * need single pixel precision, draw in abs. coordiante system
1011  ***************************************/
1012 
1013 static void
draw_ripple_lines(int x,int y,int w,int h,int angle,FL_COLOR col FL_UNUSED_ARG)1014 draw_ripple_lines( int      x,
1015                    int      y,
1016                    int      w,
1017                    int      h,
1018                    int      angle,
1019                    FL_COLOR col  FL_UNUSED_ARG )
1020 {
1021     float ym = y + h / 2,
1022           ys;
1023     float xm = x + w / 2,
1024           xs;
1025     int i,
1026         mw = FL_BOUND_WIDTH;
1027 
1028     if ( h < 14 )
1029         return;
1030 
1031     xs = xm + 5;
1032     ys = ym + 5;
1033 
1034     if ( angle == 90 || angle == 270 )
1035     {
1036         for ( i = 0; i < 3; i++ )
1037         {
1038             flps_line( xs, y + mw, xs, y + h - mw - 1, FL_RIGHT_BCOL );
1039             xs -= 1;
1040             flps_line( xs, y + mw, xs, y + h - mw - 1, FL_LEFT_BCOL );
1041             xs -= 3;
1042         }
1043     }
1044     else
1045     {
1046         for ( i = 0; i < 3; i++ )
1047         {
1048             flps_line( x + mw, ys, x + w - mw - 1, ys, FL_LEFT_BCOL );
1049             ys -= 1;
1050             flps_line( x + mw, ys, x + w - mw - 1, ys, FL_RIGHT_BCOL );
1051             ys -= 3;
1052         }
1053     }
1054 }
1055 
1056 
1057 #define AddVertex( p, xp, yp)    do {             \
1058                                      p->x = xp;   \
1059                                      p->y = yp;   \
1060                                      p++;         \
1061                                  } while ( 0 )
1062 
1063 
1064 /***************************************
1065  ***************************************/
1066 
1067 static void
draw_bararrowhead(int x,int y,int w,int h,int angle,FL_COLOR col)1068 draw_bararrowhead( int      x,
1069                    int      y,
1070                    int      w,
1071                    int      h,
1072                    int      angle,
1073                    FL_COLOR col )
1074 {
1075     float xc = x + 0.5 * w,
1076           yc = y + 0.5 * h;
1077     int d = 3 + ( w + h ) * 0.06;
1078     float dx,
1079           dy,
1080           mar,
1081           dbar,
1082           xl;
1083     FL_POINT point[ 5 ],
1084              *p;
1085 
1086     x += d;
1087     y += d;
1088     w -= 2 * d;
1089     h -= 2 * d;
1090     dx = w / 2;
1091     dy = h / 2;
1092 
1093     dbar = dx * 0.4;
1094     mar  = 0.2 * dx;
1095 
1096     flps_output( "gsave %.1f %.1f translate %d rotate\n", xc, yc, angle );
1097 
1098     xl = -dx + 1.1 * mar;
1099 
1100     p  = point;
1101     AddVertex( p, xl, -dy );
1102     AddVertex( p, xl + dbar, -dy );
1103     AddVertex( p, xl + dbar, dy );
1104     AddVertex( p, xl, dy );
1105     flps_poly( 1, point, 4, col );
1106     flps_poly( 0, point, 4, FL_RIGHT_BCOL );
1107 
1108     p = point;
1109     AddVertex( p, -mar, -dy );
1110     AddVertex( p, -mar + dx, 0 );
1111     AddVertex( p, -mar, dy );
1112     flps_poly( 1, point, 3, col );
1113     flps_poly( 0, point, 3, FL_RIGHT_BCOL );
1114 
1115     flps_output( "grestore\n" );
1116 }
1117 
1118 
1119 /* all PS drawings have a size of 2 pixels and centered at origin */
1120 
1121 static PS_draw psdraw[ ] =
1122 {
1123     { "returnarrow", "symreturnarrow",
1124       "-0.8 0.0 -0.1 0.7 -0.1 0.05 0.6 0.05 0.6 0.7 0.7 0.7 0.7 -0.05\n"
1125       "-0.1 -0.05 -0.1 -0.7 9 P", 0, 0, 0, 0 },
1126 
1127     { "->", "symrarrow",
1128       "-0.8 -0.4 -0.8 0.4 0 0.4 0 0.8 0.8 0 0 -0.8 0 -0.4 7 P", 0, 0, 0, 0 },
1129 
1130     { "<-", "180 rotate", 0, -1, 0, 0, 0 },
1131 
1132     { ">", "symrarrowh", "-0.2 0.7 M 0.5 0.0 LT -0.2 -0.7 LT C", 0, 0, 0, 0 },
1133 
1134     { "<", "180 rotate", 0, -1, 0, 0, 0 },
1135 
1136     { "<->", "symdarrow",
1137       "-0.25 0.4 0.25 0.4 0.25 0.8 0.85 0 0.25 -0.8 0.25 -0.4 -0.25 -0.4\n"
1138       "-0.25 -0.8 -0.85 0 -0.25 0.8 10 P", 0, 0, 0, 0 },
1139 
1140     { "plus", "symplus",
1141       "-0.9 -0.13 -0.9 0.13 -0.13 0.13 -0.13 0.9 0.13 0.9 0.13 0.13 0.9 0.13\n"
1142       "0.9 -0.13 0.13 -0.13 0.13 -0.9 -0.13 -0.9 -0.13 -0.13 12 P",
1143       0, 0, 0, 0 },
1144 
1145     { ">>", "symdarrowh",
1146       "0.15 0.7 0.85 0 0.15 -0.7 0.15 -0.001 -0.55 -0.7 -0.55 0.7 0.15 0.001\n"
1147       "7 P", 0, 0, 0, 0 },
1148 
1149     { "<<", "180 rotate", 0, -1, 0, 0, 0 },
1150 
1151     { "arrow", "symthinarrow",
1152       "-0.9 0.02 M 0.65 0.02 LT 0.65 0.15 LT 0.9 0 LT 0.65 -0.15 LT\n"
1153       "0.65 -0.02 LT -0.9 -0.02 LT C", 0, 0, 0, 0 },
1154 
1155     { "circle", "symcircle", "0 0 0.77 0 360 arc", 0, 0, 0, 0 },
1156 
1157     { "square", "symsquare",
1158       "-0.77 -0.77 M -0.77 0.77 LT 0.77 0.77 LT 0.77 -0.77 LT C",
1159       0, 0, 0, 0 },
1160 
1161     { "line", "symline",
1162       "-0.97 0.01 M  0.97 0.01 LT 0.97 -0.01 LT -0.08 -0.01 LT C",
1163       0, 0, 0, 0 },
1164 
1165     { "->|", "symarrowbar",
1166       "-0.75 0.35 -0.1 0.35 -0.1 0.75 0.6 0.001 0.6 0.75 0.75 0.75\n"
1167       " 0.75 -0.75 0.6 -0.75 0.6 -0.001 -0.1 -0.75 -0.1 -0.35 -0.75 "
1168       "-0.35 12 P\n", 0, 0, 0, 0 },
1169 
1170     { "|<-", "180 rotate", 0, -1, 0, 0, 0 },
1171 
1172     { ">|", "symarrowheadbar",  /* bar 0.25 */
1173       "-0.60 0.7 0.22 0.001 0.22 0.7 0.47 0.7 0.47 -0.7 0.22 -0.7\n"
1174       " 0.22 -0.001 -0.60 -0.7 8 P", 0, 0, 0, 0 },
1175 
1176     { "|<", "180 rotate", 0, -1, 0, 0, 0 },
1177 
1178     { "|>", "symbararrowhead", 0, -1, draw_bararrowhead, 1, 0 },
1179 
1180     { "DnLine", "symdnline", 0, -1, draw_dnline, 0, 0 },
1181 
1182     { "dnline", "symdnline", 0, -1, draw_dnline, 0, 0 },
1183 
1184     { "UpLine", "symupline", 0, -1, draw_upline, 0, 0 },
1185 
1186     { "upline", "symupline", 0, -1, draw_upline, 0, 0 },
1187 
1188     { "UpArrow", "symuparrow", 0, -1, draw_uparrow, 1, 0 },
1189 
1190     { "DnArrow", "symdnarrow", 0, -1, draw_dnarrow, 1, 0 },
1191 
1192     { "=", "symRippleLines", 0, -1, draw_ripple_lines, 1, 0 },
1193 
1194     /* aliases */
1195 
1196     { "RippleLines", "symRippleLines", 0, -1, draw_ripple_lines, 1, 0 },
1197 
1198     { "+", "symplus",
1199       "-0.9 -0.13 -0.9 0.13 -0.13 0.13 -0.13 0.9 0.13 0.9 0.13 0.13 0.9 0.13\n"
1200       "0.9 -0.13 0.13 -0.13 0.13 -0.9 -0.13 -0.9 -0.13 -0.13 12 P",
1201       0, 0, 0, 0 },
1202 
1203     { "-->", "symthinarrow",
1204       "-0.9 0.02 M 0.65 0.02 LT 0.65 0.15 LT 0.9 0 LT 0.65 -0.15 LT\n"
1205       "0.65 -0.02 LT -0.9 -0.02 LT C", 0, 0, 0, 0 }
1206 };
1207 
1208 
1209 /***************************************
1210  ***************************************/
1211 
1212 static void
define_symbol(PS_draw * p)1213 define_symbol( PS_draw * p )
1214 {
1215     if ( ! p->defined && ! p->fdrawit )
1216     {
1217         if ( p->otherdef )
1218             define_symbol( p + p->otherdef );
1219         else
1220             flps_output( "/%s {%s} BD\n", p->psname, p->draw );
1221         p->defined = 1;
1222     }
1223 }
1224 
1225 
1226 /***************************************
1227  * invalidate symbols cache
1228  ***************************************/
1229 
1230 void
flps_invalidate_symbol_cache(void)1231 flps_invalidate_symbol_cache( void )
1232 {
1233     PS_draw *p = psdraw,
1234             *ps = psdraw + sizeof psdraw / sizeof *psdraw;
1235 
1236     for ( ; p < ps; p++ )
1237         p->defined = 0;
1238 }
1239 
1240 
1241 /***************************************
1242  ***************************************/
1243 
1244 static PS_draw *
find(const char * s)1245 find( const char * s )
1246 {
1247     PS_draw *p = psdraw,
1248             *ps = psdraw + sizeof psdraw / sizeof *psdraw;
1249 
1250     for ( ; p < ps; p++ )
1251         if ( strcmp( s, p->name ) == 0 )
1252         {
1253             define_symbol( p );
1254             return p;
1255         }
1256 
1257     return NULL;
1258 }
1259 
1260 
1261 #define swapit( t, a, b )      do {         \
1262                                    t t_;    \
1263                                    t_ = a;  \
1264                                    a = b;   \
1265                                    b = t_;  \
1266                                } while ( 0 )
1267 
1268 
1269 /***************************************
1270  ***************************************/
1271 
1272 int
flps_draw_symbol(const char * label,int x,int y,int w,int h,FL_COLOR col)1273 flps_draw_symbol( const char * label,
1274                   int          x,
1275                   int          y,
1276                   int          w,
1277                   int          h,
1278                   FL_COLOR     col )
1279 {
1280     int pos,
1281         shift,
1282         equalscale = 0;
1283     short defr[ ] = { 0, 225, 270, 315, 180, 0, 0, 135, 90, 45 };
1284     PS_draw *s;
1285     int rotated = 0;
1286     int sw = w,
1287         sh = h;
1288     int delta = 0;
1289 
1290     if ( ! label || *label != '@' )
1291         return 0;
1292 
1293     if ( flps->verbose )
1294         fprintf( flps->fp, "%%Symbol %s: %d %d %d %d\n",
1295                  label + 1, x, y, w, h );
1296 
1297     x += 1.2;
1298     y += 1.2;
1299     w -= 2.4;
1300     h -= 2.4;
1301 
1302     /* check special operators */
1303 
1304     pos = 1;
1305 
1306     while (    ( label[ pos ] == '-' && isdigit( ( int ) label[ pos + 1 ] ) )
1307             || ( label[ pos ] == '+' && isdigit( ( int ) label[ pos + 1 ] ) )
1308             || label[pos] == '#' )
1309     {
1310         switch ( label[ pos ] )
1311         {
1312             case '+' :
1313                 delta = '0' - label[ ++pos ];
1314                 break;
1315 
1316             case '-' :
1317                 delta = label[ ++pos ] - '0';
1318                 break;
1319 
1320             case '#' :
1321                 equalscale = 1;
1322                 break;
1323         }
1324 
1325         pos++;
1326     }
1327 
1328     shift = pos;
1329 
1330     if ( label[ pos ] >= '1' && label[ pos ] <= '9' )
1331     {
1332         rotated = defr[ label[ pos ] - '0' ];
1333         shift = pos + 1;
1334     }
1335     else if ( label[ pos ] == '0' )
1336     {
1337         rotated =   100 * ( label[ pos + 1 ] - '0' )
1338                   +  10 * ( label[ pos + 2 ] - '0' )
1339                   +   1 * ( label[ pos + 3 ] - '0' );
1340         shift = pos + 4;
1341     }
1342 
1343     /* short hand with @4 etc */
1344 
1345     if ( ! ( s = ( label[ shift ] ? find( label + shift ) : psdraw ) ) )
1346     {
1347         fprintf( stderr, "Bad label %s\n", label + shift );
1348         if ( flps->verbose )
1349             fprintf( flps->fp, "%% unknown symbol %s. Not drawn\n", label );
1350         return 0;
1351     }
1352 
1353     if ( equalscale )
1354         sw = sh = FL_min( w, h );
1355 
1356     if ( delta )
1357     {
1358         if ( s->abs_coordinate )
1359         {
1360             x += delta;
1361             y += delta;
1362         }
1363 
1364         sw -= 2 * delta;
1365         sh -= 2 * delta;
1366     }
1367 
1368     if ( sw <= 5 )
1369         sw = 5;
1370     if ( sh <= 5 )
1371         sw = 5;
1372 
1373     if ( ! s->abs_coordinate )
1374     {
1375         flps_output( "gsave\n%.1f %.1f translate %.1f %.1f scale %d rotate ",
1376                      x + 0.5 * w, y + 0.5 * h, 0.5 * sw, 0.5 * sh, rotated );
1377         flps_output( "%.3f %.3f LW\n", 3.0 / ( sw + sh ), 3.0 / ( sh + sw ) );
1378     }
1379 
1380     if ( s->fdrawit )
1381     {
1382         s->fdrawit( x, y, w, h, rotated, col );
1383         if ( ! s->abs_coordinate )
1384             flps_output( "grestore\n" );
1385         flps_invalidate_color_cache( );
1386         return 1;
1387     }
1388 
1389     if ( s->otherdef )
1390     {
1391         flps_output( "%s ", s->psname );
1392         s = s + s->otherdef;
1393     }
1394 
1395     flps_color( col );
1396     flps_output( "%s F ", s->psname );
1397     flps_color( FL_BLACK );
1398     flps_output( "%s S\n", s->psname );
1399     flps_output( "grestore\n" );
1400 
1401     flps_reset_cache( );
1402 
1403     return 1;
1404 }
1405 
1406 
1407 /***************************************
1408  ***************************************/
1409 
1410 void
flps_emit_prolog(void)1411 flps_emit_prolog( void )
1412 {
1413     /* basic graphics defines */
1414 
1415     flps_output( "/BD {bind def} def\n" );
1416     flps_output( "/M {moveto} BD /LT {lineto} BD\n" );
1417     flps_output( "/RLT {rlineto} BD\n" );
1418     flps_output( "/L {M LT} BD  /C  {closepath} BD\n" );
1419     flps_output( "/LW {setlinewidth} BD\n" );
1420     flps_output( "/S {stroke} BD /F {fill} BD\n" );
1421     flps_output( "/G {setgray} BD /RGB {setrgbcolor} BD\n" );
1422 
1423     /* x y x y N */
1424 
1425     flps_output( "/P  {3 1 roll M 2 exch 1 exch {pop LT} for C} BD\n" );
1426     flps_output( "/lines {3 1 roll M 2 exch 1 exch {pop LT} for S} BD\n" );
1427     flps_output( "/DTD {[5 4 1 4] 0 setdash} BD\n" );   /* dot-dash */
1428     flps_output( "/DT {[1 3] 0 setdash} BD\n" );        /* dot   */
1429     flps_output( "/LD {[8 5] 0 setdash} BD\n" );        /* long dash */
1430     flps_output( "/D {[4 4] 0 setdash} BD\n" );         /* dash */
1431     flps_output( "/SL {[] 0 setdash} BD\n" );           /* solid */
1432     flps_output( "/NP {newpath} BD\n" );                /* solid */
1433 
1434     flps_output( "/SX %.2g def /SY %.2g def\n",
1435                  flps->final_xscale, flps->final_yscale );
1436 
1437     /* basic font support */
1438 
1439     flps_output( "/point {SX SY add 2 div div} BD\n" );
1440     flps_output( "/SetFont {findfont exch scalefont setfont} BD\n" );
1441     flps_output( "/Lshow {show} BD\n" );
1442     flps_output( "/Cshow {dup stringwidth pop -2 div 0 rmoveto show} BD\n" );
1443     flps_output( "/Rshow {dup stringwidth pop neg 0 rmoveto show} BD\n" );
1444     flps_output( "/CP {currentpoint} BD /SW {stringwidth} BD\n" );
1445 }
1446 
1447 
1448 /***************************************
1449  ***************************************/
1450 
1451 void
flps_emit_header(const char * title,int n,int xi,int yi,int xf,int yf)1452 flps_emit_header( const char * title,
1453                   int          n,
1454                   int          xi,
1455                   int          yi,
1456                   int          xf,
1457                   int          yf )
1458 {
1459     if ( flps->eps )
1460         fprintf( flps->fp, "%%!PS-Adobe-3.0 EPSF-2.0\n" );
1461     else
1462         fprintf( flps->fp, "%%!PS-Adobe-1.0\n" );
1463 
1464     fprintf( flps->fp, "%%%%Title: %s\n", title );
1465     fprintf( flps->fp, "%%%%For: %s\n", fl_whoami( ) );
1466     fprintf( flps->fp, "%%%%CreateDate: %s\n", fl_now( ) );
1467     fprintf( flps->fp, "%%%%Creator: xforms V%d.%d.%s "
1468              "Copyright (c) 1997-1999 T.C. Zhao and M. Overmars\n",
1469              FL_VERSION, FL_REVISION, FL_FIXLEVEL );
1470     fprintf( flps->fp, "%%%%Pages: %d\n", n );
1471     fprintf( flps->fp, "%%%%BoundingBox: %d %d %d %d\n", xi, yi, xf, yf );
1472     fprintf( flps->fp, "%%%%Orientation: %s\n",
1473              flps->landscape ? "Landscape" : "Portrait" );
1474     fprintf( flps->fp, "%%%%EndComments\n" );
1475 
1476     fprintf( flps->fp, "%% PaperSize: %.1fx%.1fin\n",
1477              flps->paper_w, flps->paper_h );
1478 }
1479 
1480 
1481 /***************************************
1482  ***************************************/
1483 
1484 void
flps_set_clipping(int x,int y,int w,int h)1485 flps_set_clipping( int x,
1486                    int y,
1487                    int w,
1488                    int h )
1489 {
1490 #if 0               /* rectclip is a level 2 feature */
1491     flps_output( "gsave NP %d %d %d %d rectclip\n", x, y, w, h );
1492 #else
1493     flps_output( "gsave NP %d %d M %d 0 RLT 0 %d RLT %d neg 0 RLT CP clip NP\n",
1494                  x, y, w, h, w );
1495 #endif
1496 }
1497 
1498 
1499 /***************************************
1500  ***************************************/
1501 
1502 void
flps_unset_clipping(void)1503 flps_unset_clipping( void )
1504 {
1505     flps_output( "grestore\n" );
1506     flps_reset_cache( );
1507 }
1508 
1509 
1510 /*
1511  * Local variables:
1512  * tab-width: 4
1513  * indent-tabs-mode: nil
1514  * End:
1515  */
1516