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