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