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.
63 #ifdef HAVE_LIBDMALLOC
67 /* ---------------------------------------------------------------------------
68 * prints a FAB drawing.
71 #define TEXT_SIZE MIL_TO_COORD(150)
72 #define TEXT_LINE MIL_TO_COORD(150)
73 #define DRILL_MARK_SIZE MIL_TO_COORD(16)
74 #define FAB_LINE_W MIL_TO_COORD(8)
77 fab_line (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
79 gui
->draw_line (gc
, x1
, y1
, x2
, y2
);
83 fab_circle (hidGC gc
, int x
, int y
, int r
)
85 gui
->draw_arc (gc
, x
, y
, r
, r
, 0, 180);
86 gui
->draw_arc (gc
, x
, y
, r
, r
, 180, 180);
89 /* align is 0=left, 1=center, 2=right, add 8 for underline */
91 text_at (hidGC gc
, int x
, int y
, int align
, char *fmt
, ...)
97 FontType
*font
= &PCB
->Font
;
99 vsprintf (tmp
, fmt
, a
);
103 t
.Scale
= COORD_TO_MIL(TEXT_SIZE
); /* pcnt of 100mil base height */
104 t
.Flags
= NoFlags ();
107 for (i
= 0; tmp
[i
]; i
++)
109 (font
->Symbol
[(int) tmp
[i
]].Width
+ font
->Symbol
[(int) tmp
[i
]].Delta
);
110 w
= SCALE_TEXT (w
, t
.Scale
);
111 t
.X
-= w
* (align
& 3) / 2;
114 DrawTextLowLevel (&t
, 0);
117 t
.Y
+ SCALE_TEXT (font
->MaxHeight
, t
.Scale
) + MIL_TO_COORD(10),
119 t
.Y
+ SCALE_TEXT (font
->MaxHeight
, t
.Scale
) + MIL_TO_COORD(10));
122 /* Y, +, X, circle, square */
124 drill_sym (hidGC gc
, int idx
, int x
, int y
)
128 int s2
= (size
+ 1) * DRILL_MARK_SIZE
;
133 fab_line (gc
, x
, y
, x
, y
+ s2
);
134 fab_line (gc
, x
, y
, x
+ s2
* 13 / 15, y
- s2
/ 2);
135 fab_line (gc
, x
, y
, x
- s2
* 13 / 15, y
- s2
/ 2);
136 for (i
= 1; i
<= size
; i
++)
137 fab_circle (gc
, x
, y
, i
* DRILL_MARK_SIZE
);
141 fab_line (gc
, x
, y
- s2
, x
, y
+ s2
);
142 fab_line (gc
, x
- s2
, y
, x
+ s2
, y
);
143 for (i
= 1; i
<= size
; i
++)
145 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
146 x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
);
147 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
148 x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
149 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
150 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
151 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
152 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
156 fab_line (gc
, x
- s2
* 3 / 4, y
- s2
* 3 / 4, x
+ s2
* 3 / 4,
158 fab_line (gc
, x
- s2
* 3 / 4, y
+ s2
* 3 / 4, x
+ s2
* 3 / 4,
160 for (i
= 1; i
<= size
; i
++)
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
);
166 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
167 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
168 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
169 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
172 case 3: /* circle */ ;
173 for (i
= 0; i
<= size
; i
++)
174 fab_circle (gc
, x
, y
, (i
+ 1) * DRILL_MARK_SIZE
- DRILL_MARK_SIZE
/ 2);
177 for (i
= 1; i
<= size
+ 1; i
++)
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
);
183 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
184 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
185 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
186 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
193 count_drill_lines (DrillInfoType
*AllDrills
)
196 for (n
= AllDrills
->DrillN
- 1; n
>= 0; n
--)
198 DrillType
*drill
= &(AllDrills
->Drill
[n
]);
199 if (drill
->PinCount
+ drill
->ViaCount
> drill
->UnplatedCount
)
201 if (drill
->UnplatedCount
)
209 PrintFab_overhang (void)
211 DrillInfoType
*AllDrills
= GetDrillInfo (PCB
->Data
);
212 int ds
= count_drill_lines (AllDrills
);
215 return (ds
+ 2) * TEXT_LINE
;
221 DrillInfoType
*AllDrills
;
222 int i
, n
, yoff
, total_drills
= 0, ds
= 0;
225 AllDrills
= GetDrillInfo (PCB
->Data
);
226 RoundDrillInfo (AllDrills
, MIL_TO_COORD(1));
229 /* count how many drill description lines will be needed */
230 ds
= count_drill_lines (AllDrills
);
233 * When we only have a few drill sizes we need to make sure the
234 * drill table header doesn't fall on top of the board info
239 yoff
-= (4 - ds
) * TEXT_LINE
;
242 gui
->set_line_width (gc
, FAB_LINE_W
);
244 for (n
= AllDrills
->DrillN
- 1; n
>= 0; n
--)
246 int plated_sym
= -1, unplated_sym
= -1;
247 DrillType
*drill
= &(AllDrills
->Drill
[n
]);
248 if (drill
->PinCount
+ drill
->ViaCount
> drill
->UnplatedCount
)
250 if (drill
->UnplatedCount
)
252 gui
->set_color (gc
, PCB
->PinColor
);
253 for (i
= 0; i
< drill
->PinN
; i
++)
254 drill_sym (gc
, TEST_FLAG (HOLEFLAG
, drill
->Pin
[i
]) ?
255 unplated_sym
: plated_sym
, drill
->Pin
[i
]->X
,
257 if (plated_sym
!= -1)
259 drill_sym (gc
, plated_sym
, TEXT_SIZE
, yoff
+ TEXT_SIZE
/ 4);
260 text_at (gc
, MIL_TO_COORD(1350), yoff
, MIL_TO_COORD(2), "YES");
261 text_at (gc
, MIL_TO_COORD(980), yoff
, MIL_TO_COORD(2), "%d",
262 drill
->PinCount
+ drill
->ViaCount
- drill
->UnplatedCount
);
264 if (unplated_sym
!= -1)
267 if (unplated_sym
!= -1)
269 drill_sym (gc
, unplated_sym
, TEXT_SIZE
, yoff
+ TEXT_SIZE
/ 4);
270 text_at (gc
, MIL_TO_COORD(1400), yoff
, MIL_TO_COORD(2), "NO");
271 text_at (gc
, MIL_TO_COORD(980), yoff
, MIL_TO_COORD(2), "%d", drill
->UnplatedCount
);
273 gui
->set_color (gc
, PCB
->ElementColor
);
274 text_at (gc
, MIL_TO_COORD(450), yoff
, MIL_TO_COORD(2), "%0.3f",
275 COORD_TO_INCH(drill
->DrillSize
) + 0.0004);
276 if (plated_sym
!= -1 && unplated_sym
!= -1)
277 text_at (gc
, MIL_TO_COORD(450), yoff
+ TEXT_LINE
, MIL_TO_COORD(2), "%0.3f",
278 COORD_TO_INCH(drill
->DrillSize
) + 0.0004);
280 total_drills
+= drill
->PinCount
;
281 total_drills
+= drill
->ViaCount
;
284 gui
->set_color (gc
, PCB
->ElementColor
);
285 text_at (gc
, 0, yoff
, MIL_TO_COORD(9), "Symbol");
286 text_at (gc
, MIL_TO_COORD(410), yoff
, MIL_TO_COORD(9), "Diam. (Inch)");
287 text_at (gc
, MIL_TO_COORD(950), yoff
, MIL_TO_COORD(9), "Count");
288 text_at (gc
, MIL_TO_COORD(1300), yoff
, MIL_TO_COORD(9), "Plated?");
290 text_at (gc
, 0, yoff
, 0,
291 "There are %d different drill sizes used in this layout, %d holes total",
292 AllDrills
->DrillN
, total_drills
);
293 /* Create a portable timestamp. */
294 currenttime
= time (NULL
);
296 /* avoid gcc complaints */
297 const char *fmt
= "%c UTC";
298 strftime (utcTime
, sizeof utcTime
, fmt
, gmtime (¤ttime
));
301 for (i
= 0; i
< max_copper_layer
; i
++)
303 LayerType
*l
= LAYER_PTR (i
);
304 if (l
->Name
&& (l
->LineN
|| l
->ArcN
))
306 if (strcmp ("route", l
->Name
) == 0)
308 if (strcmp ("outline", l
->Name
) == 0)
312 if (i
== max_copper_layer
)
314 gui
->set_line_width (gc
, MIL_TO_COORD(10));
315 gui
->draw_line (gc
, 0, 0, PCB
->MaxWidth
, 0);
316 gui
->draw_line (gc
, 0, 0, 0, PCB
->MaxHeight
);
317 gui
->draw_line (gc
, PCB
->MaxWidth
, 0, PCB
->MaxWidth
,
319 gui
->draw_line (gc
, 0, PCB
->MaxHeight
, PCB
->MaxWidth
,
321 /*FPrintOutline (); */
322 gui
->set_line_width (gc
, FAB_LINE_W
);
323 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0,
324 "Maximum Dimensions: %f mils wide, %f mils high",
325 COORD_TO_MIL(PCB
->MaxWidth
), COORD_TO_MIL(PCB
->MaxHeight
));
326 text_at (gc
, PCB
->MaxWidth
/ 2, PCB
->MaxHeight
+ MIL_TO_COORD(20), 1,
327 "Board outline is the centerline of this %f mil"
328 " rectangle - 0,0 to %f,%f mils",
329 COORD_TO_MIL(FAB_LINE_W
), COORD_TO_MIL(PCB
->MaxWidth
), COORD_TO_MIL(PCB
->MaxHeight
));
333 LayerType
*layer
= LAYER_PTR (i
);
334 gui
->set_line_width (gc
, MIL_TO_COORD(10));
337 gui
->draw_line (gc
, line
->Point1
.X
, line
->Point1
.Y
,
338 line
->Point2
.X
, line
->Point2
.Y
);
343 gui
->draw_arc (gc
, arc
->X
, arc
->Y
, arc
->Width
,
344 arc
->Height
, arc
->StartAngle
, arc
->Delta
);
349 DrawTextLowLevel (text
, 0);
352 gui
->set_line_width (gc
, FAB_LINE_W
);
353 text_at (gc
, PCB
->MaxWidth
/ 2, PCB
->MaxHeight
+ MIL_TO_COORD(20), 1,
354 "Board outline is the centerline of this path");
357 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0, "Date: %s", utcTime
);
359 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0, "Author: %s", pcb_author ());
361 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0,
362 "Title: %s - Fabrication Drawing", UNKNOWN (PCB
->Name
));