src/puller.c: Converted plain comments into doxygen comments.
[geda-pcb/pcjc2.git] / src / print.c
blobc512049e456f7800d9e0aef393af02010c60c52b
1 /*!
2 * \file src/print.c
4 * \brief Printing routines.
6 * \note Change History:\n
7 * 10/11/96 11:37 AJF Added support for a Text() driver function.\n
8 * This was done out of a pressing need to force text to be printed on
9 * the silkscreen layer.\n
10 * Perhaps the design is not the best.
12 * <hr>
14 * <h1><b>Copyright.</b></h1>\n
16 * PCB, interactive printed circuit board design
18 * Copyright (C) 1994,1995,1996, 2003 Thomas Nau
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 * Contact addresses for paper mail and Email:
36 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
38 * Thomas.Nau@rz.uni-ulm.de
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
45 #include "global.h"
46 #include "hid_draw.h"
48 #include <time.h>
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h>
51 #endif
54 #include "data.h"
55 #include "draw.h"
56 #include "drill.h"
57 #include "file.h"
58 #include "find.h"
59 #include "error.h"
60 #include "misc.h"
61 #include "print.h"
62 #include "polygon.h"
63 #include "rtree.h"
64 #include "search.h"
66 #include "hid.h"
68 #ifdef HAVE_LIBDMALLOC
69 #include <dmalloc.h>
70 #endif
72 /* ---------------------------------------------------------------------------
73 * prints a FAB drawing.
76 #define TEXT_SIZE MIL_TO_COORD(150)
77 #define TEXT_LINE MIL_TO_COORD(150)
78 #define DRILL_MARK_SIZE MIL_TO_COORD(16)
79 #define FAB_LINE_W MIL_TO_COORD(8)
81 static void
82 fab_line (hidGC gc, int x1, int y1, int x2, int y2)
84 gui->graphics->draw_line (gc, x1, y1, x2, y2);
87 static void
88 fab_circle (hidGC gc, int x, int y, int r)
90 gui->graphics->draw_arc (gc, x, y, r, r, 0, 180);
91 gui->graphics->draw_arc (gc, x, y, r, r, 180, 180);
94 /*!
95 * \brief Align text ?
97 * align is 0=left, 1=center, 2=right, add 8 for underline.
99 static void
100 text_at (hidGC gc, int x, int y, int align, char *fmt, ...)
102 char tmp[512];
103 int w = 0, i;
104 TextType t;
105 va_list a;
106 FontType *font = &PCB->Font;
107 va_start (a, fmt);
108 vsprintf (tmp, fmt, a);
109 va_end (a);
110 t.Direction = 0;
111 t.TextString = tmp;
112 t.Scale = COORD_TO_MIL(TEXT_SIZE); /* pcnt of 100mil base height */
113 t.Flags = NoFlags ();
114 t.X = x;
115 t.Y = y;
116 for (i = 0; tmp[i]; i++)
117 w +=
118 (font->Symbol[(int) tmp[i]].Width + font->Symbol[(int) tmp[i]].Delta);
119 w = SCALE_TEXT (w, t.Scale);
120 t.X -= w * (align & 3) / 2;
121 if (t.X < 0)
122 t.X = 0;
123 gui->graphics->draw_pcb_text (gc, &t, 0);
124 if (align & 8)
125 fab_line (gc, t.X,
126 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10),
127 t.X + w,
128 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10));
132 * \brief .
134 * Y, +, X, circle, square.
136 static void
137 drill_sym (hidGC gc, int idx, int x, int y)
139 int type = idx % 5;
140 int size = idx / 5;
141 int s2 = (size + 1) * DRILL_MARK_SIZE;
142 int i;
143 switch (type)
145 case 0: /* Y */ ;
146 fab_line (gc, x, y, x, y + s2);
147 fab_line (gc, x, y, x + s2 * 13 / 15, y - s2 / 2);
148 fab_line (gc, x, y, x - s2 * 13 / 15, y - s2 / 2);
149 for (i = 1; i <= size; i++)
150 fab_circle (gc, x, y, i * DRILL_MARK_SIZE);
151 break;
152 case 1: /* + */
154 fab_line (gc, x, y - s2, x, y + s2);
155 fab_line (gc, x - s2, y, x + s2, y);
156 for (i = 1; i <= size; i++)
158 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
159 x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE);
160 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
161 x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
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);
167 break;
168 case 2: /* X */ ;
169 fab_line (gc, x - s2 * 3 / 4, y - s2 * 3 / 4, x + s2 * 3 / 4,
170 y + s2 * 3 / 4);
171 fab_line (gc, x - s2 * 3 / 4, y + s2 * 3 / 4, x + s2 * 3 / 4,
172 y - s2 * 3 / 4);
173 for (i = 1; i <= size; i++)
175 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
176 x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE);
177 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
178 x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
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);
184 break;
185 case 3: /* circle */ ;
186 for (i = 0; i <= size; i++)
187 fab_circle (gc, x, y, (i + 1) * DRILL_MARK_SIZE - DRILL_MARK_SIZE / 2);
188 break;
189 case 4: /* square */
190 for (i = 1; i <= size + 1; i++)
192 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
193 x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE);
194 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
195 x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
196 fab_line (gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE,
197 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
198 fab_line (gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE,
199 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE);
201 break;
205 static int
206 count_drill_lines (DrillInfoType *AllDrills)
208 int n, ds = 0;
209 for (n = AllDrills->DrillN - 1; n >= 0; n--)
211 DrillType *drill = &(AllDrills->Drill[n]);
212 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount)
213 ds++;
214 if (drill->UnplatedCount)
215 ds++;
217 return ds;
222 PrintFab_overhang (void)
224 DrillInfoType *AllDrills = GetDrillInfo (PCB->Data);
225 int ds = count_drill_lines (AllDrills);
226 if (ds < 4)
227 ds = 4;
228 return (ds + 2) * TEXT_LINE;
231 void
232 PrintFab (hidGC gc)
234 DrillInfoType *AllDrills;
235 int i, n, yoff, total_drills = 0, ds = 0;
236 time_t currenttime;
237 const char *utcFmt = "%c UTC";
238 char utcTime[64];
239 #ifdef ENABLE_NLS
240 char *oldlocale;
241 #endif
242 AllDrills = GetDrillInfo (PCB->Data);
243 yoff = -TEXT_LINE;
245 /* count how many drill description lines will be needed */
246 ds = count_drill_lines (AllDrills);
249 * When we only have a few drill sizes we need to make sure the
250 * drill table header doesn't fall on top of the board info
251 * section.
253 if (ds < 4)
255 yoff -= (4 - ds) * TEXT_LINE;
258 gui->graphics->set_line_width (gc, FAB_LINE_W);
260 for (n = AllDrills->DrillN - 1; n >= 0; n--)
262 int plated_sym = -1, unplated_sym = -1;
263 DrillType *drill = &(AllDrills->Drill[n]);
264 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount)
265 plated_sym = --ds;
266 if (drill->UnplatedCount)
267 unplated_sym = --ds;
268 gui->graphics->set_color (gc, PCB->PinColor);
269 for (i = 0; i < drill->PinN; i++)
270 drill_sym (gc, TEST_FLAG (HOLEFLAG, drill->Pin[i]) ?
271 unplated_sym : plated_sym, drill->Pin[i]->X,
272 drill->Pin[i]->Y);
273 if (plated_sym != -1)
275 drill_sym (gc, plated_sym, TEXT_SIZE, yoff + TEXT_SIZE / 4);
276 text_at (gc, MIL_TO_COORD(1350), yoff, MIL_TO_COORD(2), "YES");
277 text_at (gc, MIL_TO_COORD(980), yoff, MIL_TO_COORD(2), "%d",
278 drill->PinCount + drill->ViaCount - drill->UnplatedCount);
280 if (unplated_sym != -1)
281 yoff -= TEXT_LINE;
283 if (unplated_sym != -1)
285 drill_sym (gc, unplated_sym, TEXT_SIZE, yoff + TEXT_SIZE / 4);
286 text_at (gc, MIL_TO_COORD(1400), yoff, MIL_TO_COORD(2), "NO");
287 text_at (gc, MIL_TO_COORD(980), yoff, MIL_TO_COORD(2), "%d", drill->UnplatedCount);
289 gui->graphics->set_color (gc, PCB->ElementColor);
290 text_at (gc, MIL_TO_COORD(450), yoff, MIL_TO_COORD(2), "%0.3f",
291 COORD_TO_INCH(drill->DrillSize));
292 if (plated_sym != -1 && unplated_sym != -1)
293 text_at (gc, MIL_TO_COORD(450), yoff + TEXT_LINE, MIL_TO_COORD(2), "%0.3f",
294 COORD_TO_INCH(drill->DrillSize));
295 yoff -= TEXT_LINE;
296 total_drills += drill->PinCount;
297 total_drills += drill->ViaCount;
300 gui->graphics->set_color (gc, PCB->ElementColor);
301 text_at (gc, 0, yoff, MIL_TO_COORD(9), "Symbol");
302 text_at (gc, MIL_TO_COORD(410), yoff, MIL_TO_COORD(9), "Diam. (Inch)");
303 text_at (gc, MIL_TO_COORD(950), yoff, MIL_TO_COORD(9), "Count");
304 text_at (gc, MIL_TO_COORD(1300), yoff, MIL_TO_COORD(9), "Plated?");
305 yoff -= TEXT_LINE;
306 text_at (gc, 0, yoff, 0,
307 "There are %d different drill sizes used in this layout, %d holes total",
308 AllDrills->DrillN, total_drills);
309 /* Create a portable timestamp. */
310 #ifdef ENABLE_NLS
311 oldlocale = setlocale (LC_TIME, "C");
312 #endif
313 currenttime = time (NULL);
314 strftime (utcTime, sizeof utcTime, utcFmt, gmtime (&currenttime));
315 #ifdef ENABLE_NLS
316 setlocale (LC_TIME, oldlocale);
317 #endif
319 yoff = -TEXT_LINE;
320 for (i = 0; i < max_copper_layer; i++)
322 LayerType *l = LAYER_PTR (i);
323 if (l->Name && (l->LineN || l->ArcN))
325 if (strcmp ("route", l->Name) == 0)
326 break;
327 if (strcmp ("outline", l->Name) == 0)
328 break;
331 if (i == max_copper_layer)
333 gui->graphics->set_line_width (gc, MIL_TO_COORD(10));
334 gui->graphics->draw_line (gc, 0, 0, PCB->MaxWidth, 0);
335 gui->graphics->draw_line (gc, 0, 0, 0, PCB->MaxHeight);
336 gui->graphics->draw_line (gc, PCB->MaxWidth, 0, PCB->MaxWidth,
337 PCB->MaxHeight);
338 gui->graphics->draw_line (gc, 0, PCB->MaxHeight, PCB->MaxWidth,
339 PCB->MaxHeight);
340 /*FPrintOutline (); */
341 gui->graphics->set_line_width (gc, FAB_LINE_W);
342 text_at (gc, MIL_TO_COORD(2000), yoff, 0,
343 "Maximum Dimensions: %f mils wide, %f mils high",
344 COORD_TO_MIL(PCB->MaxWidth), COORD_TO_MIL(PCB->MaxHeight));
345 text_at (gc, PCB->MaxWidth / 2, PCB->MaxHeight + MIL_TO_COORD(20), 1,
346 "Board outline is the centerline of this %f mil"
347 " rectangle - 0,0 to %f,%f mils",
348 COORD_TO_MIL(FAB_LINE_W), COORD_TO_MIL(PCB->MaxWidth), COORD_TO_MIL(PCB->MaxHeight));
350 else
352 LayerType *layer = LAYER_PTR (i);
353 gui->graphics->set_line_width (gc, MIL_TO_COORD(10));
354 LINE_LOOP (layer);
356 gui->graphics->draw_line (gc, line->Point1.X, line->Point1.Y,
357 line->Point2.X, line->Point2.Y);
359 END_LOOP;
360 ARC_LOOP (layer);
362 gui->graphics->draw_arc (gc, arc->X, arc->Y, arc->Width,
363 arc->Height, arc->StartAngle, arc->Delta);
365 END_LOOP;
366 TEXT_LOOP (layer);
368 gui->graphics->draw_pcb_text (gc, text, 0);
370 END_LOOP;
371 gui->graphics->set_line_width (gc, FAB_LINE_W);
372 text_at (gc, PCB->MaxWidth / 2, PCB->MaxHeight + MIL_TO_COORD(20), 1,
373 "Board outline is the centerline of this path");
375 yoff -= TEXT_LINE;
376 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Date: %s", utcTime);
377 yoff -= TEXT_LINE;
378 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Author: %s", pcb_author ());
379 yoff -= TEXT_LINE;
380 text_at (gc, MIL_TO_COORD(2000), yoff, 0,
381 "Title: %s - Fabrication Drawing", UNKNOWN (PCB->Name));