PLplot: plr.c Source File

PLplot 5.10.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plr.c
Go to the documentation of this file.
1 // $Id: plr.c 12288 2013-01-30 04:40:35Z airwin $
2 //
3 // Copyright 1993, 1994, 1995
4 // Maurice LeBrun
5 // IFS, University of Texas at Austin
6 //
7 // This software may be freely copied, modified and redistributed under the
8 // terms of the GNU Library General Public License.
9 //
10 // There is no warranty or other guarantee of fitness of this software.
11 // It is provided solely "as is". The author(s) disclaim(s) all
12 // responsibility and liability with respect to this software's usage or
13 // its effect upon hardware or computer systems.
14 //
15 //--------------------------------------------------------------------------
16 //
17 // Support routines to render a PLplot byte stream, interpreting the PLplot
18 // metacode.
19 //
20 // Although this code is duplicated to some extent by plrender and the
21 // plot buffer redraw code (in plbuf.c), they are all different in some
22 // significant ways, namely:
23 //
24 // - plrender must always retain backward compatibility code to
25 // handle old metafiles, as well as stuff to support seeking.
26 //
27 // - plbuf by definition is redrawing on the same machine so no
28 // special effort is necessary to make the byte stream portable,
29 // also, only low-level graphics calls are used (grline, etc)
30 //
31 // The rendering code here must (by contrast to plbuf) use the high level
32 // plot routines (as does plrender), to support local zooms as well as the
33 // ability to dump the associated window into plot space to a file, but is
34 // otherwise pretty minimal. A portable byte stream is used since network
35 // communication over a socket may be used.
36 //
37 //--------------------------------------------------------------------------
38
39 //
40 // #define DEBUG
41 // #define DEBUG_ENTER
42 //
43
44 #include "plserver.h"
45 #include "plevent.h"
46 #include "metadefs.h"
47
48 // Some wrapper macros to return (-1) on error
49
50 // Note we use %lu and an explicit cast to unsigned long to print size_t pointers.
51 // C99 adds %zd as an explicit format specifier for size_t but this is not yet
52 // fully adopted.
53
54 #define plr_rd( code ) \
55 if ( code ) { fprintf( stderr, \
56 "Unable to read from %s in %s at line %d, bytecount %lu\n", \
57 plr->iodev->typeName, __FILE__, __LINE__, (unsigned long) plr->pdfs->bp ); \
58 return -1; }
59
60 #define plr_cmd( code ) \
61 if ( ( code ) == -1 ) return -1;
62
63 // Error termination
64
65 #define barf( msg ) \
66 { fprintf( stderr, "%s\nCommand code: %d, byte count: %lu\n", \
67 msg, csave, (unsigned long) plr->pdfs->bp ); return -1; }
68
69 // Static function prototypes.
70
71 static int plr_process1( PLRDev *plr, int c );
72 static int plr_init( PLRDev *plr );
73 static int plr_line( PLRDev *plr, int c );
74 static int plr_eop( PLRDev *plr );
75 static int plr_bop( PLRDev *plr );
76 static int plr_state( PLRDev *plr );
77 static int plr_esc( PLRDev *plr );
78 static int plr_get( PLRDev *plr );
79 static int plr_unget( PLRDev *plr, U_CHAR c );
80 static int get_ncoords( PLRDev *plr, PLFLT *x, PLFLT *y, PLINT n );
81 static int plresc_fill( PLRDev *plr );
82
83 // variables
84
85 static int csave = -1;
86 static U_CHAR dum_uchar;
87 static U_SHORT dum_ushort;
88 static PLFLT xstatic[PL_MAXPOLY], ystatic[PL_MAXPOLY];
89
90 //--------------------------------------------------------------------------
91 // plr_start()
92 //
93 // Set default state parameters before anyone else has a chance to.
94 //--------------------------------------------------------------------------
95
96 void
97 plr_start( PLRDev *plr )
98 {
99 dbug_enter( "plr_start" );
100
101 plr->xmin = 0;
102 plr->xmax = PIXELS_X - 1;
103 plr->ymin = 0;
104 plr->ymax = PIXELS_Y - 1;
105
106 plr->xold = PL_UNDEFINED;
107 plr->yold = PL_UNDEFINED;
108 }
109
110 //--------------------------------------------------------------------------
111 // plr_process()
112 //
113 // Read & process commands until plr->nbytes bytes have been read.
114 //--------------------------------------------------------------------------
115
116 int
117 plr_process( PLRDev *plr )
118 {
119 int c;
120
121 dbug_enter( "plr_process" );
122
123 while ( plr->pdfs->bp < (size_t) plr->nbytes )
124 {
125 plr_cmd( c = plr_get( plr ) );
126 csave = c;
127 plr_cmd( plr_process1( plr, c ) );
128 }
129 return 0;
130 }
131
132 //--------------------------------------------------------------------------
133 // plr_process1()
134 //
135 // Process a command. Note: because of line->polyline compression, this
136 // may actually process an arbitrary number of LINE or LINETO commands.
137 // Since the data buffer (fifo or socket) is only flushed after a complete
138 // command, there should be no danger in rushing blindly ahead to execute
139 // each plot command.
140 //--------------------------------------------------------------------------
141
142 static int
143 plr_process1( PLRDev *plr, int c )
144 {
145 switch ( c )
146 {
147 case INITIALIZE:
148 plr_cmd( plr_init( plr ) );
149 break;
150
151 case LINE:
152 case LINETO:
153 case POLYLINE:
154 plr_cmd( plr_line( plr, c ) );
155 break;
156
157 case EOP:
158 plr->at_eop = 1;
159 plr_cmd( plr_eop( plr ) );
160 break;
161
162 case BOP:
163 plr->at_bop = 1;
164 plr_cmd( plr_bop( plr ) );
165 break;
166
167 case CHANGE_STATE:
168 plr_cmd( plr_state( plr ) );
169 break;
170
171 case ESCAPE:
172 plr_cmd( plr_esc( plr ) );
173 break;
174
175 default:
176 fprintf( stderr, "plr_process1: Unrecognized command code %d\n", c );
177 }
178
179 return 0;
180 }
181
182 //--------------------------------------------------------------------------
183 // void plr_init()
184 //
185 // Handle initialization.
186 //--------------------------------------------------------------------------
187
188 static int
189 plr_init( PLRDev *plr )
190 {
191 char tk_magic[80], tk_version[80], tag[80];
192
193 dbug_enter( "plr_init" );
194
195 // Read header info
196
197 plr_cmd( pdf_rd_header( plr->pdfs, tk_magic ) );
198 if ( strcmp( tk_magic, PLSERV_HEADER ) )
199 barf( "plr_init: Invalid header" );
200
201 // Read version field of header. We need to check that we can read the
202 // byte stream, in case this is an old version of plserver.
203
204 plr_cmd( pdf_rd_header( plr->pdfs, tk_version ) );
205 if ( strcmp( tk_version, PLSERV_VERSION ) > 0 )
206 {
207 fprintf( stderr,
208 "Error: incapable of reading output of version %s.\n", tk_version );
209 barf( "plr_init: Please obtain a newer copy of plserver." );
210 }
211
212 // Read tagged initialization info.
213 // Overkill, but a no-brainer since plrender already uses this
214
215 for (;; )
216 {
217 plr_cmd( pdf_rd_header( plr->pdfs, tag ) );
218 if ( *tag == '\0' )
219 break;
220
221 if ( !strcmp( tag, "xmin" ) )
222 {
223 plr_rd( pdf_rd_2bytes( plr->pdfs, &dum_ushort ) );
224 plr->xmin = (short) dum_ushort;
225 continue;
226 }
227
228 if ( !strcmp( tag, "xmax" ) )
229 {
230 plr_rd( pdf_rd_2bytes( plr->pdfs, &dum_ushort ) );
231 plr->xmax = (short) dum_ushort;
232 continue;
233 }
234
235 if ( !strcmp( tag, "ymin" ) )
236 {
237 plr_rd( pdf_rd_2bytes( plr->pdfs, &dum_ushort ) );
238 plr->ymin = (short) dum_ushort;
239 continue;
240 }
241
242 if ( !strcmp( tag, "ymax" ) )
243 {
244 plr_rd( pdf_rd_2bytes( plr->pdfs, &dum_ushort ) );
245 plr->ymax = (short) dum_ushort;
246 continue;
247 }
248
249 if ( !strcmp( tag, "width" ) )
250 {
251 plr_rd( pdf_rd_1byte( plr->pdfs, &dum_uchar ) );
252 plwidth( dum_uchar );
253 continue;
254 }
255
256 barf( "plr_init: Unrecognized initialization tag." );
257 }
258
259 return 0;
260 }
261
262 //--------------------------------------------------------------------------
263 // plr_line()
264 //
265 // Draw a line or polyline.
266 //--------------------------------------------------------------------------
267
268 static int
269 plr_line( PLRDev *plr, int c )
270 {
271 int c1;
272 U_SHORT npts;
273 PLFLT *x, *y;
274
275 // "Temporary" logic until can figure out what value of npts will
276 // actually be required which would allow use of malloc whenever
277 // that npts value > PL_MAXPOLY.
278 x = xstatic;
279 y = ystatic;
280
281 npts = 1;
282 x[0] = plr->xold;
283 y[0] = plr->yold;
284
285 switch ( (int) c )
286 {
287 case LINE:
288 plr_cmd( get_ncoords( plr, x, y, 1 ) );
289 // n.b. falls through to LINETO case.
290
291 case LINETO:
292 for (;; )
293 {
294 plr_cmd( get_ncoords( plr, x + npts, y + npts, 1 ) );
295
296 npts++;
297 if ( npts == PL_MAXPOLY || ( plr->pdfs->bp == (size_t) plr->nbytes ) )
298 break;
299
300 plr_cmd( c1 = plr_get( plr ) );
301 if ( c1 != LINETO )
302 {
303 plr_cmd( plr_unget( plr, (U_CHAR) c1 ) );
304 break;
305 }
306 }
307 break;
308
309 case POLYLINE:
310 plr_rd( pdf_rd_2bytes( plr->pdfs, &npts ) );
311 plr_cmd( get_ncoords( plr, x, y, npts ) );
312 break;
313 }
314
315 plline( npts, x, y );
316
317 plr->xold = x[npts - 1];
318 plr->yold = y[npts - 1];
319
320 return 0;
321 }
322
323 //--------------------------------------------------------------------------
324 // get_ncoords()
325 //
326 // Read n coordinate vectors.
327 //--------------------------------------------------------------------------
328
329 #define plr_rdn( code ) \
330 if ( code ) { fprintf( stderr, \
331 "Unable to read from %s in %s at line %d, bytecount %d\n\
332 Bytes requested: %d\n", plr->iodev->typeName, __FILE__, __LINE__, \
333 (int) plr->pdfs->bp, (int) 2 * n ); return -1; }
334
335 static int
336 get_ncoords( PLRDev *plr, PLFLT *x, PLFLT *y, PLINT n )
337 {
338 PLINT i;
339 short _xs[PL_MAXPOLY], _ys[PL_MAXPOLY];
340 short *xs, *ys;
341
342 if ( n > PL_MAXPOLY )
343 {
344 xs = (short *) malloc( sizeof ( short ) * (size_t) n );
345 ys = (short *) malloc( sizeof ( short ) * (size_t) n );
346 }
347 else
348 {
349 xs = _xs;
350 ys = _ys;
351 }
352
353 plr_rdn( pdf_rd_2nbytes( plr->pdfs, (U_SHORT *) xs, n ) );
354 plr_rdn( pdf_rd_2nbytes( plr->pdfs, (U_SHORT *) ys, n ) );
355
356 for ( i = 0; i < n; i++ )
357 {
358 x[i] = xs[i];
359 y[i] = ys[i];
360 }
361
362 if ( n > PL_MAXPOLY )
363 {
364 free( xs );
365 free( ys );
366 }
367
368 return 0;
369 }
370
371 //--------------------------------------------------------------------------
372 // plr_eop()
373 //
374 // Clear screen.
375 //--------------------------------------------------------------------------
376
377 static int
378 plr_eop( PLRDev * PL_UNUSED( plr ) )
379 {
380 dbug_enter( "plr_eop" );
381
382 pleop();
383 return 0;
384 }
385
386 //--------------------------------------------------------------------------
387 // plr_bop()
388 //
389 // Page advancement.
390 //--------------------------------------------------------------------------
391
392 static int
393 plr_bop( PLRDev *plr )
394 {
395 dbug_enter( "plr_bop" );
396
397 // Advance and setup the page
398
399 plbop();
400 plvpor( 0., 1., 0., 1. );
401 plwind( plr->xmin, plr->xmax, plr->ymin, plr->ymax );
402
403 return 0;
404 }
405
406 //--------------------------------------------------------------------------
407 // plr_state()
408 //
409 // Handle change in PLStream state (color, pen width, fill attribute,
410 // etc).
411 //--------------------------------------------------------------------------
412
413 static int
414 plr_state( PLRDev *plr )
415 {
416 U_CHAR op;
417 int i;
418
419 plr_rd( pdf_rd_1byte( plr->pdfs, &op ) );
420
421 switch ( op )
422 {
423 case PLSTATE_WIDTH: {
424 U_SHORT width;
425
426 plr_rd( pdf_rd_2bytes( plr->pdfs, &width ) );
427
428 plwidth( width );
429 break;
430 }
431
432 case PLSTATE_COLOR0: {
433 short icol0;
434
435 plr_rd( pdf_rd_2bytes( plr->pdfs, (unsigned short *) &icol0 ) );
436
437 if ( icol0 == PL_RGB_COLOR )
438 {
439 U_CHAR r, g, b;
440 plr_rd( pdf_rd_1byte( plr->pdfs, &r ) );
441 plr_rd( pdf_rd_1byte( plr->pdfs, &g ) );
442 plr_rd( pdf_rd_1byte( plr->pdfs, &b ) );
443 plscol0( icol0, r, g, b );
444 }
445 else
446 {
447 plcol0( icol0 );
448 }
449 break;
450 }
451
452 case PLSTATE_COLOR1: {
453 U_SHORT icol1;
454 PLFLT col1;
455
456 plr_rd( pdf_rd_2bytes( plr->pdfs, &icol1 ) );
457 col1 = (double) icol1 / (double) plsc->ncol1;
458 plcol1( col1 );
459 break;
460 }
461
462 case PLSTATE_FILL: {
463 signed char patt;
464
465 plr_rd( pdf_rd_1byte( plr->pdfs, (U_CHAR *) &patt ) );
466 plpsty( patt );
467 break;
468 }
469
470 case PLSTATE_CMAP0: {
471 U_SHORT ncol0;
472
473 plr_rd( pdf_rd_2bytes( plr->pdfs, &ncol0 ) );
474 plscmap0n( (PLINT) ncol0 );
475 for ( i = 0; i < plsc->ncol0; i++ )
476 {
477 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap0[i].r ) );
478 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap0[i].g ) );
479 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap0[i].b ) );
480 }
481 plP_state( PLSTATE_CMAP0 );
482 break;
483 }
484
485 case PLSTATE_CMAP1: {
486 U_SHORT ncol1, ncp1;
487 float h, l, s;
488 U_CHAR rev;
489
490 plr_rd( pdf_rd_2bytes( plr->pdfs, &ncol1 ) );
491 plscmap1n( (PLINT) ncol1 );
492 for ( i = 0; i < plsc->ncol1; i++ )
493 {
494 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap1[i].r ) );
495 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap1[i].g ) );
496 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap1[i].b ) );
497 }
498 // Get the control points
499 plr_rd( pdf_rd_2bytes( plr->pdfs, &ncp1 ) );
500 plsc->ncp1 = ncp1;
501 for ( i = 0; i < plsc->ncp1; i++ )
502 {
503 plr_rd( pdf_rd_ieeef( plr->pdfs, &h ) );
504 plr_rd( pdf_rd_ieeef( plr->pdfs, &l ) );
505 plr_rd( pdf_rd_ieeef( plr->pdfs, &s ) );
506 plr_rd( pdf_rd_1byte( plr->pdfs, &rev ) );
507
508 plsc->cmap1cp[i].h = h;
509 plsc->cmap1cp[i].l = l;
510 plsc->cmap1cp[i].s = s;
511 plsc->cmap1cp[i].alt_hue_path = rev;
512 }
513 plP_state( PLSTATE_CMAP1 );
514 break;
515 }
516 }
517
518 return 0;
519 }
520
521 //--------------------------------------------------------------------------
522 // plr_esc()
523 //
524 // Handle all escape functions.
525 // Only those that require additional data to be read need to be
526 // explicitly handled; the others are merely passed on to the actual
527 // driver.
528 //--------------------------------------------------------------------------
529
530 static int
531 plr_esc( PLRDev *plr )
532 {
533 U_CHAR op;
534
535 plr_rd( pdf_rd_1byte( plr->pdfs, &op ) );
536
537 switch ( op )
538 {
539 case PLESC_FILL:
540 plr_cmd( plresc_fill( plr ) );
541 break;
542
543 default:
544 pl_cmd( (PLINT) op, NULL );
545 break;
546 }
547
548 return 0;
549 }
550
551 //--------------------------------------------------------------------------
552 // plresc_fill()
553 //
554 // Fill polygon described in points plsc->dev_x[] and plsc->dev_y[].
555 //--------------------------------------------------------------------------
556
557 static int
558 plresc_fill( PLRDev *plr )
559 {
560 U_SHORT npts;
561 PLFLT *x, *y;
562
563 dbug_enter( "plresc_fill" );
564
565 plr_rd( pdf_rd_2bytes( plr->pdfs, &npts ) );
566 if ( npts > PL_MAXPOLY )
567 {
568 x = (PLFLT *) malloc( sizeof ( PLFLT ) * npts );
569 y = (PLFLT *) malloc( sizeof ( PLFLT ) * npts );
570 }
571 else
572 {
573 x = xstatic;
574 y = ystatic;
575 }
576 get_ncoords( plr, x, y, npts );
577 plfill( npts, x, y );
578
579 if ( npts > PL_MAXPOLY )
580 {
581 free( x );
582 free( y );
583 }
584 return 0;
585 }
586
587 //--------------------------------------------------------------------------
588 // plr_get()
589 //
590 // Read & return the next command
591 //--------------------------------------------------------------------------
592
593 static int
594 plr_get( PLRDev *plr )
595 {
596 int c;
597
598 c = pdf_getc( plr->pdfs );
599 if ( c == EOF )
600 {
601 barf( "plr_get: Unable to read character" );
602 }
603
604 return c;
605 }
606
607 //--------------------------------------------------------------------------
608 // plr_unget()
609 //
610 // Push back the last command read.
611 //--------------------------------------------------------------------------
612
613 static int
614 plr_unget( PLRDev *plr, U_CHAR c )
615 {
616 if ( pdf_ungetc( c, plr->pdfs ) == EOF )
617 {
618 barf( "plr_unget: Unable to push back character" );
619 }
620
621 return 0;
622 }