116
125
* some PS code for arcs comes from the output of 'Fig2Dev'. Thanks to
119
static PrintDeviceType PS_QueryConstants = {
134
PS_PrintElementPackage,
135
NULL, /* no drill information */
139
NULL, /* no group IDs */
140
True, /* driver can handle color */
141
False, /* handles no drill information */
142
True, /* handles different media */
143
True, /* allows mirroring */
144
True }, /* allows rotate */
146
EPS_QueryConstants = {
147
"encapsulated PostScript",
161
PS_PrintElementPackage,
162
NULL, /* no drill information */
166
NULL, /* no group ID */
169
False, /* encapsulated doesn't allow media changes */
171
True }; /* allows rotate */
173
static PrintInitType PS_Flags;
175
static char *PS_Functions[] = {
177
"/PcbDict 200 dict def",
179
"PcbDict /DictMatrix matrix put",
182
"/Black {0.0 mysetgray} def",
183
"/White {1.0 mysetgray} def",
184
"/TAN {0.207106781} def",
185
"/MTAN {-0.207106781} def",
187
"% draw a filled polygon",
188
"% get (x,y)... and number of points from stack",
193
" number 1 sub { lineto } repeat",
194
" closepath fill stroke",
198
"% draw a pin-polygon,",
199
"% get x, y and thickness from stack",
200
" /thickness exch def /y exch def /x exch def",
201
" gsave x y translate thickness thickness scale",
214
"% pin or via, x, y and thickness are on the stack",
215
" /drillinghole exch def /thickness exch def /y exch def /x exch def",
217
"% draw drilling hole",
218
" gsave White 0 setlinewidth",
219
" newpath x y drillinghole 2 div 0 360 arc closepath fill stroke",
224
"% pin or via, x, y and thickness are on the stack",
225
" /drillinghole exch def /thickness exch def /y exch def /x exch def",
226
" gsave 0 setlinewidth",
227
" newpath x y thickness 2 div 0 360 arc closepath fill stroke",
228
"% draw drilling whole",
230
" newpath x y drillinghole 2 div 0 360 arc closepath fill stroke",
235
"% square pin or via, x, y and thickness are on the stack",
236
" /drillinghole exch def /thickness exch def /y exch def /x exch def",
237
" newpath x thickness 2 div sub y thickness 2 div sub moveto",
238
" thickness 0 rlineto 0 thickness rlineto",
239
" thickness neg 0 rlineto closepath fill stroke",
240
"% draw drilling hole",
241
" gsave White 0 setlinewidth",
242
" newpath x y drillinghole 2 div 0 360 arc closepath fill stroke",
247
"% drill helpher; x, y, hole, copper-thickness are on stack",
248
" /copper exch def /hole exch def /y exch def /x exch def",
249
" gsave copper setlinewidth",
250
" newpath x y hole copper add 2 div 0 360 arc closepath stroke",
255
"% line, get x1, y1, x2, y2 and thickness from stack",
256
" /thick exch def /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
257
" gsave thick setlinewidth",
258
" x1 y1 moveto x2 y2 lineto stroke",
263
"% line, get x1, y1, x2, y2 and thickness from stack",
264
" /thick exch def /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
265
" gsave White thick setlinewidth",
266
" x1 y1 moveto x2 y2 lineto stroke",
271
"% filled box, get x1, y1, x2 and y2 from stack",
272
" /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
274
" x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto",
275
" closepath fill stroke",
279
"% pad, same as line",
284
"% arc for elements, get x, y, width, height, thickness",
285
"% startangle and delta-angle from stack",
286
" /delta exch def /start exch def /thickness exch def",
287
" /height exch def /width exch def /y exch def /x exch def",
289
" gsave thickness setlinewidth /save DictMatrix currentmatrix def",
290
"% scaling is less then zero because the coord system has to be swapped",
291
" x y translate width neg height scale",
292
" 0 0 1 start start delta add arc save setmatrix stroke",
297
"% arc for elements, get x, y, width, height, thickness",
298
"% startangle and delta-angle from stack",
299
" /delta exch def /start exch def /thickness exch def",
300
" /height exch def /width exch def /y exch def /x exch def",
302
" gsave White thickness setlinewidth /save DictMatrix currentmatrix def",
303
"% scaling is less then zero because the coord system has to be swapped",
304
" x y translate width neg height scale",
305
" 0 0 1 start start delta add arc save setmatrix stroke",
310
"% clears a pin/via for groundplane; x,y and thickness are on stack",
311
" /thickness exch def /y exch def /x exch def",
312
" gsave White x y thickness P grestore",
316
"% clears a square pin, x,y and thickness are on stack",
317
" /thickness exch def /y exch def /x exch def",
319
" newpath x thickness 2 div sub y thickness 2 div sub moveto",
320
" thickness 0 rlineto 0 thickness rlineto",
321
" thickness neg 0 rlineto closepath fill stroke",
326
"% clears a round pin/via for groundplane; x,y and thickness are on the stack",
327
" /thickness exch def /y exch def /x exch def",
328
" gsave White 0 setlinewidth",
329
" newpath x y thickness 2 div 0 360 arc closepath fill stroke",
334
"% clear line, get x1, y1, x2, y2 and thickness from stack",
335
" /thick exch def /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
336
" gsave White thick setlinewidth",
337
" x1 y1 moveto x2 y2 lineto stroke",
342
"% cleared box, get x1, y1, x2 and y2 from stack",
343
" /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
344
" gsave White newpath",
345
" x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto",
346
" closepath fill stroke",
351
"% draw a filled rectangle for the ground plane",
352
"% get x1, y1, x2 and y2 from stack",
353
" /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
354
" gsave 0 setlinewidth",
356
" x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto",
357
" closepath fill stroke",
362
"% outline, get x1, y1, x2 and y2 from stack",
363
" /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
364
" gsave 0.175 setlinewidth",
366
" x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto",
372
"% alignment targets, get x1, y1, x2, y2 and distance from stack",
373
" /dis exch def /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
374
" gsave 0.175 setlinewidth",
375
" newpath x1 y1 dis add moveto",
376
" 0 dis 2 mul neg rlineto",
377
" dis neg dis rmoveto",
378
" dis 2 mul 0 rlineto",
380
" newpath x1 y1 dis 0 90 arcn stroke",
381
" newpath x1 y2 dis sub moveto 0 dis rlineto dis 0 rlineto stroke",
382
" newpath x2 y2 dis sub moveto",
383
" 0 2 dis mul rlineto",
384
" dis dup neg rmoveto",
385
" 2 dis mul neg 0 rlineto"
387
" newpath x2 y1 dis add moveto 0 dis neg rlineto dis neg 0 rlineto stroke",
392
static char *PS_ColorFunctions[] = {
393
"/mysetgray { setgray } def",
394
"/mysetrgbcolor { setrgbcolor } def",
397
static char *PS_InvertColorFunctions[] = {
398
"/mysetgray {neg 1.0 add setgray} def",
400
" /blue exch def /green exch def /red exch def",
401
" 1.0 red sub 1.0 green sub 1.0 blue sub setrgbcolor",
405
static char *PS_Setup[] = {
128
static PrintDeviceType PS_QueryConstants = {
143
PS_PrintElementPackage,
144
NULL, /* no drill information */
148
NULL, /* no group IDs */
149
True, /* driver can handle color */
150
False, /* handles no drill information */
151
True, /* handles different media */
152
True, /* allows mirroring */
153
True, /* allows rotate */
155
}, /* allows scaling */
159
"encapsulated PostScript", "eps", EPS_Init, EPS_Exit, EPS_Preamble, EPS_Postamble, PS_SetColor, PS_Invert, PS_PrintLine, PS_PrintArc, PS_PrintPolygon, PS_PrintText, PS_PrintPad, PS_PrintPinOrVia, PS_PrintElementPackage, NULL, /* no drill information */
160
PS_Outline, PS_Alignment, PS_DrillHelper, NULL, /* no group ID */
161
True, False, False, /* encapsulated doesn't allow media changes */
162
True, True, /* allows rotate */
163
True}; /* allows scaling */
165
static PrintInitType PS_Flags;
166
static Boolean preamble = False;
168
static char *PS_Functions[] = {
170
"/PcbDict 200 dict def",
172
"PcbDict /DictMatrix matrix put",
175
"/Black {0.0 mysetgray} def",
176
"/White {1.0 mysetgray} def",
177
"/TAN {0.207106781} def",
178
"/MTAN {-0.207106781} def",
180
"% draw a filled polygon",
181
"% get (x,y)... and number of points from stack",
186
" number 1 sub { lineto } repeat",
187
" closepath fill stroke",
191
"% draw a pin-polygon,",
192
"% get x, y and thickness from stack",
193
" /thickness exch def /y exch def /x exch def",
194
" gsave x y translate thickness thickness scale",
207
"% pin or via, x, y and thickness are on the stack",
208
" /drillinghole exch def /thickness exch def /y exch def /x exch def",
210
"% draw drilling hole",
211
" gsave White 0 setlinewidth",
212
" newpath x y drillinghole 2 div 0 360 arc closepath fill stroke",
217
"% pin or via, x, y and thickness are on the stack",
218
" /drillinghole exch def /thickness exch def /y exch def /x exch def",
219
" gsave 0 setlinewidth",
220
" newpath x y thickness 2 div 0 360 arc closepath fill stroke",
221
"% draw drilling whole",
223
" newpath x y drillinghole 2 div 0 360 arc closepath fill stroke",
228
"% square pin or via, x, y and thickness are on the stack",
229
" /drillinghole exch def /thickness exch def /y exch def /x exch def",
230
" newpath x thickness 2 div sub y thickness 2 div sub moveto",
231
" thickness 0 rlineto 0 thickness rlineto",
232
" thickness neg 0 rlineto closepath fill stroke",
233
"% draw drilling hole",
234
" gsave White 0 setlinewidth",
235
" newpath x y drillinghole 2 div 0 360 arc closepath fill stroke",
240
"% drill helpher; x, y, hole, copper-thickness are on stack",
241
" /copper exch def /hole exch def /y exch def /x exch def",
242
" gsave copper setlinewidth",
243
" newpath x y hole copper add 2 div 0 360 arc closepath stroke",
248
"% line, get x1, y1, x2, y2 and thickness from stack",
249
" /thick exch def /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
250
" gsave thick setlinewidth",
251
" x1 y1 moveto x2 y2 lineto stroke",
256
"% line, get x1, y1, x2, y2 and thickness from stack",
257
" /thick exch def /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
258
" gsave White thick setlinewidth",
259
" x1 y1 moveto x2 y2 lineto stroke",
264
"% filled box, get x1, y1, x2 and y2 from stack",
265
" /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
267
" x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto",
268
" closepath fill stroke",
272
"% pad, same as line",
277
"% arc for elements, get x, y, width, height, thickness",
278
"% startangle and delta-angle from stack",
279
" /delta exch def /start exch def /thickness exch def",
280
" /height exch def /width exch def /y exch def /x exch def",
282
" gsave thickness setlinewidth /save DictMatrix currentmatrix def",
283
"% scaling is less then zero because the coord system has to be swapped",
284
" x y translate width neg height scale",
285
" 0 0 1 start start delta add arc save setmatrix stroke",
290
"% arc for elements, get x, y, width, height, thickness",
291
"% startangle and delta-angle from stack",
292
" /delta exch def /start exch def /thickness exch def",
293
" /height exch def /width exch def /y exch def /x exch def",
295
" gsave White thickness setlinewidth /save DictMatrix currentmatrix def",
296
"% scaling is less then zero because the coord system has to be swapped",
297
" x y translate width neg height scale",
298
" 0 0 1 start start delta add arc save setmatrix stroke",
303
"% clears a pin/via for groundplane; x,y and thickness are on stack",
304
" /thickness exch def /y exch def /x exch def",
305
" gsave White x y thickness P grestore",
309
"% clears a square pin, x,y and thickness are on stack",
310
" /thickness exch def /y exch def /x exch def",
312
" newpath x thickness 2 div sub y thickness 2 div sub moveto",
313
" thickness 0 rlineto 0 thickness rlineto",
314
" thickness neg 0 rlineto closepath fill stroke",
319
"% clears a round pin/via for groundplane; x,y and thickness are on the stack",
320
" /thickness exch def /y exch def /x exch def",
321
" gsave White 0 setlinewidth",
322
" newpath x y thickness 2 div 0 360 arc closepath fill stroke",
327
"% clear line, get x1, y1, x2, y2 and thickness from stack",
328
" /thick exch def /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
329
" gsave White thick setlinewidth",
330
" x1 y1 moveto x2 y2 lineto stroke",
335
"% cleared box, get x1, y1, x2 and y2 from stack",
336
" /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
337
" gsave White newpath",
338
" x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto",
339
" closepath fill stroke",
344
"% draw a filled rectangle for the ground plane",
345
"% get x1, y1, x2 and y2 from stack",
346
" /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
347
" gsave 0 setlinewidth",
349
" x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto",
350
" closepath fill stroke",
355
"% outline, get x1, y1, x2 and y2 from stack",
356
" /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
357
" gsave 0.175 setlinewidth",
359
" x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto",
365
"% alignment targets, get x1, y1, x2, y2 and distance from stack",
366
" /dis exch def /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
367
" gsave 0.175 setlinewidth",
368
" newpath x1 y1 dis add moveto",
369
" 0 dis 2 mul neg rlineto",
370
" dis neg dis rmoveto",
371
" dis 2 mul 0 rlineto",
373
" newpath x1 y1 dis 0 90 arcn stroke",
374
" newpath x1 y2 dis sub moveto 0 dis rlineto dis 0 rlineto stroke",
375
" newpath x2 y2 dis sub moveto",
376
" 0 2 dis mul rlineto",
377
" dis dup neg rmoveto",
378
" 2 dis mul neg 0 rlineto" " stroke",
379
" newpath x2 y1 dis add moveto 0 dis neg rlineto dis neg 0 rlineto stroke",
385
static char *PS_ColorFunctions[] = {
386
"/mysetgray { setgray } def",
387
"/mysetrgbcolor { setrgbcolor } def",
391
static char *PS_InvertColorFunctions[] = {
392
"/mysetgray {neg 1.0 add setgray} def",
394
" /blue exch def /green exch def /red exch def",
395
" 1.0 red sub 1.0 green sub 1.0 blue sub setrgbcolor",
399
static char *PS_Setup[] = {
410
405
/* ---------------------------------------------------------------------------
411
406
* prints a string array
413
static void PrintStringArray(char **Array, int Number, FILE *FP)
409
PrintStringArray (char **Array, int Number, FILE * FP)
415
for (; Number; Number--, Array++)
416
fprintf(FP, "%s\n", *Array);
411
for (; Number; Number--, Array++)
412
fprintf (FP, "%s\n", *Array);
419
415
/* ---------------------------------------------------------------------------
420
416
* returns information about the PostScript driver
422
PrintDeviceTypePtr PS_Query(void)
424
return(&PS_QueryConstants);
421
return (&PS_QueryConstants);
427
424
/* ---------------------------------------------------------------------------
428
425
* returns information about the encapsulated PostScript driver
430
PrintDeviceTypePtr EPS_Query(void)
432
return(&EPS_QueryConstants);
430
return (&EPS_QueryConstants);
435
433
/* ----------------------------------------------------------------------
436
434
* call init routine for PostScript output
438
static char *PS_Preamble(PrintInitTypePtr Flags, char *Description)
437
PS_Preamble (PrintInitTypePtr Flags, char *Description)
440
return(PS_EPS_Init(Flags, Description, False));
439
return (PS_EPS_Init (Flags, Description, False));
442
static void PS_Init(PrintInitTypePtr wasted)
442
PS_Init (PrintInitTypePtr wasted)
446
446
/* ----------------------------------------------------------------------
447
447
* call init routine for encapsulated PostScript output
449
static char *EPS_Preamble(PrintInitTypePtr Flags, char *Description)
451
return(PS_EPS_Init(Flags, Description, True));
453
static void EPS_Init(PrintInitTypePtr wasted)
456
static void PS_Invert(int mode)
460
if (PS_Flags.InvertFlag)
461
PrintStringArray(PS_ColorFunctions,
462
ENTRIES(PS_ColorFunctions), PS_Flags.FP);
464
PrintStringArray(PS_InvertColorFunctions,
465
ENTRIES(PS_InvertColorFunctions), PS_Flags.FP);
450
EPS_Preamble (PrintInitTypePtr Flags, char *Description)
452
return (PS_EPS_Init (Flags, Description, True));
455
EPS_Init (PrintInitTypePtr wasted)
463
if (PS_Flags.InvertFlag)
464
PrintStringArray (PS_ColorFunctions,
465
ENTRIES (PS_ColorFunctions), PS_Flags.FP);
467
PrintStringArray (PS_InvertColorFunctions,
468
ENTRIES (PS_InvertColorFunctions), PS_Flags.FP);
469
472
/* ----------------------------------------------------------------------
470
473
* prints PostScript or enc. PostScript header with function definition
471
474
* info struct is are passed in
473
static char *PS_EPS_Init(PrintInitTypePtr Flags, char *Description,
477
PS_EPS_Init (PrintInitTypePtr Flags, char *Description, Boolean CreateEPS)
479
struct passwd *pwentry;
481
/* save passed-in data */
483
currenttime = time(NULL);
485
/* adjust the 'mirror' flag because (0,0) is in the lower/left
486
* corner which is different to X11
488
if (!Settings.ShowSolderSide)
489
PS_Flags.MirrorFlag = !PS_Flags.MirrorFlag;
491
/* adjusting the offsets is also necessary because the
492
* passed coordinates are X11 ones (upper/left corner is 0,0)
494
dx = dy = PS_Flags.Scale;
495
dx *= (float) (PS_Flags.BoundingBox.X2 -PS_Flags.BoundingBox.X1);
496
dy *= (float) (PS_Flags.BoundingBox.Y2 -PS_Flags.BoundingBox.Y1);
498
/* create standard PS header */
501
PS_Flags.OffsetX = 0;
502
PS_Flags.OffsetY = 0;
503
fputs("%!PS-Adobe-3.0 EPSF-3.0\n", PS_Flags.FP);
507
PS_Flags.OffsetY = PS_Flags.SelectedMedia->Height -PS_Flags.OffsetY;
508
PS_Flags.OffsetY -= (Dimension) (PS_Flags.RotateFlag ? dx : dy);
509
fputs("%!PS-Adobe-3.0\n", PS_Flags.FP);
511
fprintf(PS_Flags.FP, "%%%%Title: %s, %s\n", UNKNOWN(PCB->Name),
512
UNKNOWN(Description));
513
fprintf(PS_Flags.FP, "%%%%Creator: %s "RELEASE"\n", Progname);
514
fprintf(PS_Flags.FP, "%%%%CreationDate: %s",
515
asctime(localtime(¤ttime)));
516
pwentry = getpwuid(getuid());
517
fprintf(PS_Flags.FP, "%%%%For: %s (%s)\n", pwentry->pw_name,
519
fputs("%%LanguageLevel: 1\n", PS_Flags.FP);
520
fputs("%%Orientation: Portrait\n", PS_Flags.FP);
522
/* - calculate the width and height of the bounding box;
523
* - write bounding box data to file
525
* - transform to PS coordinates#
527
box.X1 = (Position) ((float) PS_Flags.OffsetX * PS_UNIT) -1;
528
box.Y1 = (Position) ((float) PS_Flags.OffsetY * PS_UNIT) -1;
529
if (!PS_Flags.RotateFlag)
531
box.X2= (Position)((dx +PS_Flags.OffsetX) *PS_UNIT) +1;
532
box.Y2= (Position)((dy +PS_Flags.OffsetY) *PS_UNIT) +1;
536
box.X2= (Position)((dy +PS_Flags.OffsetX) *PS_UNIT) +1;
537
box.Y2= (Position)((dx +PS_Flags.OffsetY) *PS_UNIT) +1;
540
/* print it if encapsulated PostScript has been requested
541
* and add the appropriate structured comments
545
fprintf(PS_Flags.FP, "%%%%BoundingBox: %i %i %i %i\n",
546
(int) box.X1, (int) box.Y1, (int) box.X2, (int) box.Y2);
547
fputs("%%Pages: 0\n", PS_Flags.FP);
551
fputs("%%Pages: 1\n", PS_Flags.FP);
552
fputs("%%PageOrder: Ascend\n", PS_Flags.FP);
553
fprintf(PS_Flags.FP, "%%%%IncludeFeature: *PageSize %s\n",
554
PS_Flags.SelectedMedia->Name);
557
/* OK, continue with structured comments */
558
fputs("%%EndComments\n", PS_Flags.FP);
559
fputs("%%BeginProlog\n", PS_Flags.FP);
560
PrintStringArray(PS_Functions, ENTRIES(PS_Functions), PS_Flags.FP);
561
if (PS_Flags.InvertFlag)
562
PrintStringArray(PS_InvertColorFunctions,
563
ENTRIES(PS_InvertColorFunctions), PS_Flags.FP);
565
PrintStringArray(PS_ColorFunctions,
566
ENTRIES(PS_ColorFunctions), PS_Flags.FP);
567
fputs("%%EndProlog\n", PS_Flags.FP);
568
fputs("%%BeginDefaults\n", PS_Flags.FP);
569
fputs("%%EndDefaults\n", PS_Flags.FP);
570
fputs("%%BeginSetup\n", PS_Flags.FP);
571
if (!CreateEPS && strcmp(PS_Flags.SelectedMedia->Name, USERMEDIANAME))
572
fprintf(PS_Flags.FP, "%s\n", PS_Flags.SelectedMedia->Name);
573
PrintStringArray(PS_Setup, ENTRIES(PS_Setup), PS_Flags.FP);
574
fputs("%%EndSetup\n", PS_Flags.FP);
578
fputs("%%Page: 1 1\n", PS_Flags.FP);
579
fputs("%%BeginPageSetup\n", PS_Flags.FP);
580
fputs("%%EndPageSetup\n", PS_Flags.FP);
584
fputs("gsave White newpath\n", PS_Flags.FP);
586
"%i %i moveto %i %i lineto %i %i lineto %i %i lineto\n",
587
(int) box.X1, (int) box.Y1,
588
(int) box.X2, (int) box.Y1,
589
(int) box.X2, (int) box.Y2,
590
(int) box.X1, (int) box.Y2);
591
fputs("closepath fill stroke grestore\n", PS_Flags.FP);
593
/* add information about layout size, offset ... */
594
fprintf(PS_Flags.FP, "%% PCBMIN(%d,%d), PCBMAX(%d,%d)\n",
595
(int) PS_Flags.BoundingBox.X1,
596
(int) PS_Flags.BoundingBox.Y1,
597
(int) PS_Flags.BoundingBox.X2,
598
(int) PS_Flags.BoundingBox.Y2);
599
fprintf(PS_Flags.FP, "%% PCBOFFSET(%d,%d), PCBSCALE(%.5f)\n",
603
fputs("% PCBSTARTDATA --- do not remove ---\n", PS_Flags.FP);
604
fputs("gsave\n", PS_Flags.FP);
606
/* now insert transformation commands (reverse order):
607
* - move upper/left edge of layout to (0,0)
608
* - mirror it to transform X to PostScript coordinates
609
* - move to (0,0) again
610
* - if rotation is required, rotate and move to (0,0)
611
* - apply user scaling
612
* - move to new offset
613
* - scale to PostScript (72 dots per inch)
615
fprintf(PS_Flags.FP, "%.5f %.5f scale\n",
617
fprintf(PS_Flags.FP, "%i %i translate\n",
620
fprintf(PS_Flags.FP, "%.3f %.3f scale\n",
623
if (PS_Flags.RotateFlag)
625
fprintf(PS_Flags.FP, "%i 0 translate\n",
626
(int) PS_Flags.BoundingBox.Y2 -PS_Flags.BoundingBox.Y1);
627
fputs("90 rotate\n", PS_Flags.FP);
629
if (PS_Flags.MirrorFlag)
631
fprintf(PS_Flags.FP, "0 %i translate\n",
632
(int) (PS_Flags.BoundingBox.Y2 -PS_Flags.BoundingBox.Y1));
633
fputs("1 -1 scale\n", PS_Flags.FP);
635
fprintf(PS_Flags.FP, "%i %i translate\n",
636
-PS_Flags.BoundingBox.X1,
637
-PS_Flags.BoundingBox.Y1);
482
struct passwd *pwentry;
484
/* save passed-in data */
486
/* adjust the 'mirror' flag because (0,0) is in the lower/left
487
* corner which is different from X coordinates
489
if (!Settings.ShowSolderSide)
490
PS_Flags.MirrorFlag = !PS_Flags.MirrorFlag;
492
/* adjusting the offsets is also necessary because the
493
* passed coordinates are X (upper/left corner is 0,0)
495
dx = dy = PS_Flags.Scale;
496
dx *= (float) (PS_Flags.BoundingBox.X2 - PS_Flags.BoundingBox.X1);
497
dy *= (float) (PS_Flags.BoundingBox.Y2 - PS_Flags.BoundingBox.Y1);
499
/* create standard PS header */
502
PS_Flags.OffsetX = 0;
503
PS_Flags.OffsetY = 0;
507
PS_Flags.OffsetY = PS_Flags.SelectedMedia->Height - PS_Flags.OffsetY;
508
PS_Flags.OffsetY -= (BDimension) (PS_Flags.RotateFlag ? dx : dy);
514
fputs ("%!PS-Adobe-3.0 EPSF-3.0\n", PS_Flags.FP);
516
fputs ("%!PS-Adobe-3.0\n", PS_Flags.FP);
517
currenttime = time (NULL);
519
fprintf (PS_Flags.FP, "%%%%Title: %s, %s\n", UNKNOWN (PCB->Name),
520
UNKNOWN (Description));
521
fprintf (PS_Flags.FP, "%%%%Creator: %s " VERSION "\n", Progname);
522
fprintf (PS_Flags.FP, "%%%%CreationDate: %s",
523
asctime (localtime (¤ttime)));
524
pwentry = getpwuid (getuid ());
525
fprintf (PS_Flags.FP, "%%%%For: %s (%s)\n", pwentry->pw_name,
527
fputs ("%%LanguageLevel: 1\n", PS_Flags.FP);
528
fputs ("%%Orientation: Portrait\n", PS_Flags.FP);
530
/* - calculate the width and height of the bounding box;
531
* - write bounding box data to file
533
* - transform to PS coordinates#
535
box.X1 = (LocationType) ((float) PS_Flags.OffsetX * PS_UNIT) - 1;
536
box.Y1 = (LocationType) ((float) PS_Flags.OffsetY * PS_UNIT) - 1;
537
if (!PS_Flags.RotateFlag)
539
box.X2 = (LocationType) ((dx + PS_Flags.OffsetX) * PS_UNIT) + 1;
540
box.Y2 = (LocationType) ((dy + PS_Flags.OffsetY) * PS_UNIT) + 1;
544
box.X2 = (LocationType) ((dy + PS_Flags.OffsetX) * PS_UNIT) + 1;
545
box.Y2 = (LocationType) ((dx + PS_Flags.OffsetY) * PS_UNIT) + 1;
548
/* print it if encapsulated PostScript has been requested
549
* and add the appropriate structured comments
553
fprintf (PS_Flags.FP, "%%%%BoundingBox: %i %i %i %i\n",
554
(int) box.X1, (int) box.Y1, (int) box.X2, (int) box.Y2);
555
fputs ("%%Pages: 0\n", PS_Flags.FP);
559
fputs ("%%Pages: 1\n", PS_Flags.FP);
560
fputs ("%%PageOrder: Ascend\n", PS_Flags.FP);
561
fprintf (PS_Flags.FP, "%%%%DocumentMedia: %s %d %d\n",
562
PS_Flags.SelectedMedia->Name,
563
POST_SCALE(PS_Flags.SelectedMedia->Width),
564
POST_SCALE(PS_Flags.SelectedMedia->Height));
567
/* OK, continue with structured comments */
568
fputs ("%%EndComments\n", PS_Flags.FP);
569
fputs ("%%BeginProlog\n", PS_Flags.FP);
570
PrintStringArray (PS_Functions, ENTRIES (PS_Functions), PS_Flags.FP);
571
if (PS_Flags.InvertFlag)
572
PrintStringArray (PS_InvertColorFunctions,
573
ENTRIES (PS_InvertColorFunctions), PS_Flags.FP);
575
PrintStringArray (PS_ColorFunctions,
576
ENTRIES (PS_ColorFunctions), PS_Flags.FP);
577
fputs ("%%EndProlog\n", PS_Flags.FP);
578
fputs ("%%BeginDefaults\n", PS_Flags.FP);
579
fputs ("%%EndDefaults\n", PS_Flags.FP);
580
fputs ("%%BeginSetup\n", PS_Flags.FP);
581
PrintStringArray (PS_Setup, ENTRIES (PS_Setup), PS_Flags.FP);
582
fputs ("%%EndSetup\n", PS_Flags.FP);
586
fputs ("%%Page: 1 1\n", PS_Flags.FP);
587
fputs ("%%BeginPageSetup\n", PS_Flags.FP);
588
fputs ("%%EndPageSetup\n", PS_Flags.FP);
592
fputs ("gsave White newpath\n", PS_Flags.FP);
593
fprintf (PS_Flags.FP,
594
"%i %i moveto %i %i lineto %i %i lineto %i %i lineto\n",
595
(int) box.X1, (int) box.Y1,
596
(int) box.X2, (int) box.Y1,
597
(int) box.X2, (int) box.Y2, (int) box.X1, (int) box.Y2);
598
fputs ("closepath fill stroke grestore\n", PS_Flags.FP);
600
/* add information about layout size, offset ... */
601
fprintf (PS_Flags.FP, "%% PCBMIN(%d,%d), PCBMAX(%d,%d)\n",
602
(int) PS_Flags.BoundingBox.X1,
603
(int) PS_Flags.BoundingBox.Y1,
604
(int) PS_Flags.BoundingBox.X2, (int) PS_Flags.BoundingBox.Y2);
605
fprintf (PS_Flags.FP, "%% PCBOFFSET(%d,%d), PCBSCALE(%.5f)\n",
606
PS_Flags.OffsetX, PS_Flags.OffsetY, PS_Flags.Scale);
607
fputs ("% PCBSTARTDATA --- do not remove ---\n", PS_Flags.FP);
608
fputs ("gsave\n", PS_Flags.FP);
611
fputs ("grestore\ngsave\n", PS_Flags.FP);
614
/* now insert transformation commands (reverse order):
615
* - move upper/left edge of layout to (0,0)
616
* - mirror it to transform X to PostScript coordinates
617
* - move to (0,0) again
618
* - if rotation is required, rotate and move to (0,0)
619
* - apply user scaling
620
* - move to new offset
621
* - scale to PostScript (72 dots per inch)
623
fprintf (PS_Flags.FP, "%.5f %.5f scale\n", PS_UNIT, PS_UNIT);
624
fprintf (PS_Flags.FP, "%i %i translate\n",
625
PS_Flags.OffsetX, PS_Flags.OffsetY);
626
fprintf (PS_Flags.FP, "%.3f %.3f scale\n", PS_Flags.Scale, PS_Flags.Scale);
627
if (PS_Flags.RotateFlag)
629
fprintf (PS_Flags.FP, "%i 0 translate\n",
630
(int) PS_Flags.BoundingBox.Y2 - PS_Flags.BoundingBox.Y1);
631
fputs ("90 rotate\n", PS_Flags.FP);
633
if (PS_Flags.MirrorFlag)
635
fprintf (PS_Flags.FP, "0 %i translate\n",
636
(int) (PS_Flags.BoundingBox.Y2 - PS_Flags.BoundingBox.Y1));
637
fputs ("1 -1 scale\n", PS_Flags.FP);
639
fprintf (PS_Flags.FP, "%i %i translate\n",
640
-PS_Flags.BoundingBox.X1, -PS_Flags.BoundingBox.Y1);
641
644
/* ----------------------------------------------------------------------
642
645
* call exit routine for PostScript output
644
static void PS_Postamble(void)
648
static void PS_Exit(void)
652
658
/* ----------------------------------------------------------------------
653
659
* call exit routine for encapsulated PostScript output
655
static void EPS_Postamble(void)
659
static void EPS_Exit(void)
663
672
/* ---------------------------------------------------------------------------
664
673
* exit code for this driver is empty
666
static void PS_EPS_Exit(Boolean CreateEPS)
676
PS_EPS_Exit (Boolean CreateEPS)
668
/* print trailing commands */
669
fputs("grestore\n", PS_Flags.FP);
670
fputs("% PCBENDDATA --- do not remove ---\n", PS_Flags.FP);
672
fputs("showpage\n", PS_Flags.FP);
673
fputs("%%EOF\n", PS_Flags.FP);
678
/* print trailing commands */
679
fputs ("grestore\n", PS_Flags.FP);
680
fputs ("% PCBENDDATA --- do not remove ---\n", PS_Flags.FP);
682
fputs ("showpage\n", PS_Flags.FP);
683
fputs ("%%EOF\n", PS_Flags.FP);
676
686
/* ----------------------------------------------------------------------
679
static void PS_PrintLine(LineTypePtr Line, Boolean Clear)
690
PS_PrintLine (LineTypePtr Line, Boolean Clear)
682
fprintf(PS_Flags.FP, "%d %d %d %d %d CL\n",
683
(int) Line->Point1.X,
684
(int) Line->Point1.Y,
685
(int) Line->Point2.X,
686
(int) Line->Point2.Y,
687
(int) Line->Thickness + (int) Line->Clearance);
689
fprintf(PS_Flags.FP, "%d %d %d %d %d L\n",
690
(int) Line->Point1.X,
691
(int) Line->Point1.Y,
692
(int) Line->Point2.X,
693
(int) Line->Point2.Y,
694
(int) Line->Thickness);
693
fprintf (PS_Flags.FP, "%d %d %d %d %d CL\n",
694
(int) Line->Point1.X,
695
(int) Line->Point1.Y,
696
(int) Line->Point2.X,
697
(int) Line->Point2.Y,
698
(int) Line->Thickness + (int) Line->Clearance);
700
fprintf (PS_Flags.FP, "%d %d %d %d %d L\n",
701
(int) Line->Point1.X,
702
(int) Line->Point1.Y,
703
(int) Line->Point2.X,
704
(int) Line->Point2.Y, (int) Line->Thickness);
697
707
/* ---------------------------------------------------------------------------
700
static void PS_PrintArc(ArcTypePtr arc, Boolean Clear)
711
PS_PrintArc (ArcTypePtr arc, Boolean Clear)
703
fprintf(PS_Flags.FP, "%d %d %d %d %d %d %d CA\n",
708
(int) arc->Thickness + (int) arc->Clearance,
709
(arc->Delta < 0) ? arc->StartAngle + arc->Delta : arc->StartAngle,
710
(arc->Delta < 0) ? -arc->Delta : arc->Delta);
712
fprintf(PS_Flags.FP, "%d %d %d %d %d %d %d A\n",
717
(int) arc->Thickness,
718
(arc->Delta < 0) ? arc->StartAngle + arc->Delta : arc->StartAngle,
719
(arc->Delta < 0) ? -arc->Delta : arc->Delta);
714
fprintf (PS_Flags.FP, "%d %d %d %d %d %ld %ld CA\n",
719
(int) arc->Thickness + (int) arc->Clearance,
721
0) ? arc->StartAngle + arc->Delta : arc->StartAngle,
722
(arc->Delta < 0) ? -arc->Delta : arc->Delta);
724
fprintf (PS_Flags.FP, "%d %d %d %d %d %ld %ld A\n", (int) arc->X,
725
(int) arc->Y, (int) arc->Width, (int) arc->Height,
726
(int) arc->Thickness,
728
0) ? arc->StartAngle + arc->Delta : arc->StartAngle,
729
(arc->Delta < 0) ? -arc->Delta : arc->Delta);
722
732
/* ---------------------------------------------------------------------------
723
733
* prints a filled polygon
725
static void PS_PrintPolygon(PolygonTypePtr Ptr)
736
PS_PrintPolygon (PolygonTypePtr Ptr)
729
POLYGONPOINT_LOOP(Ptr,
732
fputc('\n', PS_Flags.FP);
733
fprintf(PS_Flags.FP, "%i %i ",
738
fprintf(PS_Flags.FP, "%d PO\n", Ptr->PointN);
740
POLYGONPOINT_LOOP (Ptr);
743
fputc ('\n', PS_Flags.FP);
744
fprintf (PS_Flags.FP, "%i %i ", (int) point->X, (int) point->Y);
747
fprintf (PS_Flags.FP, "%d PO\n", Ptr->PointN);
741
750
/* ----------------------------------------------------------------------
833
843
* Albert John FitzPatrick III <ajf_nylorac@acm.org>
834
844
* see ../CHANGES for details
836
static void PS_PrintText(TextTypePtr Text)
847
PS_PrintText (TextTypePtr Text)
838
PS_PrintTextLowLevel(Text);
849
PS_PrintTextLowLevel (Text);
841
852
/* ----------------------------------------------------------------------
842
853
* prints package outline
844
static void PS_PrintElementPackage(ElementTypePtr Element)
856
PS_PrintElementPackage (ElementTypePtr Element)
846
ELEMENTLINE_LOOP(Element, PS_PrintLine(line, False););
848
fprintf(PS_Flags.FP, "%d %d %d %d %d %d %d A\n",
853
(int) arc->Thickness,
857
if (!TEST_FLAG(HIDENAMEFLAG, Element))
858
PS_PrintTextLowLevel(&ELEMENT_TEXT(PCB, Element));
858
ELEMENTLINE_LOOP (Element);
860
PS_PrintLine (line, False);
865
fprintf (PS_Flags.FP, "%d %d %d %d %d %ld %ld A\n",
870
(int) arc->Thickness, arc->StartAngle, arc->Delta);
873
if (!TEST_FLAG (HIDENAMEFLAG, Element))
874
PS_PrintTextLowLevel (&ELEMENT_TEXT (PCB, Element));
861
877
/* ----------------------------------------------------------------------
864
static void PS_PrintPad(PadTypePtr Pad, int mode)
881
PS_PrintPad (PadTypePtr Pad, int mode)
866
Dimension scrunch = 0;
872
scrunch = Pad->Thickness;
875
scrunch = (Pad->Thickness + Pad->Clearance);
882
if (TEST_FLAG(SQUAREFLAG, Pad))
885
fprintf(PS_Flags.FP, "%d %d %d %d %s\n",
886
((Pad->Point1.X > Pad->Point2.X) ? Pad->Point2.X : Pad->Point1.X) - scrunch,
887
((Pad->Point1.Y > Pad->Point2.Y) ? Pad->Point2.Y : Pad->Point1.Y) - scrunch,
888
((Pad->Point1.X > Pad->Point2.X) ? Pad->Point1.X : Pad->Point2.X) + scrunch,
889
((Pad->Point1.Y > Pad->Point2.Y) ? Pad->Point1.Y : Pad->Point2.Y) + scrunch,
890
(mode == 1 || mode == 2) ? "CLRB" : "B");
893
fprintf(PS_Flags.FP, "%d %d %d %d %d %s\n",
899
(mode == 1 || mode == 2) ? "CLRPA" : "PA");
883
Dimension scrunch = 0;
889
scrunch = Pad->Thickness;
892
scrunch = (Pad->Thickness + Pad->Clearance);
899
if (TEST_FLAG (SQUAREFLAG, Pad))
902
fprintf (PS_Flags.FP, "%d %d %d %d %s\n",
903
((Pad->Point1.X > Pad->Point2.X) ? Pad->Point2.X : Pad->
905
((Pad->Point1.Y > Pad->Point2.Y) ? Pad->Point2.Y : Pad->
907
((Pad->Point1.X > Pad->Point2.X) ? Pad->Point1.X : Pad->
909
((Pad->Point1.Y > Pad->Point2.Y) ? Pad->Point1.Y : Pad->
910
Point2.Y) + scrunch, (mode == 1 || mode == 2) ? "CLRB" : "B");
913
fprintf (PS_Flags.FP, "%d %d %d %d %d %s\n",
918
(int) scrunch, (mode == 1 || mode == 2) ? "CLRPA" : "PA");
902
921
/* ----------------------------------------------------------------------
903
922
* prints a via or pin
905
static void PS_PrintPinOrVia(PinTypePtr Ptr, int mode)
912
size = Ptr->Thickness;
915
size = Ptr->Thickness + Ptr->Clearance;
923
fprintf(PS_Flags.FP, "%d %d %d %s\n",
927
TEST_FLAG(SQUAREFLAG, Ptr) ? "CLRPVSQ"
928
: TEST_FLAG(OCTAGONFLAG, Ptr) ? "CLRPV" : "CLRPVR");
931
if (TEST_FLAG(USETHERMALFLAG, Ptr))
933
int size2 = (size + Ptr->Clearance)/2;
934
if (!TEST_FLAG(SQUAREFLAG, Ptr))
935
size2 = (7 * size2) / 10;
936
fprintf(PS_Flags.FP, "%d %d %d %d %d L\n",
937
Ptr->X - size2, Ptr->Y - size2,
938
Ptr->X + size2, Ptr->Y + size2,
940
fprintf(PS_Flags.FP, "%d %d %d %d %d L\n",
941
Ptr->X - size2, Ptr->Y + size2,
942
Ptr->X + size2, Ptr->Y - size2,
944
CLEAR_FLAG(USETHERMALFLAG, Ptr);
946
fprintf(PS_Flags.FP, "%d %d %d %d %s\n",
950
(int) Ptr->DrillingHole,
951
TEST_FLAG(SQUAREFLAG, Ptr) ? "PVSQ"
952
: TEST_FLAG(OCTAGONFLAG, Ptr) ? "PV" : "PVR");
956
/* ---------------------------------------------------------------------------
957
* draws a filled rectangle for the ground plane
959
static void PS_FilledRectangle(Position X1, Position Y1,
960
Position X2, Position Y2)
962
fprintf(PS_Flags.FP, "%d %d %d %d FILL\n",
925
PS_PrintPinOrVia (PinTypePtr Ptr, int mode)
932
size = Ptr->Thickness;
935
size = Ptr->Thickness + Ptr->Clearance;
945
fprintf (PS_Flags.FP, "%d %d %d %s\n",
949
TEST_FLAG (SQUAREFLAG, Ptr) ? "CLRPVSQ"
950
: TEST_FLAG (OCTAGONFLAG, Ptr) ? "CLRPV" : "CLRPVR");
953
if (TEST_FLAG (USETHERMALFLAG, Ptr))
955
int size2 = (size + Ptr->Clearance) / 2;
956
int finger = (Ptr->Thickness - Ptr->DrillingHole) * PCB->ThermScale;
958
if (!TEST_FLAG (SQUAREFLAG, Ptr))
959
size2 = (7 * size2) / 10;
960
fprintf (PS_Flags.FP, "%d %d %d %d %d L\n",
961
Ptr->X - size2, Ptr->Y - size2,
962
Ptr->X + size2, Ptr->Y + size2, finger);
963
fprintf (PS_Flags.FP, "%d %d %d %d %d L\n",
964
Ptr->X - size2, Ptr->Y + size2,
965
Ptr->X + size2, Ptr->Y - size2, finger);
966
CLEAR_FLAG (USETHERMALFLAG, Ptr);
968
fprintf (PS_Flags.FP, "%d %d %d %d %s\n",
972
(int) Ptr->DrillingHole,
973
TEST_FLAG (SQUAREFLAG, Ptr) ? "PVSQ"
974
: TEST_FLAG (OCTAGONFLAG, Ptr) ? "PV" : "PVR");
969
978
/* ---------------------------------------------------------------------------
970
979
* draw the outlines of a layout;
971
980
* the upper/left and lower/right corner are passed
973
static void PS_Outline(Position X1, Position Y1,
974
Position X2, Position Y2)
983
PS_Outline (LocationType X1, LocationType Y1, LocationType X2, LocationType Y2)
976
fprintf(PS_Flags.FP, "%d %d %d %d Outline\n",
985
fprintf (PS_Flags.FP, "%d %d %d %d Outline\n",
986
(int) X1, (int) Y1, (int) X2, (int) Y2);
983
989
/* ---------------------------------------------------------------------------
984
990
* draw the alignment targets;
985
991
* the upper/left and lower/right corner are passed
987
static void PS_Alignment(Position X1, Position Y1,
988
Position X2, Position Y2)
994
PS_Alignment (LocationType X1, LocationType Y1, LocationType X2, LocationType Y2)
990
fprintf(PS_Flags.FP, "%d %d %d %d %d Alignment\n",
995
(int) Settings.AlignmentDistance);
996
fprintf (PS_Flags.FP, "%d %d %d %d %d Alignment\n",
998
(int) Y1, (int) X2, (int) Y2, (int) Settings.AlignmentDistance);
998
1001
/* ----------------------------------------------------------------------
999
1002
* prints a via or pin
1001
static void PS_DrillHelper(PinTypePtr Ptr, int unused)
1005
PS_DrillHelper (PinTypePtr Ptr, int unused)
1003
if (Ptr->DrillingHole >= 4*MIN_PINORVIAHOLE)
1004
fprintf(PS_Flags.FP, "%d %d %d %d DH\n",
1007
(int) 2*MIN_PINORVIAHOLE,
1008
(int) MIN_PINORVIAHOLE);
1007
if (Ptr->DrillingHole >= 4 * MIN_PINORVIAHOLE)
1008
fprintf (PS_Flags.FP, "%d %d %d %d DH\n",
1011
(int) 2 * MIN_PINORVIAHOLE, (int) MIN_PINORVIAHOLE);
1011
1014
/* ----------------------------------------------------------------------
1012
* queries color from X11 database and generates PostScript command
1013
* set PostScript identifier to the calculated value or to black by
1015
* Convert X color to postscript
1016
static void PS_SetColor(XColor RGB)
1018
PS_SetColor (XColor RGB)
1018
fprintf(PS_Flags.FP,
1019
"/Color {%.3f %.3f %.3f mysetrgbcolor} def Color\n",
1020
(float) RGB.red /65535.0,
1021
(float) RGB.green /65535.0,
1022
(float) RGB.blue /65535.0);
1020
fprintf (PS_Flags.FP,
1021
"/Color {%.3f %.3f %.3f mysetrgbcolor} def Color\n",
1022
(float) RGB.red / 65535.0,
1023
(float) RGB.green / 65535.0, (float) RGB.blue / 65535.0);