20 #include "../hidint.h"
21 #include "hid/common/draw_helpers.h"
23 #include "../../print.h"
25 #ifdef HAVE_LIBDMALLOC
31 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented PS function %s.\n", __FUNCTION__); abort()
33 typedef struct hid_gc_struct
38 unsigned char r
, g
, b
;
43 static double calibration_x
= 1.0, calibration_y
= 1.0;
46 static int pagecount
= 0;
47 static int linewidth
= -1;
48 static int lastgroup
= -1;
49 static int lastcap
= -1;
50 static int lastcolor
= -1;
51 static int print_group
[MAX_LAYER
];
52 static int print_layer
[MAX_LAYER
];
53 static double fade_ratio
= 0.4;
54 static double antifade_ratio
= 0.6;
55 static int multi_file
= 0;
56 static double media_width
, media_height
, ps_width
, ps_height
;
58 static const char *medias
[] = {
59 "A0", "A1", "A2", "A3", "A4", "A5",
60 "A6", "A7", "A8", "A9", "A10",
61 "B0", "B1", "B2", "B3", "B4", "B5",
62 "B6", "B7", "B8", "B9", "B10",
63 "Letter", "11x17", "Ledger",
66 "C-Size", "D-size", "E-size",
67 "US-Business_Card", "Intl-Business_Card",
74 long int Width
, Height
;
75 long int MarginX
, MarginY
;
76 } MediaType
, *MediaTypePtr
;
79 * Metric ISO sizes in mm. See http://en.wikipedia.org/wiki/ISO_paper_sizes
105 * awk '{printf(" {\"%s\", %d, %d, MARGINX, MARGINY},\n", $2, $3*100000/25.4, $5*100000/25.4)}'
107 * See http://en.wikipedia.org/wiki/Paper_size#Loose_sizes for some of the other sizes. The
108 * {A,B,C,D,E}-Size here are the ANSI sizes and not the architectural sizes.
111 #define MARGINX 50000
112 #define MARGINY 50000
114 static MediaType media_data
[] = {
115 {"A0", 3311023, 4681102, MARGINX
, MARGINY
},
116 {"A1", 2338582, 3311023, MARGINX
, MARGINY
},
117 {"A2", 1653543, 2338582, MARGINX
, MARGINY
},
118 {"A3", 1169291, 1653543, MARGINX
, MARGINY
},
119 {"A4", 826771, 1169291, MARGINX
, MARGINY
},
120 {"A5", 582677, 826771, MARGINX
, MARGINY
},
121 {"A6", 413385, 582677, MARGINX
, MARGINY
},
122 {"A7", 291338, 413385, MARGINX
, MARGINY
},
123 {"A8", 204724, 291338, MARGINX
, MARGINY
},
124 {"A9", 145669, 204724, MARGINX
, MARGINY
},
125 {"A10", 102362, 145669, MARGINX
, MARGINY
},
126 {"B0", 3937007, 5566929, MARGINX
, MARGINY
},
127 {"B1", 2783464, 3937007, MARGINX
, MARGINY
},
128 {"B2", 1968503, 2783464, MARGINX
, MARGINY
},
129 {"B3", 1389763, 1968503, MARGINX
, MARGINY
},
130 {"B4", 984251, 1389763, MARGINX
, MARGINY
},
131 {"B5", 692913, 984251, MARGINX
, MARGINY
},
132 {"B6", 492125, 692913, MARGINX
, MARGINY
},
133 {"B7", 346456, 492125, MARGINX
, MARGINY
},
134 {"B8", 244094, 346456, MARGINX
, MARGINY
},
135 {"B9", 173228, 244094, MARGINX
, MARGINY
},
136 {"B10", 122047, 173228, MARGINX
, MARGINY
},
137 {"Letter", 850000, 1100000, MARGINX
, MARGINY
},
138 {"11x17", 1100000, 1700000, MARGINX
, MARGINY
},
139 {"Ledger", 1700000, 1100000, MARGINX
, MARGINY
},
140 {"Legal", 850000, 1400000, MARGINX
, MARGINY
},
141 {"Executive", 750000, 1000000, MARGINX
, MARGINY
},
142 {"A-size", 850000, 1100000, MARGINX
, MARGINY
},
143 {"B-size", 1100000, 1700000, MARGINX
, MARGINY
},
144 {"C-size", 1700000, 2200000, MARGINX
, MARGINY
},
145 {"D-size", 2200000, 3400000, MARGINX
, MARGINY
},
146 {"E-size", 3400000, 4400000, MARGINX
, MARGINY
},
147 {"US-Business_Card", 350000, 200000, 0, 0},
148 {"Intl-Business_Card", 337500, 212500, 0, 0}
154 HID_Attribute ps_attribute_list
[] = {
155 /* other HIDs expect this to be first. */
156 {"psfile", "Postscript output file",
157 HID_String
, 0, 0, {0, 0, 0}, 0, 0},
159 {"drill-helper", "Prints a centering target in large drill holes",
160 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
161 #define HA_drillhelper 1
162 {"align-marks", "Prints alignment marks on each layer",
163 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
164 #define HA_alignmarks 2
165 {"outline", "Prints outline on each layer",
166 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
168 {"mirror", "Prints mirror image of each layer",
169 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
171 {"fill-page", "Scale board to fill page",
172 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
173 #define HA_fillpage 5
174 {"auto-mirror", "Prints mirror image of appropriate layers",
175 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
176 #define HA_automirror 6
177 {"ps-color", "Prints in color",
178 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
180 {"ps-bloat", "Amount to add to trace/pad/pin edges (1 = 1/100 mil)",
181 HID_Integer
, -10000, 10000, {0, 0, 0}, 0, 0},
183 {"ps-invert", "Draw images as white-on-black",
184 HID_Boolean
, 0, 0, {0, 0, 0}, 0, 0},
185 #define HA_psinvert 9
186 {"media", "media type",
187 HID_Enum
, 0, 0, {22, 0, 0}, medias
, 0},
189 {"psfade", "Fade amount for assembly drawings (0.0=missing, 1.0=solid)",
190 HID_Real
, 0, 1, {0, 0, 0.40}, 0, 0},
192 {"scale", "Scale value to compensate for printer sizing errors (1.0 = full scale)",
193 HID_Real
, 0.01, 4, {0, 0, 1.00}, 0, 0},
195 {"multi-file", "Produce multiple files, one per page, instead of a single file.",
196 HID_Boolean
, 0, 0, {0, 0, 0.40}, 0, 0},
197 #define HA_multifile 13
198 {"xcalib", "X-Axis calibration (paper width).",
199 HID_Real
, 0, 0, {0, 0, 1.0}, 0, 0},
201 {"ycalib", "Y-Axis calibration (paper height).",
202 HID_Real
, 0, 0, {0, 0, 1.0}, 0, 0},
204 {"drill-copper", "Draw drill holes in pins / vias, instead of leaving solid copper.",
205 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
206 #define HA_drillcopper 16
207 {"show-legend", "Print file name and scale on printout",
208 HID_Boolean
, 0, 0, {1, 0, 0}, 0, 0},
212 #define NUM_OPTIONS (sizeof(ps_attribute_list)/sizeof(ps_attribute_list[0]))
214 REGISTER_ATTRIBUTES (ps_attribute_list
)
216 static HID_Attr_Val ps_values
[NUM_OPTIONS
];
218 static HID_Attribute
*
219 ps_get_export_options (int *n
)
221 static char *last_made_filename
= 0;
223 derive_default_filename(PCB
->Filename
, &ps_attribute_list
[HA_psfile
], ".ps", &last_made_filename
);
227 return ps_attribute_list
;
231 group_for_layer (int l
)
233 if (l
< max_layer
+ 2 && l
>= 0)
234 return GetLayerGroupNumberByNumber (l
);
235 /* else something unique */
236 return max_layer
+ 3 + l
;
240 layer_sort (const void *va
, const void *vb
)
244 int d
= group_for_layer (b
) - group_for_layer (a
);
250 static char *filename
;
251 static int drill_helper
;
252 static int align_marks
;
256 static int automirror
;
258 static int doing_toc
;
262 static int drillcopper
;
265 static LayerTypePtr outline_layer
;
267 static double fill_zoom
;
268 static double scale_value
;
271 ps_start_file (FILE *f
)
273 fprintf (f
, "%%!PS-Adobe-3.0\n\n");
277 psopen (const char *base
, const char *which
)
280 char *buf
, *suff
, *buf2
;
283 return fopen (base
, "w");
285 buf
= malloc (strlen (base
) + strlen (which
) + 5);
287 suff
= strrchr (base
, '.');
291 buf2
= strrchr (buf
, '.');
292 sprintf(buf2
, ".%s.%s", which
, suff
+1);
296 sprintf(buf
, "%s.%s.ps", base
, which
);
298 printf("PS: open %s\n", buf
);
304 static BoxType region
;
306 /* This is used by other HIDs that use a postscript format, like lpr
309 ps_hid_export_to_file (FILE * the_file
, HID_Attr_Val
* options
)
312 static int saved_layer_stack
[MAX_LAYER
];
313 FlagType save_thindraw
;
315 save_thindraw
= PCB
->Flags
;
316 CLEAR_FLAG(THINDRAWFLAG
, PCB
);
317 CLEAR_FLAG(THINDRAWPOLYFLAG
, PCB
);
320 drill_helper
= options
[HA_drillhelper
].int_value
;
321 align_marks
= options
[HA_alignmarks
].int_value
;
322 outline
= options
[HA_outline
].int_value
;
323 mirror
= options
[HA_mirror
].int_value
;
324 fillpage
= options
[HA_fillpage
].int_value
;
325 automirror
= options
[HA_automirror
].int_value
;
326 incolor
= options
[HA_color
].int_value
;
327 bloat
= options
[HA_psbloat
].int_value
;
328 invert
= options
[HA_psinvert
].int_value
;
329 fade_ratio
= options
[HA_psfade
].real_value
;
330 media
= options
[HA_media
].int_value
;
331 media_width
= media_data
[media
].Width
/ 1e5
;
332 media_height
= media_data
[media
].Height
/ 1e5
;
333 ps_width
= media_width
- 2.0*media_data
[media
].MarginX
/ 1e5
;
334 ps_height
= media_height
- 2.0*media_data
[media
].MarginY
/ 1e5
;
335 scale_value
= options
[HA_scale
].real_value
;
336 calibration_x
= options
[HA_xcalib
].real_value
;
337 calibration_y
= options
[HA_ycalib
].real_value
;
338 drillcopper
= options
[HA_drillcopper
].int_value
;
339 legend
= options
[HA_legend
].int_value
;
345 antifade_ratio
= 1.0 - fade_ratio
;
350 if (PCB
->MaxWidth
> PCB
->MaxHeight
)
352 zx
= ps_height
/ PCB
->MaxWidth
;
353 zy
= ps_width
/ PCB
->MaxHeight
;
357 zx
= ps_height
/ PCB
->MaxHeight
;
358 zy
= ps_width
/ PCB
->MaxWidth
;
369 memset (print_group
, 0, sizeof (print_group
));
370 memset (print_layer
, 0, sizeof (print_layer
));
372 outline_layer
= NULL
;
374 for (i
= 0; i
< max_layer
; i
++)
376 LayerType
*layer
= PCB
->Data
->Layer
+ i
;
377 if (layer
->LineN
|| layer
->TextN
|| layer
->ArcN
|| layer
->PolygonN
)
378 print_group
[GetLayerGroupNumberByNumber (i
)] = 1;
380 if (strcmp (layer
->Name
, "outline") == 0
381 || strcmp (layer
->Name
, "route") == 0)
383 printf("see outline layer\n");
384 outline_layer
= layer
;
387 print_group
[GetLayerGroupNumberByNumber (max_layer
)] = 1;
388 print_group
[GetLayerGroupNumberByNumber (max_layer
+ 1)] = 1;
389 for (i
= 0; i
< max_layer
; i
++)
390 if (print_group
[GetLayerGroupNumberByNumber (i
)])
393 memcpy (saved_layer_stack
, LayerStack
, sizeof (LayerStack
));
394 qsort (LayerStack
, max_layer
, sizeof (LayerStack
[0]), layer_sort
);
403 region
.X2
= PCB
->MaxWidth
;
404 region
.Y2
= PCB
->MaxHeight
;
409 fprintf (f
, "%%%%Page: 1\n");
410 fprintf (f
, "/Times-Roman findfont 24 scalefont setfont\n");
412 "/rightshow { /s exch def s stringwidth pop -1 mul 0 rmoveto s show } def\n");
414 "/y 72 9 mul def /toc { 100 y moveto show /y y 24 sub def } bind def\n");
415 fprintf (f
, "/tocp { /y y 12 sub def 90 y moveto rightshow } bind def\n");
417 hid_expose_callback (&ps_hid
, ®ion
, 0);
423 hid_expose_callback (&ps_hid
, ®ion
, 0);
426 fprintf (f
, "showpage\n");
428 memcpy (LayerStack
, saved_layer_stack
, sizeof (LayerStack
));
429 PCB
->Flags
= save_thindraw
;
433 ps_do_export (HID_Attr_Val
* options
)
435 int save_ons
[MAX_LAYER
+ 2];
440 ps_get_export_options (0);
441 for (i
= 0; i
< NUM_OPTIONS
; i
++)
442 ps_values
[i
] = ps_attribute_list
[i
].default_val
;
446 filename
= options
[HA_psfile
].str_value
;
448 filename
= "pcb-out.ps";
450 multi_file
= options
[HA_multifile
].int_value
;
456 f
= psopen (filename
, "toc");
465 hid_save_and_show_layer_ons (save_ons
);
466 ps_hid_export_to_file (f
, options
);
467 hid_restore_layer_ons (save_ons
);
474 extern void hid_parse_command_line (int *argc
, char ***argv
);
477 ps_parse_arguments (int *argc
, char ***argv
)
479 hid_register_attributes (ps_attribute_list
,
480 sizeof (ps_attribute_list
) /
481 sizeof (ps_attribute_list
[0]));
482 hid_parse_command_line (argc
, argv
);
486 corner (int x
, int y
, int dx
, int dy
)
489 int len
= (PCB
->MaxWidth
+ PCB
->MaxHeight
) / 10;
490 int len2
= (PCB
->MaxWidth
+ PCB
->MaxHeight
) / 50;
497 fprintf (f
, "gsave %d setlinewidth %d %d translate %d %d scale\n",
498 thick
* 2, x
, y
, dx
, dy
);
499 fprintf (f
, "%d %d moveto %d %d %d 0 90 arc %d %d lineto\n",
500 len
, thick
, thick
, thick
, len2
+ thick
, thick
, len
);
501 if (dx
< 0 && dy
< 0)
502 fprintf (f
, "%d %d moveto 0 %d rlineto\n",
503 len2
* 2 + thick
, thick
, -len2
);
504 fprintf (f
, "stroke grestore\n");
510 static int is_copper
;
514 ps_set_layer (const char *name
, int group
, int empty
)
516 int idx
= (group
>= 0
518 max_layer
) ? PCB
->LayerGroups
.Entries
[group
][0] : group
;
520 name
= PCB
->Data
->Layer
[idx
].Name
;
525 if (idx
>= 0 && idx
< max_layer
&& !print_layer
[idx
])
528 if (strcmp (name
, "invisible") == 0)
531 is_drill
= (SL_TYPE (idx
) == SL_PDRILL
|| SL_TYPE (idx
) == SL_UDRILL
);
532 is_mask
= (SL_TYPE (idx
) == SL_MASK
);
533 is_assy
= (SL_TYPE (idx
) == SL_ASSY
);
534 is_copper
= (SL_TYPE (idx
) == 0);
535 is_paste
= (SL_TYPE (idx
) == SL_PASTE
);
537 printf ("Layer %s group %d drill %d mask %d\n", name
, group
, is_drill
,
543 if (group
< 0 || group
!= lastgroup
)
547 fprintf (f
, "(%d.) tocp\n", pagecount
);
549 fprintf (f
, "(%s) toc\n", name
);
553 if (group
< 0 || group
!= lastgroup
)
561 fprintf (f
, "showpage\n");
568 f
= psopen (filename
, layer_type_to_file_name (idx
));
577 fprintf (f
, "%%%%Page: %d\n", pagecount
);
580 mirror_this
= 1 - mirror_this
;
583 ((idx
>= 0 && group
== GetLayerGroupNumberByNumber (max_layer
))
584 || (idx
< 0 && SL_SIDE (idx
) == SL_BOTTOM_SIDE
)))
585 mirror_this
= 1 - mirror_this
;
587 fprintf (f
, "/Helvetica findfont 10 scalefont setfont\n");
590 fprintf (f
, "30 30 moveto (%s) show\n", PCB
->Filename
);
592 fprintf (f
, "30 41 moveto (%s, %s) show\n",
593 PCB
->Name
, layer_type_to_file_name (idx
));
595 fprintf (f
, "30 41 moveto (%s) show\n",
596 layer_type_to_file_name (idx
));
598 fprintf (f
, "( \\(mirrored\\)) show\n");
601 fprintf (f
, "(, not to scale) show\n");
603 fprintf (f
, "(, scale = 1:%.3f) show\n", scale_value
);
605 fprintf (f
, "newpath\n");
607 fprintf (f
, "72 72 scale %g %g translate\n", 0.5*media_width
, 0.5*media_height
);
609 boffset
= 0.5*media_height
;
610 if (PCB
->MaxWidth
> PCB
->MaxHeight
)
612 fprintf (f
, "90 rotate\n");
613 boffset
= 0.5*media_width
;
614 fprintf (f
, "%g %g scale %% calibration\n", calibration_y
, calibration_x
);
617 fprintf (f
, "%g %g scale %% calibration\n", calibration_x
, calibration_y
);
620 fprintf (f
, "1 -1 scale\n");
622 if (SL_TYPE (idx
) == SL_FAB
)
623 fprintf (f
, "0.00001 dup neg scale\n");
625 fprintf (f
, "%g dup neg scale\n", (fill_zoom
* scale_value
));
626 fprintf (f
, "%d %d translate\n",
627 -PCB
->MaxWidth
/ 2, -PCB
->MaxHeight
/ 2);
629 /* Keep the drill list from falling off the left edge of the paper,
630 * even if it means some of the board falls off the right edge.
631 * If users don't want to make smaller boards, or use fewer drill
632 * sizes, they can always ignore this sheet. */
633 if (SL_TYPE (idx
) == SL_FAB
) {
634 int natural
= (int) ((boffset
- 0.5) * 100000) - PCB
->MaxHeight
/ 2;
635 int needed
= PrintFab_overhang();
636 fprintf (f
, "%% PrintFab overhang natural %d, needed %d\n", natural
, needed
);
637 if (needed
> natural
)
638 fprintf (f
, "0 %d translate\n", needed
- natural
);
643 fprintf (f
, "/gray { 1 exch sub setgray } bind def\n");
645 "/rgb { 1 1 3 { pop 1 exch sub 3 1 roll } for setrgbcolor } bind def\n");
649 fprintf (f
, "/gray { setgray } bind def\n");
650 fprintf (f
, "/rgb { setrgbcolor } bind def\n");
653 if ((outline
&& !outline_layer
) || invert
)
656 "0 setgray 0 setlinewidth 0 0 moveto 0 %d lineto %d %d lineto %d 0 lineto closepath %s\n",
657 PCB
->MaxHeight
, PCB
->MaxWidth
, PCB
->MaxHeight
, PCB
->MaxWidth
,
658 invert
? "fill" : "stroke");
663 corner (0, 0, -1, -1);
664 corner (PCB
->MaxWidth
, 0, 1, -1);
665 corner (PCB
->MaxWidth
, PCB
->MaxHeight
, 1, 1);
666 corner (0, PCB
->MaxHeight
, -1, 1);
673 fprintf (f
, "/ts 10000 def\n");
675 "/ty ts neg def /tx 0 def /Helvetica findfont ts scalefont setfont\n");
676 fprintf (f
, "/t { moveto lineto stroke } bind def\n");
678 "/r { /y2 exch def /x2 exch def /y1 exch def /x1 exch def\n");
680 " x1 y1 moveto x1 y2 lineto x2 y2 lineto x2 y1 lineto closepath fill } bind def\n");
681 fprintf (f
, "/c { 0 360 arc fill } bind def\n");
683 "/a { gsave setlinewidth translate scale 0 0 1 5 3 roll arc stroke grestore} bind def\n");
686 "/dh { gsave %d setlinewidth 0 gray %d 0 360 arc stroke grestore} bind def\n",
687 MIN_PINORVIAHOLE
, MIN_PINORVIAHOLE
* 3 / 2);
690 /* Try to outsmart ps2pdf's heuristics for page rotation, by putting
691 * text on all pages -- even if that text is blank */
692 if (SL_TYPE (idx
) != SL_FAB
)
694 "gsave tx ty translate 1 -1 scale 0 0 moveto (Layer %s) show grestore newpath /ty ty ts sub def\n",
697 fprintf (f
, "gsave tx ty translate 1 -1 scale 0 0 moveto ( ) show grestore newpath /ty ty ts sub def\n");
700 /* If we're printing a copper layer other than the outline layer,
701 and we want to "print outlines", and we have an outline layer,
702 print the outline layer on this layer also. */
705 && outline_layer
!= PCB
->Data
->Layer
+idx
706 && SL_TYPE (idx
) == 0 /* copper */
707 && strcmp (name
, "outline")
708 && strcmp (name
, "route"))
710 printf("attempting to draw outlines on %s\n", name
);
711 DrawLayer (outline_layer
, ®ion
);
720 hidGC rv
= (hidGC
) calloc (1, sizeof (hid_gc_struct
));
721 rv
->me_pointer
= &ps_hid
;
727 ps_destroy_gc (hidGC gc
)
733 ps_use_mask (int use_it
)
739 ps_set_color (hidGC gc
, const char *name
)
741 if (strcmp (name
, "erase") == 0 || strcmp (name
, "drill") == 0)
743 gc
->r
= gc
->g
= gc
->b
= 255;
749 sscanf (name
+ 1, "%02x%02x%02x", &r
, &g
, &b
);
757 gc
->r
= gc
->g
= gc
->b
= 0;
763 ps_set_line_cap (hidGC gc
, EndCapStyle style
)
769 ps_set_line_width (hidGC gc
, int width
)
775 ps_set_draw_xor (hidGC gc
, int xor)
781 ps_set_draw_faded (hidGC gc
, int faded
)
787 ps_set_line_cap_angle (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
795 if (gc
->me_pointer
!= &ps_hid
)
797 fprintf (stderr
, "Fatal: GC from another HID passed to ps HID\n");
800 if (linewidth
!= gc
->width
)
802 fprintf (f
, "%d setlinewidth\n",
803 gc
->width
+ (gc
->erase
? -2 : 2) * bloat
);
804 linewidth
= gc
->width
;
806 if (lastcap
!= gc
->cap
)
820 fprintf (f
, "%d setlinecap %d setlinejoin\n", c
, c
);
823 #define CBLEND(gc) (((gc->r)<<24)|((gc->g)<<16)|((gc->b)<<8)|(gc->faded))
824 if (lastcolor
!= CBLEND (gc
))
826 if (is_drill
|| is_mask
)
828 fprintf (f
, "%d gray\n", gc
->erase
? 0 : 1);
839 r
= antifade_ratio
* 255 + fade_ratio
* r
;
840 g
= antifade_ratio
* 255 + fade_ratio
* g
;
841 b
= antifade_ratio
* 255 + fade_ratio
* b
;
843 if (gc
->r
== gc
->g
&& gc
->g
== gc
->b
)
844 fprintf (f
, "%g gray\n", r
/ 255.0);
846 fprintf (f
, "%g %g %g rgb\n", r
/ 255.0, g
/ 255.0, b
/ 255.0);
847 lastcolor
= CBLEND (gc
);
853 ps_draw_rect (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
856 fprintf (f
, "%d %d %d %d r\n", x1
, y1
, x2
, y2
);
859 static void ps_fill_rect (hidGC gc
, int x1
, int y1
, int x2
, int y2
);
860 static void ps_fill_circle (hidGC gc
, int cx
, int cy
, int radius
);
863 ps_draw_line (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
866 /* If you're etching your own paste mask, this will reduce the
867 amount of brass you need to etch by drawing outlines for large
868 pads. See also ps_fill_rect. */
869 if (is_paste
&& gc
->width
> 2500 && gc
->cap
== Square_Cap
870 && (x1
== x2
|| y1
== y2
))
874 { t
= x1
; x1
= x2
; x2
= t
; }
876 { t
= y1
; y1
= y2
; y2
= t
; }
878 ps_fill_rect (gc
, x1
-w
, y1
-w
, x2
+w
, y2
+w
);
882 if (x1
== x2
&& y1
== y2
)
884 int w
= gc
->width
/ 2;
885 if (gc
->cap
== Square_Cap
)
886 ps_fill_rect (gc
, x1
- w
, y1
- w
, x1
+ w
, y1
+ w
);
888 ps_fill_circle (gc
, x1
, y1
, w
);
892 fprintf (f
, "%d %d %d %d t\n", x1
, y1
, x2
, y2
);
896 ps_draw_arc (hidGC gc
, int cx
, int cy
, int width
, int height
,
897 int start_angle
, int delta_angle
)
903 ea
= start_angle
+ delta_angle
;
907 sa
= start_angle
+ delta_angle
;
911 printf ("draw_arc %d,%d %dx%d %d..%d %d..%d\n",
912 cx
, cy
, width
, height
, start_angle
, delta_angle
, sa
, ea
);
915 fprintf (f
, "%d %d %d %d %d %d %g a\n",
917 -width
, height
, cx
, cy
, (double) (linewidth
+ 2 * bloat
) / width
);
921 ps_fill_circle (hidGC gc
, int cx
, int cy
, int radius
)
924 if (!gc
->erase
|| !is_copper
|| drillcopper
)
926 if (gc
->erase
&& is_copper
&& drill_helper
927 && radius
>= PCB
->minDrill
/4)
928 radius
= PCB
->minDrill
/4;
929 fprintf (f
, "%d %d %d c\n", cx
, cy
, radius
+ (gc
->erase
? -1 : 1) * bloat
);
934 ps_fill_polygon (hidGC gc
, int n_coords
, int *x
, int *y
)
939 for (i
= 0; i
< n_coords
; i
++)
941 fprintf (f
, "%d %d %s\n", x
[i
], y
[i
], op
);
944 fprintf (f
, "fill\n");
948 ps_fill_rect (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
964 /* See comment in ps_draw_line. */
965 if (is_paste
&& (x2
-x1
)>2500 && (y2
-y1
)>2500)
969 fprintf(f
, "1000 setlinewidth 1 setlinecap 1 setlinejoin\n");
970 fprintf(f
, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath stroke\n",
971 x1
+500-bloat
, y1
+500-bloat
,
972 x1
+500-bloat
, y2
-500+bloat
,
973 x2
-500+bloat
, y2
-500+bloat
,
974 x2
-500+bloat
, y1
+500-bloat
);
978 fprintf (f
, "%d %d %d %d r\n", x1
-bloat
, y1
-bloat
, x2
+bloat
, y2
+bloat
);
981 HID_Attribute ps_calib_attribute_list
[] = {
982 {"lprcommand", "Command to print",
983 HID_String
, 0, 0, {0, 0, 0}, 0, 0},
986 static const char * const calib_lines
[] = {
992 "0.375 0.375 moveto\n",
993 "8.125 0.375 lineto\n",
994 "8.125 10.625 lineto\n",
995 "0.375 10.625 lineto\n",
996 "closepath stroke\n",
998 "0.5 0.5 translate\n",
999 "0.001 setlinewidth\n",
1001 "/Times-Roman findfont 0.2 scalefont setfont\n",
1004 " 0 lt { -1 } { 1 } ifelse\n",
1008 " /units exch def\n",
1012 " /x x sign 0.5 mul def\n",
1014 " 0 setlinewidth\n",
1015 " newpath x y 0.25 0 180 arc gsave 0.85 setgray fill grestore closepath stroke\n",
1016 " newpath x 0 0.25 180 360 arc gsave 0.85 setgray fill grestore closepath stroke\n",
1017 " 0.001 setlinewidth\n",
1021 "% -0.07 -0.2 rlineto 0.14 0 rmoveto -0.07 0.2 rlineto\n",
1023 " -0.1 0 rlineto 0.2 0 rlineto\n",
1026 "% -0.07 0.2 rlineto 0.14 0 rmoveto -0.07 -0.2 rlineto\n",
1028 " -0.1 0 rlineto 0.2 0 rlineto\n",
1032 " y 0.2 sub moveto\n",
1039 " 1.5 y moveto str show\n",
1040 " /y y 0.25 sub def\n",
1043 "(Please measure ONE of the horizontal lines, in the units indicated for)t\n",
1044 "(that line, and enter that value as X. Similarly, measure ONE of the)t\n",
1045 "(vertical lines and enter that value as Y. Measurements should be)t\n",
1046 "(between the flat faces of the semicircles.)t\n",
1048 "(The large box is 10.25 by 7.75 inches)t\n",
1050 "/in { } bind def\n",
1051 "/cm { 2.54 div } bind def\n",
1052 "/mm { 25.4 div } bind def\n",
1058 guess(double val
, double close_to
, double *calib
)
1060 if (val
>= close_to
* 0.9
1061 && val
<= close_to
* 1.1)
1063 *calib
= close_to
/ val
;
1070 ps_calibrate_1 (double xval
, double yval
, int use_command
)
1072 HID_Attr_Val vals
[3];
1074 int used_popen
= 0, c
;
1076 if (xval
> 0 && yval
> 0)
1078 if (guess (xval
, 4, &calibration_x
))
1079 if (guess (xval
, 15, &calibration_x
))
1080 if (guess (xval
, 7.5, &calibration_x
))
1083 ps_attribute_list
[HA_xcalib
].default_val
.real_value
=
1084 calibration_x
= xval
;
1086 Message("X value of %g is too far off.\n"
1087 "Expecting it near: 1.0, 4.0, 15.0, 7.5\n", xval
);
1089 if (guess (yval
, 4, &calibration_y
))
1090 if (guess (yval
, 20, &calibration_y
))
1091 if (guess (yval
, 10, &calibration_y
))
1094 ps_attribute_list
[HA_ycalib
].default_val
.real_value
=
1095 calibration_y
= yval
;
1097 Message("Y value of %g is too far off.\n"
1098 "Expecting it near: 1.0, 4.0, 20.0, 10.0\n", yval
);
1103 if (ps_calib_attribute_list
[0].default_val
.str_value
== NULL
)
1105 ps_calib_attribute_list
[0].default_val
.str_value
= strdup ("lpr");
1108 if (gui
->attribute_dialog (ps_calib_attribute_list
, 1, vals
, "Print Calibration Page", "Generates a printer calibration page"))
1111 if (use_command
|| strchr (vals
[0].str_value
, '|'))
1113 char *cmd
= vals
[0].str_value
;
1114 while (*cmd
== ' ' || *cmd
== '|')
1116 f
= popen (cmd
, "w");
1120 f
= fopen (vals
[0].str_value
, "w");
1122 for (c
=0; calib_lines
[c
]; c
++)
1123 fputs(calib_lines
[c
], f
);
1125 fprintf (f
, "4 in 0.5 (Y in) cbar\n");
1126 fprintf (f
, "20 cm 1.5 (Y cm) cbar\n");
1127 fprintf (f
, "10 in 2.5 (Y in) cbar\n");
1128 fprintf (f
, "-90 rotate\n");
1129 fprintf (f
, "4 in -0.5 (X in) cbar\n");
1130 fprintf (f
, "15 cm -1.5 (X cm) cbar\n");
1131 fprintf (f
, "7.5 in -2.5 (X in) cbar\n");
1133 fprintf (f
, "showpage\n");
1142 ps_calibrate (double xval
, double yval
)
1144 ps_calibrate_1 (xval
, yval
, 0);
1148 ps_set_crosshair (int x
, int y
, int action
)
1155 "Postscript export.",
1157 ps_get_export_options
,
1160 0 /* ps_invalidate_wh */ ,
1161 0 /* ps_invalidate_lr */ ,
1162 0 /* ps_invalidate_all */ ,
1172 ps_set_line_cap_angle
,
1178 common_fill_pcb_polygon
,
1179 0 /* ps_thindraw_pcb_polygon */,
1182 0 /* ps_shift_is_pressed */ ,
1183 0 /* ps_control_is_pressed */ ,
1184 0 /* ps_get_coords */ ,
1186 0 /* ps_add_timer */ ,
1187 0 /* ps_stop_timer */ ,
1188 0 /* ps_watch_file */ ,
1189 0 /* ps_unwatch_file */ ,
1190 0 /* ps_add_block_hook */ ,
1191 0 /* ps_stop_block_hook */ ,
1194 0 /* ps_confirm_dialog */ ,
1195 0 /* ps_close_confirm_dialog */ ,
1196 0 /* ps_report_dialog */ ,
1197 0 /* ps_prompt_for */ ,
1198 0 /* ps_fileselect */ ,
1199 0 /* ps_attribute_dialog */ ,
1200 0 /* ps_show_item */ ,
1205 #include "dolists.h"
1210 apply_default_hid (&ps_hid
, 0);
1211 hid_register_hid (&ps_hid
);
1214 #include "ps_lists.h"