Revert "Fix locale-dependent gerber output"
[geda-pcb/whiteaudio.git] / src / print.c
blob4c0172124e11e62bdcb51a3df71d8b585e2fdd34
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 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)
80 static void
81 fab_line (hidGC gc, int x1, int y1, int x2, int y2)
83 gui->draw_line (gc, x1, y1, x2, y2);
86 static void
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 */
94 static void
95 text_at (hidGC gc, int x, int y, int align, char *fmt, ...)
97 char tmp[512];
98 int w = 0, i;
99 TextType t;
100 va_list a;
101 FontTypePtr font = &PCB->Font;
102 va_start (a, fmt);
103 vsprintf (tmp, fmt, a);
104 va_end (a);
105 t.Direction = 0;
106 t.TextString = tmp;
107 t.Scale = COORD_TO_MIL(TEXT_SIZE); /* pcnt of 100mil base height */
108 t.Flags = NoFlags ();
109 t.X = x;
110 t.Y = y;
111 for (i = 0; tmp[i]; i++)
112 w +=
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;
116 if (t.X < 0)
117 t.X = 0;
118 DrawTextLowLevel (&t, 0);
119 if (align & 8)
120 fab_line (gc, t.X,
121 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10),
122 t.X + w,
123 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10));
126 /* Y, +, X, circle, square */
127 static void
128 drill_sym (hidGC gc, int idx, int x, int y)
130 int type = idx % 5;
131 int size = idx / 5;
132 int s2 = (size + 1) * DRILL_MARK_SIZE;
133 int i;
134 switch (type)
136 case 0: /* Y */ ;
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);
142 break;
143 case 1: /* + */
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);
158 break;
159 case 2: /* X */ ;
160 fab_line (gc, x - s2 * 3 / 4, y - s2 * 3 / 4, x + s2 * 3 / 4,
161 y + s2 * 3 / 4);
162 fab_line (gc, x - s2 * 3 / 4, y + s2 * 3 / 4, x + s2 * 3 / 4,
163 y - 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);
175 break;
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);
179 break;
180 case 4: /* square */
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);
192 break;
196 static int
197 count_drill_lines (DrillInfoTypePtr AllDrills)
199 int n, ds = 0;
200 for (n = AllDrills->DrillN - 1; n >= 0; n--)
202 DrillTypePtr drill = &(AllDrills->Drill[n]);
203 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount)
204 ds++;
205 if (drill->UnplatedCount)
206 ds++;
208 return ds;
213 PrintFab_overhang (void)
215 DrillInfoTypePtr AllDrills = GetDrillInfo (PCB->Data);
216 int ds = count_drill_lines (AllDrills);
217 if (ds < 4)
218 ds = 4;
219 return (ds + 2) * TEXT_LINE;
222 void
223 PrintFab (hidGC gc)
225 DrillInfoTypePtr AllDrills;
226 int i, n, yoff, total_drills = 0, ds = 0;
227 time_t currenttime;
228 char utcTime[64];
229 AllDrills = GetDrillInfo (PCB->Data);
230 RoundDrillInfo (AllDrills, MIL_TO_COORD(1));
231 yoff = -TEXT_LINE;
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
239 * section.
241 if (ds < 4)
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)
253 plated_sym = --ds;
254 if (drill->UnplatedCount)
255 unplated_sym = --ds;
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,
260 drill->Pin[i]->Y);
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)
269 yoff -= TEXT_LINE;
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);
283 yoff -= TEXT_LINE;
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?");
293 yoff -= TEXT_LINE;
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 (&currenttime));
304 yoff = -TEXT_LINE;
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)
311 break;
312 if (strcmp ("outline", l->Name) == 0)
313 break;
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,
322 PCB->MaxHeight);
323 gui->draw_line (gc, 0, PCB->MaxHeight, PCB->MaxWidth,
324 PCB->MaxHeight);
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));
335 else
337 LayerTypePtr layer = LAYER_PTR (i);
338 gui->set_line_width (gc, MIL_TO_COORD(10));
339 LINE_LOOP (layer);
341 gui->draw_line (gc, line->Point1.X, line->Point1.Y,
342 line->Point2.X, line->Point2.Y);
344 END_LOOP;
345 ARC_LOOP (layer);
347 gui->draw_arc (gc, arc->X, arc->Y, arc->Width,
348 arc->Height, arc->StartAngle, arc->Delta);
350 END_LOOP;
351 TEXT_LOOP (layer);
353 DrawTextLowLevel (text, 0);
355 END_LOOP;
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");
360 yoff -= TEXT_LINE;
361 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Date: %s", utcTime);
362 yoff -= TEXT_LINE;
363 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Author: %s", pcb_author ());
364 yoff -= TEXT_LINE;
365 text_at (gc, MIL_TO_COORD(2000), yoff, 0,
366 "Title: %s - Fabrication Drawing", UNKNOWN (PCB->Name));