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