4 * \brief Printing routines.
6 * \note Change History:\n
7 * 10/11/96 11:37 AJF Added support for a Text() driver function.\n
8 * This was done out of a pressing need to force text to be printed on
9 * the silkscreen layer.\n
10 * Perhaps the design is not the best.
14 * <h1><b>Copyright.</b></h1>\n
16 * PCB, interactive printed circuit board design
18 * Copyright (C) 1994,1995,1996, 2003 Thomas Nau
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 * Contact addresses for paper mail and Email:
36 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
38 * Thomas.Nau@rz.uni-ulm.de
68 #ifdef HAVE_LIBDMALLOC
72 /* ---------------------------------------------------------------------------
73 * prints a FAB drawing.
76 #define TEXT_SIZE MIL_TO_COORD(150)
77 #define TEXT_LINE MIL_TO_COORD(150)
78 #define DRILL_MARK_SIZE MIL_TO_COORD(16)
79 #define FAB_LINE_W MIL_TO_COORD(8)
82 fab_line (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
84 gui
->graphics
->draw_line (gc
, x1
, y1
, x2
, y2
);
88 fab_circle (hidGC gc
, int x
, int y
, int r
)
90 gui
->graphics
->draw_arc (gc
, x
, y
, r
, r
, 0, 180);
91 gui
->graphics
->draw_arc (gc
, x
, y
, r
, r
, 180, 180);
97 * align is 0=left, 1=center, 2=right, add 8 for underline.
100 text_at (hidGC gc
, int x
, int y
, int align
, char *fmt
, ...)
106 FontType
*font
= &PCB
->Font
;
108 vsprintf (tmp
, fmt
, a
);
112 t
.Scale
= COORD_TO_MIL(TEXT_SIZE
); /* pcnt of 100mil base height */
113 t
.Flags
= NoFlags ();
116 for (i
= 0; tmp
[i
]; i
++)
118 (font
->Symbol
[(int) tmp
[i
]].Width
+ font
->Symbol
[(int) tmp
[i
]].Delta
);
119 w
= SCALE_TEXT (w
, t
.Scale
);
120 t
.X
-= w
* (align
& 3) / 2;
123 gui
->graphics
->draw_pcb_text (gc
, &t
, 0);
126 t
.Y
+ SCALE_TEXT (font
->MaxHeight
, t
.Scale
) + MIL_TO_COORD(10),
128 t
.Y
+ SCALE_TEXT (font
->MaxHeight
, t
.Scale
) + MIL_TO_COORD(10));
134 * Y, +, X, circle, square.
137 drill_sym (hidGC gc
, int idx
, int x
, int y
)
141 int s2
= (size
+ 1) * DRILL_MARK_SIZE
;
146 fab_line (gc
, x
, y
, x
, y
+ s2
);
147 fab_line (gc
, x
, y
, x
+ s2
* 13 / 15, y
- s2
/ 2);
148 fab_line (gc
, x
, y
, x
- s2
* 13 / 15, y
- s2
/ 2);
149 for (i
= 1; i
<= size
; i
++)
150 fab_circle (gc
, x
, y
, i
* DRILL_MARK_SIZE
);
154 fab_line (gc
, x
, y
- s2
, x
, y
+ s2
);
155 fab_line (gc
, x
- s2
, y
, x
+ s2
, y
);
156 for (i
= 1; i
<= size
; i
++)
158 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
159 x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
);
160 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
161 x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
162 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
163 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
164 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
165 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
169 fab_line (gc
, x
- s2
* 3 / 4, y
- s2
* 3 / 4, x
+ s2
* 3 / 4,
171 fab_line (gc
, x
- s2
* 3 / 4, y
+ s2
* 3 / 4, x
+ s2
* 3 / 4,
173 for (i
= 1; i
<= size
; i
++)
175 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
176 x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
);
177 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
178 x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
179 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
180 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
181 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
182 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
185 case 3: /* circle */ ;
186 for (i
= 0; i
<= size
; i
++)
187 fab_circle (gc
, x
, y
, (i
+ 1) * DRILL_MARK_SIZE
- DRILL_MARK_SIZE
/ 2);
190 for (i
= 1; i
<= size
+ 1; i
++)
192 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
193 x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
);
194 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
195 x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
196 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
197 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
198 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
199 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
206 count_drill_lines (DrillInfoType
*AllDrills
)
209 for (n
= AllDrills
->DrillN
- 1; n
>= 0; n
--)
211 DrillType
*drill
= &(AllDrills
->Drill
[n
]);
212 if (drill
->PinCount
+ drill
->ViaCount
> drill
->UnplatedCount
)
214 if (drill
->UnplatedCount
)
222 PrintFab_overhang (void)
224 DrillInfoType
*AllDrills
= GetDrillInfo (PCB
->Data
);
225 int ds
= count_drill_lines (AllDrills
);
228 return (ds
+ 2) * TEXT_LINE
;
234 DrillInfoType
*AllDrills
;
235 int i
, n
, yoff
, total_drills
= 0, ds
= 0;
237 const char *utcFmt
= "%c UTC";
242 AllDrills
= GetDrillInfo (PCB
->Data
);
245 /* count how many drill description lines will be needed */
246 ds
= count_drill_lines (AllDrills
);
249 * When we only have a few drill sizes we need to make sure the
250 * drill table header doesn't fall on top of the board info
255 yoff
-= (4 - ds
) * TEXT_LINE
;
258 gui
->graphics
->set_line_width (gc
, FAB_LINE_W
);
260 for (n
= AllDrills
->DrillN
- 1; n
>= 0; n
--)
262 int plated_sym
= -1, unplated_sym
= -1;
263 DrillType
*drill
= &(AllDrills
->Drill
[n
]);
264 if (drill
->PinCount
+ drill
->ViaCount
> drill
->UnplatedCount
)
266 if (drill
->UnplatedCount
)
268 gui
->graphics
->set_color (gc
, PCB
->PinColor
);
269 for (i
= 0; i
< drill
->PinN
; i
++)
270 drill_sym (gc
, TEST_FLAG (HOLEFLAG
, drill
->Pin
[i
]) ?
271 unplated_sym
: plated_sym
, drill
->Pin
[i
]->X
,
273 if (plated_sym
!= -1)
275 drill_sym (gc
, plated_sym
, TEXT_SIZE
, yoff
+ TEXT_SIZE
/ 4);
276 text_at (gc
, MIL_TO_COORD(1350), yoff
, MIL_TO_COORD(2), "YES");
277 text_at (gc
, MIL_TO_COORD(980), yoff
, MIL_TO_COORD(2), "%d",
278 drill
->PinCount
+ drill
->ViaCount
- drill
->UnplatedCount
);
280 if (unplated_sym
!= -1)
283 if (unplated_sym
!= -1)
285 drill_sym (gc
, unplated_sym
, TEXT_SIZE
, yoff
+ TEXT_SIZE
/ 4);
286 text_at (gc
, MIL_TO_COORD(1400), yoff
, MIL_TO_COORD(2), "NO");
287 text_at (gc
, MIL_TO_COORD(980), yoff
, MIL_TO_COORD(2), "%d", drill
->UnplatedCount
);
289 gui
->graphics
->set_color (gc
, PCB
->ElementColor
);
290 text_at (gc
, MIL_TO_COORD(450), yoff
, MIL_TO_COORD(2), "%0.3f",
291 COORD_TO_INCH(drill
->DrillSize
));
292 if (plated_sym
!= -1 && unplated_sym
!= -1)
293 text_at (gc
, MIL_TO_COORD(450), yoff
+ TEXT_LINE
, MIL_TO_COORD(2), "%0.3f",
294 COORD_TO_INCH(drill
->DrillSize
));
296 total_drills
+= drill
->PinCount
;
297 total_drills
+= drill
->ViaCount
;
300 gui
->graphics
->set_color (gc
, PCB
->ElementColor
);
301 text_at (gc
, 0, yoff
, MIL_TO_COORD(9), "Symbol");
302 text_at (gc
, MIL_TO_COORD(410), yoff
, MIL_TO_COORD(9), "Diam. (Inch)");
303 text_at (gc
, MIL_TO_COORD(950), yoff
, MIL_TO_COORD(9), "Count");
304 text_at (gc
, MIL_TO_COORD(1300), yoff
, MIL_TO_COORD(9), "Plated?");
306 text_at (gc
, 0, yoff
, 0,
307 "There are %d different drill sizes used in this layout, %d holes total",
308 AllDrills
->DrillN
, total_drills
);
309 /* Create a portable timestamp. */
311 oldlocale
= setlocale (LC_TIME
, "C");
313 currenttime
= time (NULL
);
314 strftime (utcTime
, sizeof utcTime
, utcFmt
, gmtime (¤ttime
));
316 setlocale (LC_TIME
, oldlocale
);
320 for (i
= 0; i
< max_copper_layer
; i
++)
322 LayerType
*l
= LAYER_PTR (i
);
323 if (l
->Name
&& (l
->LineN
|| l
->ArcN
))
325 if (strcmp ("route", l
->Name
) == 0)
327 if (strcmp ("outline", l
->Name
) == 0)
331 if (i
== max_copper_layer
)
333 gui
->graphics
->set_line_width (gc
, MIL_TO_COORD(10));
334 gui
->graphics
->draw_line (gc
, 0, 0, PCB
->MaxWidth
, 0);
335 gui
->graphics
->draw_line (gc
, 0, 0, 0, PCB
->MaxHeight
);
336 gui
->graphics
->draw_line (gc
, PCB
->MaxWidth
, 0, PCB
->MaxWidth
,
338 gui
->graphics
->draw_line (gc
, 0, PCB
->MaxHeight
, PCB
->MaxWidth
,
340 /*FPrintOutline (); */
341 gui
->graphics
->set_line_width (gc
, FAB_LINE_W
);
342 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0,
343 "Maximum Dimensions: %f mils wide, %f mils high",
344 COORD_TO_MIL(PCB
->MaxWidth
), COORD_TO_MIL(PCB
->MaxHeight
));
345 text_at (gc
, PCB
->MaxWidth
/ 2, PCB
->MaxHeight
+ MIL_TO_COORD(20), 1,
346 "Board outline is the centerline of this %f mil"
347 " rectangle - 0,0 to %f,%f mils",
348 COORD_TO_MIL(FAB_LINE_W
), COORD_TO_MIL(PCB
->MaxWidth
), COORD_TO_MIL(PCB
->MaxHeight
));
352 LayerType
*layer
= LAYER_PTR (i
);
353 gui
->graphics
->set_line_width (gc
, MIL_TO_COORD(10));
356 gui
->graphics
->draw_line (gc
, line
->Point1
.X
, line
->Point1
.Y
,
357 line
->Point2
.X
, line
->Point2
.Y
);
362 gui
->graphics
->draw_arc (gc
, arc
->X
, arc
->Y
, arc
->Width
,
363 arc
->Height
, arc
->StartAngle
, arc
->Delta
);
368 gui
->graphics
->draw_pcb_text (gc
, text
, 0);
371 gui
->graphics
->set_line_width (gc
, FAB_LINE_W
);
372 text_at (gc
, PCB
->MaxWidth
/ 2, PCB
->MaxHeight
+ MIL_TO_COORD(20), 1,
373 "Board outline is the centerline of this path");
376 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0, "Date: %s", utcTime
);
378 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0, "Author: %s", pcb_author ());
380 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0,
381 "Title: %s - Fabrication Drawing", UNKNOWN (PCB
->Name
));