1 /*!
2 * \file src/draw.c
3 *
4 * \brief Drawing routines.
5 *
6 * <hr>
7 *
8 * <h1><b>Copyright.</b></h1>\n
9 *
10 * PCB, interactive printed circuit board design
11 *
12 * Copyright (C) 1994,1995,1996, 2003, 2004 Thomas Nau
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *
28 * Contact addresses for paper mail and Email:
29 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
30 * Thomas.Nau@rz.uni-ulm.de
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "global.h"
38 #include "hid_draw.h"
39
40 /*#include "clip.h"*/
41 #include "compat.h"
42 #include "crosshair.h"
43 #include "data.h"
44 #include "draw.h"
45 #include "error.h"
46 #include "mymem.h"
47 #include "misc.h"
48 #include "rotate.h"
49 #include "rtree.h"
50 #include "search.h"
51 #include "select.h"
52 #include "print.h"
53
54 #ifdef HAVE_LIBDMALLOC
55 #include <dmalloc.h>
56 #endif
57
58 #undef NDEBUG
59 #include <assert.h>
60
61 #ifndef MAXINT
62 #define MAXINT (((unsigned int)(~0))>>1)
63 #endif
64
65 #define SMALL_SMALL_TEXT_SIZE 0
66 #define SMALL_TEXT_SIZE 1
67 #define NORMAL_TEXT_SIZE 2
68 #define LARGE_TEXT_SIZE 3
69 #define N_TEXT_SIZES 4
70
71
72 /* ---------------------------------------------------------------------------
73 * some local identifiers
74 */
75 static BoxType Block = {MAXINT, MAXINT, -MAXINT, -MAXINT};
76
77 static int doing_pinout = 0;
78 static bool doing_assy = false;
79
80 static int current_layergroup; /* used by via_callback */
81
82 /* ---------------------------------------------------------------------------
83 * some local prototypes
84 */
85 static void DrawEverything (const BoxType *);
86 static void DrawPPV (int group, const BoxType *);
87 static void AddPart (void *);
88 static void DrawEMark (ElementType *, Coord, Coord, bool);
89 static void DrawRats (const BoxType *);
90
91 static void
set_object_color(AnyObjectType * obj,char * warn_color,char * selected_color,char * connected_color,char * found_color,char * normal_color)92 set_object_color (AnyObjectType *obj, char *warn_color, char *selected_color,
93 char *connected_color, char *found_color, char *normal_color)
94 {
95 char *color;
96
97 if (warn_color != NULL && TEST_FLAG (WARNFLAG, obj)) color = warn_color;
98 else if (selected_color != NULL && TEST_FLAG (SELECTEDFLAG, obj)) color = selected_color;
99 else if (connected_color != NULL && TEST_FLAG (CONNECTEDFLAG, obj)) color = connected_color;
100 else if (found_color != NULL && TEST_FLAG (FOUNDFLAG, obj)) color = found_color;
101 else color = normal_color;
102
103 gui->graphics->set_color (Output.fgGC, color);
104 }
105
106 static void
set_layer_object_color(LayerType * layer,AnyObjectType * obj)107 set_layer_object_color (LayerType *layer, AnyObjectType *obj)
108 {
109 set_object_color (obj, NULL, layer->SelectedColor, PCB->ConnectedColor, PCB->FoundColor, layer->Color);
110 }
111
112 /*!
113 * \brief Adds the update rect to the update region.
114 */
115 static void
AddPart(void * b)116 AddPart (void *b)
117 {
118 BoxType *box = (BoxType *) b;
119
120 Block.X1 = MIN (Block.X1, box->X1);
121 Block.X2 = MAX (Block.X2, box->X2);
122 Block.Y1 = MIN (Block.Y1, box->Y1);
123 Block.Y2 = MAX (Block.Y2, box->Y2);
124 }
125
126 /*!
127 * \brief Initiate the actual redrawing of the updated area.
128 */
129 void
Draw(void)130 Draw (void)
131 {
132 if (Block.X1 <= Block.X2 && Block.Y1 <= Block.Y2)
133 gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2);
134
135 /* shrink the update block */
136 Block.X1 = Block.Y1 = MAXINT;
137 Block.X2 = Block.Y2 = -MAXINT;
138 }
139
140 /*!
141 * \brief Redraws all the data by the event handlers.
142 */
143 void
Redraw(void)144 Redraw (void)
145 {
146 gui->invalidate_all ();
147 }
148
149 static void
_draw_pv_name(PinType * pv)150 _draw_pv_name (PinType *pv)
151 {
152 BoxType box;
153 bool vert;
154 TextType text;
155
156 if (!pv->Name || !pv->Name[0])
157 text.TextString = EMPTY (pv->Number);
158 else
159 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pv->Number : pv->Name);
160
161 vert = TEST_FLAG (EDGE2FLAG, pv);
162
163 if (vert)
164 {
165 box.X1 = pv->X - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
166 box.Y1 = pv->Y - pv->DrillingHole / 2 - Settings.PinoutTextOffsetX;
167 }
168 else
169 {
170 box.X1 = pv->X + pv->DrillingHole / 2 + Settings.PinoutTextOffsetX;
171 box.Y1 = pv->Y - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
172 }
173
174 gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);
175
176 text.Flags = NoFlags ();
177 /* Set font height to approx 56% of pin thickness */
178 text.Scale = 56 * pv->Thickness / FONT_CAPHEIGHT;
179 text.X = box.X1;
180 text.Y = box.Y1;
181 text.Direction = vert ? 1 : 0;
182
183 if (gui->gui)
184 doing_pinout++;
185 gui->graphics->draw_pcb_text (Output.fgGC, &text, 0);
186 if (gui->gui)
187 doing_pinout--;
188 }
189
190 static void
_draw_pv(PinType * pv,bool draw_hole)191 _draw_pv (PinType *pv, bool draw_hole)
192 {
193 if (TEST_FLAG (THINDRAWFLAG, PCB))
194 gui->graphics->thindraw_pcb_pv (Output.fgGC, Output.fgGC, pv, draw_hole, false);
195 else if (!ViaIsOnAnyVisibleLayer (pv))
196 gui->graphics->thindraw_pcb_pv (Output.fgGC, Output.fgGC, pv, false, false);
197 else
198 {
199 gui->graphics->fill_pcb_pv (Output.fgGC, Output.bgGC, pv, draw_hole, false);
200 if (gui->gui
201 && VIA_IS_BURIED (pv)
202 && !(TEST_FLAG (SELECTEDFLAG, pv)
203 || TEST_FLAG (CONNECTEDFLAG, pv)
204 || TEST_FLAG (FOUNDFLAG, pv)))
205 {
206 int w = (pv->Thickness - pv->DrillingHole) / 4;
207 int r = pv->DrillingHole / 2 + w / 2;
208 gui->graphics->set_line_cap (Output.fgGC, Square_Cap);
209 gui->graphics->set_color (Output.fgGC, PCB->Data->Layer[pv->BuriedFrom].Color);
210 gui->graphics->set_line_width (Output.fgGC, w);
211 gui->graphics->draw_arc (Output.fgGC, pv->X, pv->Y, r, r, 270, 180);
212 gui->graphics->set_color (Output.fgGC, PCB->Data->Layer[pv->BuriedTo].Color);
213 gui->graphics->set_line_width (Output.fgGC, w);
214 gui->graphics->draw_arc (Output.fgGC, pv->X, pv->Y, r, r, 90, 180);
215 }
216 }
217
218 if ((!TEST_FLAG (HOLEFLAG, pv) && TEST_FLAG (DISPLAYNAMEFLAG, pv)) || doing_pinout)
219 _draw_pv_name (pv);
220 }
221
222 static void
draw_pin(PinType * pin,bool draw_hole)223 draw_pin (PinType *pin, bool draw_hole)
224 {
225 if (doing_pinout)
226 gui->graphics->set_color (Output.fgGC, PCB->PinColor);
227 else
228 set_object_color ((AnyObjectType *)pin,
229 PCB->WarnColor, PCB->PinSelectedColor,
230 PCB->ConnectedColor, PCB->FoundColor, PCB->PinColor);
231
232 _draw_pv (pin, draw_hole);
233 }
234
235 static int
pin_callback(const BoxType * b,void * cl)236 pin_callback (const BoxType * b, void *cl)
237 {
238 draw_pin ((PinType *)b, false);
239 return 1;
240 }
241
242 static void
draw_via(PinType * via,bool draw_hole)243 draw_via (PinType *via, bool draw_hole)
244 {
245 if (doing_pinout)
246 gui->graphics->set_color (Output.fgGC, PCB->ViaColor);
247 else
248 set_object_color ((AnyObjectType *)via,
249 PCB->WarnColor, PCB->ViaSelectedColor,
250 PCB->ConnectedColor, PCB->FoundColor, PCB->ViaColor);
251
252 _draw_pv (via, draw_hole);
253 }
254
255 static bool
via_visible_on_layer_group(PinType * via)256 via_visible_on_layer_group (PinType *via)
257 {
258 if (current_layergroup == -1)
259 return true;
260 else
261 return ViaIsOnLayerGroup (via, current_layergroup);
262 }
263
264 static int
via_callback(const BoxType * b,void * cl)265 via_callback (const BoxType * b, void *cl)
266 {
267 PinType *via = (PinType *)b;
268
269 if (via_visible_on_layer_group (via))
270 draw_via (via, false);
271
272 return 1;
273 }
274
275 static void
draw_pad_name(PadType * pad)276 draw_pad_name (PadType *pad)
277 {
278 BoxType box;
279 bool vert;
280 TextType text;
281
282 if (!pad->Name || !pad->Name[0])
283 text.TextString = EMPTY (pad->Number);
284 else
285 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pad->Number : pad->Name);
286
287 /* should text be vertical ? */
288 vert = (pad->Point1.X == pad->Point2.X);
289
290 if (vert)
291 {
292 box.X1 = pad->Point1.X - pad->Thickness / 2;
293 box.Y1 = MAX (pad->Point1.Y, pad->Point2.Y) + pad->Thickness / 2;
294 box.X1 += Settings.PinoutTextOffsetY;
295 box.Y1 -= Settings.PinoutTextOffsetX;
296 }
297 else
298 {
299 box.X1 = MIN (pad->Point1.X, pad->Point2.X) - pad->Thickness / 2;
300 box.Y1 = pad->Point1.Y - pad->Thickness / 2;
301 box.X1 += Settings.PinoutTextOffsetX;
302 box.Y1 += Settings.PinoutTextOffsetY;
303 }
304
305 gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);
306
307 text.Flags = NoFlags ();
308 /* Set font height to approx 90% of pin thickness */
309 text.Scale = 90 * pad->Thickness / FONT_CAPHEIGHT;
310 text.X = box.X1;
311 text.Y = box.Y1;
312 text.Direction = vert ? 1 : 0;
313
314 gui->graphics->draw_pcb_text (Output.fgGC, &text, 0);
315 }
316
317 static void
_draw_pad(hidGC gc,PadType * pad,bool clear,bool mask)318 _draw_pad (hidGC gc, PadType *pad, bool clear, bool mask)
319 {
320 if (clear && !mask && pad->Clearance <= 0)
321 return;
322
323 if (TEST_FLAG (THINDRAWFLAG, PCB) ||
324 (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
325 gui->graphics->thindraw_pcb_pad (gc, pad, clear, mask);
326 else
327 gui->graphics->fill_pcb_pad (gc, pad, clear, mask);
328 }
329
330 static void
draw_pad(PadType * pad)331 draw_pad (PadType *pad)
332 {
333 if (doing_pinout)
334 gui->graphics->set_color (Output.fgGC, PCB->PinColor);
335 else
336 set_object_color ((AnyObjectType *)pad, PCB->WarnColor,
337 PCB->PinSelectedColor, PCB->ConnectedColor, PCB->FoundColor,
338 FRONT (pad) ? PCB->PinColor : PCB->InvisibleObjectsColor);
339
340 _draw_pad (Output.fgGC, pad, false, false);
341
342 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, pad))
343 draw_pad_name (pad);
344 }
345
346 static int
pad_callback(const BoxType * b,void * cl)347 pad_callback (const BoxType * b, void *cl)
348 {
349 PadType *pad = (PadType *) b;
350 int *side = cl;
351
352 if (ON_SIDE (pad, *side))
353 draw_pad (pad);
354 return 1;
355 }
356
357 static void
draw_element_name(ElementType * element)358 draw_element_name (ElementType *element)
359 {
360 if ((TEST_FLAG (HIDENAMESFLAG, PCB) && gui->gui) ||
361 TEST_FLAG (HIDENAMEFLAG, element))
362 return;
363 if (doing_pinout || doing_assy)
364 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
365 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
366 gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor);
367 else if (FRONT (element))
368 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
369 else
370 gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
371 gui->graphics->draw_pcb_text (Output.fgGC, &ELEMENT_TEXT (PCB, element), PCB->minSlk);
372 }
373
374 static int
name_callback(const BoxType * b,void * cl)375 name_callback (const BoxType * b, void *cl)
376 {
377 TextType *text = (TextType *) b;
378 ElementType *element = (ElementType *) text->Element;
379 int *side = cl;
380
381 if (TEST_FLAG (HIDENAMEFLAG, element))
382 return 0;
383
384 if (ON_SIDE (element, *side))
385 draw_element_name (element);
386 return 0;
387 }
388
389 static void
draw_element_pins_and_pads(ElementType * element)390 draw_element_pins_and_pads (ElementType *element)
391 {
392 PAD_LOOP (element);
393 {
394 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
395 draw_pad (pad);
396 }
397 END_LOOP;
398 PIN_LOOP (element);
399 {
400 draw_pin (pin, true);
401 }
402 END_LOOP;
403 }
404
405 static int
EMark_callback(const BoxType * b,void * cl)406 EMark_callback (const BoxType * b, void *cl)
407 {
408 ElementType *element = (ElementType *) b;
409
410 DrawEMark (element, element->MarkX, element->MarkY, !FRONT (element));
411 return 1;
412 }
413
414 typedef struct
415 {
416 int plated;
417 bool drill_pair;
418 Cardinal group_from;
419 Cardinal group_to;
420 } hole_info;
421
422 static int
hole_callback(const BoxType * b,void * cl)423 hole_callback (const BoxType * b, void *cl)
424 {
425 hole_info his = {-1, false, 0, 0};
426 hole_info *hi = &his;
427 PinType *pv = (PinType *) b;
428
429 if (cl)
430 hi = (hole_info *)cl;
431
432 if (hi->drill_pair)
433 {
434 if (hi->group_from != 0
435 || hi->group_to != 0)
436 {
437 if (VIA_IS_BURIED (pv))
438 {
439 if (hi->group_from == GetLayerGroupNumberByNumber (pv->BuriedFrom)
440 && hi->group_to == GetLayerGroupNumberByNumber (pv->BuriedTo))
441 goto via_ok;
442 }
443 }
444 else
445 if (!VIA_IS_BURIED (pv))
446 goto via_ok;
447
448 return 1;
449 }
450
451 via_ok:
452 if ((hi->plated == 0 && !TEST_FLAG (HOLEFLAG, pv)) ||
453 (hi->plated == 1 && TEST_FLAG (HOLEFLAG, pv)))
454 return 1;
455
456 if (!via_visible_on_layer_group (pv))
457 return 1;
458
459 if (TEST_FLAG (THINDRAWFLAG, PCB))
460 {
461 if (!TEST_FLAG (HOLEFLAG, pv))
462 {
463 gui->graphics->set_line_cap (Output.fgGC, Round_Cap);
464 gui->graphics->set_line_width (Output.fgGC, 0);
465 gui->graphics->draw_arc (Output.fgGC,
466 pv->X, pv->Y, pv->DrillingHole / 2,
467 pv->DrillingHole / 2, 0, 360);
468 }
469 }
470 else
471 if (ViaIsOnAnyVisibleLayer (pv))
472 gui->graphics->fill_circle (Output.bgGC, pv->X, pv->Y, pv->DrillingHole / 2);
473 else
474 {
475 gui->graphics->set_line_cap (Output.fgGC, Round_Cap);
476 gui->graphics->set_line_width (Output.fgGC, 0);
477 gui->graphics->draw_arc (Output.fgGC,
478 pv->X, pv->Y, pv->DrillingHole / 2,
479 pv->DrillingHole / 2, 0, 360);
480 }
481
482 if (TEST_FLAG (HOLEFLAG, pv))
483 {
484 set_object_color ((AnyObjectType *) pv,
485 PCB->WarnColor, PCB->ViaSelectedColor,
486 NULL, NULL, Settings.BlackColor);
487
488 gui->graphics->set_line_cap (Output.fgGC, Round_Cap);
489 gui->graphics->set_line_width (Output.fgGC, 0);
490 gui->graphics->draw_arc (Output.fgGC,
491 pv->X, pv->Y, pv->DrillingHole / 2,
492 pv->DrillingHole / 2, 0, 360);
493 }
494 return 1;
495 }
496
497 void
DrawHoles(bool draw_plated,bool draw_unplated,const BoxType * drawn_area,Cardinal g_from,Cardinal g_to)498 DrawHoles (bool draw_plated, bool draw_unplated, const BoxType *drawn_area, Cardinal g_from, Cardinal g_to)
499 {
500 hole_info hi = {-1, true, g_from, g_to};
501
502 if ( draw_plated && !draw_unplated) hi.plated = 1;
503 if (!draw_plated && draw_unplated) hi.plated = 0;
504
505 current_layergroup = -1;
506
507 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, &hi);
508 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, &hi);
509 }
510
511 static int
line_callback(const BoxType * b,void * cl)512 line_callback (const BoxType * b, void *cl)
513 {
514 LayerType *layer = (LayerType *) cl;
515 LineType *line = (LineType *) b;
516
517 set_layer_object_color (layer, (AnyObjectType *) line);
518 gui->graphics->draw_pcb_line (Output.fgGC, line);
519
520 return 1;
521 }
522
523 static int
rat_callback(const BoxType * b,void * cl)524 rat_callback (const BoxType * b, void *cl)
525 {
526 RatType *rat = (RatType *)b;
527
528 set_object_color ((AnyObjectType *) rat, NULL, PCB->RatSelectedColor,
529 PCB->ConnectedColor, PCB->FoundColor, PCB->RatColor);
530
531 if (Settings.RatThickness < 100)
532 rat->Thickness = pixel_slop * Settings.RatThickness;
533 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
534 if (TEST_FLAG(VIAFLAG, rat))
535 {
536 int w = rat->Thickness;
537
538 if (TEST_FLAG (THINDRAWFLAG, PCB))
539 gui->graphics->set_line_width (Output.fgGC, 0);
540 else
541 gui->graphics->set_line_width (Output.fgGC, w);
542 gui->graphics->draw_arc (Output.fgGC, rat->Point1.X, rat->Point1.Y,
543 w * 2, w * 2, 0, 360);
544 }
545 else
546 gui->graphics->draw_pcb_line (Output.fgGC, (LineType *) rat);
547 return 1;
548 }
549
550 static int
arc_callback(const BoxType * b,void * cl)551 arc_callback (const BoxType * b, void *cl)
552 {
553 LayerType *layer = (LayerType *) cl;
554 ArcType *arc = (ArcType *) b;
555
556 set_layer_object_color (layer, (AnyObjectType *) arc);
557 gui->graphics->draw_pcb_arc (Output.fgGC, arc);
558
559 return 1;
560 }
561
562 static void
draw_element_package(ElementType * element)563 draw_element_package (ElementType *element)
564 {
565 /* set color and draw lines, arcs, text and pins */
566 if (doing_pinout || doing_assy)
567 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
568 else if (TEST_FLAG (SELECTEDFLAG, element))
569 gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor);
570 else if (FRONT (element))
571 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
572 else
573 gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
574
575 /* draw lines, arcs, text and pins */
576 ELEMENTLINE_LOOP (element);
577 {
578 gui->graphics->draw_pcb_line (Output.fgGC, line);
579 }
580 END_LOOP;
581 ARC_LOOP (element);
582 {
583 gui->graphics->draw_pcb_arc (Output.fgGC, arc);
584 }
585 END_LOOP;
586 }
587
588 static int
element_callback(const BoxType * b,void * cl)589 element_callback (const BoxType * b, void *cl)
590 {
591 ElementType *element = (ElementType *) b;
592 int *side = cl;
593
594 if (ON_SIDE (element, *side))
595 draw_element_package (element);
596 return 1;
597 }
598
599 /*!
600 * \brief Prints assembly drawing.
601 */
602 void
PrintAssembly(int side,const BoxType * drawn_area)603 PrintAssembly (int side, const BoxType * drawn_area)
604 {
605 int side_group = GetLayerGroupNumberBySide (side);
606
607 doing_assy = true;
608 gui->graphics->set_draw_faded (Output.fgGC, 1);
609 DrawLayerGroup (side_group, drawn_area);
610 gui->graphics->set_draw_faded (Output.fgGC, 0);
611
612 /* draw package */
613 DrawSilk (side, drawn_area);
614 doing_assy = false;
615 }
616
617 /*!
618 * \brief Initializes some identifiers for a new zoom factor and redraws
619 * whole screen.
620 */
621 static void
DrawEverything(const BoxType * drawn_area)622 DrawEverything (const BoxType *drawn_area)
623 {
624 int i, ngroups, side;
625 int top_group, bottom_group;
626 /* This is the list of layer groups we will draw. */
627 int do_group[MAX_GROUP];
628 /* This is the reverse of the order in which we draw them. */
629 int drawn_groups[MAX_GROUP];
630 int plated, unplated;
631 bool paste_empty;
632 int g_from, g_to;
633 char s[22];
634
635 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
636 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
637
638 memset (do_group, 0, sizeof (do_group));
639 for (ngroups = 0, i = 0; i < max_copper_layer; i++)
640 {
641 LayerType *l = LAYER_ON_STACK (i);
642 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
643 if (l->On && !do_group[group])
644 {
645 do_group[group] = 1;
646 drawn_groups[ngroups++] = group;
647 }
648 }
649
650 top_group = GetLayerGroupNumberBySide (TOP_SIDE);
651 bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE);
652
653 /*
654 * first draw all 'invisible' stuff
655 */
656 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
657 && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
658 {
659 side = SWAP_IDENT ? TOP_SIDE : BOTTOM_SIDE;
660 if (PCB->ElementOn)
661 {
662 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
663 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
664 DrawLayer (&(PCB->Data->Layer[max_copper_layer + side]), drawn_area);
665 }
666 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
667 gui->end_layer ();
668 }
669
670 /* draw all layers in layerstack order */
671 for (i = ngroups - 1; i >= 0; i--)
672 {
673 int group = drawn_groups[i];
674
675 if (gui->set_layer (0, group, 0))
676 {
677 DrawLayerGroup (group, drawn_area);
678 gui->end_layer ();
679 }
680 }
681
682 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
683 return;
684
685 /* Draw pins, pads, vias below silk */
686 if (gui->gui)
687 DrawPPV (SWAP_IDENT ? bottom_group : top_group, drawn_area);
688 else
689 {
690 CountHoles (&plated, &unplated, drawn_area);
691
692 if (plated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
693 {
694 DrawHoles (true, false, drawn_area, 0, 0);
695 gui->end_layer ();
696 }
697
698 if (unplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
699 {
700 DrawHoles (false, true, drawn_area, 0, 0);
701 gui->end_layer ();
702 }
703
704 for (g_from = 0; g_from < (max_group - 1); g_from++)
705 for (g_to = g_from+1 ; g_to < max_group; g_to++ )
706 {
707 CountHolesEx (&plated, &unplated, drawn_area, g_from, g_to);
708 sprintf (s, "plated-drill_%02d-%02d", g_from+1, g_to+1);
709 if (plated && gui->set_layer (s, SL (PDRILL, 0), 0))
710 {
711 DrawHoles (true, false, drawn_area, g_from, g_to);
712 gui->end_layer ();
713 }
714
715 sprintf (s, "unplated-drill_%02d-%02d", g_from+1, g_to+1);
716 if (unplated && gui->set_layer (s, SL (UDRILL, 0), 0))
717 {
718 DrawHoles (false, true, drawn_area, g_from, g_to);
719 gui->end_layer ();
720 }
721 }
722
723
724 }
725
726 /* Draw the solder mask if turned on */
727 if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
728 {
729 DrawMask (TOP_SIDE, drawn_area);
730 gui->end_layer ();
731 }
732
733 if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
734 {
735 DrawMask (BOTTOM_SIDE, drawn_area);
736 gui->end_layer ();
737 }
738
739 if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
740 {
741 DrawSilk (TOP_SIDE, drawn_area);
742 gui->end_layer ();
743 }
744
745 if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
746 {
747 DrawSilk (BOTTOM_SIDE, drawn_area);
748 gui->end_layer ();
749 }
750
751 if (gui->gui)
752 {
753 /* Draw element Marks */
754 if (PCB->PinOn)
755 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
756 NULL);
757 /* Draw rat lines on top */
758 if (gui->set_layer ("rats", SL (RATS, 0), 0))
759 {
760 DrawRats(drawn_area);
761 gui->end_layer ();
762 }
763 }
764
765 paste_empty = IsPasteEmpty (TOP_SIDE);
766 if (gui->set_layer ("toppaste", SL (PASTE, TOP), paste_empty))
767 {
768 DrawPaste (TOP_SIDE, drawn_area);
769 gui->end_layer ();
770 }
771
772 paste_empty = IsPasteEmpty (BOTTOM_SIDE);
773 if (gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), paste_empty))
774 {
775 DrawPaste (BOTTOM_SIDE, drawn_area);
776 gui->end_layer ();
777 }
778
779 if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
780 {
781 PrintAssembly (TOP_SIDE, drawn_area);
782 gui->end_layer ();
783 }
784
785 if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
786 {
787 PrintAssembly (BOTTOM_SIDE, drawn_area);
788 gui->end_layer ();
789 }
790
791 if (gui->set_layer ("fab", SL (FAB, 0), 0))
792 {
793 PrintFab (Output.fgGC);
794 gui->end_layer ();
795 }
796 }
797
798 static void
DrawEMark(ElementType * e,Coord X,Coord Y,bool invisible)799 DrawEMark (ElementType *e, Coord X, Coord Y, bool invisible)
800 {
801 Coord mark_size = EMARK_SIZE;
802 if (!PCB->InvisibleObjectsOn && invisible)
803 return;
804
805 if (e->Pin != NULL)
806 {
807 PinType *pin0 = e->Pin->data;
808 if (TEST_FLAG (HOLEFLAG, pin0))
809 mark_size = MIN (mark_size, pin0->DrillingHole / 2);
810 else
811 mark_size = MIN (mark_size, pin0->Thickness / 2);
812 }
813
814 if (e->Pad != NULL)
815 {
816 PadType *pad0 = e->Pad->data;
817 mark_size = MIN (mark_size, pad0->Thickness / 2);
818 }
819
820 gui->graphics->set_color (Output.fgGC,
821 invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
822 gui->graphics->set_line_cap (Output.fgGC, Trace_Cap);
823 gui->graphics->set_line_width (Output.fgGC, 0);
824 gui->graphics->draw_line (Output.fgGC, X - mark_size, Y, X, Y - mark_size);
825 gui->graphics->draw_line (Output.fgGC, X + mark_size, Y, X, Y - mark_size);
826 gui->graphics->draw_line (Output.fgGC, X - mark_size, Y, X, Y + mark_size);
827 gui->graphics->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
828
829 /*
830 * If an element is locked, place a "L" on top of the "diamond".
831 * This provides a nice visual indication that it is locked that
832 * works even for color blind users.
833 */
834 if (TEST_FLAG (LOCKFLAG, e) )
835 {
836 gui->graphics->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
837 gui->graphics->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
838 }
839 }
840
841 /*!
842 * \brief Draws pins pads and vias - Always draws for non-gui HIDs,
843 * otherwise drawing depends on PCB->PinOn and PCB->ViaOn.
844 */
845 static void
DrawPPV(int group,const BoxType * drawn_area)846 DrawPPV (int group, const BoxType *drawn_area)
847 {
848 int top_group = GetLayerGroupNumberBySide (TOP_SIDE);
849 int bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE);
850 int side;
851
852 if (PCB->PinOn || !gui->gui)
853 {
854 /* draw element pins */
855 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback, NULL);
856
857 /* draw element pads */
858 if (group == top_group)
859 {
860 side = TOP_SIDE;
861 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
862 }
863
864 if (group == bottom_group)
865 {
866 side = BOTTOM_SIDE;
867 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
868 }
869 }
870
871 /* draw vias */
872 if (PCB->ViaOn || !gui->gui)
873 {
874
875 current_layergroup = (gui->gui)?(-1):group; /* Limit vias only for layer group */
876
877 r_search (PCB->Data->via_tree, drawn_area, NULL, via_callback, NULL);
878 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, NULL);
879 }
880 if (PCB->PinOn || doing_assy)
881 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, NULL);
882 }
883
884 static int
clearPin_callback(const BoxType * b,void * cl)885 clearPin_callback (const BoxType * b, void *cl)
886 {
887 PinType *pin = (PinType *) b;
888 bool do_clear=true;
889 int side;
890 if (TEST_FLAG (VIAFLAG, pin) && VIA_IS_BURIED (pin))
891 {
892 side=*((int*)cl);
893 if ((side == TOP_SIDE && pin->BuriedFrom != 0)
894 || (side == BOTTOM_SIDE && pin->BuriedTo != GetMaxBottomLayer ()))
895 do_clear = false;
896 }
897 if (do_clear)
898 {
899 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
900 gui->graphics->thindraw_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
901 else
902 gui->graphics->fill_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
903 }
904 return 1;
905 }
906
907 struct poly_info {
908 const BoxType *drawn_area;
909 LayerType *layer;
910 };
911
912 static int
poly_callback(const BoxType * b,void * cl)913 poly_callback (const BoxType * b, void *cl)
914 {
915 struct poly_info *i = cl;
916 PolygonType *polygon = (PolygonType *)b;
917
918 set_layer_object_color (i->layer, (AnyObjectType *) polygon);
919
920 gui->graphics->draw_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
921
922 return 1;
923 }
924
925 static int
clearPad_callback(const BoxType * b,void * cl)926 clearPad_callback (const BoxType * b, void *cl)
927 {
928 PadType *pad = (PadType *) b;
929 int *side = cl;
930 if (ON_SIDE (pad, *side) && pad->Mask)
931 _draw_pad (Output.pmGC, pad, true, true);
932 return 1;
933 }
934
935 /*!
936 * \brief Draws silk layer.
937 */
938 void
DrawSilk(int side,const BoxType * drawn_area)939 DrawSilk (int side, const BoxType * drawn_area)
940 {
941 #if 0
942 /* This code is used when you want to mask silk to avoid exposed
943 pins and pads. We decided it was a bad idea to do this
944 unconditionally, but the code remains. */
945 #endif
946
947 #if 0
948 if (gui->poly_before)
949 {
950 gui->graphics->use_mask (HID_MASK_BEFORE);
951 #endif
952 DrawLayer (LAYER_PTR (max_copper_layer + side), drawn_area);
953 /* draw package */
954 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
955 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
956 #if 0
957 }
958
959 gui->graphics->use_mask (HID_MASK_CLEAR);
960 r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, NULL);
961 r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, NULL);
962 r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &side);
963
964 if (gui->poly_after)
965 {
966 gui->graphics->use_mask (HID_MASK_AFTER);
967 DrawLayer (LAYER_PTR (max_copper_layer + layer), drawn_area);
968 /* draw package */
969 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
970 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
971 }
972 gui->graphics->use_mask (HID_MASK_OFF);
973 #endif
974 }
975
976
977 static void
DrawMaskBoardArea(int mask_type,const BoxType * drawn_area)978 DrawMaskBoardArea (int mask_type, const BoxType *drawn_area)
979 {
980 /* Skip the mask drawing if the GUI doesn't want this type */
981 if ((mask_type == HID_MASK_BEFORE && !gui->poly_before) ||
982 (mask_type == HID_MASK_AFTER && !gui->poly_after))
983 return;
984
985 gui->graphics->use_mask (mask_type);
986 gui->graphics->set_color (Output.fgGC, PCB->MaskColor);
987 if (drawn_area == NULL)
988 gui->graphics->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
989 else
990 gui->graphics->fill_rect (Output.fgGC, drawn_area->X1, drawn_area->Y1,
991 drawn_area->X2, drawn_area->Y2);
992 }
993
994 /*!
995 * \brief Draws solder mask layer - this will cover nearly everything.
996 */
997 void
DrawMask(int side,const BoxType * screen)998 DrawMask (int side, const BoxType *screen)
999 {
1000 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
1001
1002 if (thin)
1003 gui->graphics->set_color (Output.pmGC, PCB->MaskColor);
1004 else
1005 {
1006 DrawMaskBoardArea (HID_MASK_BEFORE, screen);
1007 gui->graphics->use_mask (HID_MASK_CLEAR);
1008 }
1009
1010 r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, NULL);
1011 r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, &side);
1012 r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &side);
1013
1014 if (thin)
1015 gui->graphics->set_color (Output.pmGC, "erase");
1016 else
1017 {
1018 DrawMaskBoardArea (HID_MASK_AFTER, screen);
1019 gui->graphics->use_mask (HID_MASK_OFF);
1020 }
1021 }
1022
1023 /*!
1024 * \brief Draws solder paste layer for a given side of the board.
1025 */
1026 void
DrawPaste(int side,const BoxType * drawn_area)1027 DrawPaste (int side, const BoxType *drawn_area)
1028 {
1029 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
1030 ALLPAD_LOOP (PCB->Data);
1031 {
1032 if (ON_SIDE (pad, side) && !TEST_FLAG (NOPASTEFLAG, pad) && pad->Mask > 0)
1033 {
1034 Coord save_thickness = pad->Thickness;
1035 Coord save_mask = pad->Mask;
1036
1037 if (Settings.PasteAdjust != 0)
1038 {
1039 pad->Thickness = pad->Thickness + Settings.PasteAdjust;
1040 pad->Mask = pad->Mask + Settings.PasteAdjust;
1041 if (pad->Thickness < 0) {
1042 printf ("adjust thickness %8.4f -> %8.4f mask %8.4f -> %8.4f\n",
1043 COORD_TO_MM(save_thickness), COORD_TO_MM(pad->Thickness),
1044 COORD_TO_MM(save_mask), COORD_TO_MM(pad->Mask));
1045 pad->Thickness = 0;
1046 }
1047 if (pad->Mask < 0)
1048 pad->Mask = 0;
1049 }
1050 if (pad->Mask < pad->Thickness)
1051 _draw_pad (Output.fgGC, pad, true, true);
1052 else
1053 _draw_pad (Output.fgGC, pad, false, false);
1054 pad->Thickness = save_thickness;
1055 pad->Mask = save_mask;
1056 }
1057 }
1058 ENDALL_LOOP;
1059 }
1060
1061 static void
DrawRats(const BoxType * drawn_area)1062 DrawRats (const BoxType *drawn_area)
1063 {
1064 /*
1065 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
1066 * XXX gtk only allows negative drawing.
1067 * XXX using the mask here is to get rat transparency
1068 */
1069 int can_mask = strcmp(gui->name, "lesstif") == 0;
1070
1071 if (can_mask)
1072 gui->graphics->use_mask (HID_MASK_CLEAR);
1073 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
1074 if (can_mask)
1075 gui->graphics->use_mask (HID_MASK_OFF);
1076 }
1077
1078 static int
text_callback(const BoxType * b,void * cl)1079 text_callback (const BoxType * b, void *cl)
1080 {
1081 LayerType *layer = cl;
1082 TextType *text = (TextType *)b;
1083 int min_silk_line;
1084
1085 if (TEST_FLAG (SELECTEDFLAG, text))
1086 gui->graphics->set_color (Output.fgGC, layer->SelectedColor);
1087 else
1088 gui->graphics->set_color (Output.fgGC, layer->Color);
1089 if (layer == &PCB->Data->SILKLAYER ||
1090 layer == &PCB->Data->BACKSILKLAYER)
1091 min_silk_line = PCB->minSlk;
1092 else
1093 min_silk_line = PCB->minWid;
1094 gui->graphics->draw_pcb_text (Output.fgGC, text, min_silk_line);
1095 return 1;
1096 }
1097
1098 void
DrawLayer(LayerType * Layer,const BoxType * screen)1099 DrawLayer (LayerType *Layer, const BoxType *screen)
1100 {
1101 struct poly_info info = {screen, Layer};
1102
1103 /* print the non-clearing polys */
1104 r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
1105
1106 if (TEST_FLAG (CHECKPLANESFLAG, PCB))
1107 return;
1108
1109 /* draw all visible lines this layer */
1110 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
1111
1112 /* draw the layer arcs on screen */
1113 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
1114
1115 /* draw the layer text on screen */
1116 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
1117
1118 /* We should check for gui->gui here, but it's kinda cool seeing the
1119 auto-outline magically disappear when you first add something to
1120 the "outline" layer. */
1121 if (IsLayerEmpty (Layer)
1122 && (strcmp (Layer->Name, "outline") == 0
1123 || strcmp (Layer->Name, "route") == 0))
1124 {
1125 gui->graphics->set_color (Output.fgGC, Layer->Color);
1126 gui->graphics->set_line_width (Output.fgGC, PCB->minWid);
1127 gui->graphics->draw_rect (Output.fgGC,
1128 0, 0,
1129 PCB->MaxWidth, PCB->MaxHeight);
1130 }
1131 }
1132
1133 /*!
1134 * \brief Draws one layer group.
1135 *
1136 * If the exporter is not a GUI, also draws the pins / pads / vias in
1137 * this layer group.
1138 */
1139 void
DrawLayerGroup(int group,const BoxType * drawn_area)1140 DrawLayerGroup (int group, const BoxType *drawn_area)
1141 {
1142 int i, rv = 1;
1143 int layernum;
1144 LayerType *Layer;
1145 int n_entries = PCB->LayerGroups.Number[group];
1146 Cardinal *layers = PCB->LayerGroups.Entries[group];
1147
1148 for (i = n_entries - 1; i >= 0; i--)
1149 {
1150 layernum = layers[i];
1151 Layer = PCB->Data->Layer + layers[i];
1152 if (strcmp (Layer->Name, "outline") == 0 ||
1153 strcmp (Layer->Name, "route") == 0)
1154 rv = 0;
1155 if (layernum < max_copper_layer && Layer->On)
1156 DrawLayer (Layer, drawn_area);
1157 }
1158 if (n_entries > 1)
1159 rv = 1;
1160
1161 if (rv && !gui->gui)
1162 DrawPPV (group, drawn_area);
1163 }
1164
1165 static void
GatherPVName(PinType * Ptr)1166 GatherPVName (PinType *Ptr)
1167 {
1168 BoxType box;
1169 bool vert = TEST_FLAG (EDGE2FLAG, Ptr);
1170
1171 if (vert)
1172 {
1173 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1174 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
1175 }
1176 else
1177 {
1178 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
1179 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1180 }
1181
1182 if (vert)
1183 {
1184 box.X2 = box.X1;
1185 box.Y2 = box.Y1;
1186 }
1187 else
1188 {
1189 box.X2 = box.X1;
1190 box.Y2 = box.Y1;
1191 }
1192 AddPart (&box);
1193 }
1194
1195 static void
GatherPadName(PadType * Pad)1196 GatherPadName (PadType *Pad)
1197 {
1198 BoxType box;
1199 bool vert;
1200
1201 /* should text be vertical ? */
1202 vert = (Pad->Point1.X == Pad->Point2.X);
1203
1204 if (vert)
1205 {
1206 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1207 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1208 box.X1 += Settings.PinoutTextOffsetY;
1209 box.Y1 -= Settings.PinoutTextOffsetX;
1210 box.X2 = box.X1;
1211 box.Y2 = box.Y1;
1212 }
1213 else
1214 {
1215 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1216 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1217 box.X1 += Settings.PinoutTextOffsetX;
1218 box.Y1 += Settings.PinoutTextOffsetY;
1219 box.X2 = box.X1;
1220 box.Y2 = box.Y1;
1221 }
1222
1223 AddPart (&box);
1224 return;
1225 }
1226
1227 /*!
1228 * \brief Draw a via object.
1229 */
1230 void
DrawVia(PinType * Via)1231 DrawVia (PinType *Via)
1232 {
1233 AddPart (Via);
1234 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1235 DrawViaName (Via);
1236 }
1237
1238 /*!
1239 * \brief Draws the name of a via.
1240 */
1241 void
DrawViaName(PinType * Via)1242 DrawViaName (PinType *Via)
1243 {
1244 GatherPVName (Via);
1245 }
1246
1247 /*!
1248 * \brief Draw a pin object.
1249 */
1250 void
DrawPin(PinType * Pin)1251 DrawPin (PinType *Pin)
1252 {
1253 AddPart (Pin);
1254 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1255 || doing_pinout)
1256 DrawPinName (Pin);
1257 }
1258
1259 /*!
1260 * \brief Draws the name of a pin.
1261 */
1262 void
DrawPinName(PinType * Pin)1263 DrawPinName (PinType *Pin)
1264 {
1265 GatherPVName (Pin);
1266 }
1267
1268 /*!
1269 * \brief Draw a pad object.
1270 */
1271 void
DrawPad(PadType * Pad)1272 DrawPad (PadType *Pad)
1273 {
1274 AddPart (Pad);
1275 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1276 DrawPadName (Pad);
1277 }
1278
1279 /*!
1280 * \brief Draws the name of a pad.
1281 */
1282 void
DrawPadName(PadType * Pad)1283 DrawPadName (PadType *Pad)
1284 {
1285 GatherPadName (Pad);
1286 }
1287
1288 /*!
1289 * \brief Draws a line on a layer.
1290 */
1291 void
DrawLine(LayerType * Layer,LineType * Line)1292 DrawLine (LayerType *Layer, LineType *Line)
1293 {
1294 AddPart (Line);
1295 }
1296
1297 /*!
1298 * \brief Draws a ratline.
1299 */
1300 void
DrawRat(RatType * Rat)1301 DrawRat (RatType *Rat)
1302 {
1303 if (Settings.RatThickness < 100)
1304 Rat->Thickness = pixel_slop * Settings.RatThickness;
1305 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1306 if (TEST_FLAG(VIAFLAG, Rat))
1307 {
1308 Coord w = Rat->Thickness;
1309
1310 BoxType b;
1311
1312 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1313 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1314 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1315 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1316 AddPart (&b);
1317 }
1318 else
1319 DrawLine (NULL, (LineType *)Rat);
1320 }
1321
1322 /*!
1323 * \brief Draws an arc on a layer.
1324 */
1325 void
DrawArc(LayerType * Layer,ArcType * Arc)1326 DrawArc (LayerType *Layer, ArcType *Arc)
1327 {
1328 AddPart (Arc);
1329 }
1330
1331 /*!
1332 * \brief Draws a text on a layer.
1333 */
1334 void
DrawText(LayerType * Layer,TextType * Text)1335 DrawText (LayerType *Layer, TextType *Text)
1336 {
1337 AddPart (Text);
1338 }
1339
1340
1341 /*!
1342 * \brief Draws a polygon on a layer.
1343 */
1344 void
DrawPolygon(LayerType * Layer,PolygonType * Polygon)1345 DrawPolygon (LayerType *Layer, PolygonType *Polygon)
1346 {
1347 AddPart (Polygon);
1348 }
1349
1350 /*!
1351 * \brief Draws an element.
1352 */
1353 void
DrawElement(ElementType * Element)1354 DrawElement (ElementType *Element)
1355 {
1356 DrawElementPackage (Element);
1357 DrawElementName (Element);
1358 DrawElementPinsAndPads (Element);
1359 }
1360
1361 /*!
1362 * \brief Draws the name of an element.
1363 */
1364 void
DrawElementName(ElementType * Element)1365 DrawElementName (ElementType *Element)
1366 {
1367 if (TEST_FLAG (HIDENAMEFLAG, Element))
1368 return;
1369 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1370 }
1371
1372 /*!
1373 * \brief Draws the package of an element.
1374 */
1375 void
DrawElementPackage(ElementType * Element)1376 DrawElementPackage (ElementType *Element)
1377 {
1378 ELEMENTLINE_LOOP (Element);
1379 {
1380 DrawLine (NULL, line);
1381 }
1382 END_LOOP;
1383 ARC_LOOP (Element);
1384 {
1385 DrawArc (NULL, arc);
1386 }
1387 END_LOOP;
1388 }
1389
1390 /*!
1391 * \brief Draw pins of an element.
1392 */
1393 void
DrawElementPinsAndPads(ElementType * Element)1394 DrawElementPinsAndPads (ElementType *Element)
1395 {
1396 PAD_LOOP (Element);
1397 {
1398 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
1399 DrawPad (pad);
1400 }
1401 END_LOOP;
1402 PIN_LOOP (Element);
1403 {
1404 DrawPin (pin);
1405 }
1406 END_LOOP;
1407 }
1408
1409 /*!
1410 * \brief Erase a via.
1411 */
1412 void
EraseVia(PinType * Via)1413 EraseVia (PinType *Via)
1414 {
1415 AddPart (Via);
1416 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
1417 EraseViaName (Via);
1418 }
1419
1420 /*!
1421 * \brief Erase a ratline.
1422 */
1423 void
EraseRat(RatType * Rat)1424 EraseRat (RatType *Rat)
1425 {
1426 if (TEST_FLAG(VIAFLAG, Rat))
1427 {
1428 Coord w = Rat->Thickness;
1429
1430 BoxType b;
1431
1432 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1433 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1434 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1435 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1436 AddPart (&b);
1437 }
1438 else
1439 EraseLine ((LineType *)Rat);
1440 }
1441
1442
1443 /*!
1444 * \brief Erase a via name.
1445 */
1446 void
EraseViaName(PinType * Via)1447 EraseViaName (PinType *Via)
1448 {
1449 GatherPVName (Via);
1450 }
1451
1452 /*!
1453 * \brief Erase a pad object.
1454 */
1455 void
ErasePad(PadType * Pad)1456 ErasePad (PadType *Pad)
1457 {
1458 AddPart (Pad);
1459 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1460 ErasePadName (Pad);
1461 }
1462
1463 /*!
1464 * \brief Erase a pad name.
1465 */
1466 void
ErasePadName(PadType * Pad)1467 ErasePadName (PadType *Pad)
1468 {
1469 GatherPadName (Pad);
1470 }
1471
1472 /*!
1473 * \brief Erase a pin object.
1474 */
1475 void
ErasePin(PinType * Pin)1476 ErasePin (PinType *Pin)
1477 {
1478 AddPart (Pin);
1479 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1480 ErasePinName (Pin);
1481 }
1482
1483 /*!
1484 * \brief Erase a pin name.
1485 */
1486 void
ErasePinName(PinType * Pin)1487 ErasePinName (PinType *Pin)
1488 {
1489 GatherPVName (Pin);
1490 }
1491
1492 /*!
1493 * \brief Erases a line on a layer.
1494 */
1495 void
EraseLine(LineType * Line)1496 EraseLine (LineType *Line)
1497 {
1498 AddPart (Line);
1499 }
1500
1501 /*!
1502 * \brief Erases an arc on a layer.
1503 */
1504 void
EraseArc(ArcType * Arc)1505 EraseArc (ArcType *Arc)
1506 {
1507 if (!Arc->Thickness)
1508 return;
1509 AddPart (Arc);
1510 }
1511
1512 /*!
1513 * \brief Erases a text on a layer.
1514 */
1515 void
EraseText(LayerType * Layer,TextType * Text)1516 EraseText (LayerType *Layer, TextType *Text)
1517 {
1518 /* r_delete_entry (Layer->text_tree, (BoxType *) Text); */
1519 AddPart (Text);
1520 }
1521
1522 /*!
1523 * \brief Erases a polygon on a layer.
1524 */
1525 void
ErasePolygon(PolygonType * Polygon)1526 ErasePolygon (PolygonType *Polygon)
1527 {
1528 AddPart (Polygon);
1529 }
1530
1531 /*!
1532 * \brief Erases an element.
1533 */
1534 void
EraseElement(ElementType * Element)1535 EraseElement (ElementType *Element)
1536 {
1537 ELEMENTLINE_LOOP (Element);
1538 {
1539 EraseLine (line);
1540 }
1541 END_LOOP;
1542 ARC_LOOP (Element);
1543 {
1544 EraseArc (arc);
1545 }
1546 END_LOOP;
1547 EraseElementName (Element);
1548 EraseElementPinsAndPads (Element);
1549 }
1550
1551 /*!
1552 * \brief Erases all pins and pads of an element.
1553 */
1554 void
EraseElementPinsAndPads(ElementType * Element)1555 EraseElementPinsAndPads (ElementType *Element)
1556 {
1557 PIN_LOOP (Element);
1558 {
1559 ErasePin (pin);
1560 }
1561 END_LOOP;
1562 PAD_LOOP (Element);
1563 {
1564 ErasePad (pad);
1565 }
1566 END_LOOP;
1567 }
1568
1569 /*!
1570 * \brief Erases the name of an element.
1571 */
1572 void
EraseElementName(ElementType * Element)1573 EraseElementName (ElementType *Element)
1574 {
1575 if (TEST_FLAG (HIDENAMEFLAG, Element))
1576 return;
1577 EraseText (NULL, &ELEMENT_TEXT (PCB, Element));}
1578
1579
1580 void
EraseObject(int type,void * lptr,void * ptr)1581 EraseObject (int type, void *lptr, void *ptr)
1582 {
1583 switch (type)
1584 {
1585 case VIA_TYPE:
1586 case PIN_TYPE:
1587 ErasePin ((PinType *) ptr);
1588 break;
1589 case TEXT_TYPE:
1590 EraseText ((LayerType *)lptr, (TextType *) ptr);
1591 break;
1592 case ELEMENTNAME_TYPE:
1593 EraseElementName ((ElementType *) ptr);
1594 break;
1595 case POLYGON_TYPE:
1596 ErasePolygon ((PolygonType *) ptr);
1597 break;
1598 case ELEMENT_TYPE:
1599 EraseElement ((ElementType *) ptr);
1600 break;
1601 case LINE_TYPE:
1602 case ELEMENTLINE_TYPE:
1603 case RATLINE_TYPE:
1604 EraseLine ((LineType *) ptr);
1605 break;
1606 case PAD_TYPE:
1607 ErasePad ((PadType *) ptr);
1608 break;
1609 case ARC_TYPE:
1610 case ELEMENTARC_TYPE:
1611 EraseArc ((ArcType *) ptr);
1612 break;
1613 default:
1614 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
1615 }
1616 }
1617
1618
1619
1620 void
DrawObject(int type,void * ptr1,void * ptr2)1621 DrawObject (int type, void *ptr1, void *ptr2)
1622 {
1623 switch (type)
1624 {
1625 case VIA_TYPE:
1626 if (PCB->ViaOn)
1627 DrawVia ((PinType *) ptr2);
1628 break;
1629 case LINE_TYPE:
1630 if (((LayerType *) ptr1)->On)
1631 DrawLine ((LayerType *) ptr1, (LineType *) ptr2);
1632 break;
1633 case ARC_TYPE:
1634 if (((LayerType *) ptr1)->On)
1635 DrawArc ((LayerType *) ptr1, (ArcType *) ptr2);
1636 break;
1637 case TEXT_TYPE:
1638 if (((LayerType *) ptr1)->On)
1639 DrawText ((LayerType *) ptr1, (TextType *) ptr2);
1640 break;
1641 case POLYGON_TYPE:
1642 if (((LayerType *) ptr1)->On)
1643 DrawPolygon ((LayerType *) ptr1, (PolygonType *) ptr2);
1644 break;
1645 case ELEMENT_TYPE:
1646 if (PCB->ElementOn &&
1647 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1648 DrawElement ((ElementType *) ptr2);
1649 break;
1650 case RATLINE_TYPE:
1651 if (PCB->RatOn)
1652 DrawRat ((RatType *) ptr2);
1653 break;
1654 case PIN_TYPE:
1655 if (PCB->PinOn)
1656 DrawPin ((PinType *) ptr2);
1657 break;
1658 case PAD_TYPE:
1659 if (PCB->PinOn)
1660 DrawPad ((PadType *) ptr2);
1661 break;
1662 case ELEMENTNAME_TYPE:
1663 if (PCB->ElementOn &&
1664 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1665 DrawElementName ((ElementType *) ptr1);
1666 break;
1667 }
1668 }
1669
1670 static void
draw_element(ElementType * element)1671 draw_element (ElementType *element)
1672 {
1673 draw_element_package (element);
1674 draw_element_name (element);
1675 draw_element_pins_and_pads (element);
1676 }
1677
1678 /*!
1679 * \brief HID drawing callback.
1680 */
1681 void
hid_expose_callback(HID * hid,BoxType * region,void * item)1682 hid_expose_callback (HID * hid, BoxType * region, void *item)
1683 {
1684 HID *old_gui = gui;
1685
1686 gui = hid;
1687 Output.fgGC = gui->graphics->make_gc ();
1688 Output.bgGC = gui->graphics->make_gc ();
1689 Output.pmGC = gui->graphics->make_gc ();
1690
1691 hid->graphics->set_color (Output.pmGC, "erase");
1692 hid->graphics->set_color (Output.bgGC, "drill");
1693
1694 if (item)
1695 {
1696 doing_pinout = true;
1697 draw_element ((ElementType *)item);
1698 doing_pinout = false;
1699 }
1700 else
1701 DrawEverything (region);
1702
1703 gui->graphics->destroy_gc (Output.fgGC);
1704 gui->graphics->destroy_gc (Output.bgGC);
1705 gui->graphics->destroy_gc (Output.pmGC);
1706 gui = old_gui;
1707 }
1708