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

plbuf.c

Go to the documentation of this file.
00001 // $Id: plbuf.c 11680 2011-03-27 17:57:51Z airwin $
00002 //
00003 //  Handle plot buffer.
00004 //
00005 //  Copyright (C) 1992  Maurice LeBrun
00006 //  Copyright (C) 2004  Alan W. Irwin
00007 //  Copyright (C) 2005  Thomas J. Duck
00008 //  Copyright (C) 2006  Jim Dishaw
00009 //
00010 //  This file is part of PLplot.
00011 //
00012 //  PLplot is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU Library General Public License as published
00014 //  by the Free Software Foundation; either version 2 of the License, or
00015 //  (at your option) any later version.
00016 //
00017 //  PLplot is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU Library General Public License for more details.
00021 //
00022 //  You should have received a copy of the GNU Library General Public License
00023 //  along with PLplot; if not, write to the Free Software
00024 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00025 //
00026 
00027 #define NEED_PLDEBUG
00028 #include "plplotP.h"
00029 #include "drivers.h"
00030 #include "metadefs.h"
00031 
00032 #include <string.h>
00033 
00034 // Function prototypes
00035 void * plbuf_save( PLStream *pls, void *state );
00036 
00037 static int      rd_command( PLStream *pls, U_CHAR *p_c );
00038 static void     rd_data( PLStream *pls, void *buf, size_t buf_size );
00039 static void     wr_command( PLStream *pls, U_CHAR c );
00040 static void     wr_data( PLStream *pls, void *buf, size_t buf_size );
00041 static void     plbuf_control( PLStream *pls, U_CHAR c );
00042 
00043 static void     rdbuf_init( PLStream *pls );
00044 static void     rdbuf_line( PLStream *pls );
00045 static void     rdbuf_polyline( PLStream *pls );
00046 static void     rdbuf_eop( PLStream *pls );
00047 static void     rdbuf_bop( PLStream *pls );
00048 static void     rdbuf_state( PLStream *pls );
00049 static void     rdbuf_esc( PLStream *pls );
00050 
00051 static void     plbuf_fill( PLStream *pls );
00052 static void     rdbuf_fill( PLStream *pls );
00053 static void     plbuf_swin( PLStream *pls, PLWindow *plwin );
00054 static void     rdbuf_swin( PLStream *pls );
00055 
00056 //--------------------------------------------------------------------------
00057 // plbuf_init()
00058 //
00059 // Initialize device.
00060 // Actually just disables writes if plot buffer is already open (occurs
00061 // when one stream is cloned, as in printing).
00062 //--------------------------------------------------------------------------
00063 
00064 void
00065 plbuf_init( PLStream *pls )
00066 {
00067     dbug_enter( "plbuf_init" );
00068 
00069     pls->plbuf_read = FALSE;
00070 #ifdef BUFFERED_FILE
00071     if ( pls->plbufFile != NULL )
00072         pls->plbuf_write = FALSE;
00073 #else
00074     if ( pls->plbuf_buffer != NULL )
00075         pls->plbuf_write = FALSE;
00076 #endif
00077 }
00078 
00079 //--------------------------------------------------------------------------
00080 // plbuf_line()
00081 //
00082 // Draw a line in the current color from (x1,y1) to (x2,y2).
00083 //--------------------------------------------------------------------------
00084 
00085 void
00086 plbuf_line( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00087 {
00088     short xpl[2], ypl[2];
00089 
00090     dbug_enter( "plbuf_line" );
00091 
00092     wr_command( pls, (U_CHAR) LINE );
00093 
00094     xpl[0] = x1a;
00095     xpl[1] = x2a;
00096     ypl[0] = y1a;
00097     ypl[1] = y2a;
00098 
00099     wr_data( pls, xpl, sizeof ( short ) * 2 );
00100     wr_data( pls, ypl, sizeof ( short ) * 2 );
00101 }
00102 
00103 //--------------------------------------------------------------------------
00104 // plbuf_polyline()
00105 //
00106 // Draw a polyline in the current color.
00107 //--------------------------------------------------------------------------
00108 
00109 void
00110 plbuf_polyline( PLStream *pls, short *xa, short *ya, PLINT npts )
00111 {
00112     dbug_enter( "plbuf_polyline" );
00113 
00114     wr_command( pls, (U_CHAR) POLYLINE );
00115 
00116     wr_data( pls, &npts, sizeof ( PLINT ) );
00117 
00118     wr_data( pls, xa, sizeof ( short ) * npts );
00119     wr_data( pls, ya, sizeof ( short ) * npts );
00120 }
00121 
00122 //--------------------------------------------------------------------------
00123 // plbuf_eop()
00124 //
00125 // End of page.
00126 //--------------------------------------------------------------------------
00127 
00128 void
00129 plbuf_eop( PLStream *pls )
00130 {
00131     dbug_enter( "plbuf_eop" );
00132 }
00133 
00134 //--------------------------------------------------------------------------
00135 // plbuf_bop()
00136 //
00137 // Set up for the next page.
00138 // To avoid problems redisplaying partially filled pages, on each BOP the
00139 // old file is thrown away and a new one is obtained.  This way we can just
00140 // read up to EOF to get everything on the current page.
00141 //
00142 // Also write state information to ensure the next page is correct.
00143 //--------------------------------------------------------------------------
00144 
00145 void
00146 plbuf_bop( PLStream *pls )
00147 {
00148     dbug_enter( "plbuf_bop" );
00149 
00150     plbuf_tidy( pls );
00151 
00152 #ifdef BUFFERED_FILE
00153     pls->plbufFile = pl_create_tempfile( NULL );
00154     if ( pls->plbufFile == NULL )
00155         plexit( "plbuf_bop: Error opening plot data storage file." );
00156 #else
00157     // Need a better place to initialize this value
00158     pls->plbuf_buffer_grow = 128 * 1024;
00159 
00160     if ( pls->plbuf_buffer == NULL )
00161     {
00162         // We have not allocated a buffer, so do it now
00163         if ( ( pls->plbuf_buffer = malloc( pls->plbuf_buffer_grow ) ) == NULL )
00164             plexit( "plbuf_bop: Error allocating plot buffer." );
00165 
00166         pls->plbuf_buffer_size = pls->plbuf_buffer_grow;
00167         pls->plbuf_top         = 0;
00168         pls->plbuf_readpos     = 0;
00169     }
00170     else
00171     {
00172         // Buffer is allocated, move the top to the beginning
00173         pls->plbuf_top = 0;
00174     }
00175 #endif
00176 
00177     wr_command( pls, (U_CHAR) BOP );
00178     plbuf_state( pls, PLSTATE_COLOR0 );
00179     plbuf_state( pls, PLSTATE_WIDTH );
00180 }
00181 
00182 //--------------------------------------------------------------------------
00183 // plbuf_tidy()
00184 //
00185 // Close graphics file
00186 //--------------------------------------------------------------------------
00187 
00188 void
00189 plbuf_tidy( PLStream *pls )
00190 {
00191     dbug_enter( "plbuf_tidy" );
00192 
00193 #ifdef BUFFERED_FILE
00194     if ( pls->plbufFile == NULL )
00195         return;
00196 
00197     fclose( pls->plbufFile )
00198     pls->plbufFile = NULL;
00199 #endif
00200 }
00201 
00202 //--------------------------------------------------------------------------
00203 // plbuf_state()
00204 //
00205 // Handle change in PLStream state (color, pen width, fill attribute, etc).
00206 //--------------------------------------------------------------------------
00207 
00208 void
00209 plbuf_state( PLStream *pls, PLINT op )
00210 {
00211     dbug_enter( "plbuf_state" );
00212 
00213     wr_command( pls, (U_CHAR) CHANGE_STATE );
00214     wr_command( pls, (U_CHAR) op );
00215 
00216     switch ( op )
00217     {
00218     case PLSTATE_WIDTH:
00219         wr_data( pls, &( pls->width ), sizeof ( pls->width ) );
00220         break;
00221 
00222     case PLSTATE_COLOR0:
00223         wr_data( pls, &( pls->icol0 ), sizeof ( pls->icol0 ) );
00224         if ( pls->icol0 == PL_RGB_COLOR )
00225         {
00226             wr_data( pls, &( pls->curcolor.r ), sizeof ( pls->curcolor.r ) );
00227             wr_data( pls, &( pls->curcolor.g ), sizeof ( pls->curcolor.g ) );
00228             wr_data( pls, &( pls->curcolor.b ), sizeof ( pls->curcolor.b ) );
00229         }
00230         break;
00231 
00232     case PLSTATE_COLOR1:
00233         wr_data( pls, &( pls->icol1 ), sizeof ( pls->icol1 ) );
00234         break;
00235 
00236     case PLSTATE_FILL:
00237         wr_data( pls, &( pls->patt ), sizeof ( pls->patt ) );
00238         break;
00239     }
00240 }
00241 
00242 
00243 //--------------------------------------------------------------------------
00244 // plbuf_image()
00245 //
00246 // write image described in points pls->dev_x[], pls->dev_y[], pls->dev_z[].
00247 //                      pls->nptsX, pls->nptsY.
00248 //--------------------------------------------------------------------------
00249 
00250 static void
00251 plbuf_image( PLStream *pls, IMG_DT *img_dt )
00252 {
00253     PLINT npts = pls->dev_nptsX * pls->dev_nptsY;
00254 
00255     dbug_enter( "plbuf_image" );
00256 
00257     wr_data( pls, &pls->dev_nptsX, sizeof ( PLINT ) );
00258     wr_data( pls, &pls->dev_nptsY, sizeof ( PLINT ) );
00259 
00260     wr_data( pls, &img_dt->xmin, sizeof ( PLFLT ) );
00261     wr_data( pls, &img_dt->ymin, sizeof ( PLFLT ) );
00262     wr_data( pls, &img_dt->dx, sizeof ( PLFLT ) );
00263     wr_data( pls, &img_dt->dy, sizeof ( PLFLT ) );
00264 
00265     wr_data( pls, &pls->dev_zmin, sizeof ( short ) );
00266     wr_data( pls, &pls->dev_zmax, sizeof ( short ) );
00267 
00268     wr_data( pls, pls->dev_ix, sizeof ( short ) * npts );
00269     wr_data( pls, pls->dev_iy, sizeof ( short ) * npts );
00270     wr_data( pls, pls->dev_z, sizeof ( unsigned short ) * ( pls->dev_nptsX - 1 ) * ( pls->dev_nptsY - 1 ) );
00271 }
00272 
00273 //--------------------------------------------------------------------------
00274 // plbuf_text()
00275 //
00276 // Handle text call.
00277 //--------------------------------------------------------------------------
00278 
00279 static void
00280 plbuf_text( PLStream *pls, EscText *text )
00281 {
00282     PLUNICODE fci;
00283 
00284     dbug_enter( "plbuf_text" );
00285 
00286     // Retrieve the font characterization integer
00287     plgfci( &fci );
00288 
00289     // Write the text information
00290 
00291     wr_data( pls, &fci, sizeof ( PLUNICODE ) );
00292 
00293     wr_data( pls, &pls->chrht, sizeof ( PLFLT ) );
00294     wr_data( pls, &pls->diorot, sizeof ( PLFLT ) );
00295     wr_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
00296     wr_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
00297     wr_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
00298     wr_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
00299 
00300     wr_data( pls, &text->base, sizeof ( PLINT ) );
00301     wr_data( pls, &text->just, sizeof ( PLFLT ) );
00302     wr_data( pls, text->xform, sizeof ( PLFLT ) * 4 );
00303     wr_data( pls, &text->x, sizeof ( PLINT ) );
00304     wr_data( pls, &text->y, sizeof ( PLINT ) );
00305     wr_data( pls, &text->refx, sizeof ( PLINT ) );
00306     wr_data( pls, &text->refy, sizeof ( PLINT ) );
00307 
00308     wr_data( pls, &text->unicode_array_len, sizeof ( PLINT ) );
00309     if ( text->unicode_array_len )
00310         wr_data( pls, text->unicode_array, sizeof ( PLUNICODE ) * text->unicode_array_len );
00311 }
00312 
00313 //--------------------------------------------------------------------------
00314 // plbuf_text_unicode()
00315 //
00316 // Handle text buffering for the new unicode pathway.
00317 //--------------------------------------------------------------------------
00318 
00319 static void
00320 plbuf_text_unicode( PLStream *pls, EscText *text )
00321 {
00322     PLUNICODE fci;
00323 
00324     dbug_enter( "plbuf_text" );
00325 
00326     // Retrieve the font characterization integer
00327     plgfci( &fci );
00328 
00329     // Write the text information
00330 
00331     wr_data( pls, &fci, sizeof ( PLUNICODE ) );
00332 
00333     wr_data( pls, &pls->chrht, sizeof ( PLFLT ) );
00334     wr_data( pls, &pls->diorot, sizeof ( PLFLT ) );
00335     wr_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
00336     wr_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
00337     wr_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
00338     wr_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
00339 
00340     wr_data( pls, &text->base, sizeof ( PLINT ) );
00341     wr_data( pls, &text->just, sizeof ( PLFLT ) );
00342     wr_data( pls, text->xform, sizeof ( PLFLT ) * 4 );
00343     wr_data( pls, &text->x, sizeof ( PLINT ) );
00344     wr_data( pls, &text->y, sizeof ( PLINT ) );
00345     wr_data( pls, &text->refx, sizeof ( PLINT ) );
00346     wr_data( pls, &text->refy, sizeof ( PLINT ) );
00347 
00348     wr_data( pls, &text->n_fci, sizeof ( PLUNICODE ) );
00349     wr_data( pls, &text->n_char, sizeof ( PLUNICODE ) );
00350     wr_data( pls, &text->n_ctrl_char, sizeof ( PLINT ) );
00351 
00352     wr_data( pls, &text->unicode_array_len, sizeof ( PLINT ) );
00353 }
00354 
00355 
00356 //--------------------------------------------------------------------------
00357 // plbuf_esc()
00358 //
00359 // Escape function.  Note that any data written must be in device
00360 // independent form to maintain the transportability of the metafile.
00361 //
00362 // Functions:
00363 //
00364 //      PLESC_FILL          Fill polygon
00365 //      PLESC_SWIN          Set plot window parameters
00366 //  PLESC_IMAGE     Draw image
00367 //  PLESC_HAS_TEXT  Draw PostScript text
00368 //      PLESC_CLEAR         Clear Background
00369 //      PLESC_START_RASTERIZE
00370 //      PLESC_END_RASTERIZE Start and stop rasterization
00371 //--------------------------------------------------------------------------
00372 
00373 void
00374 plbuf_esc( PLStream *pls, PLINT op, void *ptr )
00375 {
00376     dbug_enter( "plbuf_esc" );
00377 
00378     wr_command( pls, (U_CHAR) ESCAPE );
00379     wr_command( pls, (U_CHAR) op );
00380 
00381     switch ( op )
00382     {
00383     case PLESC_FILL:
00384         plbuf_fill( pls );
00385         break;
00386     case PLESC_SWIN:
00387         plbuf_swin( pls, (PLWindow *) ptr );
00388         break;
00389     case PLESC_IMAGE:
00390         plbuf_image( pls, (IMG_DT *) ptr );
00391         break;
00392     case PLESC_HAS_TEXT:
00393         if ( ptr != NULL ) // Check required by GCW driver, please don't remove
00394             plbuf_text( pls, (EscText *) ptr );
00395         break;
00396     case PLESC_BEGIN_TEXT:
00397     case PLESC_TEXT_CHAR:
00398     case PLESC_CONTROL_CHAR:
00399     case PLESC_END_TEXT:
00400         plbuf_text_unicode( pls, (EscText *) ptr );
00401         break;
00402 #if 0
00403     // These are a no-op.  They just need an entry in the buffer.
00404     case PLESC_CLEAR:
00405     case PLESC_START_RASTERIZE:
00406     case PLESC_END_RASTERIZE:
00407         break;
00408 #endif
00409     }
00410 }
00411 
00412 //--------------------------------------------------------------------------
00413 // plbuf_fill()
00414 //
00415 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
00416 //--------------------------------------------------------------------------
00417 
00418 static void
00419 plbuf_fill( PLStream *pls )
00420 {
00421     dbug_enter( "plbuf_fill" );
00422 
00423     wr_data( pls, &pls->dev_npts, sizeof ( PLINT ) );
00424     wr_data( pls, pls->dev_x, sizeof ( short ) * pls->dev_npts );
00425     wr_data( pls, pls->dev_y, sizeof ( short ) * pls->dev_npts );
00426 }
00427 
00428 //--------------------------------------------------------------------------
00429 // plbuf_swin()
00430 //
00431 // Set up plot window parameters.
00432 //--------------------------------------------------------------------------
00433 
00434 static void
00435 plbuf_swin( PLStream *pls, PLWindow *plwin )
00436 {
00437     wr_data( pls, &plwin->dxmi, sizeof ( PLFLT ) );
00438     wr_data( pls, &plwin->dxma, sizeof ( PLFLT ) );
00439     wr_data( pls, &plwin->dymi, sizeof ( PLFLT ) );
00440     wr_data( pls, &plwin->dyma, sizeof ( PLFLT ) );
00441 
00442     wr_data( pls, &plwin->wxmi, sizeof ( PLFLT ) );
00443     wr_data( pls, &plwin->wxma, sizeof ( PLFLT ) );
00444     wr_data( pls, &plwin->wymi, sizeof ( PLFLT ) );
00445     wr_data( pls, &plwin->wyma, sizeof ( PLFLT ) );
00446 }
00447 
00448 //--------------------------------------------------------------------------
00449 // Routines to read from & process the plot buffer.
00450 //--------------------------------------------------------------------------
00451 
00452 //--------------------------------------------------------------------------
00453 // rdbuf_init()
00454 //
00455 // Initialize device.
00456 //--------------------------------------------------------------------------
00457 
00458 static void
00459 rdbuf_init( PLStream *pls )
00460 {
00461     dbug_enter( "rdbuf_init" );
00462 }
00463 
00464 //--------------------------------------------------------------------------
00465 // rdbuf_line()
00466 //
00467 // Draw a line in the current color from (x1,y1) to (x2,y2).
00468 //--------------------------------------------------------------------------
00469 
00470 static void
00471 rdbuf_line( PLStream *pls )
00472 {
00473     short xpl[2], ypl[2];
00474     PLINT npts = 2;
00475 
00476     dbug_enter( "rdbuf_line" );
00477 
00478     rd_data( pls, xpl, sizeof ( short ) * npts );
00479     rd_data( pls, ypl, sizeof ( short ) * npts );
00480 
00481     plP_line( xpl, ypl );
00482 }
00483 
00484 //--------------------------------------------------------------------------
00485 // rdbuf_polyline()
00486 //
00487 // Draw a polyline in the current color.
00488 //--------------------------------------------------------------------------
00489 
00490 static void
00491 rdbuf_polyline( PLStream *pls )
00492 {
00493     short _xpl[PL_MAXPOLY], _ypl[PL_MAXPOLY];
00494     short *xpl, *ypl;
00495     PLINT npts;
00496 
00497     dbug_enter( "rdbuf_polyline" );
00498 
00499     rd_data( pls, &npts, sizeof ( PLINT ) );
00500 
00501     if ( npts > PL_MAXPOLY )
00502     {
00503         xpl = (short *) malloc( ( npts + 1 ) * sizeof ( PLINT ) );
00504         ypl = (short *) malloc( ( npts + 1 ) * sizeof ( PLINT ) );
00505 
00506         if ( ( xpl == NULL ) || ( ypl == NULL ) )
00507         {
00508             plexit( "rdbuf_polyline: Insufficient memory for large polyline" );
00509         }
00510     }
00511     else
00512     {
00513         xpl = _xpl;
00514         ypl = _ypl;
00515     }
00516 
00517 
00518     rd_data( pls, xpl, sizeof ( short ) * npts );
00519     rd_data( pls, ypl, sizeof ( short ) * npts );
00520 
00521     plP_polyline( xpl, ypl, npts );
00522 
00523     if ( npts > PL_MAXPOLY )
00524     {
00525         free( xpl );
00526         free( ypl );
00527     }
00528 }
00529 
00530 //--------------------------------------------------------------------------
00531 // rdbuf_eop()
00532 //
00533 // End of page.
00534 //--------------------------------------------------------------------------
00535 
00536 static void
00537 rdbuf_eop( PLStream *pls )
00538 {
00539     dbug_enter( "rdbuf_eop" );
00540 }
00541 
00542 //--------------------------------------------------------------------------
00543 // rdbuf_bop()
00544 //
00545 // Set up for the next page.
00546 //--------------------------------------------------------------------------
00547 
00548 static void
00549 rdbuf_bop( PLStream *pls )
00550 {
00551     dbug_enter( "rdbuf_bop" );
00552 
00553     pls->nplwin = 0;
00554 }
00555 
00556 //--------------------------------------------------------------------------
00557 // rdbuf_state()
00558 //
00559 // Handle change in PLStream state (color, pen width, fill attribute, etc).
00560 //--------------------------------------------------------------------------
00561 
00562 static void
00563 rdbuf_state( PLStream *pls )
00564 {
00565     U_CHAR op;
00566 
00567     dbug_enter( "rdbuf_state" );
00568 
00569     rd_data( pls, &op, sizeof ( U_CHAR ) );
00570 
00571     switch ( op )
00572     {
00573     case PLSTATE_WIDTH: {
00574         U_CHAR width;
00575 
00576         rd_data( pls, &width, sizeof ( U_CHAR ) );
00577         pls->width = width;
00578         plP_state( PLSTATE_WIDTH );
00579 
00580         break;
00581     }
00582 
00583     case PLSTATE_COLOR0: {
00584         short  icol0;
00585         U_CHAR r, g, b;
00586         PLFLT  a;
00587 
00588         rd_data( pls, &icol0, sizeof ( short ) );
00589         if ( icol0 == PL_RGB_COLOR )
00590         {
00591             rd_data( pls, &r, sizeof ( U_CHAR ) );
00592             rd_data( pls, &g, sizeof ( U_CHAR ) );
00593             rd_data( pls, &b, sizeof ( U_CHAR ) );
00594             a = 1.0;
00595         }
00596         else
00597         {
00598             if ( (int) icol0 >= pls->ncol0 )
00599             {
00600                 char buffer[256];
00601                 snprintf( buffer, 256, "rdbuf_state: Invalid color map entry: %d", (int) icol0 );
00602                 plabort( buffer );
00603                 return;
00604             }
00605             r = pls->cmap0[icol0].r;
00606             g = pls->cmap0[icol0].g;
00607             b = pls->cmap0[icol0].b;
00608             a = pls->cmap0[icol0].a;
00609         }
00610         pls->icol0      = icol0;
00611         pls->curcolor.r = r;
00612         pls->curcolor.g = g;
00613         pls->curcolor.b = b;
00614         pls->curcolor.a = a;
00615 
00616         plP_state( PLSTATE_COLOR0 );
00617         break;
00618     }
00619 
00620     case PLSTATE_COLOR1: {
00621         short icol1;
00622 
00623         rd_data( pls, &icol1, sizeof ( short ) );
00624 
00625         pls->icol1      = icol1;
00626         pls->curcolor.r = pls->cmap1[icol1].r;
00627         pls->curcolor.g = pls->cmap1[icol1].g;
00628         pls->curcolor.b = pls->cmap1[icol1].b;
00629         pls->curcolor.a = pls->cmap1[icol1].a;
00630 
00631         plP_state( PLSTATE_COLOR1 );
00632         break;
00633     }
00634 
00635     case PLSTATE_FILL: {
00636         signed char patt;
00637 
00638         rd_data( pls, &patt, sizeof ( signed char ) );
00639 
00640         pls->patt = patt;
00641         plP_state( PLSTATE_FILL );
00642         break;
00643     }
00644     }
00645 }
00646 
00647 //--------------------------------------------------------------------------
00648 // rdbuf_esc()
00649 //
00650 // Escape function.
00651 // Must fill data structure with whatever data that was written,
00652 // then call escape function.
00653 //
00654 // Note: it is best to only call the escape function for op-codes that
00655 // are known to be supported.
00656 //
00657 // Functions:
00658 //
00659 //      PLESC_FILL          Fill polygon
00660 //      PLESC_SWIN          Set plot window parameters
00661 //      PLESC_IMAGE         Draw image
00662 //      PLESC_HAS_TEXT      Draw PostScript text
00663 //      PLESC_BEGIN_TEXT    Commands for the alternative unicode text handling path
00664 //      PLESC_TEXT_CHAR
00665 //      PLESC_CONTROL_CHAR
00666 //      PLESC_END_TEXT
00667 //      PLESC_CLEAR         Clear Background
00668 //--------------------------------------------------------------------------
00669 
00670 static void
00671 rdbuf_image( PLStream *pls );
00672 
00673 static void
00674 rdbuf_text( PLStream *pls );
00675 
00676 static void
00677 rdbuf_text_unicode( PLINT op, PLStream *pls );
00678 
00679 static void
00680 rdbuf_esc( PLStream *pls )
00681 {
00682     U_CHAR op;
00683 
00684     dbug_enter( "rdbuf_esc" );
00685 
00686     rd_data( pls, &op, sizeof ( U_CHAR ) );
00687 
00688     switch ( op )
00689     {
00690     case PLESC_FILL:
00691         rdbuf_fill( pls );
00692         break;
00693     case PLESC_SWIN:
00694         rdbuf_swin( pls );
00695         break;
00696     case PLESC_IMAGE:
00697         rdbuf_image( pls );
00698         break;
00699     case PLESC_HAS_TEXT:
00700         rdbuf_text( pls );
00701         break;
00702     case PLESC_BEGIN_TEXT:
00703     case PLESC_TEXT_CHAR:
00704     case PLESC_CONTROL_CHAR:
00705     case PLESC_END_TEXT:
00706         rdbuf_text_unicode( op, pls );
00707         break;
00708     case PLESC_CLEAR:
00709         plP_esc( PLESC_CLEAR, NULL );
00710         break;
00711     case PLESC_START_RASTERIZE:
00712         plP_esc( PLESC_START_RASTERIZE, NULL );
00713         break;
00714     case PLESC_END_RASTERIZE:
00715         plP_esc( PLESC_END_RASTERIZE, NULL );
00716         break;
00717     }
00718 }
00719 
00720 //--------------------------------------------------------------------------
00721 // rdbuf_fill()
00722 //
00723 // Fill polygon described by input points.
00724 //--------------------------------------------------------------------------
00725 
00726 static void
00727 rdbuf_fill( PLStream *pls )
00728 {
00729     short _xpl[PL_MAXPOLY], _ypl[PL_MAXPOLY];
00730     short *xpl, *ypl;
00731     PLINT npts;
00732 
00733     dbug_enter( "rdbuf_fill" );
00734 
00735     rd_data( pls, &npts, sizeof ( PLINT ) );
00736 
00737     if ( npts > PL_MAXPOLY )
00738     {
00739         xpl = (short *) malloc( ( npts + 1 ) * sizeof ( PLINT ) );
00740         ypl = (short *) malloc( ( npts + 1 ) * sizeof ( PLINT ) );
00741 
00742         if ( ( xpl == NULL ) || ( ypl == NULL ) )
00743         {
00744             plexit( "rdbuf_polyline: Insufficient memory for large polyline" );
00745         }
00746     }
00747     else
00748     {
00749         xpl = _xpl;
00750         ypl = _ypl;
00751     }
00752 
00753     rd_data( pls, xpl, sizeof ( short ) * npts );
00754     rd_data( pls, ypl, sizeof ( short ) * npts );
00755 
00756     plP_fill( xpl, ypl, npts );
00757 
00758     if ( npts > PL_MAXPOLY )
00759     {
00760         free( xpl );
00761         free( ypl );
00762     }
00763 }
00764 
00765 //--------------------------------------------------------------------------
00766 // rdbuf_image()
00767 //
00768 // .
00769 //--------------------------------------------------------------------------
00770 
00771 static void
00772 rdbuf_image( PLStream *pls )
00773 {
00774     short          *dev_ix, *dev_iy;
00775     unsigned short *dev_z, dev_zmin, dev_zmax;
00776     PLINT          nptsX, nptsY, npts;
00777     PLFLT          xmin, ymin, dx, dy;
00778 
00779     dbug_enter( "rdbuf_image" );
00780 
00781     rd_data( pls, &nptsX, sizeof ( PLINT ) );
00782     rd_data( pls, &nptsY, sizeof ( PLINT ) );
00783     npts = nptsX * nptsY;
00784 
00785     rd_data( pls, &xmin, sizeof ( PLFLT ) );
00786     rd_data( pls, &ymin, sizeof ( PLFLT ) );
00787     rd_data( pls, &dx, sizeof ( PLFLT ) );
00788     rd_data( pls, &dy, sizeof ( PLFLT ) );
00789 
00790     rd_data( pls, &dev_zmin, sizeof ( short ) );
00791     rd_data( pls, &dev_zmax, sizeof ( short ) );
00792 
00793     // NOTE:  Even though for memory buffered version all the data is in memory,
00794     // we still allocate and copy the data because I think that method works
00795     // better in a multithreaded environment.  I could be wrong.
00796     //
00797     if ( ( ( dev_ix = (short *) malloc( npts * sizeof ( short ) ) ) == NULL ) ||
00798          ( ( dev_iy = (short *) malloc( npts * sizeof ( short ) ) ) == NULL ) ||
00799          ( ( dev_z = (unsigned short *) malloc( ( nptsX - 1 ) * ( nptsY - 1 ) * sizeof ( unsigned short ) ) ) == NULL ) )
00800         plexit( "rdbuf_image: Insufficient memory" );
00801 
00802     rd_data( pls, dev_ix, sizeof ( short ) * npts );
00803     rd_data( pls, dev_iy, sizeof ( short ) * npts );
00804     rd_data( pls, dev_z, sizeof ( unsigned short ) * ( nptsX - 1 ) * ( nptsY - 1 ) );
00805 
00806     //
00807     // COMMENTED OUT by Hezekiah Carty
00808     // Commented (hopefullly temporarily) until the dev_fastimg rendering
00809     // path can be updated to support the new plimage internals. In the
00810     // meantime this function is not actually used so the issue of how to
00811     // update the code to support the new interface can be ignored.
00812     //
00813     //plP_image(dev_ix, dev_iy, dev_z, nptsX, nptsY, xmin, ymin, dx, dy, dev_zmin, dev_zmax);
00814 
00815     free( dev_ix );
00816     free( dev_iy );
00817     free( dev_z );
00818 }
00819 
00820 //--------------------------------------------------------------------------
00821 // rdbuf_swin()
00822 //
00823 // Set up plot window parameters.
00824 //--------------------------------------------------------------------------
00825 
00826 static void
00827 rdbuf_swin( PLStream *pls )
00828 {
00829     PLWindow plwin;
00830 
00831     rd_data( pls, &plwin.dxmi, sizeof ( PLFLT ) );
00832     rd_data( pls, &plwin.dxma, sizeof ( PLFLT ) );
00833     rd_data( pls, &plwin.dymi, sizeof ( PLFLT ) );
00834     rd_data( pls, &plwin.dyma, sizeof ( PLFLT ) );
00835 
00836     rd_data( pls, &plwin.wxmi, sizeof ( PLFLT ) );
00837     rd_data( pls, &plwin.wxma, sizeof ( PLFLT ) );
00838     rd_data( pls, &plwin.wymi, sizeof ( PLFLT ) );
00839     rd_data( pls, &plwin.wyma, sizeof ( PLFLT ) );
00840 
00841     plP_swin( &plwin );
00842 }
00843 
00844 //--------------------------------------------------------------------------
00845 // rdbuf_text()
00846 //
00847 // Draw PostScript text.
00848 //--------------------------------------------------------------------------
00849 
00850 static void
00851 rdbuf_text( PLStream *pls )
00852 {
00853     PLUNICODE( fci );
00854     EscText  text;
00855     PLFLT    xform[4];
00856     PLUNICODE* unicode;
00857 
00858     text.xform = xform;
00859 
00860 
00861     // Read in the data
00862 
00863     rd_data( pls, &fci, sizeof ( PLUNICODE ) );
00864 
00865     rd_data( pls, &pls->chrht, sizeof ( PLFLT ) );
00866     rd_data( pls, &pls->diorot, sizeof ( PLFLT ) );
00867     rd_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
00868     rd_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
00869     rd_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
00870     rd_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
00871 
00872     rd_data( pls, &text.base, sizeof ( PLINT ) );
00873     rd_data( pls, &text.just, sizeof ( PLFLT ) );
00874     rd_data( pls, text.xform, sizeof ( PLFLT ) * 4 );
00875     rd_data( pls, &text.x, sizeof ( PLINT ) );
00876     rd_data( pls, &text.y, sizeof ( PLINT ) );
00877     rd_data( pls, &text.refx, sizeof ( PLINT ) );
00878     rd_data( pls, &text.refy, sizeof ( PLINT ) );
00879 
00880     rd_data( pls, &text.unicode_array_len, sizeof ( PLINT ) );
00881     if ( text.unicode_array_len )
00882     {
00883         if ( ( unicode = (PLUNICODE *) malloc( text.unicode_array_len * sizeof ( PLUNICODE ) ) )
00884              == NULL )
00885             plexit( "rdbuf_text: Insufficient memory" );
00886 
00887         rd_data( pls, unicode, sizeof ( PLUNICODE ) * text.unicode_array_len );
00888         text.unicode_array = unicode;
00889     }
00890     else
00891         text.unicode_array = NULL;
00892 
00893     // Make the call for unicode devices
00894     if ( pls->dev_unicode )
00895     {
00896         plsfci( fci );
00897         plP_esc( PLESC_HAS_TEXT, &text );
00898     }
00899 }
00900 
00901 //--------------------------------------------------------------------------
00902 // rdbuf_text_unicode()
00903 //
00904 // Draw text for the new unicode handling pathway.
00905 //--------------------------------------------------------------------------
00906 
00907 static void
00908 rdbuf_text_unicode( PLINT op, PLStream *pls )
00909 {
00910     PLUNICODE( fci );
00911     EscText text;
00912     PLFLT   xform[4];
00913 
00914     text.xform = xform;
00915 
00916 
00917     // Read in the data
00918 
00919     rd_data( pls, &fci, sizeof ( PLUNICODE ) );
00920 
00921     rd_data( pls, &pls->chrht, sizeof ( PLFLT ) );
00922     rd_data( pls, &pls->diorot, sizeof ( PLFLT ) );
00923     rd_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
00924     rd_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
00925     rd_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
00926     rd_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
00927 
00928     rd_data( pls, &text.base, sizeof ( PLINT ) );
00929     rd_data( pls, &text.just, sizeof ( PLFLT ) );
00930     rd_data( pls, text.xform, sizeof ( PLFLT ) * 4 );
00931     rd_data( pls, &text.x, sizeof ( PLINT ) );
00932     rd_data( pls, &text.y, sizeof ( PLINT ) );
00933     rd_data( pls, &text.refx, sizeof ( PLINT ) );
00934     rd_data( pls, &text.refy, sizeof ( PLINT ) );
00935 
00936     rd_data( pls, &text.n_fci, sizeof ( PLUNICODE ) );
00937     rd_data( pls, &text.n_char, sizeof ( PLUNICODE ) );
00938     rd_data( pls, &text.n_ctrl_char, sizeof ( PLINT ) );
00939 
00940     rd_data( pls, &text.unicode_array_len, sizeof ( PLINT ) );
00941 
00942     if ( pls->dev_unicode )
00943     {
00944         plsfci( fci );
00945         plP_esc( op, &text );
00946     }
00947 }
00948 
00949 //--------------------------------------------------------------------------
00950 // plRemakePlot()
00951 //
00952 // Rebuilds plot from plot buffer, usually in response to a window
00953 // resize or exposure event.
00954 //--------------------------------------------------------------------------
00955 
00956 void
00957 plRemakePlot( PLStream *pls )
00958 {
00959     U_CHAR   c;
00960     int      plbuf_status;
00961     PLStream *save_pls;
00962 
00963     dbug_enter( "plRemakePlot" );
00964 
00965     // Change the status of the flags before checking for a buffer.
00966     // Actually, more thought is needed if we want to support multithreaded
00967     // code correctly, specifically the case where two threads are using
00968     // the same plot stream (e.g. one thread is drawing the plot and another
00969     // thread is processing window manager messages).
00970     //
00971     plbuf_status     = pls->plbuf_write;
00972     pls->plbuf_write = FALSE;
00973     pls->plbuf_read  = TRUE;
00974 
00975 #ifdef BUFFERED_FILE
00976     if ( pls->plbufFile )
00977     {
00978         rewind( pls->plbufFile );
00979 #else
00980     if ( pls->plbuf_buffer )
00981     {
00982         pls->plbuf_readpos = 0;
00983 #endif
00984         // Need to change where plsc points to before processing the commands.
00985         // If we have multiple plot streams, this will prevent the commands from
00986         // going to the wrong plot stream.
00987         //
00988         save_pls = plsc;
00989         plsc     = pls;
00990 
00991         while ( rd_command( pls, &c ) )
00992         {
00993             plbuf_control( pls, c );
00994         }
00995 
00996         plsc = save_pls;
00997     }
00998 
00999     pls->plbuf_read  = FALSE;
01000     pls->plbuf_write = plbuf_status;
01001 }
01002 
01003 //--------------------------------------------------------------------------
01004 // plbuf_control()
01005 //
01006 // Processes commands read from the plot buffer.
01007 //--------------------------------------------------------------------------
01008 
01009 static void
01010 plbuf_control( PLStream *pls, U_CHAR c )
01011 {
01012     static U_CHAR c_old = 0;
01013 
01014     dbug_enter( "plbuf_control" );
01015 
01016     switch ( (int) c )
01017     {
01018     case INITIALIZE:
01019         rdbuf_init( pls );
01020         break;
01021 
01022     case EOP:
01023         rdbuf_eop( pls );
01024         break;
01025 
01026     case BOP:
01027         rdbuf_bop( pls );
01028         break;
01029 
01030     case CHANGE_STATE:
01031         rdbuf_state( pls );
01032         break;
01033 
01034     case LINE:
01035         rdbuf_line( pls );
01036         break;
01037 
01038     case POLYLINE:
01039         rdbuf_polyline( pls );
01040         break;
01041 
01042     case ESCAPE:
01043         rdbuf_esc( pls );
01044         break;
01045 
01046     default:
01047         pldebug( "plbuf_control", "Unrecognized command %d, previous %d\n", c, c_old );
01048     }
01049     c_old = c;
01050 }
01051 
01052 //--------------------------------------------------------------------------
01053 // rd_command()
01054 //
01055 // Read & return the next command
01056 //--------------------------------------------------------------------------
01057 
01058 static int
01059 rd_command( PLStream *pls, U_CHAR *p_c )
01060 {
01061     int count;
01062 
01063 #ifdef BUFFERED_FILE
01064     count = fread( p_c, sizeof ( U_CHAR ), 1, pls->plbufFile );
01065 #else
01066     if ( pls->plbuf_readpos < pls->plbuf_top )
01067     {
01068         *p_c = *(U_CHAR *) ( (U_CHAR *) pls->plbuf_buffer + pls->plbuf_readpos );
01069         pls->plbuf_readpos += sizeof ( U_CHAR );
01070         count = sizeof ( U_CHAR );
01071     }
01072     else
01073     {
01074         count = 0;
01075     }
01076 #endif
01077     return ( count );
01078 }
01079 
01080 //--------------------------------------------------------------------------
01081 // rd_data()
01082 //
01083 // Read the data associated with the command
01084 //--------------------------------------------------------------------------
01085 
01086 static void
01087 rd_data( PLStream *pls, void *buf, size_t buf_size )
01088 {
01089 #ifdef BUFFERED_FILE
01090     plio_fread( buf, buf_size, 1, pls->plbufFile );
01091 #else
01092 // If U_CHAR is not the same size as what memcpy() expects (typically 1 byte)
01093 // then this code will have problems.  A better approach might be to use
01094 // uint8_t from <stdint.h> but I do not know how portable that approach is
01095 //
01096     memcpy( buf, (U_CHAR *) pls->plbuf_buffer + pls->plbuf_readpos, buf_size );
01097     pls->plbuf_readpos += buf_size;
01098 #endif
01099 }
01100 
01101 //--------------------------------------------------------------------------
01102 // wr_command()
01103 //
01104 // Write the next command
01105 //--------------------------------------------------------------------------
01106 
01107 static void
01108 wr_command( PLStream *pls, U_CHAR c )
01109 {
01110 #ifdef BUFFERED_FILE
01111     plio_fwrite( &c1, sizeof ( U_CHAR ), 1, pls->plbufFile );
01112 #else
01113     if ( ( pls->plbuf_top + sizeof ( U_CHAR ) ) >= pls->plbuf_buffer_size )
01114     {
01115         // Not enough space, need to grow the buffer
01116         pls->plbuf_buffer_size += pls->plbuf_buffer_grow;
01117 
01118         if ( pls->verbose )
01119             printf( "Growing buffer to %d KB\n", (int) ( pls->plbuf_buffer_size / 1024 ) );
01120         if ( ( pls->plbuf_buffer = realloc( pls->plbuf_buffer, pls->plbuf_buffer_size ) ) == NULL )
01121             plexit( "plbuf wr_data:  Plot buffer grow failed" );
01122     }
01123 
01124     *(U_CHAR *) ( (U_CHAR *) pls->plbuf_buffer + pls->plbuf_top ) = c;
01125     pls->plbuf_top += sizeof ( U_CHAR );
01126 #endif
01127 }
01128 
01129 //--------------------------------------------------------------------------
01130 // wr_data()
01131 //
01132 // Write the data associated with a command
01133 //--------------------------------------------------------------------------
01134 
01135 static void
01136 wr_data( PLStream *pls, void *buf, size_t buf_size )
01137 {
01138 #ifdef BUFFERED_FILE
01139     plio_fwrite( buf, buf_size, 1, pls->plbufFile );
01140 #else
01141     if ( ( pls->plbuf_top + buf_size ) >= pls->plbuf_buffer_size )
01142     {
01143         // Not enough space, need to grow the buffer
01144         // Must make sure the increase is enough for this data
01145         pls->plbuf_buffer_size += pls->plbuf_buffer_grow *
01146                                   ( ( pls->plbuf_top + buf_size - pls->plbuf_buffer_size ) /
01147                                     pls->plbuf_buffer_grow + 1 );
01148         while ( pls->plbuf_top + buf_size >= pls->plbuf_buffer_size )
01149             ;
01150 
01151         if ( ( pls->plbuf_buffer = realloc( pls->plbuf_buffer, pls->plbuf_buffer_size ) ) == NULL )
01152             plexit( "plbuf wr_data:  Plot buffer grow failed" );
01153     }
01154 
01155 // If U_CHAR is not the same size as what memcpy() expects (typically 1 byte)
01156 // then this code will have problems.  A better approach might be to use
01157 // uint8_t from <stdint.h> but I do not know how portable that approach is
01158 //
01159     memcpy( (U_CHAR *) pls->plbuf_buffer + pls->plbuf_top, buf, buf_size );
01160     pls->plbuf_top += buf_size;
01161 #endif
01162 }
01163 
01164 // plbuf_save(state)
01165 //
01166 // Saves the current state of the plot into a save buffer.
01167 // This code was originally in gcw.c and gcw-lib.c.  The original
01168 // code used a temporary file for the plot buffer and memory
01169 // to perserve colormaps.  That method does not offer a clean
01170 // break between using memory buffers and file buffers.  This
01171 // function preserves the same functionality by returning a data
01172 // structure that saves the plot buffer and colormaps seperately.
01173 //
01174 // The caller passes an existing save buffer for reuse or NULL
01175 // to force the allocation of a new buffer.  Since one malloc()
01176 // is used for everything, the entire save buffer can be freed
01177 // with one free() call.
01178 //
01179 //
01180 struct _color_map
01181 {
01182     PLColor *cmap;
01183     PLINT   icol;
01184     PLINT   ncol;
01185 };
01186 
01187 struct _state
01188 {
01189     size_t            size;  // Size of the save buffer
01190     int               valid; // Flag to indicate a valid save state
01191 #ifdef BUFFERED_FILE
01192     FILE              *plbufFile;
01193 #else
01194     void              *plbuf_buffer;
01195     size_t            plbuf_buffer_size;
01196     size_t            plbuf_top;
01197     size_t            plbuf_readpos;
01198 #endif
01199     struct _color_map *color_map;
01200 };
01201 
01202 void * plbuf_save( PLStream *pls, void *state )
01203 {
01204     size_t        save_size;
01205     struct _state *plot_state = (struct _state *) state;
01206     PLINT         i;
01207     U_CHAR        *buf; // Assume that this is byte-sized
01208 
01209     if ( pls->plbuf_write )
01210     {
01211         pls->plbuf_write = FALSE;
01212         pls->plbuf_read  = TRUE;
01213 
01214         // Determine the size of the buffer required to save everything. We
01215         // assume that there are only two colormaps, but have written the code
01216         // that more than two can be handled with minimal changes.
01217         //
01218         save_size = sizeof ( struct _state )
01219                     + 2 * sizeof ( struct _color_map )
01220                     + pls->ncol0 * sizeof ( PLColor )
01221                     + pls->ncol1 * sizeof ( PLColor );
01222 
01223 #ifndef BUFFERED_FILE
01224         // Only copy as much of the plot buffer that is being used
01225         save_size += pls->plbuf_top;
01226 #endif
01227 
01228         // If a buffer exists, determine if we need to resize it
01229         if ( state != NULL )
01230         {
01231             // We have a save buffer, is it smaller than the current size requirement?
01232             if ( plot_state->size < save_size )
01233             {
01234                 // Yes, reallocate a larger one
01235                 if ( ( plot_state = (struct _state *) realloc( state, save_size ) ) == NULL )
01236                 {
01237                     // NOTE: If realloc fails, then plot_state ill be NULL.
01238                     // This will leave the original buffer untouched, thus we
01239                     // mark it as invalid and return it back to the caller.
01240                     //
01241                     plwarn( "plbuf: Unable to reallocate sufficient memory to save state" );
01242                     plot_state->valid = 0;
01243 
01244                     return state;
01245                 }
01246                 plot_state->size = save_size;
01247             }
01248         }
01249         else
01250         {
01251             // A buffer does not exist, so we need to allocate one
01252             if ( ( plot_state = (struct _state *) malloc( save_size ) ) == NULL )
01253             {
01254                 plwarn( "plbuf: Unable to allocate sufficient memory to save state" );
01255 
01256                 return NULL;
01257             }
01258             plot_state->size = save_size;
01259 
01260 #ifdef BUFFERED_FILE
01261             // Make sure the FILE pointer is NULL in order to preven bad things from happening...
01262             plot_state->plbufFile = NULL;
01263 #endif
01264         }
01265 
01266         // At this point we have an appropriately sized save buffer.
01267         // We need to invalidate the state of the save buffer, since it
01268         // will not be valid until after everything is copied.  We use
01269         // this approach vice freeing the memory and returning a NULL pointer
01270         // in order to prevent allocating and freeing memory needlessly.
01271         //
01272         plot_state->valid = 0;
01273 
01274         // Point buf to the space after the struct _state
01275         buf = (U_CHAR *) ( plot_state + 1 );
01276 
01277 #ifdef BUFFERED_FILE
01278         // Remove the old tempfile, if it exists
01279         if ( plot_state->plbufFile != NULL )
01280         {
01281             fclose( plot_state->plbufFile );
01282         }
01283 
01284         // Copy the plot buffer to a tempfile
01285         if ( ( plot_state->plbufFile = pl_create_tempfile( NULL ) ) == NULL )
01286         {
01287             // Throw a warning since this might be a permissions problem
01288             // and we may not want to force an exit
01289             //
01290             plwarn( "plbuf: Unable to open temporary file to save state" );
01291             return (void *) plot_state;
01292         }
01293         else
01294         {
01295             U_CHAR tmp;
01296 
01297             rewind( pls->plbufFile );
01298             while ( count = fread( &tmp, sizeof ( U_CHAR ), 1, pls->plbufFile ) )
01299             {
01300                 if ( fwrite( &tmp, sizeof ( U_CHAR ), 1, plot_state->plbufFile ) != count )
01301                 {
01302                     // Throw a warning since this might be a permissions problem
01303                     // and we may not want to force an exit
01304                     //
01305                     plwarn( "plbuf: Unable to write to temporary file" );
01306                     fclose( plot_state->plbufFile );
01307                     plot_state->plbufFile = NULL;
01308                     return (void *) plot_state;
01309                 }
01310             }
01311         }
01312 #else
01313         // Again, note, that we only copy the portion of the plot buffer that is being used
01314         plot_state->plbuf_buffer_size = pls->plbuf_top;
01315         plot_state->plbuf_top         = pls->plbuf_top;
01316         plot_state->plbuf_readpos     = 0;
01317 
01318         // Create a pointer that points in the space we allocated after struct _state
01319         plot_state->plbuf_buffer = (void *) buf;
01320         buf += pls->plbuf_top;
01321 
01322         // Copy the plot buffer to our new buffer.  Again, I must stress, that we only
01323         // are copying the portion of the plot buffer that is being used
01324         //
01325         if ( memcpy( plot_state->plbuf_buffer, pls->plbuf_buffer, pls->plbuf_top ) == NULL )
01326         {
01327             // This should never be NULL
01328             plwarn( "plbuf: Got a NULL in memcpy!" );
01329             return (void *) plot_state;
01330         }
01331 #endif
01332 
01333         pls->plbuf_write = TRUE;
01334         pls->plbuf_read  = FALSE;
01335 
01336         // Save the colormaps.  First create a pointer that points in the space we allocated
01337         // after the plot buffer
01338         plot_state->color_map = (struct _color_map *) buf;
01339         buf += sizeof ( struct _color_map ) * 2;
01340 
01341         // Then we need to make space for the colormaps themselves
01342         plot_state->color_map[0].cmap = (PLColor *) buf;
01343         buf += sizeof ( PLColor ) * pls->ncol0;
01344         plot_state->color_map[1].cmap = (PLColor *) buf;
01345         buf += sizeof ( PLColor ) * pls->ncol1;
01346 
01347         // Save cmap 0
01348         plot_state->color_map[0].icol = pls->icol0;
01349         plot_state->color_map[0].ncol = pls->ncol0;
01350         for ( i = 0; i < pls->ncol0; i++ )
01351         {
01352             pl_cpcolor( &( plot_state->color_map[0].cmap[i] ), &pls->cmap0[i] );
01353         }
01354 
01355         // Save cmap 1
01356         plot_state->color_map[1].icol = pls->icol1;
01357         plot_state->color_map[1].ncol = pls->ncol1;
01358         for ( i = 0; i < pls->ncol1; i++ )
01359         {
01360             pl_cpcolor( &( plot_state->color_map[1].cmap[i] ), &pls->cmap1[i] );
01361         }
01362 
01363         plot_state->valid = 1;
01364         return (void *) plot_state;
01365     }
01366 
01367     return NULL;
01368 }
01369 
01370 // plbuf_restore(PLStream *, state)
01371 //
01372 // Restores the passed state
01373 //
01374 void plbuf_restore( PLStream *pls, void *state )
01375 {
01376     struct _state *new_state = (struct _state *) state;
01377 
01378 #ifdef BUFFERED_FILE
01379     pls->plbufFile = new_state->save_file;
01380 #else
01381     pls->plbuf_buffer      = new_state->plbuf_buffer;
01382     pls->plbuf_buffer_size = new_state->plbuf_buffer_size;
01383     pls->plbuf_top         = new_state->plbuf_top;
01384     pls->plbuf_readpos     = new_state->plbuf_readpos;
01385 #endif
01386     // cmap 0
01387     pls->cmap0 = new_state->color_map[0].cmap;
01388     pls->icol0 = new_state->color_map[0].icol;
01389     pls->ncol0 = new_state->color_map[0].ncol;
01390     // cmap 1
01391     pls->cmap1 = new_state->color_map[1].cmap;
01392     pls->icol1 = new_state->color_map[1].icol;
01393     pls->ncol1 = new_state->color_map[1].ncol;
01394 }
01395 
01396 // plbuf_switch(PLStream *, state)
01397 //
01398 // Makes the passed state the current one.  Preserves the previous state
01399 // by returning a save buffer.
01400 //
01401 // NOTE:  The current implementation can cause a memory leak under the
01402 // following scenario:
01403 //    1) plbuf_save() is called
01404 //    2) plbuf_switch() is called
01405 //    3) Commands are called which cause the plot buffer to grow
01406 //    4) plbuf_swtich() is called
01407 //
01408 void * plbuf_switch( PLStream *pls, void *state )
01409 {
01410     struct _state *new_state = (struct _state *) state;
01411     struct _state *prev_state;
01412     size_t        save_size;
01413 
01414     // No saved state was passed, return a NULL--we hope the caller
01415     // is smart enough to notice
01416     //
01417     if ( state == NULL )
01418         return NULL;
01419 
01420     if ( !new_state->valid )
01421     {
01422         plwarn( "plbuf: Attempting to switch to an invalid saved state" );
01423         return NULL;
01424     }
01425 
01426     save_size = sizeof ( struct _state )
01427                 + 2 * sizeof ( struct _color_map );
01428 
01429     if ( ( prev_state = (struct _state *) malloc( save_size ) ) == NULL )
01430     {
01431         plwarn( "plbuf: Unable to allocate memory to save state" );
01432         return NULL;
01433     }
01434 
01435     // Set some housekeeping variables
01436     prev_state->size  = save_size;
01437     prev_state->valid = 1;
01438 
01439     // Preserve the existing state
01440 #ifdef BUFFERED_FILE
01441     prev_state->plbufFile = pls->plbufFile;
01442 #else
01443     prev_state->plbuf_buffer      = pls->plbuf_buffer;
01444     prev_state->plbuf_buffer_size = pls->plbuf_buffer_size;
01445     prev_state->plbuf_top         = pls->plbuf_top;
01446     prev_state->plbuf_readpos     = pls->plbuf_readpos;
01447 #endif
01448     // cmap 0
01449     prev_state->color_map[0].cmap = pls->cmap0;
01450     prev_state->color_map[0].icol = pls->icol0;
01451     prev_state->color_map[0].ncol = pls->ncol0;
01452     // cmap 1
01453     prev_state->color_map[1].cmap = pls->cmap1;
01454     prev_state->color_map[1].icol = pls->icol1;
01455     prev_state->color_map[1].ncol = pls->ncol1;
01456 
01457     plbuf_restore( pls, new_state );
01458 
01459     return (void *) prev_state;
01460 }
01461 
01462 

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