Use trackball to allow rotation of 3D view
[geda-pcb/pcjc2.git] / src / print.c
blob972d13ef7cc1101381e64f8ce2f83bf4ba3c8a95
1 /*
2 * COPYRIGHT
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
27 /* Change History:
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.
34 /* printing routines
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
40 #include "global.h"
42 #include <time.h>
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46 #include <setjmp.h>
49 #include "data.h"
50 #include "draw.h"
51 #include "drill.h"
52 #include "file.h"
53 #include "find.h"
54 #include "error.h"
55 #include "misc.h"
56 #include "print.h"
57 #include "polygon.h"
58 #include "rtree.h"
59 #include "search.h"
61 #include "hid.h"
63 #ifdef HAVE_LIBDMALLOC
64 #include <dmalloc.h>
65 #endif
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)
76 static void
77 fab_line (hidGC gc, int x1, int y1, int x2, int y2)
79 gui->draw_line (gc, x1, y1, x2, y2);
82 static void
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 */
90 static void
91 text_at (hidGC gc, int x, int y, int align, char *fmt, ...)
93 char tmp[512];
94 int w = 0, i;
95 TextType t;
96 va_list a;
97 FontType *font = &PCB->Font;
98 va_start (a, fmt);
99 vsprintf (tmp, fmt, a);
100 va_end (a);
101 t.Direction = 0;
102 t.TextString = tmp;
103 t.Scale = COORD_TO_MIL(TEXT_SIZE); /* pcnt of 100mil base height */
104 t.Flags = NoFlags ();
105 t.X = x;
106 t.Y = y;
107 for (i = 0; tmp[i]; i++)
108 w +=
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;
112 if (t.X < 0)
113 t.X = 0;
114 DrawTextLowLevel (&t, 0);
115 if (align & 8)
116 fab_line (gc, t.X,
117 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10),
118 t.X + w,
119 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10));
122 /* Y, +, X, circle, square */
123 static void
124 drill_sym (hidGC gc, int idx, int x, int y)
126 int type = idx % 5;
127 int size = idx / 5;
128 int s2 = (size + 1) * DRILL_MARK_SIZE;
129 int i;
130 switch (type)
132 case 0: /* Y */ ;
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);
138 break;
139 case 1: /* + */
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);
154 break;
155 case 2: /* X */ ;
156 fab_line (gc, x - s2 * 3 / 4, y - s2 * 3 / 4, x + s2 * 3 / 4,
157 y + s2 * 3 / 4);
158 fab_line (gc, 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 (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);
171 break;
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);
175 break;
176 case 4: /* square */
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);
188 break;
192 static int
193 count_drill_lines (DrillInfoType *AllDrills)
195 int n, ds = 0;
196 for (n = AllDrills->DrillN - 1; n >= 0; n--)
198 DrillType *drill = &(AllDrills->Drill[n]);
199 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount)
200 ds++;
201 if (drill->UnplatedCount)
202 ds++;
204 return ds;
209 PrintFab_overhang (void)
211 DrillInfoType *AllDrills = GetDrillInfo (PCB->Data);
212 int ds = count_drill_lines (AllDrills);
213 if (ds < 4)
214 ds = 4;
215 return (ds + 2) * TEXT_LINE;
218 void
219 PrintFab (hidGC gc)
221 DrillInfoType *AllDrills;
222 int i, n, yoff, total_drills = 0, ds = 0;
223 time_t currenttime;
224 char utcTime[64];
225 AllDrills = GetDrillInfo (PCB->Data);
226 RoundDrillInfo (AllDrills, MIL_TO_COORD(1));
227 yoff = -TEXT_LINE;
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
235 * section.
237 if (ds < 4)
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)
249 plated_sym = --ds;
250 if (drill->UnplatedCount)
251 unplated_sym = --ds;
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,
256 drill->Pin[i]->Y);
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)
265 yoff -= TEXT_LINE;
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);
279 yoff -= TEXT_LINE;
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?");
289 yoff -= TEXT_LINE;
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 (&currenttime));
300 yoff = -TEXT_LINE;
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)
307 break;
308 if (strcmp ("outline", l->Name) == 0)
309 break;
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,
318 PCB->MaxHeight);
319 gui->draw_line (gc, 0, PCB->MaxHeight, PCB->MaxWidth,
320 PCB->MaxHeight);
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));
331 else
333 LayerType *layer = LAYER_PTR (i);
334 gui->set_line_width (gc, MIL_TO_COORD(10));
335 LINE_LOOP (layer);
337 gui->draw_line (gc, line->Point1.X, line->Point1.Y,
338 line->Point2.X, line->Point2.Y);
340 END_LOOP;
341 ARC_LOOP (layer);
343 gui->draw_arc (gc, arc->X, arc->Y, arc->Width,
344 arc->Height, arc->StartAngle, arc->Delta);
346 END_LOOP;
347 TEXT_LOOP (layer);
349 DrawTextLowLevel (text, 0);
351 END_LOOP;
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");
356 yoff -= TEXT_LINE;
357 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Date: %s", utcTime);
358 yoff -= TEXT_LINE;
359 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Author: %s", pcb_author ());
360 yoff -= TEXT_LINE;
361 text_at (gc, MIL_TO_COORD(2000), yoff, 0,
362 "Title: %s - Fabrication Drawing", UNKNOWN (PCB->Name));