PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plmeta.c
Go to the documentation of this file.
1 // $Id: plmeta.c 12081 2011-12-01 11:52:28Z andrewross $
2 //
3 // Copyright (C) 1991, 1992, 1993, 1994, 1995 Geoffrey Furnish
4 // Copyright (C) 1991, 1992, 1993, 1994, 1995 Maurice LeBrun
5 //
6 // PLplot is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU Library General Public License as published
8 // by the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // PLplot is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Library General Public License for more details.
15 //
16 // You should have received a copy of the GNU Library General Public License
17 // along with PLplot; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 //--------------------------------------------------------------------------
21 //
22 // This is a metafile writer for PLplot.
23 //
24 //
25 #include "plDevs.h"
26 
27 //#define DEBUG
28 
29 #ifdef PLD_plmeta
30 
31 #define NEED_PLDEBUG
32 #include "plplotP.h"
33 #include "drivers.h"
34 #include "metadefs.h"
35 #include <string.h>
36 
37 // Device info
38 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_plmeta = "plmeta:PLplot Native Meta-File:0:plmeta:26:plm\n";
39 
40 
42 
43 void plD_init_plm( PLStream * );
44 void plD_line_plm( PLStream *, short, short, short, short );
45 void plD_polyline_plm( PLStream *, short *, short *, PLINT );
46 void plD_eop_plm( PLStream * );
47 void plD_bop_plm( PLStream * );
48 void plD_tidy_plm( PLStream * );
49 void plD_state_plm( PLStream *, PLINT );
50 void plD_esc_plm( PLStream *, PLINT, void * );
51 
52 // Struct to hold device-specific info.
53 
54 typedef struct
55 {
56  PLFLT pxlx, pxly;
57  PLINT xold, yold;
58 
59  PLINT xmin, xmax, xlen;
60  PLINT ymin, ymax, ylen;
61 
62  FPOS_T lp_offset, index_offset;
63 
64  int notfirst;
65 } PLmDev;
66 
67 // Used for constructing error messages
68 
69 #define BUFFER_LEN 256
70 static char buffer[BUFFER_LEN];
71 
72 // Function prototypes
73 
74 static void WriteFileHeader( PLStream *pls );
75 static void UpdatePrevPagehdr( PLStream *pls );
76 static void WritePageInfo( PLStream *pls, FPOS_T pp_offset );
77 static void UpdateIndex( PLStream *pls, FPOS_T cp_offset );
78 static void plm_fill( PLStream *pls );
79 static void plm_swin( PLStream *pls );
80 
81 // A little function to help with debugging
82 
83 #ifdef DEBUG
84 #define DEBUG_PRINT_LOCATION( a ) PrintLocation( pls, a )
85 
86 static void PrintLocation( PLStream *pls, char *tag )
87 {
88  int isfile = ( pls->output_type == 0 );
89  if ( isfile )
90  {
91  FILE *file = pls->OutFile;
92  FPOS_T current_offset;
93 
94  if ( pl_fgetpos( file, &current_offset ) )
95  plexit( "PrintLocation (plmeta.c): fgetpos call failed" );
96 
97  pldebug( tag, "at offset %d in file %s\n",
98  (int) current_offset, pls->FileName );
99  }
100 }
101 #else
102 #define DEBUG_PRINT_LOCATION( a )
103 #endif
104 
106 {
107 #ifndef ENABLE_DYNDRIVERS
108  pdt->pl_MenuStr = "PLplot Native Meta-File";
109  pdt->pl_DevName = "plmeta";
110 #endif
112  pdt->pl_seq = 26;
113  pdt->pl_init = (plD_init_fp) plD_init_plm;
114  pdt->pl_line = (plD_line_fp) plD_line_plm;
115  pdt->pl_polyline = (plD_polyline_fp) plD_polyline_plm;
116  pdt->pl_eop = (plD_eop_fp) plD_eop_plm;
117  pdt->pl_bop = (plD_bop_fp) plD_bop_plm;
118  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_plm;
119  pdt->pl_state = (plD_state_fp) plD_state_plm;
120  pdt->pl_esc = (plD_esc_fp) plD_esc_plm;
121 }
122 
123 //--------------------------------------------------------------------------
124 // plD_init_plm()
125 //
126 // Initialize device.
127 //--------------------------------------------------------------------------
128 
129 void
130 plD_init_plm( PLStream *pls )
131 {
132  PLmDev *dev;
133  U_CHAR c = (U_CHAR) INITIALIZE;
134 
135  dbug_enter( "plD_init_plm" );
136 
137  pls->color = 1; // Is a color device
138  pls->dev_fill0 = 1; // Handle solid fills
139  pls->dev_fill1 = 1; // Driver handles pattern fills
140 
141 // Initialize family file info
142 
143  plFamInit( pls );
144 
145 // Prompt for a file name if not already set
146 
147  plOpenFile( pls );
148  pls->pdfs = pdf_finit( pls->OutFile );
149 
150 // Allocate and initialize device-specific data
151 
152  pls->dev = calloc( 1, (size_t) sizeof ( PLmDev ) );
153  if ( pls->dev == NULL )
154  plexit( "plD_init_plm: Out of memory." );
155 
156  dev = (PLmDev *) pls->dev;
157 
158  dev->xold = PL_UNDEFINED;
159  dev->yold = PL_UNDEFINED;
160 
161  dev->xmin = 0;
162  dev->xmax = PIXELS_X - 1;
163  dev->ymin = 0;
164  dev->ymax = PIXELS_Y - 1;
165 
166  dev->pxlx = (double) PIXELS_X / (double) LPAGE_X;
167  dev->pxly = (double) PIXELS_Y / (double) LPAGE_Y;
168 
169  plP_setpxl( dev->pxlx, dev->pxly );
170  plP_setphy( dev->xmin, dev->xmax, dev->ymin, dev->ymax );
171 
172 // Write Metafile header.
173 
174  WriteFileHeader( pls );
175 
176 // Write color map state info
177 
178  plD_state_plm( pls, PLSTATE_CMAP0 );
179  plD_state_plm( pls, PLSTATE_CMAP1 );
180 
181 // Write initialization command.
182 
183  DEBUG_PRINT_LOCATION( "before init" );
184  plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
185 }
186 
187 //--------------------------------------------------------------------------
188 // plD_line_plm()
189 //
190 // Draw a line in the current color from (x1,y1) to (x2,y2).
191 //--------------------------------------------------------------------------
192 
193 void
194 plD_line_plm( PLStream *pls, short x1, short y1, short x2, short y2 )
195 {
196  PLmDev *dev = (PLmDev *) pls->dev;
197  U_CHAR c;
198  U_SHORT xy[4];
199 
200  // dbug_enter("plD_line_plm");
201 
202  // Failsafe check
203 
204 #ifdef DEBUG
205  if ( x1 < dev->xmin || x1 > dev->xmax ||
206  x2 < dev->xmin || x2 > dev->xmax ||
207  y1 < dev->ymin || y1 > dev->ymax ||
208  y2 < dev->ymin || y2 > dev->ymax )
209  {
210  pldebug( "plD_line_plm",
211  "coordinates out of bounds -- \nActual: (%i,%i), (%i,%i) Bounds: (%i,%i,%i,%i)\n",
212  x1, y1, x2, y2, dev->xmin, dev->xmax, dev->ymin, dev->ymax );
213  }
214 #endif
215 
216 // If continuation of previous line send the LINETO command, which uses
217 // the previous (x,y) point as it's starting location. This results in a
218 // storage reduction of not quite 50%, since the instruction length for
219 // a LINETO is 5/9 of that for the LINE command, and given that most
220 // graphics applications use this command heavily.
221 //
222 // Still not quite as efficient as tektronix format since we also send the
223 // command each time (so shortest command is 25% larger), but a lot easier
224 // to implement than the tek method.
225 //
226  if ( x1 == dev->xold && y1 == dev->yold )
227  {
228  c = (U_CHAR) LINETO;
229  plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
230 
231  xy[0] = x2;
232  xy[1] = y2;
233  plm_wr( pdf_wr_2nbytes( pls->pdfs, xy, 2 ) );
234  }
235  else
236  {
237  c = (U_CHAR) LINE;
238  plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
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 
256 void
257 plD_polyline_plm( PLStream *pls, short *xa, short *ya, PLINT npts )
258 {
259  PLmDev *dev = (PLmDev *) pls->dev;
260  U_CHAR c = (U_CHAR) POLYLINE;
261 
262  dbug_enter( "plD_polyline_plm" );
263 
264  plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
265 
266  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) npts ) );
267 
268  plm_wr( pdf_wr_2nbytes( pls->pdfs, (U_SHORT *) xa, npts ) );
269  plm_wr( pdf_wr_2nbytes( pls->pdfs, (U_SHORT *) ya, npts ) );
270 
271  dev->xold = xa[npts - 1];
272  dev->yold = ya[npts - 1];
273 }
274 
275 //--------------------------------------------------------------------------
276 // plD_eop_plm()
277 //
278 // End of page.
279 //--------------------------------------------------------------------------
280 
281 void
282 plD_eop_plm( PLStream *pls )
283 {
284  U_CHAR c = (U_CHAR) EOP;
285 
286  plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
287 }
288 
289 //--------------------------------------------------------------------------
290 // plD_bop_plm()
291 //
292 // Set up for the next page.
293 //
294 // Page header layout as follows:
295 //
296 // BOP (U_CHAR)
297 // page number (U_SHORT)
298 // prev page offset (U_LONG)
299 // next page offset (U_LONG)
300 //
301 // Each call after the first is responsible for updating the table of
302 // contents and the next page offset from the previous page.
303 //--------------------------------------------------------------------------
304 
305 void
306 plD_bop_plm( PLStream *pls )
307 {
308  PLmDev *dev = (PLmDev *) pls->dev;
309  int isfile = ( pls->output_type == 0 );
310  FPOS_T pp_offset = dev->lp_offset;;
311 
312  dbug_enter( "plD_bop_plm" );
313 
314  dev->xold = PL_UNDEFINED;
315  dev->yold = PL_UNDEFINED;
316 
317 // Update previous page header
318 
319  if ( isfile )
320  UpdatePrevPagehdr( pls );
321 
322 // Start next family file if necessary.
323 
324  pls->bytecnt = pls->pdfs->bp;
325  plGetFam( pls );
326 
327 // Update page counter
328 
329  pls->page++;
330 
331 // Update table of contents info & write new page header.
332 
333  WritePageInfo( pls, pp_offset );
334 }
335 
336 //--------------------------------------------------------------------------
337 // WritePageInfo()
338 //
339 // Update table of contents info & write new page header.
340 //--------------------------------------------------------------------------
341 
342 static void
343 WritePageInfo( PLStream *pls, FPOS_T pp_offset )
344 {
345  PLmDev *dev = (PLmDev *) pls->dev;
346  FILE *file = pls->OutFile;
347  int isfile = ( pls->output_type == 0 );
348  U_CHAR c;
349  FPOS_T cp_offset = 0;
350 
351 // Update table of contents.
352 
353  if ( isfile )
354  {
355  if ( pl_fgetpos( file, &cp_offset ) )
356  plexit( "WritePageInfo (plmeta.c): fgetpos call failed" );
357 
358  UpdateIndex( pls, cp_offset );
359  }
360 
361 // Write new page header
362 
363  if ( dev->notfirst )
364  c = BOP;
365  else
366  {
367  c = BOP0;
368  dev->notfirst = 1;
369  }
370  plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
371  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->page ) );
372  plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) pp_offset ) );
373  plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) 0 ) );
374 
375 // Update last page offset with current page value
376 
377  dev->lp_offset = cp_offset;
378 
379 // Write some page state information just to make things nice later on
380 // Eventually there will be more
381 
382  plD_state_plm( pls, PLSTATE_COLOR0 );
383 }
384 
385 //--------------------------------------------------------------------------
386 // UpdatePrevPagehdr()
387 //
388 // Update previous page header.
389 //--------------------------------------------------------------------------
390 
391 static void
392 UpdatePrevPagehdr( PLStream *pls )
393 {
394  PLmDev *dev = (PLmDev *) pls->dev;
395  FILE *file = pls->OutFile;
396  FPOS_T cp_offset = 0;
397 
398  fflush( file );
399 
400 // Determine where we are
401 
402  if ( pl_fgetpos( file, &cp_offset ) )
403  plexit( "plD_bop_plm: fgetpos call failed" );
404 
405 // Seek back to previous page header.
406 
407  if ( dev->lp_offset > 0 )
408  {
409  FPOS_T fwbyte_offset = 0;
410 
411  pldebug( "UpdatePrevPagehdr 1 (plmeta.c)",
412  "Location: %d, seeking to: %d\n",
413  (int) cp_offset, (int) dev->lp_offset );
414 
415  // The forward byte offset is located exactly 7 bytes after the BOP
416  fwbyte_offset = dev->lp_offset + 7;
417  if ( pl_fsetpos( file, &fwbyte_offset ) )
418  {
419  snprintf( buffer, BUFFER_LEN, "UpdatePrevPagehdr (plmeta.c): fsetpos to fwbyte_offset (%d) failed",
420  (int) fwbyte_offset );
421  plexit( buffer );
422  }
423 
424  // DEBUG: verify current location
425 
426 #ifdef DEBUG
427  if ( pl_fgetpos( file, &fwbyte_offset ) )
428  plexit( "UpdatePrevPagehdr (plmeta.c): fgetpos call failed" );
429 
430  pldebug( "UpdatePrevPagehdr 2 (plmeta.c)",
431  "Now at: %d, to write: %d\n",
432  (int) fwbyte_offset, (int) cp_offset );
433 #endif
434 
435  // Write forward byte offset into previous page header.
436 
437  plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) cp_offset ) );
438  fflush( file );
439 
440  // DEBUG: move back to before the write & read it to verify
441 
442 #ifdef DEBUG
443  if ( pl_fsetpos( file, &fwbyte_offset ) )
444  {
445  snprintf( buffer, BUFFER_LEN, "UpdatePrevPagehdr (plmeta.c): fsetpos to fwbyte_offset (%d) failed",
446  (int) fwbyte_offset );
447  plexit( buffer );
448  }
449  {
450  U_LONG read_offset;
451  plm_rd( pdf_rd_4bytes( pls->pdfs, &read_offset ) );
452  pldebug( "UpdatePrevPagehdr 3 (plmeta.c)",
453  "Value read as: %d\n", read_offset );
454  }
455 #endif
456 
457  // Return to current page offset
458 
459  if ( pl_fsetpos( file, &cp_offset ) )
460  {
461  snprintf( buffer, BUFFER_LEN, "UpdatePrevPagehdr (plmeta.c): fsetpos to cp_offset (%d) failed",
462  (int) cp_offset );
463  plexit( buffer );
464  }
465  }
466 }
467 
468 //--------------------------------------------------------------------------
469 // UpdateIndex()
470 //
471 // Update file index.
472 //--------------------------------------------------------------------------
473 
474 static void
475 UpdateIndex( PLStream *pls, FPOS_T cp_offset )
476 {
477  PLmDev *dev = (PLmDev *) pls->dev;
478  FILE *file = pls->OutFile;
479 
480 // Update file index. Right now only number of pages.
481 // The ordering here is critical
482 
483  if ( dev->index_offset > 0 )
484  {
485  pldebug( "UpdateIndex (plmeta.c)",
486  "Location: %d, seeking to: %d\n",
487  (int) cp_offset, (int) dev->lp_offset );
488 
489  if ( pl_fsetpos( file, &dev->index_offset ) )
490  {
491  snprintf( buffer, BUFFER_LEN, "UpdateIndex (plmeta.c): fsetpos to index_offset (%d) failed",
492  (int) dev->index_offset );
493  plexit( buffer );
494  }
495  plm_wr( pdf_wr_header( pls->pdfs, "pages" ) );
496  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->page ) );
497 
498  pldebug( "UpdateIndex (plmeta.c)",
499  "Location: %d, seeking to: %d\n",
500  (int) dev->lp_offset, (int) cp_offset );
501 
502  if ( pl_fsetpos( file, &cp_offset ) )
503  {
504  snprintf( buffer, BUFFER_LEN, "UpdateIndex (plmeta.c): fsetpos to cp_offset (%d) failed",
505  (int) cp_offset );
506  plexit( buffer );
507  }
508  }
509 }
510 
511 //--------------------------------------------------------------------------
512 // plD_tidy_plm()
513 //
514 // Close graphics file
515 //--------------------------------------------------------------------------
516 
517 void
518 plD_tidy_plm( PLStream *pls )
519 {
520  U_CHAR c = (U_CHAR) CLOSE;
521 
522  dbug_enter( "plD_tidy_plm" );
523 
524  plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
525  pdf_close( pls->pdfs );
526  free_mem( pls->dev );
527 }
528 
529 //--------------------------------------------------------------------------
530 // plD_state_plm()
531 //
532 // Handle change in PLStream state (color, pen width, fill attribute, etc).
533 //--------------------------------------------------------------------------
534 
535 void
536 plD_state_plm( PLStream *pls, PLINT op )
537 {
538  U_CHAR c = (U_CHAR) CHANGE_STATE;
539  int i;
540 
541  dbug_enter( "plD_state_plm" );
542 
543  plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
544  plm_wr( pdf_wr_1byte( pls->pdfs, op ) );
545 
546  switch ( op )
547  {
548  case PLSTATE_WIDTH:
549  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) ( pls->width ) ) );
550  break;
551 
552  case PLSTATE_COLOR0:
553  plm_wr( pdf_wr_2bytes( pls->pdfs, (short) pls->icol0 ) );
554 
555  if ( pls->icol0 == PL_RGB_COLOR )
556  {
557  plm_wr( pdf_wr_1byte( pls->pdfs, pls->curcolor.r ) );
558  plm_wr( pdf_wr_1byte( pls->pdfs, pls->curcolor.g ) );
559  plm_wr( pdf_wr_1byte( pls->pdfs, pls->curcolor.b ) );
560  }
561  break;
562 
563  case PLSTATE_COLOR1:
564  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->icol1 ) );
565  break;
566 
567  case PLSTATE_FILL:
568  plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) pls->patt ) );
569  break;
570 
571  case PLSTATE_CMAP0:
572  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->ncol0 ) );
573  for ( i = 0; i < pls->ncol0; i++ )
574  {
575  plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap0[i].r ) );
576  plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap0[i].g ) );
577  plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap0[i].b ) );
578  }
579  break;
580 
581  case PLSTATE_CMAP1:
582  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->ncol1 ) );
583  for ( i = 0; i < pls->ncol1; i++ )
584  {
585  plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap1[i].r ) );
586  plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap1[i].g ) );
587  plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap1[i].b ) );
588  }
589  break;
590  }
591 }
592 
593 //--------------------------------------------------------------------------
594 // plD_esc_plm()
595 //
596 // Escape function. Note that any data written must be in device
597 // independent form to maintain the transportability of the metafile.
598 //
599 // Functions:
600 //
601 // PLESC_FILL Fill polygon
602 // PLESC_SWIN Set window parameters
603 //
604 //--------------------------------------------------------------------------
605 
606 void
607 plD_esc_plm( PLStream *pls, PLINT op, void *ptr )
608 {
609  U_CHAR c = (U_CHAR) ESCAPE;
610 
611  dbug_enter( "plD_esc_plm" );
612 
613  plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
614  plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) op ) );
615 
616  switch ( op )
617  {
618  case PLESC_FILL:
619  plm_fill( pls );
620  break;
621 
622  case PLESC_SWIN:
623  plm_swin( pls );
624  break;
625  }
626 }
627 
628 //--------------------------------------------------------------------------
629 // plm_fill()
630 //
631 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
632 //--------------------------------------------------------------------------
633 
634 static void
635 plm_fill( PLStream *pls )
636 {
637  PLmDev *dev = (PLmDev *) pls->dev;
638 
639  dbug_enter( "plm_fill" );
640 
641  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->dev_npts ) );
642 
643  plm_wr( pdf_wr_2nbytes( pls->pdfs, (U_SHORT *) pls->dev_x, pls->dev_npts ) );
644  plm_wr( pdf_wr_2nbytes( pls->pdfs, (U_SHORT *) pls->dev_y, pls->dev_npts ) );
645 
646  dev->xold = PL_UNDEFINED;
647  dev->yold = PL_UNDEFINED;
648 }
649 
650 //--------------------------------------------------------------------------
651 // plm_swin()
652 //
653 // Set window parameters.
654 // Each parameter or group of parameters is tagged to make backward
655 // compatibility easier.
656 //--------------------------------------------------------------------------
657 
658 static void
659 plm_swin( PLStream *pls )
660 {
661  dbug_enter( "plm_swin" );
662 }
663 
664 //--------------------------------------------------------------------------
665 // WriteFileHeader()
666 //
667 // Writes Metafile header.
668 //--------------------------------------------------------------------------
669 
670 static void
671 WriteFileHeader( PLStream *pls )
672 {
673  PLmDev *dev = (PLmDev *) pls->dev;
674  FILE *file = pls->OutFile;
675  int isfile = ( pls->output_type == 0 );
676 
677  dbug_enter( "WriteFileHeader(PLStream *pls" );
678 
681 
682 // Write file index info. Right now only number of pages.
683 // The order here is critical
684 
685  if ( isfile )
686  {
687  if ( pl_fgetpos( file, &dev->index_offset ) )
688  plexit( "WriteFileHeader: fgetpos call failed" );
689  }
690 
691  plm_wr( pdf_wr_header( pls->pdfs, "pages" ) );
692  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) 0 ) );
693 
694 // Write initialization info. Tag via strings to make backward
695 // compatibility with old metafiles as easy as possible.
696 
697  plm_wr( pdf_wr_header( pls->pdfs, "xmin" ) );
698  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) dev->xmin ) );
699 
700  plm_wr( pdf_wr_header( pls->pdfs, "xmax" ) );
701  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) dev->xmax ) );
702 
703  plm_wr( pdf_wr_header( pls->pdfs, "ymin" ) );
704  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) dev->ymin ) );
705 
706  plm_wr( pdf_wr_header( pls->pdfs, "ymax" ) );
707  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) dev->ymax ) );
708 
709  plm_wr( pdf_wr_header( pls->pdfs, "pxlx" ) );
710  plm_wr( pdf_wr_ieeef( pls->pdfs, (float) dev->pxlx ) );
711 
712  plm_wr( pdf_wr_header( pls->pdfs, "pxly" ) );
713  plm_wr( pdf_wr_ieeef( pls->pdfs, (float) dev->pxly ) );
714 
715 // Geometry info, needed to properly transmit e.g. aspect ratio, via the
716 // length params. Not sure if the others are useful, but they're included for
717 // completeness.
718 
719  plm_wr( pdf_wr_header( pls->pdfs, "xdpi" ) );
720  plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->xdpi ) );
721 
722  plm_wr( pdf_wr_header( pls->pdfs, "ydpi" ) );
723  plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->ydpi ) );
724 
725  plm_wr( pdf_wr_header( pls->pdfs, "xlength" ) );
726  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->xlength ) );
727 
728  plm_wr( pdf_wr_header( pls->pdfs, "ylength" ) );
729  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->ylength ) );
730 
731  plm_wr( pdf_wr_header( pls->pdfs, "xoffset" ) );
732  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->xoffset ) );
733 
734  plm_wr( pdf_wr_header( pls->pdfs, "yoffset" ) );
735  plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->yoffset ) );
736 
737  plm_wr( pdf_wr_header( pls->pdfs, "" ) );
738 }
739 
740 #else
741 int
743 {
744  return 0;
745 }
746 
747 #endif // PLD_plmeta