PLplot
5.10.0
|
00001 // Copyright 1993, 1994, 1995 00002 // Maurice LeBrun 00003 // IFS, University of Texas at Austin 00004 // 00005 // This software may be freely copied, modified and redistributed under the 00006 // terms of the GNU Library General Public License. 00007 // 00008 // There is no warranty or other guarantee of fitness of this software. 00009 // It is provided solely "as is". The author(s) disclaim(s) all 00010 // responsibility and liability with respect to this software's usage or 00011 // its effect upon hardware or computer systems. 00012 // 00013 //-------------------------------------------------------------------------- 00014 // 00015 // Support routines to render a PLplot byte stream, interpreting the PLplot 00016 // metacode. 00017 // 00018 // Although this code is duplicated to some extent by plrender and the 00019 // plot buffer redraw code (in plbuf.c), they are all different in some 00020 // significant ways, namely: 00021 // 00022 // - plrender must always retain backward compatibility code to 00023 // handle old metafiles, as well as stuff to support seeking. 00024 // 00025 // - plbuf by definition is redrawing on the same machine so no 00026 // special effort is necessary to make the byte stream portable, 00027 // also, only low-level graphics calls are used (grline, etc) 00028 // 00029 // The rendering code here must (by contrast to plbuf) use the high level 00030 // plot routines (as does plrender), to support local zooms as well as the 00031 // ability to dump the associated window into plot space to a file, but is 00032 // otherwise pretty minimal. A portable byte stream is used since network 00033 // communication over a socket may be used. 00034 // 00035 //-------------------------------------------------------------------------- 00036 00037 // 00038 // #define DEBUG 00039 // #define DEBUG_ENTER 00040 // 00041 00042 #include "plserver.h" 00043 #include "plevent.h" 00044 #include "metadefs.h" 00045 00046 // Some wrapper macros to return (-1) on error 00047 00048 // Note we use %lu and an explicit cast to unsigned long to print size_t pointers. 00049 // C99 adds %zd as an explicit format specifier for size_t but this is not yet 00050 // fully adopted. 00051 00052 #define plr_rd( code ) \ 00053 if ( code ) { fprintf( stderr, \ 00054 "Unable to read from %s in %s at line %d, bytecount %lu\n", \ 00055 plr->iodev->typeName, __FILE__, __LINE__, (unsigned long) plr->pdfs->bp ); \ 00056 return -1; } 00057 00058 #define plr_cmd( code ) \ 00059 if ( ( code ) == -1 ) return -1; 00060 00061 // Error termination 00062 00063 #define barf( msg ) \ 00064 { fprintf( stderr, "%s\nCommand code: %d, byte count: %lu\n", \ 00065 msg, csave, (unsigned long) plr->pdfs->bp ); return -1; } 00066 00067 // Static function prototypes. 00068 00069 static int plr_process1( PLRDev *plr, int c ); 00070 static int plr_init( PLRDev *plr ); 00071 static int plr_line( PLRDev *plr, int c ); 00072 static int plr_eop( PLRDev *plr ); 00073 static int plr_bop( PLRDev *plr ); 00074 static int plr_state( PLRDev *plr ); 00075 static int plr_esc( PLRDev *plr ); 00076 static int plr_get( PLRDev *plr ); 00077 static int plr_unget( PLRDev *plr, U_CHAR c ); 00078 static int get_ncoords( PLRDev *plr, PLFLT *x, PLFLT *y, PLINT n ); 00079 static int plresc_fill( PLRDev *plr ); 00080 00081 // variables 00082 00083 static int csave = -1; 00084 static U_CHAR dum_uchar; 00085 static U_SHORT dum_ushort; 00086 static PLFLT xstatic[PL_MAXPOLY], ystatic[PL_MAXPOLY]; 00087 00088 //-------------------------------------------------------------------------- 00089 // plr_start() 00090 // 00091 // Set default state parameters before anyone else has a chance to. 00092 //-------------------------------------------------------------------------- 00093 00094 void 00095 plr_start( PLRDev *plr ) 00096 { 00097 dbug_enter( "plr_start" ); 00098 00099 plr->xmin = 0; 00100 plr->xmax = PIXELS_X - 1; 00101 plr->ymin = 0; 00102 plr->ymax = PIXELS_Y - 1; 00103 00104 plr->xold = PL_UNDEFINED; 00105 plr->yold = PL_UNDEFINED; 00106 } 00107 00108 //-------------------------------------------------------------------------- 00109 // plr_process() 00110 // 00111 // Read & process commands until plr->nbytes bytes have been read. 00112 //-------------------------------------------------------------------------- 00113 00114 int 00115 plr_process( PLRDev *plr ) 00116 { 00117 int c; 00118 00119 dbug_enter( "plr_process" ); 00120 00121 while ( plr->pdfs->bp < (size_t) plr->nbytes ) 00122 { 00123 plr_cmd( c = plr_get( plr ) ); 00124 csave = c; 00125 plr_cmd( plr_process1( plr, c ) ); 00126 } 00127 return 0; 00128 } 00129 00130 //-------------------------------------------------------------------------- 00131 // plr_process1() 00132 // 00133 // Process a command. Note: because of line->polyline compression, this 00134 // may actually process an arbitrary number of LINE or LINETO commands. 00135 // Since the data buffer (fifo or socket) is only flushed after a complete 00136 // command, there should be no danger in rushing blindly ahead to execute 00137 // each plot command. 00138 //-------------------------------------------------------------------------- 00139 00140 static int 00141 plr_process1( PLRDev *plr, int c ) 00142 { 00143 switch ( c ) 00144 { 00145 case INITIALIZE: 00146 plr_cmd( plr_init( plr ) ); 00147 break; 00148 00149 case LINE: 00150 case LINETO: 00151 case POLYLINE: 00152 plr_cmd( plr_line( plr, c ) ); 00153 break; 00154 00155 case EOP: 00156 plr->at_eop = 1; 00157 plr_cmd( plr_eop( plr ) ); 00158 break; 00159 00160 case BOP: 00161 plr->at_bop = 1; 00162 plr_cmd( plr_bop( plr ) ); 00163 break; 00164 00165 case CHANGE_STATE: 00166 plr_cmd( plr_state( plr ) ); 00167 break; 00168 00169 case ESCAPE: 00170 plr_cmd( plr_esc( plr ) ); 00171 break; 00172 00173 default: 00174 fprintf( stderr, "plr_process1: Unrecognized command code %d\n", c ); 00175 } 00176 00177 return 0; 00178 } 00179 00180 //-------------------------------------------------------------------------- 00181 // void plr_init() 00182 // 00183 // Handle initialization. 00184 //-------------------------------------------------------------------------- 00185 00186 static int 00187 plr_init( PLRDev *plr ) 00188 { 00189 char tk_magic[80], tk_version[80], tag[80]; 00190 00191 dbug_enter( "plr_init" ); 00192 00193 // Read header info 00194 00195 plr_cmd( pdf_rd_header( plr->pdfs, tk_magic ) ); 00196 if ( strcmp( tk_magic, PLSERV_HEADER ) ) 00197 barf( "plr_init: Invalid header" ); 00198 00199 // Read version field of header. We need to check that we can read the 00200 // byte stream, in case this is an old version of plserver. 00201 00202 plr_cmd( pdf_rd_header( plr->pdfs, tk_version ) ); 00203 if ( strcmp( tk_version, PLSERV_VERSION ) > 0 ) 00204 { 00205 fprintf( stderr, 00206 "Error: incapable of reading output of version %s.\n", tk_version ); 00207 barf( "plr_init: Please obtain a newer copy of plserver." ); 00208 } 00209 00210 // Read tagged initialization info. 00211 // Overkill, but a no-brainer since plrender already uses this 00212 00213 for (;; ) 00214 { 00215 plr_cmd( pdf_rd_header( plr->pdfs, tag ) ); 00216 if ( *tag == '\0' ) 00217 break; 00218 00219 if ( !strcmp( tag, "xmin" ) ) 00220 { 00221 plr_rd( pdf_rd_2bytes( plr->pdfs, &dum_ushort ) ); 00222 plr->xmin = (short) dum_ushort; 00223 continue; 00224 } 00225 00226 if ( !strcmp( tag, "xmax" ) ) 00227 { 00228 plr_rd( pdf_rd_2bytes( plr->pdfs, &dum_ushort ) ); 00229 plr->xmax = (short) dum_ushort; 00230 continue; 00231 } 00232 00233 if ( !strcmp( tag, "ymin" ) ) 00234 { 00235 plr_rd( pdf_rd_2bytes( plr->pdfs, &dum_ushort ) ); 00236 plr->ymin = (short) dum_ushort; 00237 continue; 00238 } 00239 00240 if ( !strcmp( tag, "ymax" ) ) 00241 { 00242 plr_rd( pdf_rd_2bytes( plr->pdfs, &dum_ushort ) ); 00243 plr->ymax = (short) dum_ushort; 00244 continue; 00245 } 00246 00247 if ( !strcmp( tag, "width" ) ) 00248 { 00249 plr_rd( pdf_rd_1byte( plr->pdfs, &dum_uchar ) ); 00250 plwidth( dum_uchar ); 00251 continue; 00252 } 00253 00254 barf( "plr_init: Unrecognized initialization tag." ); 00255 } 00256 00257 return 0; 00258 } 00259 00260 //-------------------------------------------------------------------------- 00261 // plr_line() 00262 // 00263 // Draw a line or polyline. 00264 //-------------------------------------------------------------------------- 00265 00266 static int 00267 plr_line( PLRDev *plr, int c ) 00268 { 00269 int c1; 00270 U_SHORT npts; 00271 PLFLT *x, *y; 00272 00273 // "Temporary" logic until can figure out what value of npts will 00274 // actually be required which would allow use of malloc whenever 00275 // that npts value > PL_MAXPOLY. 00276 x = xstatic; 00277 y = ystatic; 00278 00279 npts = 1; 00280 x[0] = plr->xold; 00281 y[0] = plr->yold; 00282 00283 switch ( (int) c ) 00284 { 00285 case LINE: 00286 plr_cmd( get_ncoords( plr, x, y, 1 ) ); 00287 // n.b. falls through to LINETO case. 00288 00289 case LINETO: 00290 for (;; ) 00291 { 00292 plr_cmd( get_ncoords( plr, x + npts, y + npts, 1 ) ); 00293 00294 npts++; 00295 if ( npts == PL_MAXPOLY || ( plr->pdfs->bp == (size_t) plr->nbytes ) ) 00296 break; 00297 00298 plr_cmd( c1 = plr_get( plr ) ); 00299 if ( c1 != LINETO ) 00300 { 00301 plr_cmd( plr_unget( plr, (U_CHAR) c1 ) ); 00302 break; 00303 } 00304 } 00305 break; 00306 00307 case POLYLINE: 00308 plr_rd( pdf_rd_2bytes( plr->pdfs, &npts ) ); 00309 plr_cmd( get_ncoords( plr, x, y, npts ) ); 00310 break; 00311 } 00312 00313 plline( npts, x, y ); 00314 00315 plr->xold = x[npts - 1]; 00316 plr->yold = y[npts - 1]; 00317 00318 return 0; 00319 } 00320 00321 //-------------------------------------------------------------------------- 00322 // get_ncoords() 00323 // 00324 // Read n coordinate vectors. 00325 //-------------------------------------------------------------------------- 00326 00327 #define plr_rdn( code ) \ 00328 if ( code ) { fprintf( stderr, \ 00329 "Unable to read from %s in %s at line %d, bytecount %d\n\ 00330 Bytes requested: %d\n", plr->iodev->typeName, __FILE__, __LINE__, \ 00331 (int) plr->pdfs->bp, (int) 2 * n ); return -1; } 00332 00333 static int 00334 get_ncoords( PLRDev *plr, PLFLT *x, PLFLT *y, PLINT n ) 00335 { 00336 PLINT i; 00337 short _xs[PL_MAXPOLY], _ys[PL_MAXPOLY]; 00338 short *xs, *ys; 00339 00340 if ( n > PL_MAXPOLY ) 00341 { 00342 xs = (short *) malloc( sizeof ( short ) * (size_t) n ); 00343 ys = (short *) malloc( sizeof ( short ) * (size_t) n ); 00344 } 00345 else 00346 { 00347 xs = _xs; 00348 ys = _ys; 00349 } 00350 00351 plr_rdn( pdf_rd_2nbytes( plr->pdfs, (U_SHORT *) xs, n ) ); 00352 plr_rdn( pdf_rd_2nbytes( plr->pdfs, (U_SHORT *) ys, n ) ); 00353 00354 for ( i = 0; i < n; i++ ) 00355 { 00356 x[i] = xs[i]; 00357 y[i] = ys[i]; 00358 } 00359 00360 if ( n > PL_MAXPOLY ) 00361 { 00362 free( xs ); 00363 free( ys ); 00364 } 00365 00366 return 0; 00367 } 00368 00369 //-------------------------------------------------------------------------- 00370 // plr_eop() 00371 // 00372 // Clear screen. 00373 //-------------------------------------------------------------------------- 00374 00375 static int 00376 plr_eop( PLRDev * PL_UNUSED( plr ) ) 00377 { 00378 dbug_enter( "plr_eop" ); 00379 00380 pleop(); 00381 return 0; 00382 } 00383 00384 //-------------------------------------------------------------------------- 00385 // plr_bop() 00386 // 00387 // Page advancement. 00388 //-------------------------------------------------------------------------- 00389 00390 static int 00391 plr_bop( PLRDev *plr ) 00392 { 00393 dbug_enter( "plr_bop" ); 00394 00395 // Advance and setup the page 00396 00397 plbop(); 00398 plvpor( 0., 1., 0., 1. ); 00399 plwind( plr->xmin, plr->xmax, plr->ymin, plr->ymax ); 00400 00401 return 0; 00402 } 00403 00404 //-------------------------------------------------------------------------- 00405 // plr_state() 00406 // 00407 // Handle change in PLStream state (color, pen width, fill attribute, 00408 // etc). 00409 //-------------------------------------------------------------------------- 00410 00411 static int 00412 plr_state( PLRDev *plr ) 00413 { 00414 U_CHAR op; 00415 int i; 00416 00417 plr_rd( pdf_rd_1byte( plr->pdfs, &op ) ); 00418 00419 switch ( op ) 00420 { 00421 case PLSTATE_WIDTH: { 00422 U_SHORT width; 00423 00424 plr_rd( pdf_rd_2bytes( plr->pdfs, &width ) ); 00425 00426 plwidth( width ); 00427 break; 00428 } 00429 00430 case PLSTATE_COLOR0: { 00431 short icol0; 00432 00433 plr_rd( pdf_rd_2bytes( plr->pdfs, (unsigned short *) &icol0 ) ); 00434 00435 if ( icol0 == PL_RGB_COLOR ) 00436 { 00437 U_CHAR r, g, b; 00438 plr_rd( pdf_rd_1byte( plr->pdfs, &r ) ); 00439 plr_rd( pdf_rd_1byte( plr->pdfs, &g ) ); 00440 plr_rd( pdf_rd_1byte( plr->pdfs, &b ) ); 00441 plscol0( icol0, r, g, b ); 00442 } 00443 else 00444 { 00445 plcol0( icol0 ); 00446 } 00447 break; 00448 } 00449 00450 case PLSTATE_COLOR1: { 00451 U_SHORT icol1; 00452 PLFLT col1; 00453 00454 plr_rd( pdf_rd_2bytes( plr->pdfs, &icol1 ) ); 00455 col1 = (double) icol1 / (double) plsc->ncol1; 00456 plcol1( col1 ); 00457 break; 00458 } 00459 00460 case PLSTATE_FILL: { 00461 signed char patt; 00462 00463 plr_rd( pdf_rd_1byte( plr->pdfs, (U_CHAR *) &patt ) ); 00464 plpsty( patt ); 00465 break; 00466 } 00467 00468 case PLSTATE_CMAP0: { 00469 U_SHORT ncol0; 00470 00471 plr_rd( pdf_rd_2bytes( plr->pdfs, &ncol0 ) ); 00472 plscmap0n( (PLINT) ncol0 ); 00473 for ( i = 0; i < plsc->ncol0; i++ ) 00474 { 00475 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap0[i].r ) ); 00476 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap0[i].g ) ); 00477 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap0[i].b ) ); 00478 } 00479 plP_state( PLSTATE_CMAP0 ); 00480 break; 00481 } 00482 00483 case PLSTATE_CMAP1: { 00484 U_SHORT ncol1, ncp1; 00485 float h, l, s; 00486 U_CHAR rev; 00487 00488 plr_rd( pdf_rd_2bytes( plr->pdfs, &ncol1 ) ); 00489 plscmap1n( (PLINT) ncol1 ); 00490 for ( i = 0; i < plsc->ncol1; i++ ) 00491 { 00492 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap1[i].r ) ); 00493 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap1[i].g ) ); 00494 plr_rd( pdf_rd_1byte( plr->pdfs, &plsc->cmap1[i].b ) ); 00495 } 00496 // Get the control points 00497 plr_rd( pdf_rd_2bytes( plr->pdfs, &ncp1 ) ); 00498 plsc->ncp1 = ncp1; 00499 for ( i = 0; i < plsc->ncp1; i++ ) 00500 { 00501 plr_rd( pdf_rd_ieeef( plr->pdfs, &h ) ); 00502 plr_rd( pdf_rd_ieeef( plr->pdfs, &l ) ); 00503 plr_rd( pdf_rd_ieeef( plr->pdfs, &s ) ); 00504 plr_rd( pdf_rd_1byte( plr->pdfs, &rev ) ); 00505 00506 plsc->cmap1cp[i].h = h; 00507 plsc->cmap1cp[i].l = l; 00508 plsc->cmap1cp[i].s = s; 00509 plsc->cmap1cp[i].alt_hue_path = rev; 00510 } 00511 plP_state( PLSTATE_CMAP1 ); 00512 break; 00513 } 00514 } 00515 00516 return 0; 00517 } 00518 00519 //-------------------------------------------------------------------------- 00520 // plr_esc() 00521 // 00522 // Handle all escape functions. 00523 // Only those that require additional data to be read need to be 00524 // explicitly handled; the others are merely passed on to the actual 00525 // driver. 00526 //-------------------------------------------------------------------------- 00527 00528 static int 00529 plr_esc( PLRDev *plr ) 00530 { 00531 U_CHAR op; 00532 00533 plr_rd( pdf_rd_1byte( plr->pdfs, &op ) ); 00534 00535 switch ( op ) 00536 { 00537 case PLESC_FILL: 00538 plr_cmd( plresc_fill( plr ) ); 00539 break; 00540 00541 default: 00542 pl_cmd( (PLINT) op, NULL ); 00543 break; 00544 } 00545 00546 return 0; 00547 } 00548 00549 //-------------------------------------------------------------------------- 00550 // plresc_fill() 00551 // 00552 // Fill polygon described in points plsc->dev_x[] and plsc->dev_y[]. 00553 //-------------------------------------------------------------------------- 00554 00555 static int 00556 plresc_fill( PLRDev *plr ) 00557 { 00558 U_SHORT npts; 00559 PLFLT *x, *y; 00560 00561 dbug_enter( "plresc_fill" ); 00562 00563 plr_rd( pdf_rd_2bytes( plr->pdfs, &npts ) ); 00564 if ( npts > PL_MAXPOLY ) 00565 { 00566 x = (PLFLT *) malloc( sizeof ( PLFLT ) * npts ); 00567 y = (PLFLT *) malloc( sizeof ( PLFLT ) * npts ); 00568 } 00569 else 00570 { 00571 x = xstatic; 00572 y = ystatic; 00573 } 00574 get_ncoords( plr, x, y, npts ); 00575 plfill( npts, x, y ); 00576 00577 if ( npts > PL_MAXPOLY ) 00578 { 00579 free( x ); 00580 free( y ); 00581 } 00582 return 0; 00583 } 00584 00585 //-------------------------------------------------------------------------- 00586 // plr_get() 00587 // 00588 // Read & return the next command 00589 //-------------------------------------------------------------------------- 00590 00591 static int 00592 plr_get( PLRDev *plr ) 00593 { 00594 int c; 00595 00596 c = pdf_getc( plr->pdfs ); 00597 if ( c == EOF ) 00598 { 00599 barf( "plr_get: Unable to read character" ); 00600 } 00601 00602 return c; 00603 } 00604 00605 //-------------------------------------------------------------------------- 00606 // plr_unget() 00607 // 00608 // Push back the last command read. 00609 //-------------------------------------------------------------------------- 00610 00611 static int 00612 plr_unget( PLRDev *plr, U_CHAR c ) 00613 { 00614 if ( pdf_ungetc( c, plr->pdfs ) == EOF ) 00615 { 00616 barf( "plr_unget: Unable to push back character" ); 00617 } 00618 00619 return 0; 00620 }