Introduce POLYGONHOLE_MODE for creating holes in polygons
[geda-pcb/gde.git] / src / print.c
blob3831b4ad93d82a029a1eb65078ccc7e4dfcd550c
1 /* $Id$ */
3 /*
4 * COPYRIGHT
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
29 /* Change History:
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.
36 /* printing routines
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
42 #include "global.h"
44 #include <time.h>
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48 #include <setjmp.h>
51 #include "data.h"
52 #include "draw.h"
53 #include "drill.h"
54 #include "file.h"
55 #include "find.h"
56 #include "error.h"
57 #include "misc.h"
58 #include "print.h"
59 #include "polygon.h"
60 #include "rtree.h"
61 #include "search.h"
63 #include "hid.h"
65 #ifdef HAVE_LIBDMALLOC
66 #include <dmalloc.h>
67 #endif
69 RCSID ("$Id$");
71 /* ---------------------------------------------------------------------------
72 * prints a FAB drawing.
75 #define TEXT_SIZE 150
76 #define TEXT_LINE 15000
77 #define FAB_LINE_W 800
79 static void
80 fab_line (int x1, int y1, int x2, int y2)
82 gui->draw_line (Output.fgGC, x1, y1, x2, y2);
85 static void
86 fab_circle (int x, int y, int r)
88 gui->draw_arc (Output.fgGC, x, y, r, r, 0, 180);
89 gui->draw_arc (Output.fgGC, x, y, r, r, 180, 180);
92 /* align is 0=left, 1=center, 2=right, add 8 for underline */
93 static void
94 text_at (int x, int y, int align, char *fmt, ...)
96 char tmp[512];
97 int w = 0, i;
98 TextType t;
99 va_list a;
100 FontTypePtr font = &PCB->Font;
101 va_start (a, fmt);
102 vsprintf (tmp, fmt, a);
103 va_end (a);
104 t.Direction = 0;
105 t.TextString = tmp;
106 t.Scale = TEXT_SIZE;
107 t.Flags = NoFlags ();
108 t.X = x;
109 t.Y = y;
110 for (i = 0; tmp[i]; i++)
111 w +=
112 (font->Symbol[(int) tmp[i]].Width + font->Symbol[(int) tmp[i]].Delta);
113 w = w * TEXT_SIZE / 100;
114 t.X -= w * (align & 3) / 2;
115 if (t.X < 0)
116 t.X = 0;
117 DrawTextLowLevel (&t, 0);
118 if (align & 8)
119 fab_line (t.X,
120 t.Y +
121 font->MaxHeight * TEXT_SIZE /
122 100 + 1000, t.X + w,
123 t.Y + font->MaxHeight * TEXT_SIZE / 100 + 1000);
126 /* Y, +, X, circle, square */
127 static void
128 drill_sym (int idx, int x, int y)
130 int type = idx % 5;
131 int size = idx / 5;
132 int s2 = (size + 1) * 1600;
133 int i;
134 switch (type)
136 case 0: /* Y */ ;
137 fab_line (x, y, x, y + s2);
138 fab_line (x, y, x + s2 * 13 / 15, y - s2 / 2);
139 fab_line (x, y, x - s2 * 13 / 15, y - s2 / 2);
140 for (i = 1; i <= size; i++)
141 fab_circle (x, y, i * 1600);
142 break;
143 case 1: /* + */
145 fab_line (x, y - s2, x, y + s2);
146 fab_line (x - s2, y, x + s2, y);
147 for (i = 1; i <= size; i++)
149 fab_line (x - i * 1600, y - i * 1600, x + i * 1600, y - i * 1600);
150 fab_line (x - i * 1600, y - i * 1600, x - i * 1600, y + i * 1600);
151 fab_line (x - i * 1600, y + i * 1600, x + i * 1600, y + i * 1600);
152 fab_line (x + i * 1600, y - i * 1600, x + i * 1600, y + i * 1600);
154 break;
155 case 2: /* X */ ;
156 fab_line (x - s2 * 3 / 4, y - s2 * 3 / 4, x + s2 * 3 / 4,
157 y + s2 * 3 / 4);
158 fab_line (x - s2 * 3 / 4, y + s2 * 3 / 4, x + s2 * 3 / 4,
159 y - s2 * 3 / 4);
160 for (i = 1; i <= size; i++)
162 fab_line (x - i * 1600, y - i * 1600, x + i * 1600, y - i * 1600);
163 fab_line (x - i * 1600, y - i * 1600, x - i * 1600, y + i * 1600);
164 fab_line (x - i * 1600, y + i * 1600, x + i * 1600, y + i * 1600);
165 fab_line (x + i * 1600, y - i * 1600, x + i * 1600, y + i * 1600);
167 break;
168 case 3: /* circle */ ;
169 for (i = 0; i <= size; i++)
170 fab_circle (x, y, (i + 1) * 1600 - 800);
171 break;
172 case 4: /* square */
173 for (i = 1; i <= size + 1; i++)
175 fab_line (x - i * 1600, y - i * 1600, x + i * 1600, y - i * 1600);
176 fab_line (x - i * 1600, y - i * 1600, x - i * 1600, y + i * 1600);
177 fab_line (x - i * 1600, y + i * 1600, x + i * 1600, y + i * 1600);
178 fab_line (x + i * 1600, y - i * 1600, x + i * 1600, y + i * 1600);
180 break;
184 static int
185 count_drill_lines (DrillInfoTypePtr AllDrills)
187 int n, ds = 0;
188 for (n = AllDrills->DrillN - 1; n >= 0; n--)
190 DrillTypePtr drill = &(AllDrills->Drill[n]);
191 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount)
192 ds++;
193 if (drill->UnplatedCount)
194 ds++;
196 return ds;
201 PrintFab_overhang (void)
203 DrillInfoTypePtr AllDrills = GetDrillInfo (PCB->Data);
204 int ds = count_drill_lines (AllDrills);
205 if (ds < 4)
206 ds = 4;
207 return (ds + 2) * TEXT_LINE;
210 void
211 PrintFab (void)
213 PinType tmp_pin;
214 DrillInfoTypePtr AllDrills;
215 int i, n, yoff, total_drills = 0, ds = 0;
216 time_t currenttime;
217 char utcTime[64];
218 tmp_pin.Flags = NoFlags ();
219 AllDrills = GetDrillInfo (PCB->Data);
220 RoundDrillInfo (AllDrills, 100);
221 yoff = -TEXT_LINE;
223 /* count how many drill description lines will be needed */
224 ds = count_drill_lines (AllDrills);
227 * When we only have a few drill sizes we need to make sure the
228 * drill table header doesn't fall on top of the board info
229 * section.
231 if (ds < 4)
233 yoff -= (4 - ds) * TEXT_LINE;
236 gui->set_line_width (Output.fgGC, FAB_LINE_W);
238 for (n = AllDrills->DrillN - 1; n >= 0; n--)
240 int plated_sym = -1, unplated_sym = -1;
241 DrillTypePtr drill = &(AllDrills->Drill[n]);
242 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount)
243 plated_sym = --ds;
244 if (drill->UnplatedCount)
245 unplated_sym = --ds;
246 gui->set_color (Output.fgGC, PCB->PinColor);
247 for (i = 0; i < drill->PinN; i++)
248 drill_sym (TEST_FLAG (HOLEFLAG, drill->Pin[i]) ?
249 unplated_sym : plated_sym, drill->Pin[i]->X,
250 drill->Pin[i]->Y);
251 if (plated_sym != -1)
253 drill_sym (plated_sym, 100 * TEXT_SIZE, yoff + 100 * TEXT_SIZE / 4);
254 text_at (135000, yoff, 200, "YES");
255 text_at (98000, yoff, 200, "%d",
256 drill->PinCount + drill->ViaCount - drill->UnplatedCount);
258 if (unplated_sym != -1)
259 yoff -= TEXT_LINE;
261 if (unplated_sym != -1)
263 drill_sym (unplated_sym, 100 * TEXT_SIZE,
264 yoff + 100 * TEXT_SIZE / 4);
265 text_at (140000, yoff, 200, "NO");
266 text_at (98000, yoff, 200, "%d", drill->UnplatedCount);
268 gui->set_color (Output.fgGC, PCB->ElementColor);
269 text_at (45000, yoff, 200, "%0.3f",
270 drill->DrillSize / 100000. + 0.0004);
271 if (plated_sym != -1 && unplated_sym != -1)
272 text_at (45000, yoff + TEXT_LINE, 200, "%0.3f",
273 drill->DrillSize / 100000. + 0.0004);
274 yoff -= TEXT_LINE;
275 total_drills += drill->PinCount;
276 total_drills += drill->ViaCount;
279 gui->set_color (Output.fgGC, PCB->ElementColor);
280 text_at (0, yoff, 900, "Symbol");
281 text_at (41000, yoff, 900, "Diam. (Inch)");
282 text_at (95000, yoff, 900, "Count");
283 text_at (130000, yoff, 900, "Plated?");
284 yoff -= TEXT_LINE;
285 text_at (0, yoff, 0,
286 "There are %d different drill sizes used in this layout, %d holes total",
287 AllDrills->DrillN, total_drills);
288 /* Create a portable timestamp. */
289 currenttime = time (NULL);
291 /* avoid gcc complaints */
292 const char *fmt = "%c UTC";
293 strftime (utcTime, sizeof utcTime, fmt, gmtime (&currenttime));
295 yoff = -TEXT_LINE;
296 for (i = 0; i < max_layer; i++)
298 LayerType *l = LAYER_PTR (i);
299 if (l->Name && (l->LineN || l->ArcN))
301 if (strcmp ("route", l->Name) == 0)
302 break;
303 if (strcmp ("outline", l->Name) == 0)
304 break;
307 if (i == max_layer)
309 gui->set_line_width (Output.fgGC, 1000);
310 gui->draw_line (Output.fgGC, 0, 0, PCB->MaxWidth, 0);
311 gui->draw_line (Output.fgGC, 0, 0, 0, PCB->MaxHeight);
312 gui->draw_line (Output.fgGC, PCB->MaxWidth, 0, PCB->MaxWidth,
313 PCB->MaxHeight);
314 gui->draw_line (Output.fgGC, 0, PCB->MaxHeight, PCB->MaxWidth,
315 PCB->MaxHeight);
316 /*FPrintOutline (); */
317 gui->set_line_width (Output.fgGC, FAB_LINE_W);
318 text_at (200000, yoff, 0,
319 "Maximum Dimensions: %d mils wide, %d mils high",
320 PCB->MaxWidth / 100, PCB->MaxHeight / 100);
321 text_at (PCB->MaxWidth / 2, PCB->MaxHeight + 2000, 1,
322 "Board outline is the centerline of this 10 mil"
323 " rectangle - 0,0 to %d,%d mils",
324 PCB->MaxWidth / 100, PCB->MaxHeight / 100);
326 else
328 LayerTypePtr layer = LAYER_PTR (i);
329 gui->set_line_width (Output.fgGC, 1000);
330 LINE_LOOP (layer);
332 gui->draw_line (Output.fgGC, line->Point1.X, line->Point1.Y,
333 line->Point2.X, line->Point2.Y);
335 END_LOOP;
336 ARC_LOOP (layer);
338 gui->draw_arc (Output.fgGC, arc->X, arc->Y, arc->Width,
339 arc->Height, arc->StartAngle, arc->Delta);
341 END_LOOP;
342 TEXT_LOOP (layer);
344 DrawTextLowLevel (text, 0);
346 END_LOOP;
347 gui->set_line_width (Output.fgGC, FAB_LINE_W);
348 text_at (PCB->MaxWidth / 2, PCB->MaxHeight + 2000, 1,
349 "Board outline is the centerline of this path");
351 yoff -= TEXT_LINE;
352 text_at (200000, yoff, 0, "Date: %s", utcTime);
353 yoff -= TEXT_LINE;
354 text_at (200000, yoff, 0, "Author: %s", pcb_author ());
355 yoff -= TEXT_LINE;
356 text_at (200000, yoff, 0,
357 "Title: %s - Fabrication Drawing", UNKNOWN (PCB->Name));