• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

plr.c

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

Generated on Wed Oct 12 2011 20:42:22 for PLplot by  doxygen 1.7.1