PLplot  5.9.9
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plbuf.c
Go to the documentation of this file.
1 // $Id: plbuf.c 12008 2011-10-28 12:50:46Z andrewross $
2 //
3 // Handle plot buffer.
4 //
5 // Copyright (C) 1992 Maurice LeBrun
6 // Copyright (C) 2004 Alan W. Irwin
7 // Copyright (C) 2005 Thomas J. Duck
8 // Copyright (C) 2006 Jim Dishaw
9 //
10 // This file is part of PLplot.
11 //
12 // PLplot is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU Library General Public License as published
14 // by the Free Software Foundation; either version 2 of the License, or
15 // (at your option) any later version.
16 //
17 // PLplot is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Library General Public License for more details.
21 //
22 // You should have received a copy of the GNU Library General Public License
23 // along with PLplot; if not, write to the Free Software
24 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 //
26 
27 #define NEED_PLDEBUG
28 #include "plplotP.h"
29 #include "drivers.h"
30 #include "metadefs.h"
31 
32 #include <string.h>
33 
34 // Function prototypes
35 void * plbuf_save( PLStream *pls, void *state );
36 
37 static int rd_command( PLStream *pls, U_CHAR *p_c );
38 static void rd_data( PLStream *pls, void *buf, size_t buf_size );
39 static void wr_command( PLStream *pls, U_CHAR c );
40 static void wr_data( PLStream *pls, void *buf, size_t buf_size );
41 static void plbuf_control( PLStream *pls, U_CHAR c );
42 
43 static void rdbuf_init( PLStream *pls );
44 static void rdbuf_line( PLStream *pls );
45 static void rdbuf_polyline( PLStream *pls );
46 static void rdbuf_eop( PLStream *pls );
47 static void rdbuf_bop( PLStream *pls );
48 static void rdbuf_state( PLStream *pls );
49 static void rdbuf_esc( PLStream *pls );
50 
51 static void plbuf_fill( PLStream *pls );
52 static void rdbuf_fill( PLStream *pls );
53 static void plbuf_swin( PLStream *pls, PLWindow *plwin );
54 static void rdbuf_swin( PLStream *pls );
55 
56 //--------------------------------------------------------------------------
57 // plbuf_init()
58 //
59 // Initialize device.
60 // Actually just disables writes if plot buffer is already open (occurs
61 // when one stream is cloned, as in printing).
62 //--------------------------------------------------------------------------
63 
64 void
66 {
67  dbug_enter( "plbuf_init" );
68 
69  pls->plbuf_read = FALSE;
70 #ifdef BUFFERED_FILE
71  if ( pls->plbufFile != NULL )
72  pls->plbuf_write = FALSE;
73 #else
74  if ( pls->plbuf_buffer != NULL )
75  pls->plbuf_write = FALSE;
76 #endif
77 }
78 
79 //--------------------------------------------------------------------------
80 // plbuf_line()
81 //
82 // Draw a line in the current color from (x1,y1) to (x2,y2).
83 //--------------------------------------------------------------------------
84 
85 void
86 plbuf_line( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
87 {
88  short xpl[2], ypl[2];
89 
90  dbug_enter( "plbuf_line" );
91 
92  wr_command( pls, (U_CHAR) LINE );
93 
94  xpl[0] = x1a;
95  xpl[1] = x2a;
96  ypl[0] = y1a;
97  ypl[1] = y2a;
98 
99  wr_data( pls, xpl, sizeof ( short ) * 2 );
100  wr_data( pls, ypl, sizeof ( short ) * 2 );
101 }
102 
103 //--------------------------------------------------------------------------
104 // plbuf_polyline()
105 //
106 // Draw a polyline in the current color.
107 //--------------------------------------------------------------------------
108 
109 void
110 plbuf_polyline( PLStream *pls, short *xa, short *ya, PLINT npts )
111 {
112  dbug_enter( "plbuf_polyline" );
113 
114  wr_command( pls, (U_CHAR) POLYLINE );
115 
116  wr_data( pls, &npts, sizeof ( PLINT ) );
117 
118  wr_data( pls, xa, sizeof ( short ) * (size_t) npts );
119  wr_data( pls, ya, sizeof ( short ) * (size_t) npts );
120 }
121 
122 //--------------------------------------------------------------------------
123 // plbuf_eop()
124 //
125 // End of page.
126 //--------------------------------------------------------------------------
127 
128 void
130 {
131  dbug_enter( "plbuf_eop" );
132 }
133 
134 //--------------------------------------------------------------------------
135 // plbuf_bop()
136 //
137 // Set up for the next page.
138 // To avoid problems redisplaying partially filled pages, on each BOP the
139 // old file is thrown away and a new one is obtained. This way we can just
140 // read up to EOF to get everything on the current page.
141 //
142 // Also write state information to ensure the next page is correct.
143 //--------------------------------------------------------------------------
144 
145 void
147 {
148  dbug_enter( "plbuf_bop" );
149 
150  plbuf_tidy( pls );
151 
152 #ifdef BUFFERED_FILE
153  pls->plbufFile = pl_create_tempfile( NULL );
154  if ( pls->plbufFile == NULL )
155  plexit( "plbuf_bop: Error opening plot data storage file." );
156 #else
157  // Need a better place to initialize this value
158  pls->plbuf_buffer_grow = 128 * 1024;
159 
160  if ( pls->plbuf_buffer == NULL )
161  {
162  // We have not allocated a buffer, so do it now
163  if ( ( pls->plbuf_buffer = malloc( pls->plbuf_buffer_grow ) ) == NULL )
164  plexit( "plbuf_bop: Error allocating plot buffer." );
165 
167  pls->plbuf_top = 0;
168  pls->plbuf_readpos = 0;
169  }
170  else
171  {
172  // Buffer is allocated, move the top to the beginning
173  pls->plbuf_top = 0;
174  }
175 #endif
176 
177  wr_command( pls, (U_CHAR) BOP );
178  plbuf_state( pls, PLSTATE_COLOR0 );
179  plbuf_state( pls, PLSTATE_WIDTH );
180 }
181 
182 //--------------------------------------------------------------------------
183 // plbuf_tidy()
184 //
185 // Close graphics file
186 //--------------------------------------------------------------------------
187 
188 void
190 {
191  dbug_enter( "plbuf_tidy" );
192 
193 #ifdef BUFFERED_FILE
194  if ( pls->plbufFile == NULL )
195  return;
196 
197  fclose( pls->plbufFile )
198  pls->plbufFile = NULL;
199 #endif
200 }
201 
202 //--------------------------------------------------------------------------
203 // plbuf_state()
204 //
205 // Handle change in PLStream state (color, pen width, fill attribute, etc).
206 //--------------------------------------------------------------------------
207 
208 void
210 {
211  dbug_enter( "plbuf_state" );
212 
213  wr_command( pls, (U_CHAR) CHANGE_STATE );
214  wr_command( pls, (U_CHAR) op );
215 
216  switch ( op )
217  {
218  case PLSTATE_WIDTH:
219  wr_data( pls, &( pls->width ), sizeof ( pls->width ) );
220  break;
221 
222  case PLSTATE_COLOR0:
223  wr_data( pls, &( pls->icol0 ), sizeof ( pls->icol0 ) );
224  if ( pls->icol0 == PL_RGB_COLOR )
225  {
226  wr_data( pls, &( pls->curcolor.r ), sizeof ( pls->curcolor.r ) );
227  wr_data( pls, &( pls->curcolor.g ), sizeof ( pls->curcolor.g ) );
228  wr_data( pls, &( pls->curcolor.b ), sizeof ( pls->curcolor.b ) );
229  }
230  break;
231 
232  case PLSTATE_COLOR1:
233  wr_data( pls, &( pls->icol1 ), sizeof ( pls->icol1 ) );
234  break;
235 
236  case PLSTATE_FILL:
237  wr_data( pls, &( pls->patt ), sizeof ( pls->patt ) );
238  break;
239  }
240 }
241 
242 
243 //--------------------------------------------------------------------------
244 // plbuf_image()
245 //
246 // write image described in points pls->dev_x[], pls->dev_y[], pls->dev_z[].
247 // pls->nptsX, pls->nptsY.
248 //--------------------------------------------------------------------------
249 
250 static void
252 {
253  PLINT npts = pls->dev_nptsX * pls->dev_nptsY;
254 
255  dbug_enter( "plbuf_image" );
256 
257  wr_data( pls, &pls->dev_nptsX, sizeof ( PLINT ) );
258  wr_data( pls, &pls->dev_nptsY, sizeof ( PLINT ) );
259 
260  wr_data( pls, &img_dt->xmin, sizeof ( PLFLT ) );
261  wr_data( pls, &img_dt->ymin, sizeof ( PLFLT ) );
262  wr_data( pls, &img_dt->dx, sizeof ( PLFLT ) );
263  wr_data( pls, &img_dt->dy, sizeof ( PLFLT ) );
264 
265  wr_data( pls, &pls->dev_zmin, sizeof ( short ) );
266  wr_data( pls, &pls->dev_zmax, sizeof ( short ) );
267 
268  wr_data( pls, pls->dev_ix, sizeof ( short ) * (size_t) npts );
269  wr_data( pls, pls->dev_iy, sizeof ( short ) * (size_t) npts );
270  wr_data( pls, pls->dev_z, sizeof ( unsigned short ) * (size_t) ( ( pls->dev_nptsX - 1 ) * ( pls->dev_nptsY - 1 ) ) );
271 }
272 
273 //--------------------------------------------------------------------------
274 // plbuf_text()
275 //
276 // Handle text call.
277 //--------------------------------------------------------------------------
278 
279 static void
281 {
282  PLUNICODE fci;
283 
284  dbug_enter( "plbuf_text" );
285 
286  // Retrieve the font characterization integer
287  plgfci( &fci );
288 
289  // Write the text information
290 
291  wr_data( pls, &fci, sizeof ( PLUNICODE ) );
292 
293  wr_data( pls, &pls->chrht, sizeof ( PLFLT ) );
294  wr_data( pls, &pls->diorot, sizeof ( PLFLT ) );
295  wr_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
296  wr_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
297  wr_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
298  wr_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
299 
300  wr_data( pls, &text->base, sizeof ( PLINT ) );
301  wr_data( pls, &text->just, sizeof ( PLFLT ) );
302  wr_data( pls, text->xform, sizeof ( PLFLT ) * 4 );
303  wr_data( pls, &text->x, sizeof ( PLINT ) );
304  wr_data( pls, &text->y, sizeof ( PLINT ) );
305  wr_data( pls, &text->refx, sizeof ( PLINT ) );
306  wr_data( pls, &text->refy, sizeof ( PLINT ) );
307 
308  wr_data( pls, &text->unicode_array_len, sizeof ( PLINT ) );
309  if ( text->unicode_array_len )
310  wr_data( pls, text->unicode_array, sizeof ( PLUNICODE ) * text->unicode_array_len );
311 }
312 
313 //--------------------------------------------------------------------------
314 // plbuf_text_unicode()
315 //
316 // Handle text buffering for the new unicode pathway.
317 //--------------------------------------------------------------------------
318 
319 static void
321 {
322  PLUNICODE fci;
323 
324  dbug_enter( "plbuf_text" );
325 
326  // Retrieve the font characterization integer
327  plgfci( &fci );
328 
329  // Write the text information
330 
331  wr_data( pls, &fci, sizeof ( PLUNICODE ) );
332 
333  wr_data( pls, &pls->chrht, sizeof ( PLFLT ) );
334  wr_data( pls, &pls->diorot, sizeof ( PLFLT ) );
335  wr_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
336  wr_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
337  wr_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
338  wr_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
339 
340  wr_data( pls, &text->base, sizeof ( PLINT ) );
341  wr_data( pls, &text->just, sizeof ( PLFLT ) );
342  wr_data( pls, text->xform, sizeof ( PLFLT ) * 4 );
343  wr_data( pls, &text->x, sizeof ( PLINT ) );
344  wr_data( pls, &text->y, sizeof ( PLINT ) );
345  wr_data( pls, &text->refx, sizeof ( PLINT ) );
346  wr_data( pls, &text->refy, sizeof ( PLINT ) );
347 
348  wr_data( pls, &text->n_fci, sizeof ( PLUNICODE ) );
349  wr_data( pls, &text->n_char, sizeof ( PLUNICODE ) );
350  wr_data( pls, &text->n_ctrl_char, sizeof ( PLINT ) );
351 
352  wr_data( pls, &text->unicode_array_len, sizeof ( PLINT ) );
353 }
354 
355 
356 //--------------------------------------------------------------------------
357 // plbuf_esc()
358 //
359 // Escape function. Note that any data written must be in device
360 // independent form to maintain the transportability of the metafile.
361 //
362 // Functions:
363 //
364 // PLESC_FILL Fill polygon
365 // PLESC_SWIN Set plot window parameters
366 // PLESC_IMAGE Draw image
367 // PLESC_HAS_TEXT Draw PostScript text
368 // PLESC_CLEAR Clear Background
369 // PLESC_START_RASTERIZE
370 // PLESC_END_RASTERIZE Start and stop rasterization
371 //--------------------------------------------------------------------------
372 
373 void
374 plbuf_esc( PLStream *pls, PLINT op, void *ptr )
375 {
376  dbug_enter( "plbuf_esc" );
377 
378  wr_command( pls, (U_CHAR) ESCAPE );
379  wr_command( pls, (U_CHAR) op );
380 
381  switch ( op )
382  {
383  case PLESC_FILL:
384  plbuf_fill( pls );
385  break;
386  case PLESC_SWIN:
387  plbuf_swin( pls, (PLWindow *) ptr );
388  break;
389  case PLESC_IMAGE:
390  plbuf_image( pls, (IMG_DT *) ptr );
391  break;
392  case PLESC_HAS_TEXT:
393  if ( ptr != NULL ) // Check required by GCW driver, please don't remove
394  plbuf_text( pls, (EscText *) ptr );
395  break;
396  case PLESC_BEGIN_TEXT:
397  case PLESC_TEXT_CHAR:
398  case PLESC_CONTROL_CHAR:
399  case PLESC_END_TEXT:
400  plbuf_text_unicode( pls, (EscText *) ptr );
401  break;
402 #if 0
403  // These are a no-op. They just need an entry in the buffer.
404  case PLESC_CLEAR:
406  case PLESC_END_RASTERIZE:
407  break;
408 #endif
409  }
410 }
411 
412 //--------------------------------------------------------------------------
413 // plbuf_fill()
414 //
415 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
416 //--------------------------------------------------------------------------
417 
418 static void
420 {
421  dbug_enter( "plbuf_fill" );
422 
423  wr_data( pls, &pls->dev_npts, sizeof ( PLINT ) );
424  wr_data( pls, pls->dev_x, sizeof ( short ) * (size_t) pls->dev_npts );
425  wr_data( pls, pls->dev_y, sizeof ( short ) * (size_t) pls->dev_npts );
426 }
427 
428 //--------------------------------------------------------------------------
429 // plbuf_swin()
430 //
431 // Set up plot window parameters.
432 //--------------------------------------------------------------------------
433 
434 static void
436 {
437  wr_data( pls, &plwin->dxmi, sizeof ( PLFLT ) );
438  wr_data( pls, &plwin->dxma, sizeof ( PLFLT ) );
439  wr_data( pls, &plwin->dymi, sizeof ( PLFLT ) );
440  wr_data( pls, &plwin->dyma, sizeof ( PLFLT ) );
441 
442  wr_data( pls, &plwin->wxmi, sizeof ( PLFLT ) );
443  wr_data( pls, &plwin->wxma, sizeof ( PLFLT ) );
444  wr_data( pls, &plwin->wymi, sizeof ( PLFLT ) );
445  wr_data( pls, &plwin->wyma, sizeof ( PLFLT ) );
446 }
447 
448 //--------------------------------------------------------------------------
449 // Routines to read from & process the plot buffer.
450 //--------------------------------------------------------------------------
451 
452 //--------------------------------------------------------------------------
453 // rdbuf_init()
454 //
455 // Initialize device.
456 //--------------------------------------------------------------------------
457 
458 static void
460 {
461  dbug_enter( "rdbuf_init" );
462 }
463 
464 //--------------------------------------------------------------------------
465 // rdbuf_line()
466 //
467 // Draw a line in the current color from (x1,y1) to (x2,y2).
468 //--------------------------------------------------------------------------
469 
470 static void
472 {
473  short xpl[2], ypl[2];
474  PLINT npts = 2;
475 
476  dbug_enter( "rdbuf_line" );
477 
478  rd_data( pls, xpl, sizeof ( short ) * (size_t) npts );
479  rd_data( pls, ypl, sizeof ( short ) * (size_t) npts );
480 
481  plP_line( xpl, ypl );
482 }
483 
484 //--------------------------------------------------------------------------
485 // rdbuf_polyline()
486 //
487 // Draw a polyline in the current color.
488 //--------------------------------------------------------------------------
489 
490 static void
492 {
493  short _xpl[PL_MAXPOLY], _ypl[PL_MAXPOLY];
494  short *xpl, *ypl;
495  PLINT npts;
496 
497  dbug_enter( "rdbuf_polyline" );
498 
499  rd_data( pls, &npts, sizeof ( PLINT ) );
500 
501  if ( npts > PL_MAXPOLY )
502  {
503  xpl = (short *) malloc( (size_t) ( npts + 1 ) * sizeof ( short ) );
504  ypl = (short *) malloc( (size_t) ( npts + 1 ) * sizeof ( short ) );
505 
506  if ( ( xpl == NULL ) || ( ypl == NULL ) )
507  {
508  plexit( "rdbuf_polyline: Insufficient memory for large polyline" );
509  }
510  }
511  else
512  {
513  xpl = _xpl;
514  ypl = _ypl;
515  }
516 
517 
518  rd_data( pls, xpl, sizeof ( short ) * (size_t) npts );
519  rd_data( pls, ypl, sizeof ( short ) * (size_t) npts );
520 
521  plP_polyline( xpl, ypl, npts );
522 
523  if ( npts > PL_MAXPOLY )
524  {
525  free( xpl );
526  free( ypl );
527  }
528 }
529 
530 //--------------------------------------------------------------------------
531 // rdbuf_eop()
532 //
533 // End of page.
534 //--------------------------------------------------------------------------
535 
536 static void
538 {
539  dbug_enter( "rdbuf_eop" );
540 }
541 
542 //--------------------------------------------------------------------------
543 // rdbuf_bop()
544 //
545 // Set up for the next page.
546 //--------------------------------------------------------------------------
547 
548 static void
550 {
551  dbug_enter( "rdbuf_bop" );
552 
553  pls->nplwin = 0;
554 }
555 
556 //--------------------------------------------------------------------------
557 // rdbuf_state()
558 //
559 // Handle change in PLStream state (color, pen width, fill attribute, etc).
560 //--------------------------------------------------------------------------
561 
562 static void
564 {
565  U_CHAR op;
566 
567  dbug_enter( "rdbuf_state" );
568 
569  rd_data( pls, &op, sizeof ( U_CHAR ) );
570 
571  switch ( op )
572  {
573  case PLSTATE_WIDTH: {
574  U_CHAR width;
575 
576  rd_data( pls, &width, sizeof ( U_CHAR ) );
577  pls->width = width;
579 
580  break;
581  }
582 
583  case PLSTATE_COLOR0: {
584  short icol0;
585  U_CHAR r, g, b;
586  PLFLT a;
587 
588  rd_data( pls, &icol0, sizeof ( short ) );
589  if ( icol0 == PL_RGB_COLOR )
590  {
591  rd_data( pls, &r, sizeof ( U_CHAR ) );
592  rd_data( pls, &g, sizeof ( U_CHAR ) );
593  rd_data( pls, &b, sizeof ( U_CHAR ) );
594  a = 1.0;
595  }
596  else
597  {
598  if ( (int) icol0 >= pls->ncol0 )
599  {
600  char buffer[256];
601  snprintf( buffer, 256, "rdbuf_state: Invalid color map entry: %d", (int) icol0 );
602  plabort( buffer );
603  return;
604  }
605  r = pls->cmap0[icol0].r;
606  g = pls->cmap0[icol0].g;
607  b = pls->cmap0[icol0].b;
608  a = pls->cmap0[icol0].a;
609  }
610  pls->icol0 = icol0;
611  pls->curcolor.r = r;
612  pls->curcolor.g = g;
613  pls->curcolor.b = b;
614  pls->curcolor.a = a;
615 
617  break;
618  }
619 
620  case PLSTATE_COLOR1: {
621  short icol1;
622 
623  rd_data( pls, &icol1, sizeof ( short ) );
624 
625  pls->icol1 = icol1;
626  pls->curcolor.r = pls->cmap1[icol1].r;
627  pls->curcolor.g = pls->cmap1[icol1].g;
628  pls->curcolor.b = pls->cmap1[icol1].b;
629  pls->curcolor.a = pls->cmap1[icol1].a;
630 
632  break;
633  }
634 
635  case PLSTATE_FILL: {
636  signed char patt;
637 
638  rd_data( pls, &patt, sizeof ( signed char ) );
639 
640  pls->patt = patt;
642  break;
643  }
644  }
645 }
646 
647 //--------------------------------------------------------------------------
648 // rdbuf_esc()
649 //
650 // Escape function.
651 // Must fill data structure with whatever data that was written,
652 // then call escape function.
653 //
654 // Note: it is best to only call the escape function for op-codes that
655 // are known to be supported.
656 //
657 // Functions:
658 //
659 // PLESC_FILL Fill polygon
660 // PLESC_SWIN Set plot window parameters
661 // PLESC_IMAGE Draw image
662 // PLESC_HAS_TEXT Draw PostScript text
663 // PLESC_BEGIN_TEXT Commands for the alternative unicode text handling path
664 // PLESC_TEXT_CHAR
665 // PLESC_CONTROL_CHAR
666 // PLESC_END_TEXT
667 // PLESC_CLEAR Clear Background
668 //--------------------------------------------------------------------------
669 
670 static void
672 
673 static void
675 
676 static void
678 
679 static void
681 {
682  U_CHAR op;
683 
684  dbug_enter( "rdbuf_esc" );
685 
686  rd_data( pls, &op, sizeof ( U_CHAR ) );
687 
688  switch ( op )
689  {
690  case PLESC_FILL:
691  rdbuf_fill( pls );
692  break;
693  case PLESC_SWIN:
694  rdbuf_swin( pls );
695  break;
696  case PLESC_IMAGE:
697  rdbuf_image( pls );
698  break;
699  case PLESC_HAS_TEXT:
700  rdbuf_text( pls );
701  break;
702  case PLESC_BEGIN_TEXT:
703  case PLESC_TEXT_CHAR:
704  case PLESC_CONTROL_CHAR:
705  case PLESC_END_TEXT:
706  rdbuf_text_unicode( op, pls );
707  break;
708  case PLESC_CLEAR:
709  plP_esc( PLESC_CLEAR, NULL );
710  break;
713  break;
714  case PLESC_END_RASTERIZE:
715  plP_esc( PLESC_END_RASTERIZE, NULL );
716  break;
717  }
718 }
719 
720 //--------------------------------------------------------------------------
721 // rdbuf_fill()
722 //
723 // Fill polygon described by input points.
724 //--------------------------------------------------------------------------
725 
726 static void
728 {
729  short _xpl[PL_MAXPOLY], _ypl[PL_MAXPOLY];
730  short *xpl, *ypl;
731  PLINT npts;
732 
733  dbug_enter( "rdbuf_fill" );
734 
735  rd_data( pls, &npts, sizeof ( PLINT ) );
736 
737  if ( npts > PL_MAXPOLY )
738  {
739  xpl = (short *) malloc( (size_t) ( npts + 1 ) * sizeof ( short ) );
740  ypl = (short *) malloc( (size_t) ( npts + 1 ) * sizeof ( short ) );
741 
742  if ( ( xpl == NULL ) || ( ypl == NULL ) )
743  {
744  plexit( "rdbuf_polyline: Insufficient memory for large polyline" );
745  }
746  }
747  else
748  {
749  xpl = _xpl;
750  ypl = _ypl;
751  }
752 
753  rd_data( pls, xpl, sizeof ( short ) * (size_t) npts );
754  rd_data( pls, ypl, sizeof ( short ) * (size_t) npts );
755 
756  plP_fill( xpl, ypl, npts );
757 
758  if ( npts > PL_MAXPOLY )
759  {
760  free( xpl );
761  free( ypl );
762  }
763 }
764 
765 //--------------------------------------------------------------------------
766 // rdbuf_image()
767 //
768 // .
769 //--------------------------------------------------------------------------
770 
771 static void
773 {
774  short *dev_ix, *dev_iy = NULL;
775  unsigned short *dev_z, dev_zmin, dev_zmax;
776  PLINT nptsX, nptsY, npts;
777  PLFLT xmin, ymin, dx, dy;
778 
779  dbug_enter( "rdbuf_image" );
780 
781  rd_data( pls, &nptsX, sizeof ( PLINT ) );
782  rd_data( pls, &nptsY, sizeof ( PLINT ) );
783  npts = nptsX * nptsY;
784 
785  rd_data( pls, &xmin, sizeof ( PLFLT ) );
786  rd_data( pls, &ymin, sizeof ( PLFLT ) );
787  rd_data( pls, &dx, sizeof ( PLFLT ) );
788  rd_data( pls, &dy, sizeof ( PLFLT ) );
789 
790  rd_data( pls, &dev_zmin, sizeof ( short ) );
791  rd_data( pls, &dev_zmax, sizeof ( short ) );
792 
793  // NOTE: Even though for memory buffered version all the data is in memory,
794  // we still allocate and copy the data because I think that method works
795  // better in a multithreaded environment. I could be wrong.
796  //
797  if ( ( ( dev_ix = (short *) malloc( (size_t) npts * sizeof ( short ) ) ) == NULL ) ||
798  ( ( dev_iy = (short *) malloc( (size_t) npts * sizeof ( short ) ) ) == NULL ) ||
799  ( ( dev_z = (unsigned short *) malloc( (size_t) ( ( nptsX - 1 ) * ( nptsY - 1 ) ) * sizeof ( unsigned short ) ) ) == NULL ) )
800  plexit( "rdbuf_image: Insufficient memory" );
801 
802  rd_data( pls, dev_ix, sizeof ( short ) * (size_t) npts );
803  rd_data( pls, dev_iy, sizeof ( short ) * (size_t) npts );
804  rd_data( pls, dev_z, sizeof ( unsigned short ) * (size_t) ( ( nptsX - 1 ) * ( nptsY - 1 ) ) );
805 
806  //
807  // COMMENTED OUT by Hezekiah Carty
808  // Commented (hopefullly temporarily) until the dev_fastimg rendering
809  // path can be updated to support the new plimage internals. In the
810  // meantime this function is not actually used so the issue of how to
811  // update the code to support the new interface can be ignored.
812  //
813  //plP_image(dev_ix, dev_iy, dev_z, nptsX, nptsY, xmin, ymin, dx, dy, dev_zmin, dev_zmax);
814 
815  free( dev_ix );
816  free( dev_iy );
817  free( dev_z );
818 }
819 
820 //--------------------------------------------------------------------------
821 // rdbuf_swin()
822 //
823 // Set up plot window parameters.
824 //--------------------------------------------------------------------------
825 
826 static void
828 {
829  PLWindow plwin;
830 
831  rd_data( pls, &plwin.dxmi, sizeof ( PLFLT ) );
832  rd_data( pls, &plwin.dxma, sizeof ( PLFLT ) );
833  rd_data( pls, &plwin.dymi, sizeof ( PLFLT ) );
834  rd_data( pls, &plwin.dyma, sizeof ( PLFLT ) );
835 
836  rd_data( pls, &plwin.wxmi, sizeof ( PLFLT ) );
837  rd_data( pls, &plwin.wxma, sizeof ( PLFLT ) );
838  rd_data( pls, &plwin.wymi, sizeof ( PLFLT ) );
839  rd_data( pls, &plwin.wyma, sizeof ( PLFLT ) );
840 
841  plP_swin( &plwin );
842 }
843 
844 //--------------------------------------------------------------------------
845 // rdbuf_text()
846 //
847 // Draw PostScript text.
848 //--------------------------------------------------------------------------
849 
850 static void
852 {
853  PLUNICODE( fci );
854  EscText text;
855  PLFLT xform[4];
856  PLUNICODE* unicode;
857 
858  text.xform = xform;
859 
860 
861  // Read in the data
862 
863  rd_data( pls, &fci, sizeof ( PLUNICODE ) );
864 
865  rd_data( pls, &pls->chrht, sizeof ( PLFLT ) );
866  rd_data( pls, &pls->diorot, sizeof ( PLFLT ) );
867  rd_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
868  rd_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
869  rd_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
870  rd_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
871 
872  rd_data( pls, &text.base, sizeof ( PLINT ) );
873  rd_data( pls, &text.just, sizeof ( PLFLT ) );
874  rd_data( pls, text.xform, sizeof ( PLFLT ) * 4 );
875  rd_data( pls, &text.x, sizeof ( PLINT ) );
876  rd_data( pls, &text.y, sizeof ( PLINT ) );
877  rd_data( pls, &text.refx, sizeof ( PLINT ) );
878  rd_data( pls, &text.refy, sizeof ( PLINT ) );
879 
880  rd_data( pls, &text.unicode_array_len, sizeof ( PLINT ) );
881  if ( text.unicode_array_len )
882  {
883  if ( ( unicode = (PLUNICODE *) malloc( text.unicode_array_len * sizeof ( PLUNICODE ) ) )
884  == NULL )
885  plexit( "rdbuf_text: Insufficient memory" );
886 
887  rd_data( pls, unicode, sizeof ( PLUNICODE ) * text.unicode_array_len );
888  text.unicode_array = unicode;
889  }
890  else
891  text.unicode_array = NULL;
892 
893  // Make the call for unicode devices
894  if ( pls->dev_unicode )
895  {
896  plsfci( fci );
897  plP_esc( PLESC_HAS_TEXT, &text );
898  }
899 }
900 
901 //--------------------------------------------------------------------------
902 // rdbuf_text_unicode()
903 //
904 // Draw text for the new unicode handling pathway.
905 //--------------------------------------------------------------------------
906 
907 static void
909 {
910  PLUNICODE( fci );
911  EscText text;
912  PLFLT xform[4];
913 
914  text.xform = xform;
915 
916 
917  // Read in the data
918 
919  rd_data( pls, &fci, sizeof ( PLUNICODE ) );
920 
921  rd_data( pls, &pls->chrht, sizeof ( PLFLT ) );
922  rd_data( pls, &pls->diorot, sizeof ( PLFLT ) );
923  rd_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
924  rd_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
925  rd_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
926  rd_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
927 
928  rd_data( pls, &text.base, sizeof ( PLINT ) );
929  rd_data( pls, &text.just, sizeof ( PLFLT ) );
930  rd_data( pls, text.xform, sizeof ( PLFLT ) * 4 );
931  rd_data( pls, &text.x, sizeof ( PLINT ) );
932  rd_data( pls, &text.y, sizeof ( PLINT ) );
933  rd_data( pls, &text.refx, sizeof ( PLINT ) );
934  rd_data( pls, &text.refy, sizeof ( PLINT ) );
935 
936  rd_data( pls, &text.n_fci, sizeof ( PLUNICODE ) );
937  rd_data( pls, &text.n_char, sizeof ( PLUNICODE ) );
938  rd_data( pls, &text.n_ctrl_char, sizeof ( PLINT ) );
939 
940  rd_data( pls, &text.unicode_array_len, sizeof ( PLINT ) );
941 
942  if ( pls->dev_unicode )
943  {
944  plsfci( fci );
945  plP_esc( op, &text );
946  }
947 }
948 
949 //--------------------------------------------------------------------------
950 // plRemakePlot()
951 //
952 // Rebuilds plot from plot buffer, usually in response to a window
953 // resize or exposure event.
954 //--------------------------------------------------------------------------
955 
956 void
958 {
959  U_CHAR c;
960  int plbuf_status;
961  PLStream *save_pls;
962 
963  dbug_enter( "plRemakePlot" );
964 
965  // Change the status of the flags before checking for a buffer.
966  // Actually, more thought is needed if we want to support multithreaded
967  // code correctly, specifically the case where two threads are using
968  // the same plot stream (e.g. one thread is drawing the plot and another
969  // thread is processing window manager messages).
970  //
971  plbuf_status = pls->plbuf_write;
972  pls->plbuf_write = FALSE;
973  pls->plbuf_read = TRUE;
974 
975 #ifdef BUFFERED_FILE
976  if ( pls->plbufFile )
977  {
978  rewind( pls->plbufFile );
979 #else
980  if ( pls->plbuf_buffer )
981  {
982  pls->plbuf_readpos = 0;
983 #endif
984  // Need to change where plsc points to before processing the commands.
985  // If we have multiple plot streams, this will prevent the commands from
986  // going to the wrong plot stream.
987  //
988  save_pls = plsc;
989  plsc = pls;
990 
991  while ( rd_command( pls, &c ) )
992  {
993  plbuf_control( pls, c );
994  }
995 
996  plsc = save_pls;
997  }
998 
999  pls->plbuf_read = FALSE;
1000  pls->plbuf_write = plbuf_status;
1001 }
1002 
1003 //--------------------------------------------------------------------------
1004 // plbuf_control()
1005 //
1006 // Processes commands read from the plot buffer.
1007 //--------------------------------------------------------------------------
1008 
1009 static void
1011 {
1012  static U_CHAR c_old = 0;
1013 
1014  dbug_enter( "plbuf_control" );
1015 
1016  switch ( (int) c )
1017  {
1018  case INITIALIZE:
1019  rdbuf_init( pls );
1020  break;
1021 
1022  case EOP:
1023  rdbuf_eop( pls );
1024  break;
1025 
1026  case BOP:
1027  rdbuf_bop( pls );
1028  break;
1029 
1030  case CHANGE_STATE:
1031  rdbuf_state( pls );
1032  break;
1033 
1034  case LINE:
1035  rdbuf_line( pls );
1036  break;
1037 
1038  case POLYLINE:
1039  rdbuf_polyline( pls );
1040  break;
1041 
1042  case ESCAPE:
1043  rdbuf_esc( pls );
1044  break;
1045 
1046  default:
1047  pldebug( "plbuf_control", "Unrecognized command %d, previous %d\n", c, c_old );
1048  }
1049  c_old = c;
1050 }
1051 
1052 //--------------------------------------------------------------------------
1053 // rd_command()
1054 //
1055 // Read & return the next command
1056 //--------------------------------------------------------------------------
1057 
1058 static int
1060 {
1061  int count;
1062 
1063 #ifdef BUFFERED_FILE
1064  count = fread( p_c, sizeof ( U_CHAR ), 1, pls->plbufFile );
1065 #else
1066  if ( pls->plbuf_readpos < pls->plbuf_top )
1067  {
1068  *p_c = *(U_CHAR *) ( (U_CHAR *) pls->plbuf_buffer + pls->plbuf_readpos );
1069  pls->plbuf_readpos += sizeof ( U_CHAR );
1070  count = sizeof ( U_CHAR );
1071  }
1072  else
1073  {
1074  count = 0;
1075  }
1076 #endif
1077  return ( count );
1078 }
1079 
1080 //--------------------------------------------------------------------------
1081 // rd_data()
1082 //
1083 // Read the data associated with the command
1084 //--------------------------------------------------------------------------
1085 
1086 static void
1087 rd_data( PLStream *pls, void *buf, size_t buf_size )
1088 {
1089 #ifdef BUFFERED_FILE
1090  plio_fread( buf, buf_size, 1, pls->plbufFile );
1091 #else
1092 // If U_CHAR is not the same size as what memcpy() expects (typically 1 byte)
1093 // then this code will have problems. A better approach might be to use
1094 // uint8_t from <stdint.h> but I do not know how portable that approach is
1095 //
1096  memcpy( buf, (U_CHAR *) pls->plbuf_buffer + pls->plbuf_readpos, buf_size );
1097  pls->plbuf_readpos += buf_size;
1098 #endif
1099 }
1100 
1101 //--------------------------------------------------------------------------
1102 // wr_command()
1103 //
1104 // Write the next command
1105 //--------------------------------------------------------------------------
1106 
1107 static void
1109 {
1110 #ifdef BUFFERED_FILE
1111  plio_fwrite( &c1, sizeof ( U_CHAR ), 1, pls->plbufFile );
1112 #else
1113  if ( ( pls->plbuf_top + sizeof ( U_CHAR ) ) >= pls->plbuf_buffer_size )
1114  {
1115  // Not enough space, need to grow the buffer
1116  pls->plbuf_buffer_size += pls->plbuf_buffer_grow;
1117 
1118  if ( pls->verbose )
1119  printf( "Growing buffer to %d KB\n", (int) ( pls->plbuf_buffer_size / 1024 ) );
1120  if ( ( pls->plbuf_buffer = realloc( pls->plbuf_buffer, pls->plbuf_buffer_size ) ) == NULL )
1121  plexit( "plbuf wr_data: Plot buffer grow failed" );
1122  }
1123 
1124  *(U_CHAR *) ( (U_CHAR *) pls->plbuf_buffer + pls->plbuf_top ) = c;
1125  pls->plbuf_top += sizeof ( U_CHAR );
1126 #endif
1127 }
1128 
1129 //--------------------------------------------------------------------------
1130 // wr_data()
1131 //
1132 // Write the data associated with a command
1133 //--------------------------------------------------------------------------
1134 
1135 static void
1136 wr_data( PLStream *pls, void *buf, size_t buf_size )
1137 {
1138 #ifdef BUFFERED_FILE
1139  plio_fwrite( buf, buf_size, 1, pls->plbufFile );
1140 #else
1141  if ( ( pls->plbuf_top + buf_size ) >= pls->plbuf_buffer_size )
1142  {
1143  // Not enough space, need to grow the buffer
1144  // Must make sure the increase is enough for this data
1145  pls->plbuf_buffer_size += pls->plbuf_buffer_grow *
1146  ( ( pls->plbuf_top + buf_size - pls->plbuf_buffer_size ) /
1147  pls->plbuf_buffer_grow + 1 );
1148  while ( pls->plbuf_top + buf_size >= pls->plbuf_buffer_size )
1149  ;
1150 
1151  if ( ( pls->plbuf_buffer = realloc( pls->plbuf_buffer, pls->plbuf_buffer_size ) ) == NULL )
1152  plexit( "plbuf wr_data: Plot buffer grow failed" );
1153  }
1154 
1155 // If U_CHAR is not the same size as what memcpy() expects (typically 1 byte)
1156 // then this code will have problems. A better approach might be to use
1157 // uint8_t from <stdint.h> but I do not know how portable that approach is
1158 //
1159  memcpy( (U_CHAR *) pls->plbuf_buffer + pls->plbuf_top, buf, buf_size );
1160  pls->plbuf_top += buf_size;
1161 #endif
1162 }
1163 
1164 // plbuf_save(state)
1165 //
1166 // Saves the current state of the plot into a save buffer.
1167 // This code was originally in gcw.c and gcw-lib.c. The original
1168 // code used a temporary file for the plot buffer and memory
1169 // to perserve colormaps. That method does not offer a clean
1170 // break between using memory buffers and file buffers. This
1171 // function preserves the same functionality by returning a data
1172 // structure that saves the plot buffer and colormaps seperately.
1173 //
1174 // The caller passes an existing save buffer for reuse or NULL
1175 // to force the allocation of a new buffer. Since one malloc()
1176 // is used for everything, the entire save buffer can be freed
1177 // with one free() call.
1178 //
1179 //
1181 {
1185 };
1186 
1187 struct _state
1188 {
1189  size_t size; // Size of the save buffer
1190  int valid; // Flag to indicate a valid save state
1191 #ifdef BUFFERED_FILE
1192  FILE *plbufFile;
1193 #else
1196  size_t plbuf_top;
1198 #endif
1200 };
1201 
1202 void * plbuf_save( PLStream *pls, void *state )
1203 {
1204  size_t save_size;
1205  struct _state *plot_state = (struct _state *) state;
1206  PLINT i;
1207  U_CHAR *buf; // Assume that this is byte-sized
1208 
1209  if ( pls->plbuf_write )
1210  {
1211  pls->plbuf_write = FALSE;
1212  pls->plbuf_read = TRUE;
1213 
1214  // Determine the size of the buffer required to save everything. We
1215  // assume that there are only two colormaps, but have written the code
1216  // that more than two can be handled with minimal changes.
1217  //
1218  save_size = sizeof ( struct _state )
1219  + 2 * sizeof ( struct _color_map )
1220  + (size_t) ( pls->ncol0 ) * sizeof ( PLColor )
1221  + (size_t) ( pls->ncol1 ) * sizeof ( PLColor );
1222 
1223 #ifndef BUFFERED_FILE
1224  // Only copy as much of the plot buffer that is being used
1225  save_size += pls->plbuf_top;
1226 #endif
1227 
1228  // If a buffer exists, determine if we need to resize it
1229  if ( state != NULL )
1230  {
1231  // We have a save buffer, is it smaller than the current size requirement?
1232  if ( plot_state->size < save_size )
1233  {
1234  // Yes, reallocate a larger one
1235  if ( ( plot_state = (struct _state *) realloc( state, save_size ) ) == NULL )
1236  {
1237  // NOTE: If realloc fails, then plot_state ill be NULL.
1238  // This will leave the original buffer untouched, thus we
1239  // mark it as invalid and return it back to the caller.
1240  //
1241  plwarn( "plbuf: Unable to reallocate sufficient memory to save state" );
1242  plot_state->valid = 0;
1243 
1244  return state;
1245  }
1246  plot_state->size = save_size;
1247  }
1248  }
1249  else
1250  {
1251  // A buffer does not exist, so we need to allocate one
1252  if ( ( plot_state = (struct _state *) malloc( save_size ) ) == NULL )
1253  {
1254  plwarn( "plbuf: Unable to allocate sufficient memory to save state" );
1255 
1256  return NULL;
1257  }
1258  plot_state->size = save_size;
1259 
1260 #ifdef BUFFERED_FILE
1261  // Make sure the FILE pointer is NULL in order to preven bad things from happening...
1262  plot_state->plbufFile = NULL;
1263 #endif
1264  }
1265 
1266  // At this point we have an appropriately sized save buffer.
1267  // We need to invalidate the state of the save buffer, since it
1268  // will not be valid until after everything is copied. We use
1269  // this approach vice freeing the memory and returning a NULL pointer
1270  // in order to prevent allocating and freeing memory needlessly.
1271  //
1272  plot_state->valid = 0;
1273 
1274  // Point buf to the space after the struct _state
1275  buf = (U_CHAR *) ( plot_state + 1 );
1276 
1277 #ifdef BUFFERED_FILE
1278  // Remove the old tempfile, if it exists
1279  if ( plot_state->plbufFile != NULL )
1280  {
1281  fclose( plot_state->plbufFile );
1282  }
1283 
1284  // Copy the plot buffer to a tempfile
1285  if ( ( plot_state->plbufFile = pl_create_tempfile( NULL ) ) == NULL )
1286  {
1287  // Throw a warning since this might be a permissions problem
1288  // and we may not want to force an exit
1289  //
1290  plwarn( "plbuf: Unable to open temporary file to save state" );
1291  return (void *) plot_state;
1292  }
1293  else
1294  {
1295  U_CHAR tmp;
1296 
1297  rewind( pls->plbufFile );
1298  while ( count = fread( &tmp, sizeof ( U_CHAR ), 1, pls->plbufFile ) )
1299  {
1300  if ( fwrite( &tmp, sizeof ( U_CHAR ), 1, plot_state->plbufFile ) != count )
1301  {
1302  // Throw a warning since this might be a permissions problem
1303  // and we may not want to force an exit
1304  //
1305  plwarn( "plbuf: Unable to write to temporary file" );
1306  fclose( plot_state->plbufFile );
1307  plot_state->plbufFile = NULL;
1308  return (void *) plot_state;
1309  }
1310  }
1311  }
1312 #else
1313  // Again, note, that we only copy the portion of the plot buffer that is being used
1314  plot_state->plbuf_buffer_size = pls->plbuf_top;
1315  plot_state->plbuf_top = pls->plbuf_top;
1316  plot_state->plbuf_readpos = 0;
1317 
1318  // Create a pointer that points in the space we allocated after struct _state
1319  plot_state->plbuf_buffer = (void *) buf;
1320  buf += pls->plbuf_top;
1321 
1322  // Copy the plot buffer to our new buffer. Again, I must stress, that we only
1323  // are copying the portion of the plot buffer that is being used
1324  //
1325  if ( memcpy( plot_state->plbuf_buffer, pls->plbuf_buffer, pls->plbuf_top ) == NULL )
1326  {
1327  // This should never be NULL
1328  plwarn( "plbuf: Got a NULL in memcpy!" );
1329  return (void *) plot_state;
1330  }
1331 #endif
1332 
1333  pls->plbuf_write = TRUE;
1334  pls->plbuf_read = FALSE;
1335 
1336  // Save the colormaps. First create a pointer that points in the space we allocated
1337  // after the plot buffer
1338  plot_state->color_map = (struct _color_map *) buf;
1339  buf += sizeof ( struct _color_map ) * 2;
1340 
1341  // Then we need to make space for the colormaps themselves
1342  plot_state->color_map[0].cmap = (PLColor *) buf;
1343  buf += sizeof ( PLColor ) * (size_t) ( pls->ncol0 );
1344  plot_state->color_map[1].cmap = (PLColor *) buf;
1345  buf += sizeof ( PLColor ) * (size_t) ( pls->ncol1 );
1346 
1347  // Save cmap 0
1348  plot_state->color_map[0].icol = pls->icol0;
1349  plot_state->color_map[0].ncol = pls->ncol0;
1350  for ( i = 0; i < pls->ncol0; i++ )
1351  {
1352  pl_cpcolor( &( plot_state->color_map[0].cmap[i] ), &pls->cmap0[i] );
1353  }
1354 
1355  // Save cmap 1
1356  plot_state->color_map[1].icol = pls->icol1;
1357  plot_state->color_map[1].ncol = pls->ncol1;
1358  for ( i = 0; i < pls->ncol1; i++ )
1359  {
1360  pl_cpcolor( &( plot_state->color_map[1].cmap[i] ), &pls->cmap1[i] );
1361  }
1362 
1363  plot_state->valid = 1;
1364  return (void *) plot_state;
1365  }
1366 
1367  return NULL;
1368 }
1369 
1370 // plbuf_restore(PLStream *, state)
1371 //
1372 // Restores the passed state
1373 //
1374 void plbuf_restore( PLStream *pls, void *state )
1375 {
1376  struct _state *new_state = (struct _state *) state;
1377 
1378 #ifdef BUFFERED_FILE
1379  pls->plbufFile = new_state->save_file;
1380 #else
1381  pls->plbuf_buffer = new_state->plbuf_buffer;
1382  pls->plbuf_buffer_size = new_state->plbuf_buffer_size;
1383  pls->plbuf_top = new_state->plbuf_top;
1384  pls->plbuf_readpos = new_state->plbuf_readpos;
1385 #endif
1386  // cmap 0
1387  pls->cmap0 = new_state->color_map[0].cmap;
1388  pls->icol0 = new_state->color_map[0].icol;
1389  pls->ncol0 = new_state->color_map[0].ncol;
1390  // cmap 1
1391  pls->cmap1 = new_state->color_map[1].cmap;
1392  pls->icol1 = new_state->color_map[1].icol;
1393  pls->ncol1 = new_state->color_map[1].ncol;
1394 }
1395 
1396 // plbuf_switch(PLStream *, state)
1397 //
1398 // Makes the passed state the current one. Preserves the previous state
1399 // by returning a save buffer.
1400 //
1401 // NOTE: The current implementation can cause a memory leak under the
1402 // following scenario:
1403 // 1) plbuf_save() is called
1404 // 2) plbuf_switch() is called
1405 // 3) Commands are called which cause the plot buffer to grow
1406 // 4) plbuf_swtich() is called
1407 //
1408 void * plbuf_switch( PLStream *pls, void *state )
1409 {
1410  struct _state *new_state = (struct _state *) state;
1411  struct _state *prev_state;
1412  size_t save_size;
1413 
1414  // No saved state was passed, return a NULL--we hope the caller
1415  // is smart enough to notice
1416  //
1417  if ( state == NULL )
1418  return NULL;
1419 
1420  if ( !new_state->valid )
1421  {
1422  plwarn( "plbuf: Attempting to switch to an invalid saved state" );
1423  return NULL;
1424  }
1425 
1426  save_size = sizeof ( struct _state )
1427  + 2 * sizeof ( struct _color_map );
1428 
1429  if ( ( prev_state = (struct _state *) malloc( save_size ) ) == NULL )
1430  {
1431  plwarn( "plbuf: Unable to allocate memory to save state" );
1432  return NULL;
1433  }
1434 
1435  // Set some housekeeping variables
1436  prev_state->size = save_size;
1437  prev_state->valid = 1;
1438 
1439  // Preserve the existing state
1440 #ifdef BUFFERED_FILE
1441  prev_state->plbufFile = pls->plbufFile;
1442 #else
1443  prev_state->plbuf_buffer = pls->plbuf_buffer;
1444  prev_state->plbuf_buffer_size = pls->plbuf_buffer_size;
1445  prev_state->plbuf_top = pls->plbuf_top;
1446  prev_state->plbuf_readpos = pls->plbuf_readpos;
1447 #endif
1448  // cmap 0
1449  prev_state->color_map[0].cmap = pls->cmap0;
1450  prev_state->color_map[0].icol = pls->icol0;
1451  prev_state->color_map[0].ncol = pls->ncol0;
1452  // cmap 1
1453  prev_state->color_map[1].cmap = pls->cmap1;
1454  prev_state->color_map[1].icol = pls->icol1;
1455  prev_state->color_map[1].ncol = pls->ncol1;
1456 
1457  plbuf_restore( pls, new_state );
1458 
1459  return (void *) prev_state;
1460 }
1461 
1462 
unsigned short * dev_z
Definition: plstrm.h:593
static PLINT text
Definition: gcw.c:97
PLFLT dymi
Definition: plplot.h:372
static void wr_command(PLStream *pls, U_CHAR c)
Definition: plbuf.c:1108
Definition: plbuf.c:1187
void plP_esc(PLINT op, void *ptr)
Definition: plcore.c:270
static void wr_data(PLStream *pls, void *buf, size_t buf_size)
Definition: plbuf.c:1136
PLINT icol1
Definition: plstrm.h:545
#define PLESC_CONTROL_CHAR
Definition: plplot.h:240
PLFLT just
Definition: plplotP.h:658
void plbuf_state(PLStream *pls, PLINT op)
Definition: plbuf.c:209
void pl_cpcolor(PLColor *to, PLColor *from)
Definition: plcore.c:2619
static void rdbuf_text_unicode(PLINT op, PLStream *pls)
Definition: plbuf.c:908
unsigned char b
Definition: plplot.h:455
static void plbuf_image(PLStream *pls, IMG_DT *img_dt)
Definition: plbuf.c:251
size_t plbuf_top
Definition: plstrm.h:656
unsigned short dev_zmin
Definition: plstrm.h:594
PLFLT dxma
Definition: plplot.h:372
#define PLESC_FILL
Definition: plplot.h:219
#define PL_RGB_COLOR
Definition: plplotP.h:290
static void rdbuf_line(PLStream *pls)
Definition: plbuf.c:471
#define INITIALIZE
Definition: metadefs.h:55
PLFLT dxmi
Definition: plplot.h:372
PLUINT PLUNICODE
Definition: plplot.h:195
short * dev_iy
Definition: plstrm.h:592
void plbuf_restore(PLStream *pls, void *state)
Definition: plbuf.c:1374
PLINT icol
Definition: plbuf.c:1183
PLINT dev_npts
Definition: plstrm.h:586
FILE * pl_create_tempfile(char **fname)
Definition: plstdio.c:171
void plP_swin(PLWindow *plwin)
Definition: plcore.c:305
size_t plbuf_buffer_size
Definition: plbuf.c:1195
PLINT dev_unicode
Definition: plstrm.h:754
#define PLESC_END_TEXT
Definition: plplot.h:241
PLINT plbuf_write
Definition: plstrm.h:572
PLFLT diorot
Definition: plstrm.h:668
PLFLT a
Definition: plplot.h:456
void * plbuf_switch(PLStream *pls, void *state)
Definition: plbuf.c:1408
tuple xmin
Definition: Plframe.py:907
PLINT dev_nptsY
Definition: plstrm.h:591
#define PLSTATE_COLOR0
Definition: plplotP.h:330
static void plbuf_fill(PLStream *pls)
Definition: plbuf.c:419
void xform(PLFLT x, PLFLT y, PLFLT *tx, PLFLT *ty, PLPointer pltr_data)
void plbuf_eop(PLStream *PL_UNUSED(pls))
Definition: plbuf.c:129
void PLFLT PLINT PLINT PLFLT PLFLT PLFLT PLFLT PLINT PLINT PLINT PLFLT PLFLT PLINT PLFLT PLINT const PLINT const char *const PLINT const char *const const PLFLT const PLINT const PLINT const PLFLT * a
#define PLSTATE_COLOR1
Definition: plplotP.h:331
tuple ymin
Definition: Plframe.py:908
int valid
Definition: plbuf.c:1190
void plbuf_init(PLStream *pls)
Definition: plbuf.c:65
PLColor * cmap1
Definition: plstrm.h:551
void plbuf_esc(PLStream *pls, PLINT op, void *ptr)
Definition: plbuf.c:374
short * dev_x
Definition: plstrm.h:587
PLINT n_ctrl_char
Definition: plplotP.h:669
size_t size
Definition: plbuf.c:1189
#define PLESC_TEXT_CHAR
Definition: plplot.h:239
#define PLSTATE_WIDTH
Definition: plplotP.h:329
static void rdbuf_swin(PLStream *pls)
Definition: plbuf.c:827
int PLINT
Definition: plplot.h:175
PLFLT ymin
Definition: plplotP.h:1133
void plP_polyline(short *x, short *y, PLINT npts)
Definition: plcore.c:394
static void rdbuf_text(PLStream *pls)
Definition: plbuf.c:851
PLUNICODE n_fci
Definition: plplotP.h:667
unsigned short dev_zmax
Definition: plstrm.h:594
#define PLSTATE_FILL
Definition: plplotP.h:332
void plio_fwrite(void *buf, size_t size, size_t nmemb, FILE *stream)
Definition: plstdio.c:54
PLINT dev_nptsX
Definition: plstrm.h:591
PLINT refy
Definition: plplotP.h:663
PLINT ncol0
Definition: plstrm.h:545
unsigned char g
Definition: plplot.h:454
static void plbuf_text_unicode(PLStream *pls, EscText *text)
Definition: plbuf.c:320
int nplwin
Definition: plstrm.h:725
PLFLT wymi
Definition: plplot.h:373
PLINT clpymi
Definition: plstrm.h:711
void plbuf_polyline(PLStream *pls, short *xa, short *ya, PLINT npts)
Definition: plbuf.c:110
#define snprintf
Definition: plplotP.h:240
PLStream * pls[]
PLINT icol0
Definition: plstrm.h:545
static void rdbuf_esc(PLStream *pls)
Definition: plbuf.c:680
PLColor * cmap
Definition: plbuf.c:1182
static void rdbuf_eop(PLStream *pls)
#define dbug_enter(a)
Definition: tclMatrix.c:60
void plio_fread(void *buf, size_t size, size_t nmemb, FILE *stream)
Definition: plstdio.c:84
#define TRUE
Definition: plplotP.h:181
static void rdbuf_fill(PLStream *pls)
Definition: plbuf.c:727
#define ESCAPE
Definition: metadefs.h:65
void plbuf_tidy(PLStream *PL_UNUSED(pls))
Definition: plbuf.c:189
#define FALSE
Definition: plplotP.h:182
#define EOP
Definition: metadefs.h:59
static void rdbuf_bop(PLStream *pls)
Definition: plbuf.c:549
#define PLESC_END_RASTERIZE
Definition: plplot.h:243
gint count
Definition: gcw-lib.c:726
#define PLESC_CLEAR
Definition: plplot.h:228
PLINT verbose
Definition: plstrm.h:533
static PLINT * buffer
Definition: plfill.c:76
static void rdbuf_polyline(PLStream *pls)
Definition: plbuf.c:491
PLINT ncol
Definition: plbuf.c:1184
PLColor * cmap0
Definition: plstrm.h:550
size_t plbuf_buffer_grow
Definition: plstrm.h:653
PLFLT dyma
Definition: plplot.h:372
PLFLT wyma
Definition: plplot.h:373
static char buf[200]
Definition: tclAPI.c:819
PLINT clpxmi
Definition: plstrm.h:711
PLFLT wxmi
Definition: plplot.h:373
#define plgfci
Definition: plplot.h:629
PLFLT dx
Definition: plplotP.h:1133
#define PLESC_BEGIN_TEXT
Definition: plplot.h:238
#define LINE
Definition: metadefs.h:63
static void rdbuf_init(PLStream *pls)
void plbuf_line(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
Definition: plbuf.c:86
unsigned short unicode_array_len
Definition: plplotP.h:672
static void plbuf_text(PLStream *pls, EscText *text)
Definition: plbuf.c:280
short * dev_y
Definition: plstrm.h:587
void plabort(const char *errormsg)
Definition: plctrl.c:1877
void * plbuf_buffer
Definition: plbuf.c:1194
static void plbuf_swin(PLStream *pls, PLWindow *plwin)
Definition: plbuf.c:435
static void rdbuf_image(PLStream *pls)
Definition: plbuf.c:772
void plP_state(PLINT op)
Definition: plcore.c:253
PLINT refx
Definition: plplotP.h:662
void plP_fill(short *x, short *y, PLINT npts)
Definition: plcore.c:428
#define PLESC_SWIN
Definition: plplot.h:224
void * plbuf_save(PLStream *pls, void *state)
Definition: plbuf.c:1202
short * dev_ix
Definition: plstrm.h:592
#define PL_UNUSED(x)
Definition: plplot.h:130
void plRemakePlot(PLStream *pls)
Definition: plbuf.c:957
float PLFLT
Definition: plplot.h:159
#define PLESC_START_RASTERIZE
Definition: plplot.h:242
PLFLT chrht
Definition: plstrm.h:693
void plwarn(const char *errormsg)
Definition: plctrl.c:1846
PLINT plbuf_read
Definition: plstrm.h:572
size_t plbuf_top
Definition: plbuf.c:1196
void plP_line(short *x, short *y)
Definition: plcore.c:365
PLINT patt
Definition: plstrm.h:676
static void plbuf_control(PLStream *pls, U_CHAR c)
Definition: plbuf.c:1010
unsigned char r
Definition: plplot.h:453
#define PLESC_HAS_TEXT
Definition: plplot.h:230
PLFLT width
Definition: plstrm.h:557
void * plbuf_buffer
Definition: plstrm.h:655
PLFLT wxma
Definition: plplot.h:373
PLINT y
Definition: plplotP.h:661
void plbuf_bop(PLStream *pls)
Definition: plbuf.c:146
#define CHANGE_STATE
Definition: metadefs.h:70
#define PLESC_IMAGE
Definition: plplot.h:231
PLColor curcolor
Definition: plstrm.h:549
static int rd_command(PLStream *pls, U_CHAR *p_c)
Definition: plbuf.c:1059
PLINT clpxma
Definition: plstrm.h:711
#define POLYLINE
Definition: metadefs.h:67
dx
if { $zoomopts($this,1) == 0 } then {
Definition: Plframe.py:613
size_t plbuf_readpos
Definition: plstrm.h:657
PLINT ncol1
Definition: plstrm.h:545
size_t plbuf_readpos
Definition: plbuf.c:1197
PLINT x
Definition: plplotP.h:660
PLUNICODE n_char
Definition: plplotP.h:668
#define plsfci
Definition: plplot.h:710
PLUNICODE * unicode_array
Definition: plplotP.h:671
static void rdbuf_state(PLStream *pls)
Definition: plbuf.c:563
size_t plbuf_buffer_size
Definition: plstrm.h:654
#define BOP
Definition: metadefs.h:60
static void rd_data(PLStream *pls, void *buf, size_t buf_size)
Definition: plbuf.c:1087
PLFLT * xform
Definition: plplotP.h:659
#define U_CHAR
Definition: pdf.h:28
struct _color_map * color_map
Definition: plbuf.c:1199
#define PL_MAXPOLY
Definition: plplotP.h:288
PLFLT dy
Definition: plplotP.h:1133
PLINT base
Definition: plplotP.h:657
PLFLT xmin
Definition: plplotP.h:1133
PLINT clpyma
Definition: plstrm.h:711
void plexit(const char *errormsg)
Definition: plctrl.c:1941