PLplot 5.15.0
Loading...
Searching...
No Matches
plmeta.c
Go to the documentation of this file.
1// Copyright (C) 1991, 1992, 1993, 1994, 1995 Geoffrey Furnish
2// Copyright (C) 1991, 1992, 1993, 1994, 1995 Maurice LeBrun
3//
4// PLplot is free software; you can redistribute it and/or modify
5// it under the terms of the GNU Library General Public License as published
6// by the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// PLplot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Library General Public License for more details.
13//
14// You should have received a copy of the GNU Library General Public License
15// along with PLplot; if not, write to the Free Software
16// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17//
18//--------------------------------------------------------------------------
19//
20// This is a metafile writer for PLplot.
21//
22//
23#include "plDevs.h"
24
25//#define DEBUG
26
27#ifdef PLD_plmeta
28
29#define NEED_PLDEBUG
30#include "plplotP.h"
31#include "drivers.h"
32#include "metadefs.h"
33#include <string.h>
34
35// Device info
36PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_plmeta = "plmeta:PLplot Native Meta-File:0:plmeta:26:plm\n";
37
38
40
41void plD_init_plm( PLStream * );
42void plD_line_plm( PLStream *, short, short, short, short );
43void plD_polyline_plm( PLStream *, short *, short *, PLINT );
44void plD_eop_plm( PLStream * );
45void plD_bop_plm( PLStream * );
46void plD_tidy_plm( PLStream * );
47void plD_state_plm( PLStream *, PLINT );
48void plD_esc_plm( PLStream *, PLINT, void * );
49
50// Struct to hold device-specific info.
51
52// Used for constructing error messages
53
54#define BUFFER_LEN 256
55
56// Function prototypes
57
58static void WriteFileHeader( PLStream *pls );
59static void UpdatePrevPagehdr( PLStream *pls );
60static void WritePageInfo( PLStream *pls, FPOS_T pp_offset );
61static void UpdateIndex( PLStream *pls, FPOS_T cp_offset );
62static void plm_fill( PLStream *pls );
63static void plm_swin( PLStream *pls );
64static void plm_text( PLStream *pls, EscText *args );
65
66// A little function to help with debugging
67
68#ifdef DEBUG
69#define DEBUG_PRINT_LOCATION( a ) PrintLocation( pls, a )
70
71static void PrintLocation( PLStream *pls, char *tag )
72{
73 int isfile = ( pls->output_type == 0 );
74 if ( isfile )
75 {
76 FILE *file = pls->OutFile;
77 FPOS_T current_offset;
78
79 if ( pl_fgetpos( file, &current_offset ) )
80 plexit( "PrintLocation (plmeta.c): fgetpos call failed" );
81
82 pldebug( tag, "at offset %d in file %s\n",
83 (int) current_offset, pls->FileName );
84 }
85}
86#else
87#define DEBUG_PRINT_LOCATION( a )
88#endif
89
91{
92#ifndef ENABLE_DYNDRIVERS
93 pdt->pl_MenuStr = "PLplot Native Meta-File";
94 pdt->pl_DevName = "plmeta";
95#endif
97 pdt->pl_seq = 26;
98 pdt->pl_init = (plD_init_fp) plD_init_plm;
99 pdt->pl_line = (plD_line_fp) plD_line_plm;
100 pdt->pl_polyline = (plD_polyline_fp) plD_polyline_plm;
101 pdt->pl_eop = (plD_eop_fp) plD_eop_plm;
102 pdt->pl_bop = (plD_bop_fp) plD_bop_plm;
103 pdt->pl_tidy = (plD_tidy_fp) plD_tidy_plm;
104 pdt->pl_state = (plD_state_fp) plD_state_plm;
105 pdt->pl_esc = (plD_esc_fp) plD_esc_plm;
106}
107
108//--------------------------------------------------------------------------
109// plD_init_plm()
110//
111// Initialize device.
112//--------------------------------------------------------------------------
113
114void
115plD_init_plm( PLStream *pls )
116{
117 PLmDev *dev;
118
119 dbug_enter( "plD_init_plm" );
120
121 pls->color = 1; // Is a color device
122 pls->dev_fill0 = 1; // Handle solid fills
123 pls->dev_fill1 = 1; // Driver handles pattern fills
124
125 if ( strncmp( PLMETA_VERSION, "2005", 4 ) == 0 )
126 {
127 pls->dev_text = 0; // Disable text handling by the driver
128 pls->dev_unicode = 0; // Disable unicode support
129 pls->dev_hrshsym = 0;
130 }
131 else
132 {
133 // NOTE: This breaks compatibility with the 2005 version of
134 // the plot metafile format
135 // Unicode support is not needed because the plmeta driver
136 // stores the unprocessed string data that was passed to PLplot.
137 // However, we turn it on to force unicode representation of the
138 // plot symbols in plsym.c rather than vectorization.
139 pls->dev_text = 1; // Enable text handling by the driver
140 pls->dev_unicode = 1; // Enable unicode support
141 pls->dev_hrshsym = 0; // Disable vectorizaton of Hershey symbols
142 }
143
144// Initialize family file info
145
146 plFamInit( pls );
147
148// Prompt for a file name if not already set
149
150 plOpenFile( pls );
151 pls->pdfs = pdf_finit( pls->OutFile );
152
153// Allocate and initialize device-specific data
154
155 pls->dev = calloc( 1, (size_t) sizeof ( PLmDev ) );
156 if ( pls->dev == NULL )
157 plexit( "plD_init_plm: Out of memory." );
158
159 dev = (PLmDev *) pls->dev;
160
161 dev->xold = PL_UNDEFINED;
162 dev->yold = PL_UNDEFINED;
163
164 dev->xmin = 0;
165 dev->xmax = PIXELS_X - 1;
166 dev->ymin = 0;
167 dev->ymax = PIXELS_Y - 1;
168
169 dev->pxlx = (double) PIXELS_X / (double) LPAGE_X;
170 dev->pxly = (double) PIXELS_Y / (double) LPAGE_Y;
171
172 plP_setpxl( dev->pxlx, dev->pxly );
173 plP_setphy( dev->xmin, dev->xmax, dev->ymin, dev->ymax );
174
175// Write Metafile header.
176
177 WriteFileHeader( pls );
178
179// Write color map state info
180
181 plD_state_plm( pls, PLSTATE_CMAP0 );
182 plD_state_plm( pls, PLSTATE_CMAP1 );
183
184// Write initialization command.
185
186 DEBUG_PRINT_LOCATION( "before init" );
187 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) INITIALIZE ) );
188}
189
190//--------------------------------------------------------------------------
191// plD_line_plm()
192//
193// Draw a line in the current color from (x1,y1) to (x2,y2).
194//--------------------------------------------------------------------------
195
196void
197plD_line_plm( PLStream *pls, short x1, short y1, short x2, short y2 )
198{
199 PLmDev *dev = (PLmDev *) pls->dev;
200 U_SHORT xy[4];
201
202 // dbug_enter("plD_line_plm");
203
204 // Failsafe check
205
206#ifdef DEBUG
207 if ( x1 < dev->xmin || x1 > dev->xmax ||
208 x2 < dev->xmin || x2 > dev->xmax ||
209 y1 < dev->ymin || y1 > dev->ymax ||
210 y2 < dev->ymin || y2 > dev->ymax )
211 {
212 pldebug( "plD_line_plm",
213 "coordinates out of bounds -- \nActual: (%i,%i), (%i,%i) Bounds: (%i,%i,%i,%i)\n",
214 x1, y1, x2, y2, dev->xmin, dev->xmax, dev->ymin, dev->ymax );
215 }
216#endif
217
218// If continuation of previous line send the LINETO command, which uses
219// the previous (x,y) point as it's starting location. This results in a
220// storage reduction of not quite 50%, since the instruction length for
221// a LINETO is 5/9 of that for the LINE command, and given that most
222// graphics applications use this command heavily.
223//
224// Still not quite as efficient as tektronix format since we also send the
225// command each time (so shortest command is 25% larger), but a lot easier
226// to implement than the tek method.
227//
228 if ( x1 == dev->xold && y1 == dev->yold )
229 {
230 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) LINETO ) );
231
232 xy[0] = x2;
233 xy[1] = y2;
234 plm_wr( pdf_wr_2nbytes( pls->pdfs, xy, 2 ) );
235 }
236 else
237 {
238 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) LINE ) );
239
240 xy[0] = x1;
241 xy[1] = y1;
242 xy[2] = x2;
243 xy[3] = y2;
244 plm_wr( pdf_wr_2nbytes( pls->pdfs, xy, 4 ) );
245 }
246 dev->xold = x2;
247 dev->yold = y2;
248}
249
250//--------------------------------------------------------------------------
251// plD_polyline_plm()
252//
253// Draw a polyline in the current color.
254//--------------------------------------------------------------------------
255
256void
257plD_polyline_plm( PLStream *pls, short *xa, short *ya, PLINT npts )
258{
259 PLmDev *dev = (PLmDev *) pls->dev;
260
261 dbug_enter( "plD_polyline_plm" );
262
263 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) POLYLINE ) );
264
265 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) npts ) );
266
267 plm_wr( pdf_wr_2nbytes( pls->pdfs, (U_SHORT *) xa, npts ) );
268 plm_wr( pdf_wr_2nbytes( pls->pdfs, (U_SHORT *) ya, npts ) );
269
270 dev->xold = xa[npts - 1];
271 dev->yold = ya[npts - 1];
272}
273
274//--------------------------------------------------------------------------
275// plD_eop_plm()
276//
277// End of page.
278//--------------------------------------------------------------------------
279
280void
281plD_eop_plm( PLStream *pls )
282{
283 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) EOP ) );
284}
285
286//--------------------------------------------------------------------------
287// plD_bop_plm()
288//
289// Set up for the next page.
290//
291// Page header layout as follows:
292//
293// BOP (U_CHAR)
294// page number (U_SHORT)
295// prev page offset (U_LONG)
296// next page offset (U_LONG)
297//
298// Each call after the first is responsible for updating the table of
299// contents and the next page offset from the previous page.
300//--------------------------------------------------------------------------
301
302void
303plD_bop_plm( PLStream *pls )
304{
305 PLmDev *dev = (PLmDev *) pls->dev;
306 int isfile = ( pls->output_type == 0 );
307 FPOS_T pp_offset = dev->lp_offset;
308
309 dbug_enter( "plD_bop_plm" );
310
311 dev->xold = PL_UNDEFINED;
312 dev->yold = PL_UNDEFINED;
313
314// Update previous page header
315
316 if ( isfile )
317 UpdatePrevPagehdr( pls );
318
319// Start next family file if necessary.
320
321 pls->bytecnt = pls->pdfs->bp;
322 plGetFam( pls );
323
324// Update page counter
325
326 pls->page++;
327
328// Update table of contents info & write new page header.
329
330 WritePageInfo( pls, pp_offset );
331}
332
333//--------------------------------------------------------------------------
334// plD_tidy_plm()
335//
336// Close graphics file
337//--------------------------------------------------------------------------
338
339void
340plD_tidy_plm( PLStream *pls )
341{
342 dbug_enter( "plD_tidy_plm" );
343
344 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) CLOSE ) );
345 pdf_close( pls->pdfs );
346 free_mem( pls->dev );
347}
348
349//--------------------------------------------------------------------------
350// plD_state_plm()
351//
352// Handle change in PLStream state (color, pen width, fill attribute, etc).
353//--------------------------------------------------------------------------
354
355void
356plD_state_plm( PLStream *pls, PLINT op )
357{
358 int i;
359
360 dbug_enter( "plD_state_plm" );
361
363 plm_wr( pdf_wr_1byte( pls->pdfs, op ) );
364
365 switch ( op )
366 {
367 case PLSTATE_WIDTH:
368 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) ( pls->width ) ) );
369 break;
370
371 case PLSTATE_COLOR0:
372 plm_wr( pdf_wr_2bytes( pls->pdfs, (short) pls->icol0 ) );
373
374 if ( pls->icol0 == PL_RGB_COLOR )
375 {
376 plm_wr( pdf_wr_1byte( pls->pdfs, pls->curcolor.r ) );
377 plm_wr( pdf_wr_1byte( pls->pdfs, pls->curcolor.g ) );
378 plm_wr( pdf_wr_1byte( pls->pdfs, pls->curcolor.b ) );
379 }
380 break;
381
382 case PLSTATE_COLOR1:
383 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->icol1 ) );
384 break;
385
386 case PLSTATE_FILL:
387 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) pls->patt ) );
388 break;
389
390 case PLSTATE_CMAP0:
391 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->ncol0 ) );
392 for ( i = 0; i < pls->ncol0; i++ )
393 {
394 plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap0[i].r ) );
395 plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap0[i].g ) );
396 plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap0[i].b ) );
397 }
398 break;
399
400 case PLSTATE_CMAP1:
401 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->ncol1 ) );
402 for ( i = 0; i < pls->ncol1; i++ )
403 {
404 plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap1[i].r ) );
405 plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap1[i].g ) );
406 plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap1[i].b ) );
407 }
408 break;
409
410 case PLSTATE_CHR:
411 // save the chrdef and chrht parameters
412 if ( strncmp( PLMETA_VERSION, "2005", 4 ) != 0 )
413 {
414 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->chrdef ) );
415 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->chrht ) );
416 }
417 break;
418
419 case PLSTATE_SYM:
420 // save the symdef and symht parameters
421 if ( strncmp( PLMETA_VERSION, "2005", 4 ) != 0 )
422 {
423 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->symdef ) );
424 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->symht ) );
425 }
426 break;
427 }
428}
429
430//--------------------------------------------------------------------------
431// plD_esc_plm()
432//
433// Escape function. Note that any data written must be in device
434// independent form to maintain the transportability of the metafile.
435//
436// Functions:
437//
438// PLESC_FILL Fill polygon
439// PLESC_SWIN Set window parameters
440//
441//--------------------------------------------------------------------------
442
443void
444plD_esc_plm( PLStream *pls, PLINT op, void *ptr )
445{
446 dbug_enter( "plD_esc_plm" );
447
448 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) ESCAPE ) );
449 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) op ) );
450
451 switch ( op )
452 {
453 case PLESC_FILL:
454 plm_fill( pls );
455 break;
456
457 case PLESC_SWIN:
458 plm_swin( pls );
459 break;
460
461 // Unicode and non-Unicode text handling
462 case PLESC_HAS_TEXT:
463 plm_text( pls, (EscText *) ptr );
464 break;
465
466 // Alternate unicode text handling
467 case PLESC_BEGIN_TEXT:
468 case PLESC_TEXT_CHAR:
470 case PLESC_END_TEXT:
471 // NOP these for now until a decision is made
472 // which method should be implemented for metafiles
473 plwarn( "plmeta: Alternate Unicode text handling is not implemented" );
474 break;
475 }
476}
477
478//--------------------------------------------------------------------------
479// Private functions
480//--------------------------------------------------------------------------
481
482//--------------------------------------------------------------------------
483// plm_fill()
484//
485// Fill polygon described in points pls->dev_x[] and pls->dev_y[].
486//--------------------------------------------------------------------------
487
488static void
489plm_fill( PLStream *pls )
490{
491 PLmDev *dev = (PLmDev *) pls->dev;
492
493 dbug_enter( "plm_fill" );
494
495 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->dev_npts ) );
496
497 plm_wr( pdf_wr_2nbytes( pls->pdfs, (U_SHORT *) pls->dev_x, pls->dev_npts ) );
498 plm_wr( pdf_wr_2nbytes( pls->pdfs, (U_SHORT *) pls->dev_y, pls->dev_npts ) );
499
500 dev->xold = PL_UNDEFINED;
501 dev->yold = PL_UNDEFINED;
502}
503
504//--------------------------------------------------------------------------
505// plm_swin()
506//
507// Set window parameters.
508// Each parameter or group of parameters is tagged to make backward
509// compatibility easier.
510//--------------------------------------------------------------------------
511
512static void
513plm_swin( PLStream *pls )
514{
515 dbug_enter( "plm_swin" );
516}
517
518//--------------------------------------------------------------------------
519// plm_text()
520//
521// Stores the text into the metafile.
522//--------------------------------------------------------------------------
523
524static void
525plm_text( PLStream *pls, EscText *args )
526{
527 PLmDev *dev = (PLmDev *) pls->dev;
528 size_t len;
529
530 // Write state information needed to render the text
531
532 plm_wr( pdf_wr_ieeef( pls->pdfs, pls->chrht ) );
533 plm_wr( pdf_wr_ieeef( pls->pdfs, pls->diorot ) );
534 plm_wr( pdf_wr_2bytes( pls->pdfs, pls->clpxmi ) );
535 plm_wr( pdf_wr_2bytes( pls->pdfs, pls->clpxma ) );
536 plm_wr( pdf_wr_2bytes( pls->pdfs, pls->clpymi ) );
537 plm_wr( pdf_wr_2bytes( pls->pdfs, pls->clpyma ) );
538
539 // Write the text layout information
540
541 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->base ) );
542 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->just ) );
543
544 // Do we have a rotation shear that needs to be saved
545 if ( args->xform != NULL )
546 {
547 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->xform[0] ) );
548 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->xform[1] ) );
549 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->xform[2] ) );
550 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->xform[3] ) );
551 }
552 else
553 {
554 plwarn( "plmeta: transformation matrix undefined, using a guess" );
555 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) 1.0 ) );
556 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) 0.0 ) );
557 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) 0.0 ) );
558 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) 1.0 ) );
559 }
560
561 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->x ) );
562 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->y ) );
563 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->refx ) );
564 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->refy ) );
565 plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) args->font_face ) );
566 plm_wr( pdf_wr_4bytes( pls->pdfs, (int) args->text_type ) );
567
568 // Was a text string passed or a plot symbol?
569 if ( args->text_type == PL_STRING_TEXT )
570 {
571 // Text string
572 len = strlen( args->string );
573 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) len ) );
574 if ( len > 0 )
575 plm_wr( pdf_wr_string( pls->pdfs, args->string ) );
576 }
577 else
578 {
579 // Plot symbol
580 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->symbol ) );
581 }
582
583 // Clear the last known position
584 dev->xold = PL_UNDEFINED;
585 dev->yold = PL_UNDEFINED;
586}
587
588//--------------------------------------------------------------------------
589// Provide a consistent method for handling a failed fsetpos.
590//--------------------------------------------------------------------------
591static void
592handle_fsetpos_failed( const char *where, const char *which, FPOS_T position )
593{
594 char buffer[BUFFER_LEN];
595
596 // Format a standard message detailing the failure location
597 snprintf( buffer, BUFFER_LEN,
598 "%s: fsetpos to %s (%lu) failed",
599 where,
600 which,
601 (unsigned long) position );
602
603 plexit( buffer );
604}
605
606//--------------------------------------------------------------------------
607// WriteFileHeader()
608//
609// Writes Metafile header.
610//--------------------------------------------------------------------------
611
612static void
613WriteFileHeader( PLStream *pls )
614{
615 PLmDev *dev = (PLmDev *) pls->dev;
616 FILE *file = pls->OutFile;
617 int isfile = ( pls->output_type == 0 );
618
619 dbug_enter( "WriteFileHeader(PLStream *pls" );
620
623
624 // Write file index info. Right now only number of pages.
625 // The order here is critical
626
627 if ( isfile )
628 {
629 // Save the position of the pages field so that it can
630 // be updated when a new page is created
631 if ( pl_fgetpos( file, &dev->index_offset ) )
632 plexit( "WriteFileHeader: fgetpos call failed" );
633 }
634
635 plm_wr( pdf_wr_header( pls->pdfs, "pages" ) );
636 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) 0 ) );
637
638 // Write initialization info. Tag via strings to make backward
639 // compatibility with old metafiles as easy as possible.
640
641 plm_wr( pdf_wr_header( pls->pdfs, "xmin" ) );
642 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) dev->xmin ) );
643
644 plm_wr( pdf_wr_header( pls->pdfs, "xmax" ) );
645 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) dev->xmax ) );
646
647 plm_wr( pdf_wr_header( pls->pdfs, "ymin" ) );
648 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) dev->ymin ) );
649
650 plm_wr( pdf_wr_header( pls->pdfs, "ymax" ) );
651 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) dev->ymax ) );
652
653 plm_wr( pdf_wr_header( pls->pdfs, "pxlx" ) );
654 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) dev->pxlx ) );
655
656 plm_wr( pdf_wr_header( pls->pdfs, "pxly" ) );
657 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) dev->pxly ) );
658
659 // Geometry info, needed to properly transmit e.g. aspect ratio, via the
660 // length params. Not sure if the others are useful, but they're included
661 // for completeness.
662
663 plm_wr( pdf_wr_header( pls->pdfs, "xdpi" ) );
664 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->xdpi ) );
665
666 plm_wr( pdf_wr_header( pls->pdfs, "ydpi" ) );
667 plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->ydpi ) );
668
669 plm_wr( pdf_wr_header( pls->pdfs, "xlength" ) );
670 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->xlength ) );
671
672 plm_wr( pdf_wr_header( pls->pdfs, "ylength" ) );
673 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->ylength ) );
674
675 plm_wr( pdf_wr_header( pls->pdfs, "xoffset" ) );
676 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->xoffset ) );
677
678 plm_wr( pdf_wr_header( pls->pdfs, "yoffset" ) );
679 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->yoffset ) );
680
681 plm_wr( pdf_wr_header( pls->pdfs, "" ) );
682}
683
684//--------------------------------------------------------------------------
685// WritePageInfo()
686//
687// Update table of contents info & write new page header.
688//--------------------------------------------------------------------------
689
690static void
691WritePageInfo( PLStream *pls, FPOS_T pp_offset )
692{
693 PLmDev *dev = (PLmDev *) pls->dev;
694 FILE *file = pls->OutFile;
695 int isfile = ( pls->output_type == 0 );
696 U_CHAR c;
697 FPOS_T cp_offset = 0;
698
699 // Update table of contents.
700
701 if ( isfile )
702 {
703 // Get the position of this page in order to update the index
704 if ( pl_fgetpos( file, &cp_offset ) )
705 plexit( "WritePageInfo (plmeta.c): fgetpos call failed" );
706
707 UpdateIndex( pls, cp_offset );
708 }
709
710 // Write new page header
711
712 if ( dev->notfirst )
713 c = BOP;
714 else
715 {
716 c = BOP0;
717 dev->notfirst = 1;
718 }
719 plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
720 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->page ) );
721 plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) pp_offset ) );
722 plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) 0 ) );
723
724 // Update last page offset with current page value
725
726 dev->lp_offset = cp_offset;
727
728 // Write some page state information just to make things nice later on
729 // Eventually there will be more
730
731 plD_state_plm( pls, PLSTATE_COLOR0 );
732}
733
734//--------------------------------------------------------------------------
735// UpdatePrevPagehdr()
736//
737// Update previous page header.
738//--------------------------------------------------------------------------
739
740static void
741UpdatePrevPagehdr( PLStream *pls )
742{
743 PLmDev *dev = (PLmDev *) pls->dev;
744 FILE *file = pls->OutFile;
745 FPOS_T cp_offset = 0;
746
747 fflush( file );
748
749 // Determine where we are
750
751 if ( pl_fgetpos( file, &cp_offset ) )
752 plexit( "plD_bop_plm: fgetpos call failed" );
753
754 // Seek back to previous page header.
755
756 if ( dev->lp_offset > 0 )
757 {
758 FPOS_T fwbyte_offset = 0;
759
760 pldebug( "UpdatePrevPagehdr 1 (plmeta.c)",
761 "Location: %d, seeking to: %d\n",
762 (int) cp_offset, (int) dev->lp_offset );
763
764 // The forward byte offset is located exactly 7 bytes after the BOP
765 fwbyte_offset = dev->lp_offset + 7;
766 if ( pl_fsetpos( file, &fwbyte_offset ) )
767 {
768 handle_fsetpos_failed( "UpdatePrevPagehdr",
769 "fwbyte_offset", fwbyte_offset );
770 }
771
772 // DEBUG: verify current location
773
774#ifdef DEBUG
775 if ( pl_fgetpos( file, &fwbyte_offset ) )
776 plexit( "UpdatePrevPagehdr (plmeta.c): fgetpos call failed" );
777
778 pldebug( "UpdatePrevPagehdr 2 (plmeta.c)",
779 "Now at: %d, to write: %d\n",
780 (int) fwbyte_offset, (int) cp_offset );
781#endif
782
783 // Write forward byte offset into previous page header.
784
785 plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) cp_offset ) );
786 fflush( file );
787
788 // DEBUG: move back to before the write & read it to verify
789
790#ifdef DEBUG
791 if ( pl_fsetpos( file, &fwbyte_offset ) )
792 {
793 handle_fsetpos_failed( "UpdatePrevPagehdr",
794 "fwbyte_offset", fwbyte_offset );
795 }
796 {
797 U_LONG read_offset;
798 plm_rd( pdf_rd_4bytes( pls->pdfs, &read_offset ) );
799 pldebug( "UpdatePrevPagehdr 3 (plmeta.c)",
800 "Value read as: %d\n", read_offset );
801 }
802#endif
803
804 // Return to current page offset
805
806 if ( pl_fsetpos( file, &cp_offset ) )
807 {
808 handle_fsetpos_failed( "UpdatePrevPagehdr",
809 "cp_offset", cp_offset );
810 }
811 }
812}
813
814//--------------------------------------------------------------------------
815// UpdateIndex()
816//
817// Update file index.
818//--------------------------------------------------------------------------
819
820static void
821UpdateIndex( PLStream *pls, FPOS_T cp_offset )
822{
823 PLmDev *dev = (PLmDev *) pls->dev;
824 FILE *file = pls->OutFile;
825
826 // Update file index. Right now only number of pages.
827 // The ordering here is critical
828
829 if ( dev->index_offset > 0 )
830 {
831 pldebug( "UpdateIndex (plmeta.c)",
832 "Location: %d, seeking to: %d\n",
833 (int) cp_offset, (int) dev->lp_offset );
834
835 if ( pl_fsetpos( file, &dev->index_offset ) )
836 {
837 handle_fsetpos_failed( "UpdateIndex",
838 "index_offset", dev->index_offset );
839 }
840 plm_wr( pdf_wr_header( pls->pdfs, "pages" ) );
841 plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->page ) );
842
843 pldebug( "UpdateIndex (plmeta.c)",
844 "Location: %d, seeking to: %d\n",
845 (int) dev->lp_offset, (int) cp_offset );
846
847 if ( pl_fsetpos( file, &cp_offset ) )
848 {
849 handle_fsetpos_failed( "UpdateIndex",
850 "cp_offset", cp_offset );
851 }
852 }
853}
854
855#else
856int
858{
859 return 0;
860}
861
862#endif // PLD_plmeta
@ plDevType_FileOriented
Definition disptab.h:13
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
Definition disptab.h:68
void(* plD_tidy_fp)(struct PLStream_struct *)
Definition disptab.h:72
void(* plD_bop_fp)(struct PLStream_struct *)
Definition disptab.h:71
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
Definition disptab.h:73
void(* plD_eop_fp)(struct PLStream_struct *)
Definition disptab.h:70
void(* plD_init_fp)(struct PLStream_struct *)
Definition disptab.h:67
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
Definition disptab.h:74
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
Definition disptab.h:69
PLDLLIMPEXP_DRIVER void plD_dispatch_init_plm(PLDispatchTable *pdt)
#define CLOSE
Definition metadefs.h:54
#define LINETO
Definition metadefs.h:62
#define plm_wr(code)
Definition metadefs.h:38
#define PLMETA_HEADER
Definition metadefs.h:16
#define INITIALIZE
Definition metadefs.h:53
#define EOP
Definition metadefs.h:57
#define BOP0
Definition metadefs.h:69
#define BOP
Definition metadefs.h:58
#define PLMETA_VERSION
Definition metadefs.h:17
#define plm_rd(code)
Definition metadefs.h:41
#define CHANGE_STATE
Definition metadefs.h:68
#define POLYLINE
Definition metadefs.h:65
#define LINE
Definition metadefs.h:61
#define ESCAPE
Definition metadefs.h:63
#define U_LONG
Definition pdf.h:38
#define U_SHORT
Definition pdf.h:30
#define U_CHAR
Definition pdf.h:26
int pdf_rd_4bytes(PDFstrm *pdfs, U_LONG *ps)
Definition pdfutils.c:832
int pdf_wr_4bytes(PDFstrm *pdfs, U_LONG s)
Definition pdfutils.c:804
int pdf_wr_ieeef(PDFstrm *pdfs, float f)
Definition pdfutils.c:916
int pdf_wr_1byte(PDFstrm *pdfs, U_CHAR s)
Definition pdfutils.c:636
int pdf_wr_2bytes(PDFstrm *pdfs, U_SHORT s)
Definition pdfutils.c:684
PDFstrm * pdf_finit(FILE *file)
Definition pdfutils.c:204
int pdf_wr_header(PDFstrm *pdfs, PLCHAR_VECTOR header)
Definition pdfutils.c:509
int pdf_wr_2nbytes(PDFstrm *pdfs, U_SHORT *s, PLINT n)
Definition pdfutils.c:741
int pdf_close(PDFstrm *pdfs)
Definition pdfutils.c:238
int pdf_wr_string(PDFstrm *pdfs, PLCHAR_VECTOR string)
Definition pdfutils.c:574
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
Definition plcore.c:4238
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
Definition plcore.c:4249
static PLStream * pls[PL_NSTREAMS]
Definition plcore.h:88
void plFamInit(PLStream *pls)
Definition plctrl.c:2751
void plwarn(PLCHAR_VECTOR errormsg)
Definition plctrl.c:1863
void plOpenFile(PLStream *pls)
Definition plctrl.c:2571
void plexit(PLCHAR_VECTOR errormsg)
Definition plctrl.c:1958
void plGetFam(PLStream *pls)
Definition plctrl.c:2780
#define PLDLLIMPEXP_DRIVER
Definition pldll.h:81
static PLINT * buffer
Definition plfill.c:74
int pldummy_plmeta()
Definition plmeta.c:857
#define pl_fgetpos(a, b)
Definition plplotP.h:143
#define PLSTATE_FILL
Definition plplotP.h:365
#define pl_fsetpos(a, b)
Definition plplotP.h:142
#define PLSTATE_CHR
Definition plplotP.h:368
#define LPAGE_X
Definition plplotP.h:308
#define PIXELS_X
Definition plplotP.h:304
#define PLSTATE_SYM
Definition plplotP.h:369
#define PLSTATE_WIDTH
Definition plplotP.h:362
#define FPOS_T
Definition plplotP.h:141
#define PLSTATE_CMAP0
Definition plplotP.h:366
#define PLSTATE_COLOR1
Definition plplotP.h:364
#define PL_UNDEFINED
Definition plplotP.h:219
#define LPAGE_Y
Definition plplotP.h:309
#define PLSTATE_CMAP1
Definition plplotP.h:367
#define PL_RGB_COLOR
Definition plplotP.h:285
#define PLSTATE_COLOR0
Definition plplotP.h:363
#define free_mem(a)
Definition plplotP.h:182
#define PIXELS_Y
Definition plplotP.h:305
#define PLESC_HAS_TEXT
Definition plplot.h:290
#define PLESC_CONTROL_CHAR
Definition plplot.h:300
#define PLESC_END_TEXT
Definition plplot.h:301
#define PLESC_TEXT_CHAR
Definition plplot.h:299
#define PLESC_FILL
Definition plplot.h:279
#define PLESC_SWIN
Definition plplot.h:284
#define PLESC_BEGIN_TEXT
Definition plplot.h:298
int PLINT
Definition plplot.h:181
plD_eop_fp pl_eop
Definition disptab.h:86
const char * pl_DevName
Definition disptab.h:80
plD_esc_fp pl_esc
Definition disptab.h:90
plD_polyline_fp pl_polyline
Definition disptab.h:85
plD_state_fp pl_state
Definition disptab.h:89
plD_tidy_fp pl_tidy
Definition disptab.h:88
plD_line_fp pl_line
Definition disptab.h:84
plD_init_fp pl_init
Definition disptab.h:83
plD_bop_fp pl_bop
Definition disptab.h:87
const char * pl_MenuStr
Definition disptab.h:79
FPOS_T index_offset
Definition metadefs.h:94
FPOS_T lp_offset
Definition metadefs.h:95
PLINT ymax
Definition metadefs.h:92
int notfirst
Definition metadefs.h:97
PLINT ymin
Definition metadefs.h:92
PLINT yold
Definition metadefs.h:89
PLFLT pxlx
Definition metadefs.h:88
PLINT xmin
Definition metadefs.h:91
PLINT xold
Definition metadefs.h:89
PLFLT pxly
Definition metadefs.h:88
PLINT xmax
Definition metadefs.h:91
#define dbug_enter(a)
Definition tclMatrix.c:59