PLplot  5.10.0
plr.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines