4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996, 2003 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
28 * 10/11/96 11:37 AJF Added support for a Text() driver function.
29 * This was done out of a pressing need to force text to be printed on the
30 * silkscreen layer. Perhaps the design is not the best.
64 #ifdef HAVE_LIBDMALLOC
68 /* ---------------------------------------------------------------------------
69 * prints a FAB drawing.
72 #define TEXT_SIZE MIL_TO_COORD(150)
73 #define TEXT_LINE MIL_TO_COORD(150)
74 #define DRILL_MARK_SIZE MIL_TO_COORD(16)
75 #define FAB_LINE_W MIL_TO_COORD(8)
78 fab_line (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
80 gui
->graphics
->draw_line (gc
, x1
, y1
, x2
, y2
);
84 fab_circle (hidGC gc
, int x
, int y
, int r
)
86 gui
->graphics
->draw_arc (gc
, x
, y
, r
, r
, 0, 180);
87 gui
->graphics
->draw_arc (gc
, x
, y
, r
, r
, 180, 180);
90 /* align is 0=left, 1=center, 2=right, add 8 for underline */
92 text_at (hidGC gc
, int x
, int y
, int align
, char *fmt
, ...)
98 FontType
*font
= &PCB
->Font
;
100 vsprintf (tmp
, fmt
, a
);
104 t
.Scale
= COORD_TO_MIL(TEXT_SIZE
); /* pcnt of 100mil base height */
105 t
.Flags
= NoFlags ();
108 for (i
= 0; tmp
[i
]; i
++)
110 (font
->Symbol
[(int) tmp
[i
]].Width
+ font
->Symbol
[(int) tmp
[i
]].Delta
);
111 w
= SCALE_TEXT (w
, t
.Scale
);
112 t
.X
-= w
* (align
& 3) / 2;
115 gui
->graphics
->draw_pcb_text (gc
, &t
, 0);
118 t
.Y
+ SCALE_TEXT (font
->MaxHeight
, t
.Scale
) + MIL_TO_COORD(10),
120 t
.Y
+ SCALE_TEXT (font
->MaxHeight
, t
.Scale
) + MIL_TO_COORD(10));
123 /* Y, +, X, circle, square */
125 drill_sym (hidGC gc
, int idx
, int x
, int y
)
129 int s2
= (size
+ 1) * DRILL_MARK_SIZE
;
134 fab_line (gc
, x
, y
, x
, y
+ s2
);
135 fab_line (gc
, x
, y
, x
+ s2
* 13 / 15, y
- s2
/ 2);
136 fab_line (gc
, x
, y
, x
- s2
* 13 / 15, y
- s2
/ 2);
137 for (i
= 1; i
<= size
; i
++)
138 fab_circle (gc
, x
, y
, i
* DRILL_MARK_SIZE
);
142 fab_line (gc
, x
, y
- s2
, x
, y
+ s2
);
143 fab_line (gc
, x
- s2
, y
, x
+ s2
, y
);
144 for (i
= 1; i
<= size
; i
++)
146 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
147 x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
);
148 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
149 x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
150 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
151 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
152 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
153 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
157 fab_line (gc
, x
- s2
* 3 / 4, y
- s2
* 3 / 4, x
+ s2
* 3 / 4,
159 fab_line (gc
, x
- s2
* 3 / 4, y
+ s2
* 3 / 4, x
+ s2
* 3 / 4,
161 for (i
= 1; i
<= size
; i
++)
163 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
164 x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
);
165 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
166 x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
167 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
168 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
169 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
170 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
173 case 3: /* circle */ ;
174 for (i
= 0; i
<= size
; i
++)
175 fab_circle (gc
, x
, y
, (i
+ 1) * DRILL_MARK_SIZE
- DRILL_MARK_SIZE
/ 2);
178 for (i
= 1; i
<= size
+ 1; i
++)
180 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
181 x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
);
182 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
183 x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
184 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
185 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
186 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
187 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
194 count_drill_lines (DrillInfoType
*AllDrills
)
197 for (n
= AllDrills
->DrillN
- 1; n
>= 0; n
--)
199 DrillType
*drill
= &(AllDrills
->Drill
[n
]);
200 if (drill
->PinCount
+ drill
->ViaCount
> drill
->UnplatedCount
)
202 if (drill
->UnplatedCount
)
210 PrintFab_overhang (void)
212 DrillInfoType
*AllDrills
= GetDrillInfo (PCB
->Data
);
213 int ds
= count_drill_lines (AllDrills
);
216 return (ds
+ 2) * TEXT_LINE
;
222 DrillInfoType
*AllDrills
;
223 int i
, n
, yoff
, total_drills
= 0, ds
= 0;
226 AllDrills
= GetDrillInfo (PCB
->Data
);
227 RoundDrillInfo (AllDrills
, MIL_TO_COORD(1));
230 /* count how many drill description lines will be needed */
231 ds
= count_drill_lines (AllDrills
);
234 * When we only have a few drill sizes we need to make sure the
235 * drill table header doesn't fall on top of the board info
240 yoff
-= (4 - ds
) * TEXT_LINE
;
243 gui
->graphics
->set_line_width (gc
, FAB_LINE_W
);
245 for (n
= AllDrills
->DrillN
- 1; n
>= 0; n
--)
247 int plated_sym
= -1, unplated_sym
= -1;
248 DrillType
*drill
= &(AllDrills
->Drill
[n
]);
249 if (drill
->PinCount
+ drill
->ViaCount
> drill
->UnplatedCount
)
251 if (drill
->UnplatedCount
)
253 gui
->graphics
->set_color (gc
, PCB
->PinColor
);
254 for (i
= 0; i
< drill
->PinN
; i
++)
255 drill_sym (gc
, TEST_FLAG (HOLEFLAG
, drill
->Pin
[i
]) ?
256 unplated_sym
: plated_sym
, drill
->Pin
[i
]->X
,
258 if (plated_sym
!= -1)
260 drill_sym (gc
, plated_sym
, TEXT_SIZE
, yoff
+ TEXT_SIZE
/ 4);
261 text_at (gc
, MIL_TO_COORD(1350), yoff
, MIL_TO_COORD(2), "YES");
262 text_at (gc
, MIL_TO_COORD(980), yoff
, MIL_TO_COORD(2), "%d",
263 drill
->PinCount
+ drill
->ViaCount
- drill
->UnplatedCount
);
265 if (unplated_sym
!= -1)
268 if (unplated_sym
!= -1)
270 drill_sym (gc
, unplated_sym
, TEXT_SIZE
, yoff
+ TEXT_SIZE
/ 4);
271 text_at (gc
, MIL_TO_COORD(1400), yoff
, MIL_TO_COORD(2), "NO");
272 text_at (gc
, MIL_TO_COORD(980), yoff
, MIL_TO_COORD(2), "%d", drill
->UnplatedCount
);
274 gui
->graphics
->set_color (gc
, PCB
->ElementColor
);
275 text_at (gc
, MIL_TO_COORD(450), yoff
, MIL_TO_COORD(2), "%0.3f",
276 COORD_TO_INCH(drill
->DrillSize
) + 0.0004);
277 if (plated_sym
!= -1 && unplated_sym
!= -1)
278 text_at (gc
, MIL_TO_COORD(450), yoff
+ TEXT_LINE
, MIL_TO_COORD(2), "%0.3f",
279 COORD_TO_INCH(drill
->DrillSize
) + 0.0004);
281 total_drills
+= drill
->PinCount
;
282 total_drills
+= drill
->ViaCount
;
285 gui
->graphics
->set_color (gc
, PCB
->ElementColor
);
286 text_at (gc
, 0, yoff
, MIL_TO_COORD(9), "Symbol");
287 text_at (gc
, MIL_TO_COORD(410), yoff
, MIL_TO_COORD(9), "Diam. (Inch)");
288 text_at (gc
, MIL_TO_COORD(950), yoff
, MIL_TO_COORD(9), "Count");
289 text_at (gc
, MIL_TO_COORD(1300), yoff
, MIL_TO_COORD(9), "Plated?");
291 text_at (gc
, 0, yoff
, 0,
292 "There are %d different drill sizes used in this layout, %d holes total",
293 AllDrills
->DrillN
, total_drills
);
294 /* Create a portable timestamp. */
295 currenttime
= time (NULL
);
297 /* avoid gcc complaints */
298 const char *fmt
= "%c UTC";
299 strftime (utcTime
, sizeof utcTime
, fmt
, gmtime (¤ttime
));
302 for (i
= 0; i
< max_copper_layer
; i
++)
304 LayerType
*l
= LAYER_PTR (i
);
305 if (l
->Name
&& (l
->LineN
|| l
->ArcN
))
307 if (strcmp ("route", l
->Name
) == 0)
309 if (strcmp ("outline", l
->Name
) == 0)
313 if (i
== max_copper_layer
)
315 gui
->graphics
->set_line_width (gc
, MIL_TO_COORD(10));
316 gui
->graphics
->draw_line (gc
, 0, 0, PCB
->MaxWidth
, 0);
317 gui
->graphics
->draw_line (gc
, 0, 0, 0, PCB
->MaxHeight
);
318 gui
->graphics
->draw_line (gc
, PCB
->MaxWidth
, 0, PCB
->MaxWidth
,
320 gui
->graphics
->draw_line (gc
, 0, PCB
->MaxHeight
, PCB
->MaxWidth
,
322 /*FPrintOutline (); */
323 gui
->graphics
->set_line_width (gc
, FAB_LINE_W
);
324 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0,
325 "Maximum Dimensions: %f mils wide, %f mils high",
326 COORD_TO_MIL(PCB
->MaxWidth
), COORD_TO_MIL(PCB
->MaxHeight
));
327 text_at (gc
, PCB
->MaxWidth
/ 2, PCB
->MaxHeight
+ MIL_TO_COORD(20), 1,
328 "Board outline is the centerline of this %f mil"
329 " rectangle - 0,0 to %f,%f mils",
330 COORD_TO_MIL(FAB_LINE_W
), COORD_TO_MIL(PCB
->MaxWidth
), COORD_TO_MIL(PCB
->MaxHeight
));
334 LayerType
*layer
= LAYER_PTR (i
);
335 gui
->graphics
->set_line_width (gc
, MIL_TO_COORD(10));
338 gui
->graphics
->draw_line (gc
, line
->Point1
.X
, line
->Point1
.Y
,
339 line
->Point2
.X
, line
->Point2
.Y
);
344 gui
->graphics
->draw_arc (gc
, arc
->X
, arc
->Y
, arc
->Width
,
345 arc
->Height
, arc
->StartAngle
, arc
->Delta
);
350 gui
->graphics
->draw_pcb_text (gc
, text
, 0);
353 gui
->graphics
->set_line_width (gc
, FAB_LINE_W
);
354 text_at (gc
, PCB
->MaxWidth
/ 2, PCB
->MaxHeight
+ MIL_TO_COORD(20), 1,
355 "Board outline is the centerline of this path");
358 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0, "Date: %s", utcTime
);
360 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0, "Author: %s", pcb_author ());
362 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0,
363 "Title: %s - Fabrication Drawing", UNKNOWN (PCB
->Name
));