6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996, 2003 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
30 * 10/11/96 11:37 AJF Added support for a Text() driver function.
31 * This was done out of a pressing need to force text to be printed on the
32 * silkscreen layer. Perhaps the design is not the best.
65 #ifdef HAVE_LIBDMALLOC
71 /* ---------------------------------------------------------------------------
72 * prints a FAB drawing.
75 #define TEXT_SIZE MIL_TO_COORD(150)
76 #define TEXT_LINE MIL_TO_COORD(150)
77 #define DRILL_MARK_SIZE MIL_TO_COORD(16)
78 #define FAB_LINE_W MIL_TO_COORD(8)
81 fab_line (hidGC gc
, int x1
, int y1
, int x2
, int y2
)
83 gui
->draw_line (gc
, x1
, y1
, x2
, y2
);
87 fab_circle (hidGC gc
, int x
, int y
, int r
)
89 gui
->draw_arc (gc
, x
, y
, r
, r
, 0, 180);
90 gui
->draw_arc (gc
, x
, y
, r
, r
, 180, 180);
93 /* align is 0=left, 1=center, 2=right, add 8 for underline */
95 text_at (hidGC gc
, int x
, int y
, int align
, char *fmt
, ...)
101 FontTypePtr font
= &PCB
->Font
;
103 vsprintf (tmp
, fmt
, a
);
107 t
.Scale
= COORD_TO_MIL(TEXT_SIZE
); /* pcnt of 100mil base height */
108 t
.Flags
= NoFlags ();
111 for (i
= 0; tmp
[i
]; i
++)
113 (font
->Symbol
[(int) tmp
[i
]].Width
+ font
->Symbol
[(int) tmp
[i
]].Delta
);
114 w
= SCALE_TEXT (w
, t
.Scale
);
115 t
.X
-= w
* (align
& 3) / 2;
118 DrawTextLowLevel (&t
, 0);
121 t
.Y
+ SCALE_TEXT (font
->MaxHeight
, t
.Scale
) + MIL_TO_COORD(10),
123 t
.Y
+ SCALE_TEXT (font
->MaxHeight
, t
.Scale
) + MIL_TO_COORD(10));
126 /* Y, +, X, circle, square */
128 drill_sym (hidGC gc
, int idx
, int x
, int y
)
132 int s2
= (size
+ 1) * DRILL_MARK_SIZE
;
137 fab_line (gc
, x
, y
, x
, y
+ s2
);
138 fab_line (gc
, x
, y
, x
+ s2
* 13 / 15, y
- s2
/ 2);
139 fab_line (gc
, x
, y
, x
- s2
* 13 / 15, y
- s2
/ 2);
140 for (i
= 1; i
<= size
; i
++)
141 fab_circle (gc
, x
, y
, i
* DRILL_MARK_SIZE
);
145 fab_line (gc
, x
, y
- s2
, x
, y
+ s2
);
146 fab_line (gc
, x
- s2
, y
, x
+ s2
, y
);
147 for (i
= 1; i
<= size
; i
++)
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
);
153 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
154 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
155 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
156 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
160 fab_line (gc
, x
- s2
* 3 / 4, y
- s2
* 3 / 4, x
+ s2
* 3 / 4,
162 fab_line (gc
, x
- s2
* 3 / 4, y
+ s2
* 3 / 4, x
+ s2
* 3 / 4,
164 for (i
= 1; i
<= size
; i
++)
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
);
170 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
171 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
172 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
173 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
176 case 3: /* circle */ ;
177 for (i
= 0; i
<= size
; i
++)
178 fab_circle (gc
, x
, y
, (i
+ 1) * DRILL_MARK_SIZE
- DRILL_MARK_SIZE
/ 2);
181 for (i
= 1; i
<= size
+ 1; i
++)
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
);
187 fab_line (gc
, x
- i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
,
188 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
189 fab_line (gc
, x
+ i
* DRILL_MARK_SIZE
, y
- i
* DRILL_MARK_SIZE
,
190 x
+ i
* DRILL_MARK_SIZE
, y
+ i
* DRILL_MARK_SIZE
);
197 count_drill_lines (DrillInfoTypePtr AllDrills
)
200 for (n
= AllDrills
->DrillN
- 1; n
>= 0; n
--)
202 DrillTypePtr drill
= &(AllDrills
->Drill
[n
]);
203 if (drill
->PinCount
+ drill
->ViaCount
> drill
->UnplatedCount
)
205 if (drill
->UnplatedCount
)
213 PrintFab_overhang (void)
215 DrillInfoTypePtr AllDrills
= GetDrillInfo (PCB
->Data
);
216 int ds
= count_drill_lines (AllDrills
);
219 return (ds
+ 2) * TEXT_LINE
;
225 DrillInfoTypePtr AllDrills
;
226 int i
, n
, yoff
, total_drills
= 0, ds
= 0;
229 AllDrills
= GetDrillInfo (PCB
->Data
);
230 RoundDrillInfo (AllDrills
, MIL_TO_COORD(1));
233 /* count how many drill description lines will be needed */
234 ds
= count_drill_lines (AllDrills
);
237 * When we only have a few drill sizes we need to make sure the
238 * drill table header doesn't fall on top of the board info
243 yoff
-= (4 - ds
) * TEXT_LINE
;
246 gui
->set_line_width (gc
, FAB_LINE_W
);
248 for (n
= AllDrills
->DrillN
- 1; n
>= 0; n
--)
250 int plated_sym
= -1, unplated_sym
= -1;
251 DrillTypePtr drill
= &(AllDrills
->Drill
[n
]);
252 if (drill
->PinCount
+ drill
->ViaCount
> drill
->UnplatedCount
)
254 if (drill
->UnplatedCount
)
256 gui
->set_color (gc
, PCB
->PinColor
);
257 for (i
= 0; i
< drill
->PinN
; i
++)
258 drill_sym (gc
, TEST_FLAG (HOLEFLAG
, drill
->Pin
[i
]) ?
259 unplated_sym
: plated_sym
, drill
->Pin
[i
]->X
,
261 if (plated_sym
!= -1)
263 drill_sym (gc
, plated_sym
, TEXT_SIZE
, yoff
+ TEXT_SIZE
/ 4);
264 text_at (gc
, MIL_TO_COORD(1350), yoff
, MIL_TO_COORD(2), "YES");
265 text_at (gc
, MIL_TO_COORD(980), yoff
, MIL_TO_COORD(2), "%d",
266 drill
->PinCount
+ drill
->ViaCount
- drill
->UnplatedCount
);
268 if (unplated_sym
!= -1)
271 if (unplated_sym
!= -1)
273 drill_sym (gc
, unplated_sym
, TEXT_SIZE
, yoff
+ TEXT_SIZE
/ 4);
274 text_at (gc
, MIL_TO_COORD(1400), yoff
, MIL_TO_COORD(2), "NO");
275 text_at (gc
, MIL_TO_COORD(980), yoff
, MIL_TO_COORD(2), "%d", drill
->UnplatedCount
);
277 gui
->set_color (gc
, PCB
->ElementColor
);
278 text_at (gc
, MIL_TO_COORD(450), yoff
, MIL_TO_COORD(2), "%0.3f",
279 COORD_TO_INCH(drill
->DrillSize
) + 0.0004);
280 if (plated_sym
!= -1 && unplated_sym
!= -1)
281 text_at (gc
, MIL_TO_COORD(450), yoff
+ TEXT_LINE
, MIL_TO_COORD(2), "%0.3f",
282 COORD_TO_INCH(drill
->DrillSize
) + 0.0004);
284 total_drills
+= drill
->PinCount
;
285 total_drills
+= drill
->ViaCount
;
288 gui
->set_color (gc
, PCB
->ElementColor
);
289 text_at (gc
, 0, yoff
, MIL_TO_COORD(9), "Symbol");
290 text_at (gc
, MIL_TO_COORD(410), yoff
, MIL_TO_COORD(9), "Diam. (Inch)");
291 text_at (gc
, MIL_TO_COORD(950), yoff
, MIL_TO_COORD(9), "Count");
292 text_at (gc
, MIL_TO_COORD(1300), yoff
, MIL_TO_COORD(9), "Plated?");
294 text_at (gc
, 0, yoff
, 0,
295 "There are %d different drill sizes used in this layout, %d holes total",
296 AllDrills
->DrillN
, total_drills
);
297 /* Create a portable timestamp. */
298 currenttime
= time (NULL
);
300 /* avoid gcc complaints */
301 const char *fmt
= "%c UTC";
302 strftime (utcTime
, sizeof utcTime
, fmt
, gmtime (¤ttime
));
305 for (i
= 0; i
< max_copper_layer
; i
++)
307 LayerType
*l
= LAYER_PTR (i
);
308 if (l
->Name
&& (l
->LineN
|| l
->ArcN
))
310 if (strcmp ("route", l
->Name
) == 0)
312 if (strcmp ("outline", l
->Name
) == 0)
316 if (i
== max_copper_layer
)
318 gui
->set_line_width (gc
, MIL_TO_COORD(10));
319 gui
->draw_line (gc
, 0, 0, PCB
->MaxWidth
, 0);
320 gui
->draw_line (gc
, 0, 0, 0, PCB
->MaxHeight
);
321 gui
->draw_line (gc
, PCB
->MaxWidth
, 0, PCB
->MaxWidth
,
323 gui
->draw_line (gc
, 0, PCB
->MaxHeight
, PCB
->MaxWidth
,
325 /*FPrintOutline (); */
326 gui
->set_line_width (gc
, FAB_LINE_W
);
327 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0,
328 "Maximum Dimensions: %f mils wide, %f mils high",
329 COORD_TO_MIL(PCB
->MaxWidth
), COORD_TO_MIL(PCB
->MaxHeight
));
330 text_at (gc
, PCB
->MaxWidth
/ 2, PCB
->MaxHeight
+ MIL_TO_COORD(20), 1,
331 "Board outline is the centerline of this %f mil"
332 " rectangle - 0,0 to %f,%f mils",
333 COORD_TO_MIL(FAB_LINE_W
), COORD_TO_MIL(PCB
->MaxWidth
), COORD_TO_MIL(PCB
->MaxHeight
));
337 LayerTypePtr layer
= LAYER_PTR (i
);
338 gui
->set_line_width (gc
, MIL_TO_COORD(10));
341 gui
->draw_line (gc
, line
->Point1
.X
, line
->Point1
.Y
,
342 line
->Point2
.X
, line
->Point2
.Y
);
347 gui
->draw_arc (gc
, arc
->X
, arc
->Y
, arc
->Width
,
348 arc
->Height
, arc
->StartAngle
, arc
->Delta
);
353 DrawTextLowLevel (text
, 0);
356 gui
->set_line_width (gc
, FAB_LINE_W
);
357 text_at (gc
, PCB
->MaxWidth
/ 2, PCB
->MaxHeight
+ MIL_TO_COORD(20), 1,
358 "Board outline is the centerline of this path");
361 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0, "Date: %s", utcTime
);
363 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0, "Author: %s", pcb_author ());
365 text_at (gc
, MIL_TO_COORD(2000), yoff
, 0,
366 "Title: %s - Fabrication Drawing", UNKNOWN (PCB
->Name
));