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