PLplot 5.9.6
|
00001 /* $Id$ 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 General Library 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 PLINT npts; 00495 00496 dbug_enter( "rdbuf_polyline" ); 00497 00498 rd_data( pls, &npts, sizeof ( PLINT ) ); 00499 rd_data( pls, xpl, sizeof ( short ) * npts ); 00500 rd_data( pls, ypl, sizeof ( short ) * npts ); 00501 00502 plP_polyline( xpl, ypl, npts ); 00503 } 00504 00505 /*--------------------------------------------------------------------------*\ 00506 * rdbuf_eop() 00507 * 00508 * End of page. 00509 \*--------------------------------------------------------------------------*/ 00510 00511 static void 00512 rdbuf_eop( PLStream *pls ) 00513 { 00514 dbug_enter( "rdbuf_eop" ); 00515 } 00516 00517 /*--------------------------------------------------------------------------*\ 00518 * rdbuf_bop() 00519 * 00520 * Set up for the next page. 00521 \*--------------------------------------------------------------------------*/ 00522 00523 static void 00524 rdbuf_bop( PLStream *pls ) 00525 { 00526 dbug_enter( "rdbuf_bop" ); 00527 00528 pls->nplwin = 0; 00529 } 00530 00531 /*--------------------------------------------------------------------------*\ 00532 * rdbuf_state() 00533 * 00534 * Handle change in PLStream state (color, pen width, fill attribute, etc). 00535 \*--------------------------------------------------------------------------*/ 00536 00537 static void 00538 rdbuf_state( PLStream *pls ) 00539 { 00540 U_CHAR op; 00541 00542 dbug_enter( "rdbuf_state" ); 00543 00544 rd_data( pls, &op, sizeof ( U_CHAR ) ); 00545 00546 switch ( op ) 00547 { 00548 case PLSTATE_WIDTH: { 00549 U_CHAR width; 00550 00551 rd_data( pls, &width, sizeof ( U_CHAR ) ); 00552 pls->width = width; 00553 plP_state( PLSTATE_WIDTH ); 00554 00555 break; 00556 } 00557 00558 case PLSTATE_COLOR0: { 00559 short icol0; 00560 U_CHAR r, g, b; 00561 PLFLT a; 00562 00563 rd_data( pls, &icol0, sizeof ( short ) ); 00564 if ( icol0 == PL_RGB_COLOR ) 00565 { 00566 rd_data( pls, &r, sizeof ( U_CHAR ) ); 00567 rd_data( pls, &g, sizeof ( U_CHAR ) ); 00568 rd_data( pls, &b, sizeof ( U_CHAR ) ); 00569 a = 1.0; 00570 } 00571 else 00572 { 00573 if ( (int) icol0 >= pls->ncol0 ) 00574 { 00575 char buffer[256]; 00576 snprintf( buffer, 256, "rdbuf_state: Invalid color map entry: %d", (int) icol0 ); 00577 plabort( buffer ); 00578 return; 00579 } 00580 r = pls->cmap0[icol0].r; 00581 g = pls->cmap0[icol0].g; 00582 b = pls->cmap0[icol0].b; 00583 a = pls->cmap0[icol0].a; 00584 } 00585 pls->icol0 = icol0; 00586 pls->curcolor.r = r; 00587 pls->curcolor.g = g; 00588 pls->curcolor.b = b; 00589 pls->curcolor.a = a; 00590 00591 plP_state( PLSTATE_COLOR0 ); 00592 break; 00593 } 00594 00595 case PLSTATE_COLOR1: { 00596 short icol1; 00597 00598 rd_data( pls, &icol1, sizeof ( short ) ); 00599 00600 pls->icol1 = icol1; 00601 pls->curcolor.r = pls->cmap1[icol1].r; 00602 pls->curcolor.g = pls->cmap1[icol1].g; 00603 pls->curcolor.b = pls->cmap1[icol1].b; 00604 pls->curcolor.a = pls->cmap1[icol1].a; 00605 00606 plP_state( PLSTATE_COLOR1 ); 00607 break; 00608 } 00609 00610 case PLSTATE_FILL: { 00611 signed char patt; 00612 00613 rd_data( pls, &patt, sizeof ( signed char ) ); 00614 00615 pls->patt = patt; 00616 plP_state( PLSTATE_FILL ); 00617 break; 00618 } 00619 } 00620 } 00621 00622 /*--------------------------------------------------------------------------*\ 00623 * rdbuf_esc() 00624 * 00625 * Escape function. 00626 * Must fill data structure with whatever data that was written, 00627 * then call escape function. 00628 * 00629 * Note: it is best to only call the escape function for op-codes that 00630 * are known to be supported. 00631 * 00632 * Functions: 00633 * 00634 * PLESC_FILL Fill polygon 00635 * PLESC_SWIN Set plot window parameters 00636 * PLESC_IMAGE Draw image 00637 * PLESC_HAS_TEXT Draw PostScript text 00638 * PLESC_BEGIN_TEXT Commands for the alternative unicode text handling path 00639 * PLESC_TEXT_CHAR 00640 * PLESC_CONTROL_CHAR 00641 * PLESC_END_TEXT 00642 * PLESC_CLEAR Clear Background 00643 \*--------------------------------------------------------------------------*/ 00644 00645 static void 00646 rdbuf_image( PLStream *pls ); 00647 00648 static void 00649 rdbuf_text( PLStream *pls ); 00650 00651 static void 00652 rdbuf_text_unicode( PLINT op, PLStream *pls ); 00653 00654 static void 00655 rdbuf_esc( PLStream *pls ) 00656 { 00657 U_CHAR op; 00658 00659 dbug_enter( "rdbuf_esc" ); 00660 00661 rd_data( pls, &op, sizeof ( U_CHAR ) ); 00662 00663 switch ( op ) 00664 { 00665 case PLESC_FILL: 00666 rdbuf_fill( pls ); 00667 break; 00668 case PLESC_SWIN: 00669 rdbuf_swin( pls ); 00670 break; 00671 case PLESC_IMAGE: 00672 rdbuf_image( pls ); 00673 break; 00674 case PLESC_HAS_TEXT: 00675 rdbuf_text( pls ); 00676 break; 00677 case PLESC_BEGIN_TEXT: 00678 case PLESC_TEXT_CHAR: 00679 case PLESC_CONTROL_CHAR: 00680 case PLESC_END_TEXT: 00681 rdbuf_text_unicode( op, pls ); 00682 break; 00683 case PLESC_CLEAR: 00684 plP_esc( PLESC_CLEAR, NULL ); 00685 break; 00686 case PLESC_START_RASTERIZE: 00687 plP_esc( PLESC_START_RASTERIZE, NULL ); 00688 break; 00689 case PLESC_END_RASTERIZE: 00690 plP_esc( PLESC_END_RASTERIZE, NULL ); 00691 break; 00692 } 00693 } 00694 00695 /*--------------------------------------------------------------------------*\ 00696 * rdbuf_fill() 00697 * 00698 * Fill polygon described by input points. 00699 \*--------------------------------------------------------------------------*/ 00700 00701 static void 00702 rdbuf_fill( PLStream *pls ) 00703 { 00704 short xpl[PL_MAXPOLY], ypl[PL_MAXPOLY]; 00705 PLINT npts; 00706 00707 dbug_enter( "rdbuf_fill" ); 00708 00709 rd_data( pls, &npts, sizeof ( PLINT ) ); 00710 rd_data( pls, xpl, sizeof ( short ) * npts ); 00711 rd_data( pls, ypl, sizeof ( short ) * npts ); 00712 00713 plP_fill( xpl, ypl, npts ); 00714 } 00715 00716 /*--------------------------------------------------------------------------*\ 00717 * rdbuf_image() 00718 * 00719 * . 00720 \*--------------------------------------------------------------------------*/ 00721 00722 static void 00723 rdbuf_image( PLStream *pls ) 00724 { 00725 short *dev_ix, *dev_iy; 00726 unsigned short *dev_z, dev_zmin, dev_zmax; 00727 PLINT nptsX, nptsY, npts; 00728 PLFLT xmin, ymin, dx, dy; 00729 00730 dbug_enter( "rdbuf_image" ); 00731 00732 rd_data( pls, &nptsX, sizeof ( PLINT ) ); 00733 rd_data( pls, &nptsY, sizeof ( PLINT ) ); 00734 npts = nptsX * nptsY; 00735 00736 rd_data( pls, &xmin, sizeof ( PLFLT ) ); 00737 rd_data( pls, &ymin, sizeof ( PLFLT ) ); 00738 rd_data( pls, &dx, sizeof ( PLFLT ) ); 00739 rd_data( pls, &dy, sizeof ( PLFLT ) ); 00740 00741 rd_data( pls, &dev_zmin, sizeof ( short ) ); 00742 rd_data( pls, &dev_zmax, sizeof ( short ) ); 00743 00744 /* NOTE: Even though for memory buffered version all the data is in memory, 00745 * we still allocate and copy the data because I think that method works 00746 * better in a multithreaded environment. I could be wrong. 00747 */ 00748 if ( ( ( dev_ix = (short *) malloc( npts * sizeof ( short ) ) ) == NULL ) || 00749 ( ( dev_iy = (short *) malloc( npts * sizeof ( short ) ) ) == NULL ) || 00750 ( ( dev_z = (unsigned short *) malloc( ( nptsX - 1 ) * ( nptsY - 1 ) * sizeof ( unsigned short ) ) ) == NULL ) ) 00751 plexit( "rdbuf_image: Insufficient memory" ); 00752 00753 rd_data( pls, dev_ix, sizeof ( short ) * npts ); 00754 rd_data( pls, dev_iy, sizeof ( short ) * npts ); 00755 rd_data( pls, dev_z, sizeof ( unsigned short ) * ( nptsX - 1 ) * ( nptsY - 1 ) ); 00756 00757 /* 00758 * COMMENTED OUT by Hezekiah Carty 00759 * Commented (hopefullly temporarily) until the dev_fastimg rendering 00760 * path can be updated to support the new plimage internals. In the 00761 * meantime this function is not actually used so the issue of how to 00762 * update the code to support the new interface can be ignored. 00763 */ 00764 /*plP_image(dev_ix, dev_iy, dev_z, nptsX, nptsY, xmin, ymin, dx, dy, dev_zmin, dev_zmax);*/ 00765 00766 free( dev_ix ); 00767 free( dev_iy ); 00768 free( dev_z ); 00769 } 00770 00771 /*--------------------------------------------------------------------------*\ 00772 * rdbuf_swin() 00773 * 00774 * Set up plot window parameters. 00775 \*--------------------------------------------------------------------------*/ 00776 00777 static void 00778 rdbuf_swin( PLStream *pls ) 00779 { 00780 PLWindow plwin; 00781 00782 rd_data( pls, &plwin.dxmi, sizeof ( PLFLT ) ); 00783 rd_data( pls, &plwin.dxma, sizeof ( PLFLT ) ); 00784 rd_data( pls, &plwin.dymi, sizeof ( PLFLT ) ); 00785 rd_data( pls, &plwin.dyma, sizeof ( PLFLT ) ); 00786 00787 rd_data( pls, &plwin.wxmi, sizeof ( PLFLT ) ); 00788 rd_data( pls, &plwin.wxma, sizeof ( PLFLT ) ); 00789 rd_data( pls, &plwin.wymi, sizeof ( PLFLT ) ); 00790 rd_data( pls, &plwin.wyma, sizeof ( PLFLT ) ); 00791 00792 plP_swin( &plwin ); 00793 } 00794 00795 /*--------------------------------------------------------------------------*\ 00796 * rdbuf_text() 00797 * 00798 * Draw PostScript text. 00799 \*--------------------------------------------------------------------------*/ 00800 00801 static void 00802 rdbuf_text( PLStream *pls ) 00803 { 00804 PLUNICODE( fci ); 00805 EscText text; 00806 PLFLT xform[4]; 00807 PLUNICODE* unicode; 00808 00809 text.xform = xform; 00810 00811 00812 /* Read in the data */ 00813 00814 rd_data( pls, &fci, sizeof ( PLUNICODE ) ); 00815 00816 rd_data( pls, &pls->chrht, sizeof ( PLFLT ) ); 00817 rd_data( pls, &pls->diorot, sizeof ( PLFLT ) ); 00818 rd_data( pls, &pls->clpxmi, sizeof ( PLFLT ) ); 00819 rd_data( pls, &pls->clpxma, sizeof ( PLFLT ) ); 00820 rd_data( pls, &pls->clpymi, sizeof ( PLFLT ) ); 00821 rd_data( pls, &pls->clpyma, sizeof ( PLFLT ) ); 00822 00823 rd_data( pls, &text.base, sizeof ( PLINT ) ); 00824 rd_data( pls, &text.just, sizeof ( PLFLT ) ); 00825 rd_data( pls, text.xform, sizeof ( PLFLT ) * 4 ); 00826 rd_data( pls, &text.x, sizeof ( PLINT ) ); 00827 rd_data( pls, &text.y, sizeof ( PLINT ) ); 00828 rd_data( pls, &text.refx, sizeof ( PLINT ) ); 00829 rd_data( pls, &text.refy, sizeof ( PLINT ) ); 00830 00831 rd_data( pls, &text.unicode_array_len, sizeof ( PLINT ) ); 00832 if ( text.unicode_array_len ) 00833 { 00834 if ( ( unicode = (PLUNICODE *) malloc( text.unicode_array_len * sizeof ( PLUNICODE ) ) ) 00835 == NULL ) 00836 plexit( "rdbuf_text: Insufficient memory" ); 00837 00838 rd_data( pls, unicode, sizeof ( PLUNICODE ) * text.unicode_array_len ); 00839 text.unicode_array = unicode; 00840 } 00841 else 00842 text.unicode_array = NULL; 00843 00844 /* Make the call for unicode devices */ 00845 if ( pls->dev_unicode ) 00846 { 00847 plsfci( fci ); 00848 plP_esc( PLESC_HAS_TEXT, &text ); 00849 } 00850 } 00851 00852 /*--------------------------------------------------------------------------*\ 00853 * rdbuf_text_unicode() 00854 * 00855 * Draw text for the new unicode handling pathway. 00856 \*--------------------------------------------------------------------------*/ 00857 00858 static void 00859 rdbuf_text_unicode( PLINT op, PLStream *pls ) 00860 { 00861 PLUNICODE( fci ); 00862 EscText text; 00863 PLFLT xform[4]; 00864 00865 text.xform = xform; 00866 00867 00868 /* Read in the data */ 00869 00870 rd_data( pls, &fci, sizeof ( PLUNICODE ) ); 00871 00872 rd_data( pls, &pls->chrht, sizeof ( PLFLT ) ); 00873 rd_data( pls, &pls->diorot, sizeof ( PLFLT ) ); 00874 rd_data( pls, &pls->clpxmi, sizeof ( PLFLT ) ); 00875 rd_data( pls, &pls->clpxma, sizeof ( PLFLT ) ); 00876 rd_data( pls, &pls->clpymi, sizeof ( PLFLT ) ); 00877 rd_data( pls, &pls->clpyma, sizeof ( PLFLT ) ); 00878 00879 rd_data( pls, &text.base, sizeof ( PLINT ) ); 00880 rd_data( pls, &text.just, sizeof ( PLFLT ) ); 00881 rd_data( pls, text.xform, sizeof ( PLFLT ) * 4 ); 00882 rd_data( pls, &text.x, sizeof ( PLINT ) ); 00883 rd_data( pls, &text.y, sizeof ( PLINT ) ); 00884 rd_data( pls, &text.refx, sizeof ( PLINT ) ); 00885 rd_data( pls, &text.refy, sizeof ( PLINT ) ); 00886 00887 rd_data( pls, &text.n_fci, sizeof ( PLUNICODE ) ); 00888 rd_data( pls, &text.n_char, sizeof ( PLUNICODE ) ); 00889 rd_data( pls, &text.n_ctrl_char, sizeof ( PLINT ) ); 00890 00891 rd_data( pls, &text.unicode_array_len, sizeof ( PLINT ) ); 00892 00893 if ( pls->dev_unicode ) 00894 { 00895 plsfci( fci ); 00896 plP_esc( op, &text ); 00897 } 00898 } 00899 00900 /*--------------------------------------------------------------------------*\ 00901 * plRemakePlot() 00902 * 00903 * Rebuilds plot from plot buffer, usually in response to a window 00904 * resize or exposure event. 00905 \*--------------------------------------------------------------------------*/ 00906 00907 void 00908 plRemakePlot( PLStream *pls ) 00909 { 00910 U_CHAR c; 00911 int plbuf_status; 00912 PLStream *save_pls; 00913 00914 dbug_enter( "plRemakePlot" ); 00915 00916 /* Change the status of the flags before checking for a buffer. 00917 * Actually, more thought is needed if we want to support multithreaded 00918 * code correctly, specifically the case where two threads are using 00919 * the same plot stream (e.g. one thread is drawing the plot and another 00920 * thread is processing window manager messages). 00921 */ 00922 plbuf_status = pls->plbuf_write; 00923 pls->plbuf_write = FALSE; 00924 pls->plbuf_read = TRUE; 00925 00926 #ifdef BUFFERED_FILE 00927 if ( pls->plbufFile ) 00928 { 00929 rewind( pls->plbufFile ); 00930 #else 00931 if ( pls->plbuf_buffer ) 00932 { 00933 pls->plbuf_readpos = 0; 00934 #endif 00935 /* Need to change where plsc points to before processing the commands. 00936 * If we have multiple plot streams, this will prevent the commands from 00937 * going to the wrong plot stream. 00938 */ 00939 save_pls = plsc; 00940 plsc = pls; 00941 00942 while ( rd_command( pls, &c ) ) 00943 { 00944 plbuf_control( pls, c ); 00945 } 00946 00947 plsc = save_pls; 00948 } 00949 00950 pls->plbuf_read = FALSE; 00951 pls->plbuf_write = plbuf_status; 00952 } 00953 00954 /*--------------------------------------------------------------------------*\ 00955 * plbuf_control() 00956 * 00957 * Processes commands read from the plot buffer. 00958 \*--------------------------------------------------------------------------*/ 00959 00960 static void 00961 plbuf_control( PLStream *pls, U_CHAR c ) 00962 { 00963 static U_CHAR c_old = 0; 00964 00965 dbug_enter( "plbuf_control" ); 00966 00967 switch ( (int) c ) 00968 { 00969 case INITIALIZE: 00970 rdbuf_init( pls ); 00971 break; 00972 00973 case EOP: 00974 rdbuf_eop( pls ); 00975 break; 00976 00977 case BOP: 00978 rdbuf_bop( pls ); 00979 break; 00980 00981 case CHANGE_STATE: 00982 rdbuf_state( pls ); 00983 break; 00984 00985 case LINE: 00986 rdbuf_line( pls ); 00987 break; 00988 00989 case POLYLINE: 00990 rdbuf_polyline( pls ); 00991 break; 00992 00993 case ESCAPE: 00994 rdbuf_esc( pls ); 00995 break; 00996 00997 default: 00998 pldebug( "plbuf_control", "Unrecognized command %d, previous %d\n", c, c_old ); 00999 } 01000 c_old = c; 01001 } 01002 01003 /*--------------------------------------------------------------------------*\ 01004 * rd_command() 01005 * 01006 * Read & return the next command 01007 \*--------------------------------------------------------------------------*/ 01008 01009 static int 01010 rd_command( PLStream *pls, U_CHAR *p_c ) 01011 { 01012 int count; 01013 01014 #ifdef BUFFERED_FILE 01015 count = fread( p_c, sizeof ( U_CHAR ), 1, pls->plbufFile ); 01016 #else 01017 if ( pls->plbuf_readpos < pls->plbuf_top ) 01018 { 01019 *p_c = *(U_CHAR *) ( (U_CHAR *) pls->plbuf_buffer + pls->plbuf_readpos ); 01020 pls->plbuf_readpos += sizeof ( U_CHAR ); 01021 count = sizeof ( U_CHAR ); 01022 } 01023 else 01024 { 01025 count = 0; 01026 } 01027 #endif 01028 return ( count ); 01029 } 01030 01031 /*--------------------------------------------------------------------------*\ 01032 * rd_data() 01033 * 01034 * Read the data associated with the command 01035 \*--------------------------------------------------------------------------*/ 01036 01037 static void 01038 rd_data( PLStream *pls, void *buf, size_t buf_size ) 01039 { 01040 #ifdef BUFFERED_FILE 01041 plio_fread( buf, buf_size, 1, pls->plbufFile ); 01042 #else 01043 /* If U_CHAR is not the same size as what memcpy() expects (typically 1 byte) 01044 * then this code will have problems. A better approach might be to use 01045 * uint8_t from <stdint.h> but I do not know how portable that approach is 01046 */ 01047 memcpy( buf, (U_CHAR *) pls->plbuf_buffer + pls->plbuf_readpos, buf_size ); 01048 pls->plbuf_readpos += buf_size; 01049 #endif 01050 } 01051 01052 /*--------------------------------------------------------------------------*\ 01053 * wr_command() 01054 * 01055 * Write the next command 01056 \*--------------------------------------------------------------------------*/ 01057 01058 static void 01059 wr_command( PLStream *pls, U_CHAR c ) 01060 { 01061 #ifdef BUFFERED_FILE 01062 plio_fwrite( &c1, sizeof ( U_CHAR ), 1, pls->plbufFile ); 01063 #else 01064 if ( ( pls->plbuf_top + sizeof ( U_CHAR ) ) >= pls->plbuf_buffer_size ) 01065 { 01066 /* Not enough space, need to grow the buffer */ 01067 pls->plbuf_buffer_size += pls->plbuf_buffer_grow; 01068 01069 if ( pls->verbose ) 01070 printf( "Growing buffer to %d KB\n", (int) ( pls->plbuf_buffer_size / 1024 ) ); 01071 if ( ( pls->plbuf_buffer = realloc( pls->plbuf_buffer, pls->plbuf_buffer_size ) ) == NULL ) 01072 plexit( "plbuf wr_data: Plot buffer grow failed" ); 01073 } 01074 01075 *(U_CHAR *) ( (U_CHAR *) pls->plbuf_buffer + pls->plbuf_top ) = c; 01076 pls->plbuf_top += sizeof ( U_CHAR ); 01077 #endif 01078 } 01079 01080 /*--------------------------------------------------------------------------*\ 01081 * wr_data() 01082 * 01083 * Write the data associated with a command 01084 \*--------------------------------------------------------------------------*/ 01085 01086 static void 01087 wr_data( PLStream *pls, void *buf, size_t buf_size ) 01088 { 01089 #ifdef BUFFERED_FILE 01090 plio_fwrite( buf, buf_size, 1, pls->plbufFile ); 01091 #else 01092 if ( ( pls->plbuf_top + buf_size ) >= pls->plbuf_buffer_size ) 01093 { 01094 /* Not enough space, need to grow the buffer */ 01095 /* Must make sure the increase is enough for this data */ 01096 pls->plbuf_buffer_size += pls->plbuf_buffer_grow * 01097 ( ( pls->plbuf_top + buf_size - pls->plbuf_buffer_size ) / 01098 pls->plbuf_buffer_grow + 1 ); 01099 while ( pls->plbuf_top + buf_size >= pls->plbuf_buffer_size ) 01100 ; 01101 01102 if ( ( pls->plbuf_buffer = realloc( pls->plbuf_buffer, pls->plbuf_buffer_size ) ) == NULL ) 01103 plexit( "plbuf wr_data: Plot buffer grow failed" ); 01104 } 01105 01106 /* If U_CHAR is not the same size as what memcpy() expects (typically 1 byte) 01107 * then this code will have problems. A better approach might be to use 01108 * uint8_t from <stdint.h> but I do not know how portable that approach is 01109 */ 01110 memcpy( (U_CHAR *) pls->plbuf_buffer + pls->plbuf_top, buf, buf_size ); 01111 pls->plbuf_top += buf_size; 01112 #endif 01113 } 01114 01115 /* plbuf_save(state) 01116 * 01117 * Saves the current state of the plot into a save buffer. 01118 * This code was originally in gcw.c and gcw-lib.c. The original 01119 * code used a temporary file for the plot buffer and memory 01120 * to perserve colormaps. That method does not offer a clean 01121 * break between using memory buffers and file buffers. This 01122 * function preserves the same functionality by returning a data 01123 * structure that saves the plot buffer and colormaps seperately. 01124 * 01125 * The caller passes an existing save buffer for reuse or NULL 01126 * to force the allocation of a new buffer. Since one malloc() 01127 * is used for everything, the entire save buffer can be freed 01128 * with one free() call. 01129 * 01130 */ 01131 struct _color_map 01132 { 01133 PLColor *cmap; 01134 PLINT icol; 01135 PLINT ncol; 01136 }; 01137 01138 struct _state 01139 { 01140 size_t size; /* Size of the save buffer */ 01141 int valid; /* Flag to indicate a valid save state */ 01142 #ifdef BUFFERED_FILE 01143 FILE *plbufFile; 01144 #else 01145 void *plbuf_buffer; 01146 size_t plbuf_buffer_size; 01147 size_t plbuf_top; 01148 size_t plbuf_readpos; 01149 #endif 01150 struct _color_map *color_map; 01151 }; 01152 01153 void * plbuf_save( PLStream *pls, void *state ) 01154 { 01155 size_t save_size; 01156 struct _state *plot_state = (struct _state *) state; 01157 PLINT i; 01158 U_CHAR *buf; /* Assume that this is byte-sized */ 01159 01160 if ( pls->plbuf_write ) 01161 { 01162 pls->plbuf_write = FALSE; 01163 pls->plbuf_read = TRUE; 01164 01165 /* Determine the size of the buffer required to save everything. We 01166 * assume that there are only two colormaps, but have written the code 01167 * that more than two can be handled with minimal changes. 01168 */ 01169 save_size = sizeof ( struct _state ) 01170 + 2 * sizeof ( struct _color_map ) 01171 + pls->ncol0 * sizeof ( PLColor ) 01172 + pls->ncol1 * sizeof ( PLColor ); 01173 01174 #ifndef BUFFERED_FILE 01175 /* Only copy as much of the plot buffer that is being used */ 01176 save_size += pls->plbuf_top; 01177 #endif 01178 01179 /* If a buffer exists, determine if we need to resize it */ 01180 if ( state != NULL ) 01181 { 01182 /* We have a save buffer, is it smaller than the current size requirement? */ 01183 if ( plot_state->size < save_size ) 01184 { 01185 /* Yes, reallocate a larger one */ 01186 if ( ( plot_state = (struct _state *) realloc( state, save_size ) ) == NULL ) 01187 { 01188 /* NOTE: If realloc fails, then plot_state ill be NULL. 01189 * This will leave the original buffer untouched, thus we 01190 * mark it as invalid and return it back to the caller. 01191 */ 01192 plwarn( "plbuf: Unable to reallocate sufficient memory to save state" ); 01193 plot_state->valid = 0; 01194 01195 return state; 01196 } 01197 plot_state->size = save_size; 01198 } 01199 } 01200 else 01201 { 01202 /* A buffer does not exist, so we need to allocate one */ 01203 if ( ( plot_state = (struct _state *) malloc( save_size ) ) == NULL ) 01204 { 01205 plwarn( "plbuf: Unable to allocate sufficient memory to save state" ); 01206 01207 return NULL; 01208 } 01209 plot_state->size = save_size; 01210 01211 #ifdef BUFFERED_FILE 01212 /* Make sure the FILE pointer is NULL in order to preven bad things from happening... */ 01213 plot_state->plbufFile = NULL; 01214 #endif 01215 } 01216 01217 /* At this point we have an appropriately sized save buffer. 01218 * We need to invalidate the state of the save buffer, since it 01219 * will not be valid until after everything is copied. We use 01220 * this approach vice freeing the memory and returning a NULL pointer 01221 * in order to prevent allocating and freeing memory needlessly. 01222 */ 01223 plot_state->valid = 0; 01224 01225 /* Point buf to the space after the struct _state */ 01226 buf = (U_CHAR *) ( plot_state + 1 ); 01227 01228 #ifdef BUFFERED_FILE 01229 /* Remove the old tempfile, if it exists */ 01230 if ( plot_state->plbufFile != NULL ) 01231 { 01232 fclose( plot_state->plbufFile ); 01233 } 01234 01235 /* Copy the plot buffer to a tempfile */ 01236 if ( ( plot_state->plbufFile = pl_create_tempfile( NULL ) ) == NULL ) 01237 { 01238 /* Throw a warning since this might be a permissions problem 01239 * and we may not want to force an exit 01240 */ 01241 plwarn( "plbuf: Unable to open temporary file to save state" ); 01242 return (void *) plot_state; 01243 } 01244 else 01245 { 01246 U_CHAR tmp; 01247 01248 rewind( pls->plbufFile ); 01249 while ( count = fread( &tmp, sizeof ( U_CHAR ), 1, pls->plbufFile ) ) 01250 { 01251 if ( fwrite( &tmp, sizeof ( U_CHAR ), 1, plot_state->plbufFile ) != count ) 01252 { 01253 /* Throw a warning since this might be a permissions problem 01254 * and we may not want to force an exit 01255 */ 01256 plwarn( "plbuf: Unable to write to temporary file" ); 01257 fclose( plot_state->plbufFile ); 01258 plot_state->plbufFile = NULL; 01259 return (void *) plot_state; 01260 } 01261 } 01262 } 01263 #else 01264 /* Again, note, that we only copy the portion of the plot buffer that is being used */ 01265 plot_state->plbuf_buffer_size = pls->plbuf_top; 01266 plot_state->plbuf_top = pls->plbuf_top; 01267 plot_state->plbuf_readpos = 0; 01268 01269 /* Create a pointer that points in the space we allocated after struct _state */ 01270 plot_state->plbuf_buffer = (void *) buf; 01271 buf += pls->plbuf_top; 01272 01273 /* Copy the plot buffer to our new buffer. Again, I must stress, that we only 01274 * are copying the portion of the plot buffer that is being used 01275 */ 01276 if ( memcpy( plot_state->plbuf_buffer, pls->plbuf_buffer, pls->plbuf_top ) == NULL ) 01277 { 01278 /* This should never be NULL */ 01279 plwarn( "plbuf: Got a NULL in memcpy!" ); 01280 return (void *) plot_state; 01281 } 01282 #endif 01283 01284 pls->plbuf_write = TRUE; 01285 pls->plbuf_read = FALSE; 01286 01287 /* Save the colormaps. First create a pointer that points in the space we allocated 01288 * after the plot buffer */ 01289 plot_state->color_map = (struct _color_map *) buf; 01290 buf += sizeof ( struct _color_map ) * 2; 01291 01292 /* Then we need to make space for the colormaps themselves */ 01293 plot_state->color_map[0].cmap = (PLColor *) buf; 01294 buf += sizeof ( PLColor ) * pls->ncol0; 01295 plot_state->color_map[1].cmap = (PLColor *) buf; 01296 buf += sizeof ( PLColor ) * pls->ncol1; 01297 01298 /* Save cmap 0 */ 01299 plot_state->color_map[0].icol = pls->icol0; 01300 plot_state->color_map[0].ncol = pls->ncol0; 01301 for ( i = 0; i < pls->ncol0; i++ ) 01302 { 01303 pl_cpcolor( &( plot_state->color_map[0].cmap[i] ), &pls->cmap0[i] ); 01304 } 01305 01306 /* Save cmap 1 */ 01307 plot_state->color_map[1].icol = pls->icol1; 01308 plot_state->color_map[1].ncol = pls->ncol1; 01309 for ( i = 0; i < pls->ncol1; i++ ) 01310 { 01311 pl_cpcolor( &( plot_state->color_map[1].cmap[i] ), &pls->cmap1[i] ); 01312 } 01313 01314 plot_state->valid = 1; 01315 return (void *) plot_state; 01316 } 01317 01318 return NULL; 01319 } 01320 01321 /* plbuf_restore(PLStream *, state) 01322 * 01323 * Restores the passed state 01324 */ 01325 void plbuf_restore( PLStream *pls, void *state ) 01326 { 01327 struct _state *new_state = (struct _state *) state; 01328 01329 #ifdef BUFFERED_FILE 01330 pls->plbufFile = new_state->save_file; 01331 #else 01332 pls->plbuf_buffer = new_state->plbuf_buffer; 01333 pls->plbuf_buffer_size = new_state->plbuf_buffer_size; 01334 pls->plbuf_top = new_state->plbuf_top; 01335 pls->plbuf_readpos = new_state->plbuf_readpos; 01336 #endif 01337 /* cmap 0 */ 01338 pls->cmap0 = new_state->color_map[0].cmap; 01339 pls->icol0 = new_state->color_map[0].icol; 01340 pls->ncol0 = new_state->color_map[0].ncol; 01341 /* cmap 1 */ 01342 pls->cmap1 = new_state->color_map[1].cmap; 01343 pls->icol1 = new_state->color_map[1].icol; 01344 pls->ncol1 = new_state->color_map[1].ncol; 01345 } 01346 01347 /* plbuf_switch(PLStream *, state) 01348 * 01349 * Makes the passed state the current one. Preserves the previous state 01350 * by returning a save buffer. 01351 * 01352 * NOTE: The current implementation can cause a memory leak under the 01353 * following scenario: 01354 * 1) plbuf_save() is called 01355 * 2) plbuf_switch() is called 01356 * 3) Commands are called which cause the plot buffer to grow 01357 * 4) plbuf_swtich() is called 01358 */ 01359 void * plbuf_switch( PLStream *pls, void *state ) 01360 { 01361 struct _state *new_state = (struct _state *) state; 01362 struct _state *prev_state; 01363 size_t save_size; 01364 01365 /* No saved state was passed, return a NULL--we hope the caller 01366 * is smart enough to notice 01367 */ 01368 if ( state == NULL ) 01369 return NULL; 01370 01371 if ( !new_state->valid ) 01372 { 01373 plwarn( "plbuf: Attempting to switch to an invalid saved state" ); 01374 return NULL; 01375 } 01376 01377 save_size = sizeof ( struct _state ) 01378 + 2 * sizeof ( struct _color_map ); 01379 01380 if ( ( prev_state = (struct _state *) malloc( save_size ) ) == NULL ) 01381 { 01382 plwarn( "plbuf: Unable to allocate memory to save state" ); 01383 return NULL; 01384 } 01385 01386 /* Set some housekeeping variables */ 01387 prev_state->size = save_size; 01388 prev_state->valid = 1; 01389 01390 /* Preserve the existing state */ 01391 #ifdef BUFFERED_FILE 01392 prev_state->plbufFile = pls->plbufFile; 01393 #else 01394 prev_state->plbuf_buffer = pls->plbuf_buffer; 01395 prev_state->plbuf_buffer_size = pls->plbuf_buffer_size; 01396 prev_state->plbuf_top = pls->plbuf_top; 01397 prev_state->plbuf_readpos = pls->plbuf_readpos; 01398 #endif 01399 /* cmap 0 */ 01400 prev_state->color_map[0].cmap = pls->cmap0; 01401 prev_state->color_map[0].icol = pls->icol0; 01402 prev_state->color_map[0].ncol = pls->ncol0; 01403 /* cmap 1 */ 01404 prev_state->color_map[1].cmap = pls->cmap1; 01405 prev_state->color_map[1].icol = pls->icol1; 01406 prev_state->color_map[1].ncol = pls->ncol1; 01407 01408 plbuf_restore( pls, new_state ); 01409 01410 return (void *) prev_state; 01411 } 01412 01413