(no commit message)
[geda-pcb/pcjc2.git] / src / print.c
blob69328e781080631adbea4fef0a9d77c5cb65f0c3
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"
41 #include "hid_draw.h"
43 #include <time.h>
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47 #include <setjmp.h>
50 #include "data.h"
51 #include "draw.h"
52 #include "drill.h"
53 #include "file.h"
54 #include "find.h"
55 #include "error.h"
56 #include "misc.h"
57 #include "print.h"
58 #include "polygon.h"
59 #include "rtree.h"
60 #include "search.h"
62 #include "hid.h"
64 #ifdef HAVE_LIBDMALLOC
65 #include <dmalloc.h>
66 #endif
68 /* ---------------------------------------------------------------------------
69 * prints a FAB drawing.
72 #define TEXT_SIZE MIL_TO_COORD(150)
73 #define TEXT_LINE MIL_TO_COORD(150)
74 #define DRILL_MARK_SIZE MIL_TO_COORD(16)
75 #define FAB_LINE_W MIL_TO_COORD(8)
77 static void
78 fab_line (hidGC gc, int x1, int y1, int x2, int y2)
80 gui->graphics->draw_line (gc, x1, y1, x2, y2);
83 static void
84 fab_circle (hidGC gc, int x, int y, int r)
86 gui->graphics->draw_arc (gc, x, y, r, r, 0, 180);
87 gui->graphics->draw_arc (gc, x, y, r, r, 180, 180);
90 /* align is 0=left, 1=center, 2=right, add 8 for underline */
91 static void
92 text_at (hidGC gc, int x, int y, int align, char *fmt, ...)
94 char tmp[512];
95 int w = 0, i;
96 TextType t;
97 va_list a;
98 FontType *font = &PCB->Font;
99 va_start (a, fmt);
100 vsprintf (tmp, fmt, a);
101 va_end (a);
102 t.Direction = 0;
103 t.TextString = tmp;
104 t.Scale = COORD_TO_MIL(TEXT_SIZE); /* pcnt of 100mil base height */
105 t.Flags = NoFlags ();
106 t.X = x;
107 t.Y = y;
108 for (i = 0; tmp[i]; i++)
109 w +=
110 (font->Symbol[(int) tmp[i]].Width + font->Symbol[(int) tmp[i]].Delta);
111 w = SCALE_TEXT (w, t.Scale);
112 t.X -= w * (align & 3) / 2;
113 if (t.X < 0)
114 t.X = 0;
115 gui->graphics->draw_pcb_text (gc, &t, 0);
116 if (align & 8)
117 fab_line (gc, t.X,
118 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10),
119 t.X + w,
120 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10));
123 /* Y, +, X, circle, square */
124 static void
125 drill_sym (hidGC gc, int idx, int x, int y)
127 int type = idx % 5;
128 int size = idx / 5;
129 int s2 = (size + 1) * DRILL_MARK_SIZE;
130 int i;
131 switch (type)
133 case 0: /* Y */ ;
134 fab_line (gc, x, y, x, y + s2);
135 fab_line (gc, x, y, x + s2 * 13 / 15, y - s2 / 2);
136 fab_line (gc, x, y, x - s2 * 13 / 15, y - s2 / 2);
137 for (i = 1; i <= size; i++)
138 fab_circle (gc, x, y, i * DRILL_MARK_SIZE);
139 break;
140 case 1: /* + */
142 fab_line (gc, x, y - s2, x, y + s2);
143 fab_line (gc, x - s2, y, x + s2, y);
144 for (i = 1; i <= size; i++)
146 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
147 x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE);
148 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
149 x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
150 fab_line (gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE,
151 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
152 fab_line (gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
153 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
155 break;
156 case 2: /* X */ ;
157 fab_line (gc, x - s2 * 3 / 4, y - s2 * 3 / 4, x + s2 * 3 / 4,
158 y + s2 * 3 / 4);
159 fab_line (gc, x - s2 * 3 / 4, y + s2 * 3 / 4, x + s2 * 3 / 4,
160 y - s2 * 3 / 4);
161 for (i = 1; i <= size; i++)
163 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
164 x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE);
165 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
166 x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
167 fab_line (gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE,
168 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
169 fab_line (gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
170 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
172 break;
173 case 3: /* circle */ ;
174 for (i = 0; i <= size; i++)
175 fab_circle (gc, x, y, (i + 1) * DRILL_MARK_SIZE - DRILL_MARK_SIZE / 2);
176 break;
177 case 4: /* square */
178 for (i = 1; i <= size + 1; i++)
180 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
181 x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE);
182 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
183 x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
184 fab_line (gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE,
185 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
186 fab_line (gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
187 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
189 break;
193 static int
194 count_drill_lines (DrillInfoType *AllDrills)
196 int n, ds = 0;
197 for (n = AllDrills->DrillN - 1; n >= 0; n--)
199 DrillType *drill = &(AllDrills->Drill[n]);
200 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount)
201 ds++;
202 if (drill->UnplatedCount)
203 ds++;
205 return ds;
210 PrintFab_overhang (void)
212 DrillInfoType *AllDrills = GetDrillInfo (PCB->Data);
213 int ds = count_drill_lines (AllDrills);
214 if (ds < 4)
215 ds = 4;
216 return (ds + 2) * TEXT_LINE;
219 void
220 PrintFab (hidGC gc)
222 DrillInfoType *AllDrills;
223 int i, n, yoff, total_drills = 0, ds = 0;
224 time_t currenttime;
225 char utcTime[64];
226 AllDrills = GetDrillInfo (PCB->Data);
227 RoundDrillInfo (AllDrills, MIL_TO_COORD(1));
228 yoff = -TEXT_LINE;
230 /* count how many drill description lines will be needed */
231 ds = count_drill_lines (AllDrills);
234 * When we only have a few drill sizes we need to make sure the
235 * drill table header doesn't fall on top of the board info
236 * section.
238 if (ds < 4)
240 yoff -= (4 - ds) * TEXT_LINE;
243 gui->graphics->set_line_width (gc, FAB_LINE_W);
245 for (n = AllDrills->DrillN - 1; n >= 0; n--)
247 int plated_sym = -1, unplated_sym = -1;
248 DrillType *drill = &(AllDrills->Drill[n]);
249 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount)
250 plated_sym = --ds;
251 if (drill->UnplatedCount)
252 unplated_sym = --ds;
253 gui->graphics->set_color (gc, PCB->PinColor);
254 for (i = 0; i < drill->PinN; i++)
255 drill_sym (gc, TEST_FLAG (HOLEFLAG, drill->Pin[i]) ?
256 unplated_sym : plated_sym, drill->Pin[i]->X,
257 drill->Pin[i]->Y);
258 if (plated_sym != -1)
260 drill_sym (gc, plated_sym, TEXT_SIZE, yoff + TEXT_SIZE / 4);
261 text_at (gc, MIL_TO_COORD(1350), yoff, MIL_TO_COORD(2), "YES");
262 text_at (gc, MIL_TO_COORD(980), yoff, MIL_TO_COORD(2), "%d",
263 drill->PinCount + drill->ViaCount - drill->UnplatedCount);
265 if (unplated_sym != -1)
266 yoff -= TEXT_LINE;
268 if (unplated_sym != -1)
270 drill_sym (gc, unplated_sym, TEXT_SIZE, yoff + TEXT_SIZE / 4);
271 text_at (gc, MIL_TO_COORD(1400), yoff, MIL_TO_COORD(2), "NO");
272 text_at (gc, MIL_TO_COORD(980), yoff, MIL_TO_COORD(2), "%d", drill->UnplatedCount);
274 gui->graphics->set_color (gc, PCB->ElementColor);
275 text_at (gc, MIL_TO_COORD(450), yoff, MIL_TO_COORD(2), "%0.3f",
276 COORD_TO_INCH(drill->DrillSize) + 0.0004);
277 if (plated_sym != -1 && unplated_sym != -1)
278 text_at (gc, MIL_TO_COORD(450), yoff + TEXT_LINE, MIL_TO_COORD(2), "%0.3f",
279 COORD_TO_INCH(drill->DrillSize) + 0.0004);
280 yoff -= TEXT_LINE;
281 total_drills += drill->PinCount;
282 total_drills += drill->ViaCount;
285 gui->graphics->set_color (gc, PCB->ElementColor);
286 text_at (gc, 0, yoff, MIL_TO_COORD(9), "Symbol");
287 text_at (gc, MIL_TO_COORD(410), yoff, MIL_TO_COORD(9), "Diam. (Inch)");
288 text_at (gc, MIL_TO_COORD(950), yoff, MIL_TO_COORD(9), "Count");
289 text_at (gc, MIL_TO_COORD(1300), yoff, MIL_TO_COORD(9), "Plated?");
290 yoff -= TEXT_LINE;
291 text_at (gc, 0, yoff, 0,
292 "There are %d different drill sizes used in this layout, %d holes total",
293 AllDrills->DrillN, total_drills);
294 /* Create a portable timestamp. */
295 currenttime = time (NULL);
297 /* avoid gcc complaints */
298 const char *fmt = "%c UTC";
299 strftime (utcTime, sizeof utcTime, fmt, gmtime (&currenttime));
301 yoff = -TEXT_LINE;
302 for (i = 0; i < max_copper_layer; i++)
304 LayerType *l = LAYER_PTR (i);
305 if (l->Name && (l->LineN || l->ArcN))
307 if (strcmp ("route", l->Name) == 0)
308 break;
309 if (strcmp ("outline", l->Name) == 0)
310 break;
313 if (i == max_copper_layer)
315 gui->graphics->set_line_width (gc, MIL_TO_COORD(10));
316 gui->graphics->draw_line (gc, 0, 0, PCB->MaxWidth, 0);
317 gui->graphics->draw_line (gc, 0, 0, 0, PCB->MaxHeight);
318 gui->graphics->draw_line (gc, PCB->MaxWidth, 0, PCB->MaxWidth,
319 PCB->MaxHeight);
320 gui->graphics->draw_line (gc, 0, PCB->MaxHeight, PCB->MaxWidth,
321 PCB->MaxHeight);
322 /*FPrintOutline (); */
323 gui->graphics->set_line_width (gc, FAB_LINE_W);
324 text_at (gc, MIL_TO_COORD(2000), yoff, 0,
325 "Maximum Dimensions: %f mils wide, %f mils high",
326 COORD_TO_MIL(PCB->MaxWidth), COORD_TO_MIL(PCB->MaxHeight));
327 text_at (gc, PCB->MaxWidth / 2, PCB->MaxHeight + MIL_TO_COORD(20), 1,
328 "Board outline is the centerline of this %f mil"
329 " rectangle - 0,0 to %f,%f mils",
330 COORD_TO_MIL(FAB_LINE_W), COORD_TO_MIL(PCB->MaxWidth), COORD_TO_MIL(PCB->MaxHeight));
332 else
334 LayerType *layer = LAYER_PTR (i);
335 gui->graphics->set_line_width (gc, MIL_TO_COORD(10));
336 LINE_LOOP (layer);
338 gui->graphics->draw_line (gc, line->Point1.X, line->Point1.Y,
339 line->Point2.X, line->Point2.Y);
341 END_LOOP;
342 ARC_LOOP (layer);
344 gui->graphics->draw_arc (gc, arc->X, arc->Y, arc->Width,
345 arc->Height, arc->StartAngle, arc->Delta);
347 END_LOOP;
348 TEXT_LOOP (layer);
350 gui->graphics->draw_pcb_text (gc, text, 0);
352 END_LOOP;
353 gui->graphics->set_line_width (gc, FAB_LINE_W);
354 text_at (gc, PCB->MaxWidth / 2, PCB->MaxHeight + MIL_TO_COORD(20), 1,
355 "Board outline is the centerline of this path");
357 yoff -= TEXT_LINE;
358 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Date: %s", utcTime);
359 yoff -= TEXT_LINE;
360 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Author: %s", pcb_author ());
361 yoff -= TEXT_LINE;
362 text_at (gc, MIL_TO_COORD(2000), yoff, 0,
363 "Title: %s - Fabrication Drawing", UNKNOWN (PCB->Name));