6 #include <stdarg.h> /* not used */
9 #include <assert.h> /* not used */
17 #include "pcb-printf.h"
21 #include "../hidint.h"
22 #include "hid/common/hidnogui.h"
23 #include "hid/common/draw_helpers.h"
25 #include "../../print.h"
26 #include "hid/common/hidinit.h"
28 #ifdef HAVE_LIBDMALLOC
32 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented PS function %s.\n", __FUNCTION__); abort()
34 static int ps_set_layer (const char *name
, int group
, int empty
);
35 static void use_gc (hidGC gc
);
37 typedef struct ps_gc_struct
39 struct hid_gc_struct hid_gc
; /* Parent */
43 unsigned char r
, g
, b
;
49 static HID_DRAW ps_graphics
;
50 static HID_DRAW_CLASS ps_graphics_class
;
52 static const char *medias
[] = {
53 "A0", "A1", "A2", "A3", "A4", "A5",
54 "A6", "A7", "A8", "A9", "A10",
55 "B0", "B1", "B2", "B3", "B4", "B5",
56 "B6", "B7", "B8", "B9", "B10",
57 "Letter", "11x17", "Ledger",
60 "C-Size", "D-size", "E-size",
61 "US-Business_Card", "Intl-Business_Card",
69 Coord MarginX
, MarginY
;
73 * Metric ISO sizes in mm. See http://en.wikipedia.org/wiki/ISO_paper_sizes
99 * awk '{printf(" {\"%s\", %d, %d, MARGINX, MARGINY},\n", $2, $3*100000/25.4, $5*100000/25.4)}'
101 * See http://en.wikipedia.org/wiki/Paper_size#Loose_sizes for some of the other sizes. The
102 * {A,B,C,D,E}-Size here are the ANSI sizes and not the architectural sizes.
105 #define MARGINX MIL_TO_COORD(500)
106 #define MARGINY MIL_TO_COORD(500)
108 static MediaType media_data
[] = {
109 {"A0", MM_TO_COORD(841), MM_TO_COORD(1189), MARGINX
, MARGINY
},
110 {"A1", MM_TO_COORD(594), MM_TO_COORD(841), MARGINX
, MARGINY
},
111 {"A2", MM_TO_COORD(420), MM_TO_COORD(594), MARGINX
, MARGINY
},
112 {"A3", MM_TO_COORD(297), MM_TO_COORD(420), MARGINX
, MARGINY
},
113 {"A4", MM_TO_COORD(210), MM_TO_COORD(297), MARGINX
, MARGINY
},
114 {"A5", MM_TO_COORD(148), MM_TO_COORD(210), MARGINX
, MARGINY
},
115 {"A6", MM_TO_COORD(105), MM_TO_COORD(148), MARGINX
, MARGINY
},
116 {"A7", MM_TO_COORD(74), MM_TO_COORD(105), MARGINX
, MARGINY
},
117 {"A8", MM_TO_COORD(52), MM_TO_COORD(74), MARGINX
, MARGINY
},
118 {"A9", MM_TO_COORD(37), MM_TO_COORD(52), MARGINX
, MARGINY
},
119 {"A10", MM_TO_COORD(26), MM_TO_COORD(37), MARGINX
, MARGINY
},
120 {"B0", MM_TO_COORD(1000), MM_TO_COORD(1414), MARGINX
, MARGINY
},
121 {"B1", MM_TO_COORD(707), MM_TO_COORD(1000), MARGINX
, MARGINY
},
122 {"B2", MM_TO_COORD(500), MM_TO_COORD(707), MARGINX
, MARGINY
},
123 {"B3", MM_TO_COORD(353), MM_TO_COORD(500), MARGINX
, MARGINY
},
124 {"B4", MM_TO_COORD(250), MM_TO_COORD(353), MARGINX
, MARGINY
},
125 {"B5", MM_TO_COORD(176), MM_TO_COORD(250), MARGINX
, MARGINY
},
126 {"B6", MM_TO_COORD(125), MM_TO_COORD(176), MARGINX
, MARGINY
},
127 {"B7", MM_TO_COORD(88), MM_TO_COORD(125), MARGINX
, MARGINY
},
128 {"B8", MM_TO_COORD(62), MM_TO_COORD(88), MARGINX
, MARGINY
},
129 {"B9", MM_TO_COORD(44), MM_TO_COORD(62), MARGINX
, MARGINY
},
130 {"B10", MM_TO_COORD(31), MM_TO_COORD(44), MARGINX
, MARGINY
},
131 {"Letter", INCH_TO_COORD(8.5), INCH_TO_COORD(11), MARGINX
, MARGINY
},
132 {"11x17", INCH_TO_COORD(11), INCH_TO_COORD(17), MARGINX
, MARGINY
},
133 {"Ledger", INCH_TO_COORD(17), INCH_TO_COORD(11), MARGINX
, MARGINY
},
134 {"Legal", INCH_TO_COORD(8.5), INCH_TO_COORD(14), MARGINX
, MARGINY
},
135 {"Executive", INCH_TO_COORD(7.5), INCH_TO_COORD(10), MARGINX
, MARGINY
},
136 {"A-size", INCH_TO_COORD(8.5), INCH_TO_COORD(11), MARGINX
, MARGINY
},
137 {"B-size", INCH_TO_COORD(11), INCH_TO_COORD(17), MARGINX
, MARGINY
},
138 {"C-size", INCH_TO_COORD(17), INCH_TO_COORD(22), MARGINX
, MARGINY
},
139 {"D-size", INCH_TO_COORD(22), INCH_TO_COORD(34), MARGINX
, MARGINY
},
140 {"E-size", INCH_TO_COORD(34), INCH_TO_COORD(44), MARGINX
, MARGINY
},
141 {"US-Business_Card", INCH_TO_COORD(3.5), INCH_TO_COORD(2.0), 0, 0},
142 {"Intl-Business_Card", INCH_TO_COORD(3.375), INCH_TO_COORD(2.125), 0, 0}
148 HID_Attribute ps_attribute_list
[] = {
149 /* other HIDs expect this to be first. */
151 /* %start-doc options "91 Postscript Export"
153 @item --psfile <string>
154 Name of the postscript output file. Can contain a path.
158 {N_("psfile"), N_("Postscript output file"),
159 HID_String
, 0, 0, {0, 0, 0}, 0, 0},
162 /* %start-doc options "91 Postscript Export"
166 Print a centering target in large drill holes.
170 {N_("drill-helper"), N_("Print a centering target in large drill holes"),
171 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
172 #define HA_drillhelper 1
174 /* %start-doc options "91 Postscript Export"
178 Print alignment marks on each sheet. This is meant to ease alignment during exposure.
182 {N_("align-marks"), N_("Print alignment marks on each sheet"),
183 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
184 #define HA_alignmarks 2
186 /* %start-doc options "91 Postscript Export"
189 Print the contents of the outline layer on each sheet.
193 {N_("outline"), N_("Print outline on each sheet"),
194 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
196 /* %start-doc options "91 Postscript Export"
203 {N_("mirror"), N_("Print mirror image of every page"),
204 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
207 /* %start-doc options "91 Postscript Export"
210 Scale output to make the board fit the page.
214 {N_("fill-page"), N_("Scale board to fill page"),
215 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
216 #define HA_fillpage 5
218 /* %start-doc options "91 Postscript Export"
221 Print mirror image of appropriate layers.
225 {N_("auto-mirror"), N_("Print mirror image of appropriate layers"),
226 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
227 #define HA_automirror 6
229 /* %start-doc options "91 Postscript Export"
232 Postscript output in color.
236 {N_("ps-color"), N_("Prints in color"),
237 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
240 /* %start-doc options "91 Postscript Export"
243 @item --ps-bloat <num>
244 Amount to add to trace/pad/pin edges.
248 {N_("ps-bloat"), N_("Amount to add to trace/pad/pin edges"),
249 HID_Coord
, -MIL_TO_COORD (100), MIL_TO_COORD (100), {0, 0, 0}, 0, 0},
252 /* %start-doc options "91 Postscript Export"
256 Draw objects as white-on-black.
260 {N_("ps-invert"), N_("Draw objects as white-on-black"),
261 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
262 #define HA_psinvert 9
264 /* %start-doc options "91 Postscript Export"
266 @item --media <media-name>
267 Size of the media, the postscript is fitted to. The parameter
268 @code{<media-name>} can be any of the standard names for paper size: @samp{A0}
269 to @samp{A10}, @samp{B0} to @samp{B10}, @samp{Letter}, @samp{11x17},
270 @samp{Ledger}, @samp{Legal}, @samp{Executive}, @samp{A-Size}, @samp{B-size},
271 @samp{C-Size}, @samp{D-size}, @samp{E-size}, @samp{US-Business_Card},
272 @samp{Intl-Business_Card}.
276 {N_("media"), N_("Media type"),
277 HID_Enum
, 0, 0, {22, 0, 0}, medias
, 0},
280 /* %start-doc options "91 Postscript Export"
284 Fade amount for assembly drawings (0.0=missing, 1.0=solid).
289 N_("Fade amount for assembly drawings (0.0=missing, 1.0=solid)"),
290 HID_Real
, 0, 1, {0, 0, 0.40}, 0, 0},
293 /* %start-doc options "91 Postscript Export"
296 Scale value to compensate for printer sizing errors (1.0 = full scale).
301 N_("Scale value to compensate for printer sizing errors (1.0 = full scale)"),
302 HID_Real
, 0.01, 4, {0, 0, 1.00}, 0, 0},
305 /* %start-doc options "91 Postscript Export"
309 Produce multiple files, one per page, instead of a single multi page file.
314 N_("Produce multiple files, one per page, instead of a single file"),
315 HID_Boolean
, 0, 0, {0, 0, 0.40}, 0, 0},
316 #define HA_multifile 13
318 /* %start-doc options "91 Postscript Export"
321 Paper width. Used for x-Axis calibration.
325 {N_("xcalib"), N_("Paper width. Used for x-Axis calibration"),
326 HID_Real
, 0, 0, {0, 0, 1.0}, 0, 0},
329 /* %start-doc options "91 Postscript Export"
332 Paper height. Used for y-Axis calibration.
336 {N_("ycalib"), N_("Paper height. Used for y-Axis calibration"),
337 HID_Real
, 0, 0, {0, 0, 1.0}, 0, 0},
340 /* %start-doc options "91 Postscript Export"
343 Draw drill holes in pins / vias, instead of leaving solid copper.
348 N_("Draw drill holes in pins / vias, instead of leaving solid copper"),
349 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
350 #define HA_drillcopper 16
352 /* %start-doc options "91 Postscript Export"
356 Print file name and scale on printout.
360 {N_("show-legend"), N_("Print file name and scale on printout"),
361 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
365 #define NUM_OPTIONS (sizeof(ps_attribute_list)/sizeof(ps_attribute_list[0]))
367 REGISTER_ATTRIBUTES (ps_attribute_list
)
369 /* All file-scope data is in global struct */
371 double calibration_x
, calibration_y
;
376 bool print_group
[MAX_GROUP
];
377 bool print_layer
[MAX_LAYER
];
380 Coord media_width
, media_height
, ps_width
, ps_height
;
382 const char *filename
;
397 LayerType
*outline_layer
;
403 HID_Attr_Val ps_values
[NUM_OPTIONS
];
412 static HID_Attribute
*
413 ps_get_export_options (int *n
)
415 static char *last_made_filename
= 0;
417 derive_default_filename(PCB
->Filename
, &ps_attribute_list
[HA_psfile
], ".ps", &last_made_filename
);
421 return ps_attribute_list
;
425 layer_stack_sort (const void *va
, const void *vb
)
427 int a_layer
= *(int *) va
;
428 int b_layer
= *(int *) vb
;
429 int a_group
= GetLayerGroupNumberByNumber (a_layer
);
430 int b_group
= GetLayerGroupNumberByNumber (b_layer
);
432 if (b_group
!= a_group
)
433 return b_group
- a_group
;
435 return b_layer
- a_layer
;
439 ps_start_file (FILE *f
)
441 time_t currenttime
= time( NULL
);
443 fprintf (f
, "%%!PS-Adobe-3.0\n");
445 /* Document Structuring Conventions (DCS): */
447 /* Start General Header Comments: */
450 * %%Title DCS provides text title for the document that is useful
451 * for printing banner pages.
453 fprintf (f
, "%%%%Title: %s\n", PCB
->Filename
);
456 * %%CreationDate DCS indicates the date and time the document was
457 * created. Neither the date nor time need be in any standard
458 * format. This comment is meant to be used purely for informational
459 * purposes, such as printing on banner pages.
461 fprintf (f
, "%%%%CreationDate: %s", asctime (localtime (¤ttime
)));
464 * %%Creator DCS indicates the document creator, usually the name of
465 * the document composition software.
467 fprintf (f
, "%%%%Creator: PCB release: %s " VERSION
"\n", Progname
);
470 * %%Version DCS comment can be used to note the version and
471 * revision number of a document or resource. A document manager may
472 * wish to provide version control services, or allow substitution
473 * of compatible versions/revisions of a resource or document.
475 * The format should be in the form of 'procname':
476 * <procname>::= < name> < version> < revision>
477 * < name> ::= < text>
478 * < version> ::= < real>
479 * < revision> ::= < uint>
481 * If a version numbering scheme is not used, these fields should
482 * still be filled with a dummy value of 0.
484 * There is currently no code in PCB to manage this revision number.
487 fprintf (f
, "%%%%Version: (PCB %s " VERSION
") 0.0 0\n", Progname
);
491 * %%PageOrder DCS is intended to help document managers determine
492 * the order of pages in the document file, which in turn enables a
493 * document manager optionally to reorder the pages. 'Ascend'-The
494 * pages are in ascending order for example, 1-2-3-4-5-6.
496 fprintf (f
, "%%%%PageOrder: Ascend\n" );
499 * %%Pages: < numpages> | (atend) < numpages> ::= < uint> (Total
502 * %%Pages DCS defines the number of virtual pages that a document
503 * will image. (atend) defers the count until the end of the file,
504 * which is useful for dynamically generated contents.
506 fprintf (f
, "%%%%Pages: (atend)\n" );
509 * %%DocumentMedia: <name> <width> <height> <weight> <color> <type>
511 * Substitute 0 or "" for N/A. Width and height are in points
514 * Media sizes are in PCB units
516 pcb_fprintf (f
, "%%%%DocumentMedia: %s %mi %mi 0 \"\" \"\"\n",
517 media_data
[global
.media_idx
].name
,
518 72 * media_data
[global
.media_idx
].Width
,
519 72 * media_data
[global
.media_idx
].Height
);
520 pcb_fprintf (f
, "%%%%DocumentPaperSizes: %s\n", media_data
[global
.media_idx
].name
);
522 /* End General Header Comments. */
524 /* General Body Comments go here. Currently there are none. */
527 * %%EndComments DCS indicates an explicit end to the header
528 * comments of the document. All global DCS's must preceded
529 * this. A blank line gives an implicit end to the comments.
531 fprintf (f
, "%%%%EndComments\n\n" );
535 ps_end_file (FILE *f
)
538 * %%Trailer DCS must only occur once at the end of the document
539 * script. Any post-processing or cleanup should be contained in
540 * the trailer of the document, which is anything that follows the
541 * %%Trailer comment. Any of the document level structure comments
542 * that were deferred by using the (atend) convention must be
543 * mentioned in the trailer of the document after the %%Trailer
546 fprintf (f
, "%%%%Trailer\n" );
549 * %%Pages was deferred until the end of the document via the
550 * (atend) mentioned, in the General Header section.
552 fprintf (f
, "%%%%Pages: %d\n", global
.pagecount
);
555 * %%EOF DCS signifies the end of the document. When the document
556 * manager sees this comment, it issues an end-of-file signal to the
557 * PostScript interpreter. This is done so system-dependent file
558 * endings, such as Control-D and end-of-file packets, do not
559 * confuse the PostScript interpreter.
561 fprintf (f
, "%%%%EOF\n" );
565 psopen (const char *base
, const char *which
)
568 char *buf
, *suff
, *buf2
;
570 if (!global
.multi_file
)
571 return fopen (base
, "w");
573 buf
= (char *)malloc (strlen (base
) + strlen (which
) + 5);
575 suff
= (char *)strrchr (base
, '.');
579 buf2
= strrchr (buf
, '.');
580 sprintf(buf2
, ".%s.%s", which
, suff
+1);
584 sprintf(buf
, "%s.%s.ps", base
, which
);
586 printf("PS: open %s\n", buf
);
587 ps_open_file
= fopen(buf
, "w");
592 /* This is used by other HIDs that use a postscript format, like lpr
595 ps_hid_export_to_file (FILE * the_file
, HID_Attr_Val
* options
)
598 static int saved_layer_stack
[MAX_LAYER
];
599 FlagType save_thindraw
;
601 save_thindraw
= PCB
->Flags
;
602 CLEAR_FLAG(THINDRAWFLAG
, PCB
);
603 CLEAR_FLAG(THINDRAWPOLYFLAG
, PCB
);
604 CLEAR_FLAG(CHECKPLANESFLAG
, PCB
);
607 global
.drill_helper
= options
[HA_drillhelper
].int_value
;
608 global
.align_marks
= options
[HA_alignmarks
].int_value
;
609 global
.outline
= options
[HA_outline
].int_value
;
610 global
.mirror
= options
[HA_mirror
].int_value
;
611 global
.fillpage
= options
[HA_fillpage
].int_value
;
612 global
.automirror
= options
[HA_automirror
].int_value
;
613 global
.incolor
= options
[HA_color
].int_value
;
614 global
.bloat
= options
[HA_psbloat
].coord_value
;
615 global
.invert
= options
[HA_psinvert
].int_value
;
616 global
.fade_ratio
= CLAMP (options
[HA_psfade
].real_value
, 0, 1);
617 global
.media_idx
= options
[HA_media
].int_value
;
618 global
.media_width
= media_data
[global
.media_idx
].Width
;
619 global
.media_height
= media_data
[global
.media_idx
].Height
;
620 global
.ps_width
= global
.media_width
621 - 2.0 * media_data
[global
.media_idx
].MarginX
;
622 global
.ps_height
= global
.media_height
623 - 2.0 * media_data
[global
.media_idx
].MarginY
;
624 global
.scale_factor
= options
[HA_scale
].real_value
;
625 global
.calibration_x
= options
[HA_xcalib
].real_value
;
626 global
.calibration_y
= options
[HA_ycalib
].real_value
;
627 global
.drillcopper
= options
[HA_drillcopper
].int_value
;
628 global
.legend
= options
[HA_legend
].int_value
;
631 ps_start_file (the_file
);
636 if (PCB
->MaxWidth
> PCB
->MaxHeight
)
638 zx
= global
.ps_height
/ PCB
->MaxWidth
;
639 zy
= global
.ps_width
/ PCB
->MaxHeight
;
643 zx
= global
.ps_height
/ PCB
->MaxHeight
;
644 zy
= global
.ps_width
/ PCB
->MaxWidth
;
646 global
.scale_factor
*= MIN (zx
, zy
);
649 memset (global
.print_group
, 0, sizeof (global
.print_group
));
650 memset (global
.print_layer
, 0, sizeof (global
.print_layer
));
652 global
.outline_layer
= NULL
;
654 for (i
= 0; i
< max_copper_layer
; i
++)
656 LayerType
*layer
= PCB
->Data
->Layer
+ i
;
657 if (layer
->LineN
|| layer
->TextN
|| layer
->ArcN
|| layer
->PolygonN
)
658 global
.print_group
[GetLayerGroupNumberByNumber (i
)] = 1;
660 if (strcmp (layer
->Name
, "outline") == 0 ||
661 strcmp (layer
->Name
, "route") == 0)
663 global
.outline_layer
= layer
;
666 global
.print_group
[GetLayerGroupNumberBySide (BOTTOM_SIDE
)] = 1;
667 global
.print_group
[GetLayerGroupNumberBySide (TOP_SIDE
)] = 1;
668 for (i
= 0; i
< max_copper_layer
; i
++)
669 if (global
.print_group
[GetLayerGroupNumberByNumber (i
)])
670 global
.print_layer
[i
] = 1;
672 memcpy (saved_layer_stack
, LayerStack
, sizeof (LayerStack
));
673 qsort (LayerStack
, max_copper_layer
, sizeof (LayerStack
[0]), layer_stack_sort
);
675 global
.linewidth
= -1;
676 /* reset static vars */
677 ps_set_layer (NULL
, 0, -1);
680 global
.region
.X1
= 0;
681 global
.region
.Y1
= 0;
682 global
.region
.X2
= PCB
->MaxWidth
;
683 global
.region
.Y2
= PCB
->MaxHeight
;
685 if (!global
.multi_file
)
687 /* %%Page DSC requires both a label and an ordinal */
688 fprintf (the_file
, "%%%%Page: TableOfContents 1\n");
689 fprintf (the_file
, "/Times-Roman findfont 24 scalefont setfont\n");
690 fprintf (the_file
, "/rightshow { /s exch def s stringwidth pop -1 mul 0 rmoveto s show } def\n");
691 fprintf (the_file
, "/y 72 9 mul def /toc { 100 y moveto show /y y 24 sub def } bind def\n");
692 fprintf (the_file
, "/tocp { /y y 12 sub def 90 y moveto rightshow } bind def\n");
694 global
.doing_toc
= 1;
695 global
.pagecount
= 1; /* 'pagecount' is modified by hid_expose_callback() call */
696 hid_expose_callback (&ps_hid
, &global
.region
, 0);
699 global
.pagecount
= 1; /* Reset 'pagecount' if single file */
700 global
.doing_toc
= 0;
701 ps_set_layer (NULL
, 0, -1); /* reset static vars */
702 hid_expose_callback (&ps_hid
, &global
.region
, 0);
705 fprintf (the_file
, "showpage\n");
707 memcpy (LayerStack
, saved_layer_stack
, sizeof (LayerStack
));
708 PCB
->Flags
= save_thindraw
;
712 ps_do_export (HID_Attr_Val
* options
)
715 int save_ons
[MAX_LAYER
+ 2];
720 ps_get_export_options (0);
721 for (i
= 0; i
< NUM_OPTIONS
; i
++)
722 global
.ps_values
[i
] = ps_attribute_list
[i
].default_val
;
723 options
= global
.ps_values
;
726 global
.filename
= options
[HA_psfile
].str_value
;
727 if (!global
.filename
)
728 global
.filename
= "pcb-out.ps";
730 global
.multi_file
= options
[HA_multifile
].int_value
;
732 if (global
.multi_file
)
736 fh
= psopen (global
.filename
, "toc");
739 perror (global
.filename
);
744 hid_save_and_show_layer_ons (save_ons
);
745 ps_hid_export_to_file (fh
, options
);
746 hid_restore_layer_ons (save_ons
);
748 global
.multi_file
= 0;
757 ps_parse_arguments (int *argc
, char ***argv
)
759 hid_register_attributes (ps_attribute_list
, NUM_OPTIONS
);
760 hid_parse_command_line (argc
, argv
);
764 corner (FILE *fh
, Coord x
, Coord y
, int dx
, int dy
)
766 Coord len
= MIL_TO_COORD (2000);
767 Coord len2
= MIL_TO_COORD (200);
770 * Originally 'thick' used thicker lines. Currently is uses
771 * Postscript's "device thin" line - i.e. zero width means one
772 * device pixel. The code remains in case you want to make them
773 * thicker - it needs to offset everything so that the *edge* of the
774 * thick line lines up with the edge of the board, not the *center*
778 pcb_fprintf (fh
, "gsave %mi setlinewidth %mi %mi translate %d %d scale\n",
779 thick
* 2, x
, y
, dx
, dy
);
780 pcb_fprintf (fh
, "%mi %mi moveto %mi %mi %mi 0 90 arc %mi %mi lineto\n",
781 len
, thick
, thick
, thick
, len2
+ thick
, thick
, len
);
782 if (dx
< 0 && dy
< 0)
783 pcb_fprintf (fh
, "%mi %mi moveto 0 %mi rlineto\n", len2
* 2 + thick
, thick
, -len2
);
784 fprintf (fh
, "stroke grestore\n");
788 ps_set_layer (const char *name
, int group
, int empty
)
790 static int lastgroup
= -1;
792 int idx
= (group
>= 0 && group
< max_group
)
793 ? PCB
->LayerGroups
.Entries
[group
][0]
796 name
= PCB
->Data
->Layer
[idx
].Name
;
803 if (idx
>= 0 && idx
< max_copper_layer
&& !global
.print_layer
[idx
])
806 if (strcmp (name
, "invisible") == 0)
809 global
.is_drill
= (SL_TYPE (idx
) == SL_PDRILL
|| SL_TYPE (idx
) == SL_UDRILL
);
810 global
.is_mask
= (SL_TYPE (idx
) == SL_MASK
);
811 global
.is_assy
= (SL_TYPE (idx
) == SL_ASSY
);
812 global
.is_copper
= (SL_TYPE (idx
) == 0);
813 global
.is_paste
= (SL_TYPE (idx
) == SL_PASTE
);
815 printf ("Layer %s group %d drill %d mask %d\n", name
, group
, global
.is_drill
,
819 if (global
.doing_toc
)
821 if (group
< 0 || group
!= lastgroup
)
823 if (global
.pagecount
== 1)
825 currenttime
= time (NULL
);
826 fprintf (global
.f
, "30 30 moveto (%s) show\n", PCB
->Filename
);
828 fprintf (global
.f
, "(%d.) tocp\n", global
.pagecount
);
829 fprintf (global
.f
, "(Table of Contents \\(This Page\\)) toc\n" );
831 fprintf (global
.f
, "(Created on %s) toc\n", asctime (localtime (¤ttime
)));
832 fprintf (global
.f
, "( ) tocp\n" );
837 fprintf (global
.f
, "(%d.) tocp\n", global
.pagecount
);
839 fprintf (global
.f
, "(%s) toc\n", name
);
843 if (group
< 0 || group
!= lastgroup
)
849 if (global
.pagecount
!= 0)
851 pcb_fprintf (global
.f
, "showpage\n");
854 if (global
.multi_file
)
858 ps_end_file (global
.f
);
861 global
.f
= psopen (global
.filename
, layer_type_to_file_name (idx
, FNS_fixed
));
864 perror (global
.filename
);
868 ps_start_file (global
.f
);
872 * %%Page DSC comment marks the beginning of the PostScript
873 * language instructions that describe a particular
874 * page. %%Page: requires two arguments: a page label and a
875 * sequential page number. The label may be anything, but the
876 * ordinal page number must reflect the position of that page in
877 * the body of the PostScript file and must start with 1, not 0.
879 fprintf (global
.f
, "%%%%Page: %s %d\n", layer_type_to_file_name(idx
, FNS_fixed
), global
.pagecount
);
882 mirror_this
= !mirror_this
;
883 if (global
.automirror
885 ((idx
>= 0 && group
== GetLayerGroupNumberBySide (BOTTOM_SIDE
))
886 || (idx
< 0 && SL_SIDE (idx
) == SL_BOTTOM_SIDE
)))
887 mirror_this
= !mirror_this
;
889 fprintf (global
.f
, "/Helvetica findfont 10 scalefont setfont\n");
892 fprintf (global
.f
, "30 30 moveto (%s) show\n", PCB
->Filename
);
894 fprintf (global
.f
, "30 41 moveto (%s, %s) show\n",
895 PCB
->Name
, layer_type_to_file_name (idx
, FNS_fixed
));
897 fprintf (global
.f
, "30 41 moveto (%s) show\n",
898 layer_type_to_file_name (idx
, FNS_fixed
));
900 fprintf (global
.f
, "( \\(mirrored\\)) show\n");
903 fprintf (global
.f
, "(, not to scale) show\n");
905 fprintf (global
.f
, "(, scale = 1:%.3f) show\n", global
.scale_factor
);
907 fprintf (global
.f
, "newpath\n");
909 pcb_fprintf (global
.f
, "72 72 scale %mi %mi translate\n",
910 global
.media_width
/ 2, global
.media_height
/ 2);
912 boffset
= global
.media_height
/ 2;
913 if (PCB
->MaxWidth
> PCB
->MaxHeight
)
915 fprintf (global
.f
, "90 rotate\n");
916 boffset
= global
.media_width
/ 2;
917 fprintf (global
.f
, "%g %g scale %% calibration\n", global
.calibration_y
, global
.calibration_x
);
920 fprintf (global
.f
, "%g %g scale %% calibration\n", global
.calibration_x
, global
.calibration_y
);
923 fprintf (global
.f
, "1 -1 scale\n");
925 fprintf (global
.f
, "%g dup neg scale\n",
926 (SL_TYPE (idx
) == SL_FAB
) ? 1.0 : global
.scale_factor
);
927 pcb_fprintf (global
.f
, "%mi %mi translate\n", -PCB
->MaxWidth
/ 2, -PCB
->MaxHeight
/ 2);
929 /* Keep the drill list from falling off the left edge of the paper,
930 * even if it means some of the board falls off the right edge.
931 * If users don't want to make smaller boards, or use fewer drill
932 * sizes, they can always ignore this sheet. */
933 if (SL_TYPE (idx
) == SL_FAB
) {
934 Coord natural
= boffset
- MIL_TO_COORD(500) - PCB
->MaxHeight
/ 2;
935 Coord needed
= PrintFab_overhang ();
936 pcb_fprintf (global
.f
, "%% PrintFab overhang natural %mi, needed %mi\n", natural
, needed
);
937 if (needed
> natural
)
938 pcb_fprintf (global
.f
, "0 %mi translate\n", needed
- natural
);
943 fprintf (global
.f
, "/gray { 1 exch sub setgray } bind def\n");
945 "/rgb { 1 1 3 { pop 1 exch sub 3 1 roll } for setrgbcolor } bind def\n");
949 fprintf (global
.f
, "/gray { setgray } bind def\n");
950 fprintf (global
.f
, "/rgb { setrgbcolor } bind def\n");
953 if ((global
.outline
&& !global
.outline_layer
) || global
.invert
)
955 pcb_fprintf (global
.f
,
956 "0 setgray 0 setlinewidth 0 0 moveto 0 "
957 "%mi lineto %mi %mi lineto %mi 0 lineto closepath %s\n",
958 PCB
->MaxHeight
, PCB
->MaxWidth
, PCB
->MaxHeight
, PCB
->MaxWidth
,
959 global
.invert
? "fill" : "stroke");
962 if (global
.align_marks
)
964 corner (global
.f
, 0, 0, -1, -1);
965 corner (global
.f
, PCB
->MaxWidth
, 0, 1, -1);
966 corner (global
.f
, PCB
->MaxWidth
, PCB
->MaxHeight
, 1, 1);
967 corner (global
.f
, 0, PCB
->MaxHeight
, -1, 1);
970 global
.linewidth
= -1;
971 use_gc (NULL
); /* reset static vars */
975 "/ty ts neg def /tx 0 def /Helvetica findfont ts scalefont setfont\n"
976 "/t { moveto lineto stroke } bind def\n"
977 "/dr { /y2 exch def /x2 exch def /y1 exch def /x1 exch def\n"
978 " x1 y1 moveto x1 y2 lineto x2 y2 lineto x2 y1 lineto closepath stroke } bind def\n"
979 "/r { /y2 exch def /x2 exch def /y1 exch def /x1 exch def\n"
980 " x1 y1 moveto x1 y2 lineto x2 y2 lineto x2 y1 lineto closepath fill } bind def\n"
981 "/c { 0 360 arc fill } bind def\n"
982 "/a { gsave setlinewidth translate scale 0 0 1 5 3 roll arc stroke grestore} bind def\n");
983 if (global
.drill_helper
)
984 pcb_fprintf (global
.f
,
985 "/dh { gsave %mi setlinewidth 0 gray %mi 0 360 arc stroke grestore} bind def\n",
986 (Coord
) MIN_PINORVIAHOLE
, (Coord
) (MIN_PINORVIAHOLE
* 3 / 2));
989 /* Try to outsmart ps2pdf's heuristics for page rotation, by putting
990 * text on all pages -- even if that text is blank */
991 if (SL_TYPE (idx
) != SL_FAB
)
993 "gsave tx ty translate 1 -1 scale 0 0 moveto (Layer %s) show grestore newpath /ty ty ts sub def\n",
996 fprintf (global
.f
, "gsave tx ty translate 1 -1 scale 0 0 moveto ( ) show grestore newpath /ty ty ts sub def\n");
999 /* If we're printing a copper layer other than the outline layer,
1000 and we want to "print outlines", and we have an outline layer,
1001 print the outline layer on this layer also. */
1002 if (global
.outline
&&
1004 global
.outline_layer
!= NULL
&&
1005 global
.outline_layer
!= PCB
->Data
->Layer
+idx
&&
1006 strcmp (name
, "outline") != 0 &&
1007 strcmp (name
, "route") != 0
1010 DrawLayer (global
.outline_layer
, &global
.region
);
1019 hidGC gc
= (hidGC
) calloc (1, sizeof (struct ps_gc_struct
));
1020 psGC ps_gc
= (psGC
)gc
;
1023 gc
->hid_draw
= &ps_graphics
;
1025 ps_gc
->cap
= Trace_Cap
;
1031 ps_destroy_gc (hidGC gc
)
1037 ps_use_mask (enum mask_mode mode
)
1043 ps_set_color (hidGC gc
, const char *name
)
1045 psGC ps_gc
= (psGC
)gc
;
1047 if (strcmp (name
, "erase") == 0 || strcmp (name
, "drill") == 0)
1049 ps_gc
->r
= ps_gc
->g
= ps_gc
->b
= 255;
1052 else if (global
.incolor
)
1055 sscanf (name
+ 1, "%02x%02x%02x", &r
, &g
, &b
);
1063 ps_gc
->r
= ps_gc
->g
= ps_gc
->b
= 0;
1069 ps_set_line_cap (hidGC gc
, EndCapStyle style
)
1071 psGC ps_gc
= (psGC
)gc
;
1077 ps_set_line_width (hidGC gc
, Coord width
)
1079 psGC ps_gc
= (psGC
)gc
;
1081 ps_gc
->width
= width
;
1085 ps_set_draw_xor (hidGC gc
, int xor_
)
1091 ps_set_draw_faded (hidGC gc
, int faded
)
1093 psGC ps_gc
= (psGC
)gc
;
1095 ps_gc
->faded
= faded
;
1101 psGC ps_gc
= (psGC
)gc
;
1102 static int lastcap
= -1;
1103 static int lastcolor
= -1;
1107 lastcap
= lastcolor
= -1;
1110 if (gc
->hid
!= &ps_hid
)
1112 fprintf (stderr
, "Fatal: GC from another HID passed to ps HID\n");
1115 if (global
.linewidth
!= ps_gc
->width
)
1117 pcb_fprintf (global
.f
, "%mi setlinewidth\n",
1118 ps_gc
->width
+ (ps_gc
->erase
? -2 : 2) * global
.bloat
);
1119 global
.linewidth
= ps_gc
->width
;
1121 if (lastcap
!= ps_gc
->cap
)
1135 fprintf (global
.f
, "%d setlinecap %d setlinejoin\n", c
, c
);
1136 lastcap
= ps_gc
->cap
;
1138 #define CBLEND(gc) (((ps_gc->r)<<24)|((ps_gc->g)<<16)|((ps_gc->b)<<8)|(ps_gc->faded))
1139 if (lastcolor
!= CBLEND (gc
))
1141 if (global
.is_drill
|| global
.is_mask
)
1143 fprintf (global
.f
, "%d gray\n", ps_gc
->erase
? 0 : 1);
1154 r
= (1 - global
.fade_ratio
) * 255 + global
.fade_ratio
* r
;
1155 g
= (1 - global
.fade_ratio
) * 255 + global
.fade_ratio
* g
;
1156 b
= (1 - global
.fade_ratio
) * 255 + global
.fade_ratio
* b
;
1158 if (ps_gc
->r
== ps_gc
->g
&& ps_gc
->g
== ps_gc
->b
)
1159 fprintf (global
.f
, "%g gray\n", r
/ 255.0);
1161 fprintf (global
.f
, "%g %g %g rgb\n", r
/ 255.0, g
/ 255.0, b
/ 255.0);
1162 lastcolor
= CBLEND (gc
);
1168 ps_draw_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
1171 pcb_fprintf (global
.f
, "%mi %mi %mi %mi dr\n", x1
, y1
, x2
, y2
);
1174 static void ps_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
);
1175 static void ps_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
);
1178 ps_draw_line (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
1180 psGC ps_gc
= (psGC
)gc
;
1183 /* If you're etching your own paste mask, this will reduce the
1184 amount of brass you need to etch by drawing outlines for large
1185 pads. See also ps_fill_rect. */
1186 if (is_paste
&& ps_gc
->width
> 2500 && ps_gc
->cap
== Square_Cap
1187 && (x1
== x2
|| y1
== y2
))
1191 { t
= x1
; x1
= x2
; x2
= t
; }
1193 { t
= y1
; y1
= y2
; y2
= t
; }
1195 ps_fill_rect (gc
, x1
-w
, y1
-w
, x2
+w
, y2
+w
);
1199 if (x1
== x2
&& y1
== y2
)
1201 Coord w
= ps_gc
->width
/ 2;
1202 if (ps_gc
->cap
== Square_Cap
)
1203 ps_fill_rect (gc
, x1
- w
, y1
- w
, x1
+ w
, y1
+ w
);
1205 ps_fill_circle (gc
, x1
, y1
, w
);
1209 pcb_fprintf (global
.f
, "%mi %mi %mi %mi t\n", x1
, y1
, x2
, y2
);
1213 ps_draw_arc (hidGC gc
, Coord cx
, Coord cy
, Coord width
, Coord height
,
1214 Angle start_angle
, Angle delta_angle
)
1217 if (delta_angle
> 0)
1220 ea
= start_angle
+ delta_angle
;
1224 sa
= start_angle
+ delta_angle
;
1228 printf ("draw_arc %d,%d %dx%d %d..%d %d..%d\n",
1229 cx
, cy
, width
, height
, start_angle
, delta_angle
, sa
, ea
);
1232 pcb_fprintf (global
.f
, "%ma %ma %mi %mi %mi %mi %g a\n",
1233 sa
, ea
, -width
, height
, cx
, cy
,
1234 (double) (global
.linewidth
+ 2 * global
.bloat
) / (double) width
);
1238 ps_fill_circle (hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
1240 psGC ps_gc
= (psGC
)gc
;
1243 if (!ps_gc
->erase
|| !global
.is_copper
|| global
.drillcopper
)
1245 if (ps_gc
->erase
&& global
.is_copper
&& global
.drill_helper
1246 && radius
>= PCB
->minDrill
/ 4)
1247 radius
= PCB
->minDrill
/ 4;
1248 pcb_fprintf (global
.f
, "%mi %mi %mi c\n",
1249 cx
, cy
, radius
+ (ps_gc
->erase
? -1 : 1) * global
.bloat
);
1254 ps_fill_polygon (hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
1257 char *op
= "moveto";
1259 for (i
= 0; i
< n_coords
; i
++)
1261 pcb_fprintf (global
.f
, "%mi %mi %s\n", x
[i
], y
[i
], op
);
1264 fprintf (global
.f
, "fill\n");
1268 fill_polyarea (hidGC gc
, POLYAREA
* pa
, const BoxType
* clip_box
)
1270 /* Ignore clip_box, just draw everything */
1286 pcb_fprintf (global
.f
, "%mi %mi %s\n", v
->point
[0], v
->point
[1], op
);
1289 while ((v
= v
->next
) != pl
->head
.next
);
1291 while ((pl
= pl
->next
) != NULL
);
1293 fprintf (global
.f
, "fill\n");
1297 ps_draw_pcb_polygon (hidGC gc
, PolygonType
* poly
, const BoxType
* clip_box
)
1299 fill_polyarea (gc
, poly
->Clipped
, clip_box
);
1300 if (TEST_FLAG (FULLPOLYFLAG
, poly
))
1304 for (pa
= poly
->Clipped
->f
; pa
!= poly
->Clipped
; pa
= pa
->f
)
1305 fill_polyarea (gc
, pa
, clip_box
);
1310 ps_fill_rect (hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
1326 /* See comment in ps_draw_line. */
1327 if (is_paste
&& (x2
-x1
)>2500 && (y2
-y1
)>2500)
1330 lastcap
= Round_Cap
;
1331 fprintf(f
, "1000 setlinewidth 1 setlinecap 1 setlinejoin\n");
1332 fprintf(f
, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath stroke\n",
1333 x1
+500-bloat
, y1
+500-bloat
,
1334 x1
+500-bloat
, y2
-500+bloat
,
1335 x2
-500+bloat
, y2
-500+bloat
,
1336 x2
-500+bloat
, y1
+500-bloat
);
1340 pcb_fprintf (global
.f
, "%mi %mi %mi %mi r\n",
1341 x1
- global
.bloat
, y1
- global
.bloat
,
1342 x2
+ global
.bloat
, y2
+ global
.bloat
);
1345 HID_Attribute ps_calib_attribute_list
[] = {
1346 {N_("lprcommand"), N_("Command to print"),
1347 HID_String
, 0, 0, {0, 0, 0}, 0, 0},
1350 static const char * const calib_lines
[] = {
1352 "%%Title: Calibration Page\n",
1353 "%%PageOrder: Ascend\n",
1357 "%%Page: Calibrate 1\n",
1361 "0.375 0.375 moveto\n",
1362 "8.125 0.375 lineto\n",
1363 "8.125 10.625 lineto\n",
1364 "0.375 10.625 lineto\n",
1365 "closepath stroke\n",
1367 "0.5 0.5 translate\n",
1368 "0.001 setlinewidth\n",
1370 "/Times-Roman findfont 0.2 scalefont setfont\n",
1373 " 0 lt { -1 } { 1 } ifelse\n",
1377 " /units exch def\n",
1381 " /x x sign 0.5 mul def\n",
1383 " 0 setlinewidth\n",
1384 " newpath x y 0.25 0 180 arc gsave 0.85 setgray fill grestore closepath stroke\n",
1385 " newpath x 0 0.25 180 360 arc gsave 0.85 setgray fill grestore closepath stroke\n",
1386 " 0.001 setlinewidth\n",
1390 "% -0.07 -0.2 rlineto 0.14 0 rmoveto -0.07 0.2 rlineto\n",
1392 " -0.1 0 rlineto 0.2 0 rlineto\n",
1395 "% -0.07 0.2 rlineto 0.14 0 rmoveto -0.07 -0.2 rlineto\n",
1397 " -0.1 0 rlineto 0.2 0 rlineto\n",
1401 " y 0.2 sub moveto\n",
1408 " 1.5 y moveto str show\n",
1409 " /y y 0.25 sub def\n",
1412 "(Please measure between the flat faces of ONE pair of semi-circles on)t\n",
1413 "(both X and Y in the indicated units. Enter these values as X and Y)t\n",
1414 "(respectively. One member of each pair must be one of the semicircles)t\n",
1415 "(in the lower left corner. Nominal lengths on X are 4 in, 15 cm and 7.5 in.)t\n",
1416 "(Nominal lengths on Y are 4 in, 20 cm and 10 in.)t\n",
1418 "(The large box is 10.25 by 7.75 inches and is not used for calibration.)t\n", "\n",
1419 "/in { } bind def\n",
1420 "/cm { 2.54 div } bind def\n",
1421 "/mm { 25.4 div } bind def\n",
1427 guess(double val
, double close_to
, double *calib
)
1429 if (val
>= close_to
* 0.9
1430 && val
<= close_to
* 1.1)
1432 *calib
= close_to
/ val
;
1439 ps_calibrate_1 (double xval
, double yval
, int use_command
)
1441 HID_Attr_Val vals
[3];
1443 int used_popen
= 0, c
;
1445 if (xval
> 0 && yval
> 0)
1447 if (guess (xval
, 4, &global
.calibration_x
))
1448 if (guess (xval
, 15, &global
.calibration_x
))
1449 if (guess (xval
, 7.5, &global
.calibration_x
))
1452 ps_attribute_list
[HA_xcalib
].default_val
.real_value
=
1453 global
.calibration_x
= xval
;
1455 Message(_("X value of %g is too far off.\n"
1456 "Expecting it near: %.1f, %.1f, %.1f, %.1f\n"),
1457 xval
, 1.0, 4.0, 15.0, 7.5);
1459 if (guess (yval
, 4, &global
.calibration_y
))
1460 if (guess (yval
, 20, &global
.calibration_y
))
1461 if (guess (yval
, 10, &global
.calibration_y
))
1464 ps_attribute_list
[HA_ycalib
].default_val
.real_value
=
1465 global
.calibration_y
= yval
;
1467 Message(_("Y value of %g is too far off.\n"
1468 "Expecting it near: %.1f, %.1f, %.1f, %.1f\n"),
1469 yval
, 1.0, 4.0, 20.0, 10.0);
1474 if (ps_calib_attribute_list
[0].default_val
.str_value
== NULL
)
1476 ps_calib_attribute_list
[0].default_val
.str_value
= strdup ("lpr");
1479 if (gui
->attribute_dialog (ps_calib_attribute_list
, 1, vals
, _("Print Calibration Page"), _("Generates a printer calibration page")))
1482 if (use_command
|| strchr (vals
[0].str_value
, '|'))
1484 const char *cmd
= vals
[0].str_value
;
1485 while (*cmd
== ' ' || *cmd
== '|')
1487 ps_cal_file
= popen (cmd
, "w");
1491 ps_cal_file
= fopen (vals
[0].str_value
, "w");
1493 for (c
=0; calib_lines
[c
]; c
++)
1494 fputs(calib_lines
[c
], ps_cal_file
);
1496 fprintf (ps_cal_file
, "4 in 0.5 (Y in nom=4) cbar\n");
1497 fprintf (ps_cal_file
, "20 cm 1.5 (Y cm nom=20) cbar\n");
1498 fprintf (ps_cal_file
, "10 in 2.5 (Y in nom=10) cbar\n");
1499 fprintf (ps_cal_file
, "-90 rotate\n");
1500 fprintf (ps_cal_file
, "4 in -0.5 (X in nom=4) cbar\n");
1501 fprintf (ps_cal_file
, "15 cm -1.5 (X cm nom=15) cbar\n");
1502 fprintf (ps_cal_file
, "7.5 in -2.5 (X in nom=7.5) cbar\n");
1503 fprintf (ps_cal_file
, "showpage\n");
1505 fprintf (ps_cal_file
, "%%%%EOF\n");
1508 pclose (ps_cal_file
);
1510 fclose (ps_cal_file
);
1514 ps_calibrate (double xval
, double yval
)
1516 ps_calibrate_1 (xval
, yval
, 0);
1520 ps_set_crosshair (int x
, int y
, int action
)
1524 #include "dolists.h"
1526 void ps_ps_init (HID
*hid
)
1528 hid
->get_export_options
= ps_get_export_options
;
1529 hid
->do_export
= ps_do_export
;
1530 hid
->parse_arguments
= ps_parse_arguments
;
1531 hid
->calibrate
= ps_calibrate
;
1532 hid
->set_crosshair
= ps_set_crosshair
;
1535 void ps_ps_graphics_class_init (HID_DRAW_CLASS
*klass
)
1537 klass
->set_layer
= ps_set_layer
;
1538 klass
->make_gc
= ps_make_gc
;
1539 klass
->destroy_gc
= ps_destroy_gc
;
1540 klass
->use_mask
= ps_use_mask
;
1541 klass
->set_color
= ps_set_color
;
1542 klass
->set_line_cap
= ps_set_line_cap
;
1543 klass
->set_line_width
= ps_set_line_width
;
1544 klass
->set_draw_xor
= ps_set_draw_xor
;
1545 klass
->set_draw_faded
= ps_set_draw_faded
;
1546 klass
->draw_line
= ps_draw_line
;
1547 klass
->draw_arc
= ps_draw_arc
;
1548 klass
->draw_rect
= ps_draw_rect
;
1549 klass
->fill_circle
= ps_fill_circle
;
1550 klass
->fill_polygon
= ps_fill_polygon
;
1551 klass
->fill_rect
= ps_fill_rect
;
1553 klass
->draw_pcb_polygon
= ps_draw_pcb_polygon
;
1556 void ps_ps_graphics_init (HID_DRAW
*graphics
)
1563 memset (&ps_hid
, 0, sizeof (HID
));
1564 memset (&ps_graphics
, 0, sizeof (HID_DRAW
));
1566 common_nogui_init (&ps_hid
);
1567 ps_ps_init (&ps_hid
);
1569 ps_hid
.struct_size
= sizeof (HID
);
1571 ps_hid
.description
= N_("Postscript export");
1572 ps_hid
.exporter
= 1;
1574 ps_hid
.graphics
= &ps_graphics
;
1576 common_draw_helpers_class_init (&ps_graphics_class
);
1577 ps_ps_graphics_class_init (&ps_graphics_class
);
1579 ps_graphics
.klass
= &ps_graphics_class
;
1580 ps_graphics
.poly_before
= true;
1581 common_draw_helpers_init (&ps_graphics
);
1582 ps_ps_graphics_init (&ps_graphics
);
1584 hid_register_hid (&ps_hid
);
1587 #include "ps_lists.h"