4 * \brief Drawing routines.
8 * <h1><b>Copyright.</b></h1>\n
10 * PCB, interactive printed circuit board design
12 * Copyright (C) 1994,1995,1996, 2003, 2004 Thomas Nau
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.
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.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * Contact addresses for paper mail and Email:
29 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
30 * Thomas.Nau@rz.uni-ulm.de
42 #include "crosshair.h"
54 #ifdef HAVE_LIBDMALLOC
62 #define MAXINT (((unsigned int)(~0))>>1)
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
72 /* ---------------------------------------------------------------------------
73 * some local identifiers
75 static BoxType Block
= {MAXINT
, MAXINT
, -MAXINT
, -MAXINT
};
77 static int doing_pinout
= 0;
78 static bool doing_assy
= false;
80 /* ---------------------------------------------------------------------------
81 * some local prototypes
83 static void DrawEverything (const BoxType
*);
84 static void DrawPPV (int group
, const BoxType
*);
85 static void AddPart (void *);
86 static void DrawEMark (ElementType
*, Coord
, Coord
, bool);
87 static void DrawRats (const BoxType
*);
90 set_object_color (AnyObjectType
*obj
, char *warn_color
, char *selected_color
,
91 char *connected_color
, char *found_color
, char *normal_color
)
95 if (warn_color
!= NULL
&& TEST_FLAG (WARNFLAG
, obj
)) color
= warn_color
;
96 else if (selected_color
!= NULL
&& TEST_FLAG (SELECTEDFLAG
, obj
)) color
= selected_color
;
97 else if (connected_color
!= NULL
&& TEST_FLAG (CONNECTEDFLAG
, obj
)) color
= connected_color
;
98 else if (found_color
!= NULL
&& TEST_FLAG (FOUNDFLAG
, obj
)) color
= found_color
;
99 else color
= normal_color
;
101 gui
->graphics
->set_color (Output
.fgGC
, color
);
105 set_layer_object_color (LayerType
*layer
, AnyObjectType
*obj
)
107 set_object_color (obj
, NULL
, layer
->SelectedColor
, PCB
->ConnectedColor
, PCB
->FoundColor
, layer
->Color
);
111 * \brief Adds the update rect to the update region.
116 BoxType
*box
= (BoxType
*) b
;
118 Block
.X1
= MIN (Block
.X1
, box
->X1
);
119 Block
.X2
= MAX (Block
.X2
, box
->X2
);
120 Block
.Y1
= MIN (Block
.Y1
, box
->Y1
);
121 Block
.Y2
= MAX (Block
.Y2
, box
->Y2
);
125 * \brief Initiate the actual redrawing of the updated area.
130 if (Block
.X1
<= Block
.X2
&& Block
.Y1
<= Block
.Y2
)
131 gui
->invalidate_lr (Block
.X1
, Block
.X2
, Block
.Y1
, Block
.Y2
);
133 /* shrink the update block */
134 Block
.X1
= Block
.Y1
= MAXINT
;
135 Block
.X2
= Block
.Y2
= -MAXINT
;
139 * \brief Redraws all the data by the event handlers.
144 gui
->invalidate_all ();
148 _draw_pv_name (PinType
*pv
)
154 if (!pv
->Name
|| !pv
->Name
[0])
155 text
.TextString
= EMPTY (pv
->Number
);
157 text
.TextString
= EMPTY (TEST_FLAG (SHOWNUMBERFLAG
, PCB
) ? pv
->Number
: pv
->Name
);
159 vert
= TEST_FLAG (EDGE2FLAG
, pv
);
163 box
.X1
= pv
->X
- pv
->Thickness
/ 2 + Settings
.PinoutTextOffsetY
;
164 box
.Y1
= pv
->Y
- pv
->DrillingHole
/ 2 - Settings
.PinoutTextOffsetX
;
168 box
.X1
= pv
->X
+ pv
->DrillingHole
/ 2 + Settings
.PinoutTextOffsetX
;
169 box
.Y1
= pv
->Y
- pv
->Thickness
/ 2 + Settings
.PinoutTextOffsetY
;
172 gui
->graphics
->set_color (Output
.fgGC
, PCB
->PinNameColor
);
174 text
.Flags
= NoFlags ();
175 /* Set font height to approx 56% of pin thickness */
176 text
.Scale
= 56 * pv
->Thickness
/ FONT_CAPHEIGHT
;
179 text
.Direction
= vert
? 1 : 0;
183 gui
->graphics
->draw_pcb_text (Output
.fgGC
, &text
, 0);
189 _draw_pv (PinType
*pv
, bool draw_hole
)
191 if (TEST_FLAG (THINDRAWFLAG
, PCB
))
192 gui
->graphics
->thindraw_pcb_pv (Output
.fgGC
, Output
.fgGC
, pv
, draw_hole
, false);
194 gui
->graphics
->fill_pcb_pv (Output
.fgGC
, Output
.bgGC
, pv
, draw_hole
, false);
196 if ((!TEST_FLAG (HOLEFLAG
, pv
) && TEST_FLAG (DISPLAYNAMEFLAG
, pv
)) || doing_pinout
)
201 draw_pin (PinType
*pin
, bool draw_hole
)
204 gui
->graphics
->set_color (Output
.fgGC
, PCB
->PinColor
);
206 set_object_color ((AnyObjectType
*)pin
,
207 PCB
->WarnColor
, PCB
->PinSelectedColor
,
208 PCB
->ConnectedColor
, PCB
->FoundColor
, PCB
->PinColor
);
210 _draw_pv (pin
, draw_hole
);
214 pin_callback (const BoxType
* b
, void *cl
)
216 draw_pin ((PinType
*)b
, false);
221 draw_via (PinType
*via
, bool draw_hole
)
224 gui
->graphics
->set_color (Output
.fgGC
, PCB
->ViaColor
);
226 set_object_color ((AnyObjectType
*)via
,
227 PCB
->WarnColor
, PCB
->ViaSelectedColor
,
228 PCB
->ConnectedColor
, PCB
->FoundColor
, PCB
->ViaColor
);
230 _draw_pv (via
, draw_hole
);
234 via_callback (const BoxType
* b
, void *cl
)
236 draw_via ((PinType
*)b
, false);
241 draw_pad_name (PadType
*pad
)
247 if (!pad
->Name
|| !pad
->Name
[0])
248 text
.TextString
= EMPTY (pad
->Number
);
250 text
.TextString
= EMPTY (TEST_FLAG (SHOWNUMBERFLAG
, PCB
) ? pad
->Number
: pad
->Name
);
252 /* should text be vertical ? */
253 vert
= (pad
->Point1
.X
== pad
->Point2
.X
);
257 box
.X1
= pad
->Point1
.X
- pad
->Thickness
/ 2;
258 box
.Y1
= MAX (pad
->Point1
.Y
, pad
->Point2
.Y
) + pad
->Thickness
/ 2;
259 box
.X1
+= Settings
.PinoutTextOffsetY
;
260 box
.Y1
-= Settings
.PinoutTextOffsetX
;
264 box
.X1
= MIN (pad
->Point1
.X
, pad
->Point2
.X
) - pad
->Thickness
/ 2;
265 box
.Y1
= pad
->Point1
.Y
- pad
->Thickness
/ 2;
266 box
.X1
+= Settings
.PinoutTextOffsetX
;
267 box
.Y1
+= Settings
.PinoutTextOffsetY
;
270 gui
->graphics
->set_color (Output
.fgGC
, PCB
->PinNameColor
);
272 text
.Flags
= NoFlags ();
273 /* Set font height to approx 90% of pin thickness */
274 text
.Scale
= 90 * pad
->Thickness
/ FONT_CAPHEIGHT
;
277 text
.Direction
= vert
? 1 : 0;
279 gui
->graphics
->draw_pcb_text (Output
.fgGC
, &text
, 0);
283 _draw_pad (hidGC gc
, PadType
*pad
, bool clear
, bool mask
)
285 if (clear
&& !mask
&& pad
->Clearance
<= 0)
288 if (TEST_FLAG (THINDRAWFLAG
, PCB
) ||
289 (clear
&& TEST_FLAG (THINDRAWPOLYFLAG
, PCB
)))
290 gui
->graphics
->thindraw_pcb_pad (gc
, pad
, clear
, mask
);
292 gui
->graphics
->fill_pcb_pad (gc
, pad
, clear
, mask
);
296 draw_pad (PadType
*pad
)
299 gui
->graphics
->set_color (Output
.fgGC
, PCB
->PinColor
);
301 set_object_color ((AnyObjectType
*)pad
, PCB
->WarnColor
,
302 PCB
->PinSelectedColor
, PCB
->ConnectedColor
, PCB
->FoundColor
,
303 FRONT (pad
) ? PCB
->PinColor
: PCB
->InvisibleObjectsColor
);
305 _draw_pad (Output
.fgGC
, pad
, false, false);
307 if (doing_pinout
|| TEST_FLAG (DISPLAYNAMEFLAG
, pad
))
312 pad_callback (const BoxType
* b
, void *cl
)
314 PadType
*pad
= (PadType
*) b
;
317 if (ON_SIDE (pad
, *side
))
323 draw_element_name (ElementType
*element
)
325 if ((TEST_FLAG (HIDENAMESFLAG
, PCB
) && gui
->gui
) ||
326 TEST_FLAG (HIDENAMEFLAG
, element
))
328 if (doing_pinout
|| doing_assy
)
329 gui
->graphics
->set_color (Output
.fgGC
, PCB
->ElementColor
);
330 else if (TEST_FLAG (SELECTEDFLAG
, &ELEMENT_TEXT (PCB
, element
)))
331 gui
->graphics
->set_color (Output
.fgGC
, PCB
->ElementSelectedColor
);
332 else if (FRONT (element
))
333 gui
->graphics
->set_color (Output
.fgGC
, PCB
->ElementColor
);
335 gui
->graphics
->set_color (Output
.fgGC
, PCB
->InvisibleObjectsColor
);
336 gui
->graphics
->draw_pcb_text (Output
.fgGC
, &ELEMENT_TEXT (PCB
, element
), PCB
->minSlk
);
340 name_callback (const BoxType
* b
, void *cl
)
342 TextType
*text
= (TextType
*) b
;
343 ElementType
*element
= (ElementType
*) text
->Element
;
346 if (TEST_FLAG (HIDENAMEFLAG
, element
))
349 if (ON_SIDE (element
, *side
))
350 draw_element_name (element
);
355 draw_element_pins_and_pads (ElementType
*element
)
359 if (doing_pinout
|| doing_assy
|| FRONT (pad
) || PCB
->InvisibleObjectsOn
)
365 draw_pin (pin
, true);
371 EMark_callback (const BoxType
* b
, void *cl
)
373 ElementType
*element
= (ElementType
*) b
;
375 DrawEMark (element
, element
->MarkX
, element
->MarkY
, !FRONT (element
));
380 hole_callback (const BoxType
* b
, void *cl
)
382 PinType
*pv
= (PinType
*) b
;
383 int plated
= cl
? *(int *) cl
: -1;
385 if ((plated
== 0 && !TEST_FLAG (HOLEFLAG
, pv
)) ||
386 (plated
== 1 && TEST_FLAG (HOLEFLAG
, pv
)))
389 if (TEST_FLAG (THINDRAWFLAG
, PCB
))
391 if (!TEST_FLAG (HOLEFLAG
, pv
))
393 gui
->graphics
->set_line_cap (Output
.fgGC
, Round_Cap
);
394 gui
->graphics
->set_line_width (Output
.fgGC
, 0);
395 gui
->graphics
->draw_arc (Output
.fgGC
,
396 pv
->X
, pv
->Y
, pv
->DrillingHole
/ 2,
397 pv
->DrillingHole
/ 2, 0, 360);
401 gui
->graphics
->fill_circle (Output
.bgGC
, pv
->X
, pv
->Y
, pv
->DrillingHole
/ 2);
403 if (TEST_FLAG (HOLEFLAG
, pv
))
405 set_object_color ((AnyObjectType
*) pv
,
406 PCB
->WarnColor
, PCB
->ViaSelectedColor
,
407 NULL
, NULL
, Settings
.BlackColor
);
409 gui
->graphics
->set_line_cap (Output
.fgGC
, Round_Cap
);
410 gui
->graphics
->set_line_width (Output
.fgGC
, 0);
411 gui
->graphics
->draw_arc (Output
.fgGC
,
412 pv
->X
, pv
->Y
, pv
->DrillingHole
/ 2,
413 pv
->DrillingHole
/ 2, 0, 360);
419 DrawHoles (bool draw_plated
, bool draw_unplated
, const BoxType
*drawn_area
)
423 if ( draw_plated
&& !draw_unplated
) plated
= 1;
424 if (!draw_plated
&& draw_unplated
) plated
= 0;
426 r_search (PCB
->Data
->pin_tree
, drawn_area
, NULL
, hole_callback
, &plated
);
427 r_search (PCB
->Data
->via_tree
, drawn_area
, NULL
, hole_callback
, &plated
);
431 line_callback (const BoxType
* b
, void *cl
)
433 LayerType
*layer
= (LayerType
*) cl
;
434 LineType
*line
= (LineType
*) b
;
436 set_layer_object_color (layer
, (AnyObjectType
*) line
);
437 gui
->graphics
->draw_pcb_line (Output
.fgGC
, line
);
443 rat_callback (const BoxType
* b
, void *cl
)
445 RatType
*rat
= (RatType
*)b
;
447 set_object_color ((AnyObjectType
*) rat
, NULL
, PCB
->RatSelectedColor
,
448 PCB
->ConnectedColor
, PCB
->FoundColor
, PCB
->RatColor
);
450 if (Settings
.RatThickness
< 100)
451 rat
->Thickness
= pixel_slop
* Settings
.RatThickness
;
452 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
453 if (TEST_FLAG(VIAFLAG
, rat
))
455 int w
= rat
->Thickness
;
457 if (TEST_FLAG (THINDRAWFLAG
, PCB
))
458 gui
->graphics
->set_line_width (Output
.fgGC
, 0);
460 gui
->graphics
->set_line_width (Output
.fgGC
, w
);
461 gui
->graphics
->draw_arc (Output
.fgGC
, rat
->Point1
.X
, rat
->Point1
.Y
,
462 w
* 2, w
* 2, 0, 360);
465 gui
->graphics
->draw_pcb_line (Output
.fgGC
, (LineType
*) rat
);
470 arc_callback (const BoxType
* b
, void *cl
)
472 LayerType
*layer
= (LayerType
*) cl
;
473 ArcType
*arc
= (ArcType
*) b
;
475 set_layer_object_color (layer
, (AnyObjectType
*) arc
);
476 gui
->graphics
->draw_pcb_arc (Output
.fgGC
, arc
);
482 draw_element_package (ElementType
*element
)
484 /* set color and draw lines, arcs, text and pins */
485 if (doing_pinout
|| doing_assy
)
486 gui
->graphics
->set_color (Output
.fgGC
, PCB
->ElementColor
);
487 else if (TEST_FLAG (SELECTEDFLAG
, element
))
488 gui
->graphics
->set_color (Output
.fgGC
, PCB
->ElementSelectedColor
);
489 else if (FRONT (element
))
490 gui
->graphics
->set_color (Output
.fgGC
, PCB
->ElementColor
);
492 gui
->graphics
->set_color (Output
.fgGC
, PCB
->InvisibleObjectsColor
);
494 /* draw lines, arcs, text and pins */
495 ELEMENTLINE_LOOP (element
);
497 gui
->graphics
->draw_pcb_line (Output
.fgGC
, line
);
502 gui
->graphics
->draw_pcb_arc (Output
.fgGC
, arc
);
508 element_callback (const BoxType
* b
, void *cl
)
510 ElementType
*element
= (ElementType
*) b
;
513 if (ON_SIDE (element
, *side
))
514 draw_element_package (element
);
519 * \brief Prints assembly drawing.
522 PrintAssembly (int side
, const BoxType
* drawn_area
)
524 int side_group
= GetLayerGroupNumberBySide (side
);
527 gui
->graphics
->set_draw_faded (Output
.fgGC
, 1);
528 DrawLayerGroup (side_group
, drawn_area
);
529 gui
->graphics
->set_draw_faded (Output
.fgGC
, 0);
532 DrawSilk (side
, drawn_area
);
537 * \brief Initializes some identifiers for a new zoom factor and redraws
541 DrawEverything (const BoxType
*drawn_area
)
543 int i
, ngroups
, side
;
544 int top_group
, bottom_group
;
545 /* This is the list of layer groups we will draw. */
546 int do_group
[MAX_GROUP
];
547 /* This is the reverse of the order in which we draw them. */
548 int drawn_groups
[MAX_GROUP
];
549 int plated
, unplated
;
552 PCB
->Data
->SILKLAYER
.Color
= PCB
->ElementColor
;
553 PCB
->Data
->BACKSILKLAYER
.Color
= PCB
->InvisibleObjectsColor
;
555 memset (do_group
, 0, sizeof (do_group
));
556 for (ngroups
= 0, i
= 0; i
< max_copper_layer
; i
++)
558 LayerType
*l
= LAYER_ON_STACK (i
);
559 int group
= GetLayerGroupNumberByNumber (LayerStack
[i
]);
560 if (l
->On
&& !do_group
[group
])
563 drawn_groups
[ngroups
++] = group
;
567 top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
568 bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
571 * first draw all 'invisible' stuff
573 if (!TEST_FLAG (CHECKPLANESFLAG
, PCB
)
574 && gui
->set_layer ("invisible", SL (INVISIBLE
, 0), 0))
576 side
= SWAP_IDENT
? TOP_SIDE
: BOTTOM_SIDE
;
579 r_search (PCB
->Data
->element_tree
, drawn_area
, NULL
, element_callback
, &side
);
580 r_search (PCB
->Data
->name_tree
[NAME_INDEX (PCB
)], drawn_area
, NULL
, name_callback
, &side
);
581 DrawLayer (&(PCB
->Data
->Layer
[max_copper_layer
+ side
]), drawn_area
);
583 r_search (PCB
->Data
->pad_tree
, drawn_area
, NULL
, pad_callback
, &side
);
587 /* draw all layers in layerstack order */
588 for (i
= ngroups
- 1; i
>= 0; i
--)
590 int group
= drawn_groups
[i
];
592 if (gui
->set_layer (0, group
, 0))
594 DrawLayerGroup (group
, drawn_area
);
599 if (TEST_FLAG (CHECKPLANESFLAG
, PCB
) && gui
->gui
)
602 /* Draw pins, pads, vias below silk */
604 DrawPPV (SWAP_IDENT
? bottom_group
: top_group
, drawn_area
);
607 CountHoles (&plated
, &unplated
, drawn_area
);
609 if (plated
&& gui
->set_layer ("plated-drill", SL (PDRILL
, 0), 0))
611 DrawHoles (true, false, drawn_area
);
615 if (unplated
&& gui
->set_layer ("unplated-drill", SL (UDRILL
, 0), 0))
617 DrawHoles (false, true, drawn_area
);
622 /* Draw the solder mask if turned on */
623 if (gui
->set_layer ("componentmask", SL (MASK
, TOP
), 0))
625 DrawMask (TOP_SIDE
, drawn_area
);
629 if (gui
->set_layer ("soldermask", SL (MASK
, BOTTOM
), 0))
631 DrawMask (BOTTOM_SIDE
, drawn_area
);
635 if (gui
->set_layer ("topsilk", SL (SILK
, TOP
), 0))
637 DrawSilk (TOP_SIDE
, drawn_area
);
641 if (gui
->set_layer ("bottomsilk", SL (SILK
, BOTTOM
), 0))
643 DrawSilk (BOTTOM_SIDE
, drawn_area
);
649 /* Draw element Marks */
651 r_search (PCB
->Data
->element_tree
, drawn_area
, NULL
, EMark_callback
,
653 /* Draw rat lines on top */
654 if (gui
->set_layer ("rats", SL (RATS
, 0), 0))
656 DrawRats(drawn_area
);
661 paste_empty
= IsPasteEmpty (TOP_SIDE
);
662 if (gui
->set_layer ("toppaste", SL (PASTE
, TOP
), paste_empty
))
664 DrawPaste (TOP_SIDE
, drawn_area
);
668 paste_empty
= IsPasteEmpty (BOTTOM_SIDE
);
669 if (gui
->set_layer ("bottompaste", SL (PASTE
, BOTTOM
), paste_empty
))
671 DrawPaste (BOTTOM_SIDE
, drawn_area
);
675 if (gui
->set_layer ("topassembly", SL (ASSY
, TOP
), 0))
677 PrintAssembly (TOP_SIDE
, drawn_area
);
681 if (gui
->set_layer ("bottomassembly", SL (ASSY
, BOTTOM
), 0))
683 PrintAssembly (BOTTOM_SIDE
, drawn_area
);
687 if (gui
->set_layer ("fab", SL (FAB
, 0), 0))
689 PrintFab (Output
.fgGC
);
695 DrawEMark (ElementType
*e
, Coord X
, Coord Y
, bool invisible
)
697 Coord mark_size
= EMARK_SIZE
;
698 if (!PCB
->InvisibleObjectsOn
&& invisible
)
703 PinType
*pin0
= e
->Pin
->data
;
704 if (TEST_FLAG (HOLEFLAG
, pin0
))
705 mark_size
= MIN (mark_size
, pin0
->DrillingHole
/ 2);
707 mark_size
= MIN (mark_size
, pin0
->Thickness
/ 2);
712 PadType
*pad0
= e
->Pad
->data
;
713 mark_size
= MIN (mark_size
, pad0
->Thickness
/ 2);
716 gui
->graphics
->set_color (Output
.fgGC
,
717 invisible
? PCB
->InvisibleMarkColor
: PCB
->ElementColor
);
718 gui
->graphics
->set_line_cap (Output
.fgGC
, Trace_Cap
);
719 gui
->graphics
->set_line_width (Output
.fgGC
, 0);
720 gui
->graphics
->draw_line (Output
.fgGC
, X
- mark_size
, Y
, X
, Y
- mark_size
);
721 gui
->graphics
->draw_line (Output
.fgGC
, X
+ mark_size
, Y
, X
, Y
- mark_size
);
722 gui
->graphics
->draw_line (Output
.fgGC
, X
- mark_size
, Y
, X
, Y
+ mark_size
);
723 gui
->graphics
->draw_line (Output
.fgGC
, X
+ mark_size
, Y
, X
, Y
+ mark_size
);
726 * If an element is locked, place a "L" on top of the "diamond".
727 * This provides a nice visual indication that it is locked that
728 * works even for color blind users.
730 if (TEST_FLAG (LOCKFLAG
, e
) )
732 gui
->graphics
->draw_line (Output
.fgGC
, X
, Y
, X
+ 2 * mark_size
, Y
);
733 gui
->graphics
->draw_line (Output
.fgGC
, X
, Y
, X
, Y
- 4* mark_size
);
738 * \brief Draws pins pads and vias - Always draws for non-gui HIDs,
739 * otherwise drawing depends on PCB->PinOn and PCB->ViaOn.
742 DrawPPV (int group
, const BoxType
*drawn_area
)
744 int top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
745 int bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
748 if (PCB
->PinOn
|| !gui
->gui
)
750 /* draw element pins */
751 r_search (PCB
->Data
->pin_tree
, drawn_area
, NULL
, pin_callback
, NULL
);
753 /* draw element pads */
754 if (group
== top_group
)
757 r_search (PCB
->Data
->pad_tree
, drawn_area
, NULL
, pad_callback
, &side
);
760 if (group
== bottom_group
)
763 r_search (PCB
->Data
->pad_tree
, drawn_area
, NULL
, pad_callback
, &side
);
768 if (PCB
->ViaOn
|| !gui
->gui
)
770 r_search (PCB
->Data
->via_tree
, drawn_area
, NULL
, via_callback
, NULL
);
771 r_search (PCB
->Data
->via_tree
, drawn_area
, NULL
, hole_callback
, NULL
);
773 if (PCB
->PinOn
|| doing_assy
)
774 r_search (PCB
->Data
->pin_tree
, drawn_area
, NULL
, hole_callback
, NULL
);
778 clearPin_callback (const BoxType
* b
, void *cl
)
780 PinType
*pin
= (PinType
*) b
;
781 if (TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG (THINDRAWPOLYFLAG
, PCB
))
782 gui
->graphics
->thindraw_pcb_pv (Output
.pmGC
, Output
.pmGC
, pin
, false, true);
784 gui
->graphics
->fill_pcb_pv (Output
.pmGC
, Output
.pmGC
, pin
, false, true);
789 const BoxType
*drawn_area
;
794 poly_callback (const BoxType
* b
, void *cl
)
796 struct poly_info
*i
= cl
;
797 PolygonType
*polygon
= (PolygonType
*)b
;
799 set_layer_object_color (i
->layer
, (AnyObjectType
*) polygon
);
801 gui
->graphics
->draw_pcb_polygon (Output
.fgGC
, polygon
, i
->drawn_area
);
807 clearPad_callback (const BoxType
* b
, void *cl
)
809 PadType
*pad
= (PadType
*) b
;
811 if (ON_SIDE (pad
, *side
) && pad
->Mask
)
812 _draw_pad (Output
.pmGC
, pad
, true, true);
817 * \brief Draws silk layer.
820 DrawSilk (int side
, const BoxType
* drawn_area
)
823 /* This code is used when you want to mask silk to avoid exposed
824 pins and pads. We decided it was a bad idea to do this
825 unconditionally, but the code remains. */
829 if (gui
->poly_before
)
831 gui
->graphics
->use_mask (HID_MASK_BEFORE
);
833 DrawLayer (LAYER_PTR (max_copper_layer
+ side
), drawn_area
);
835 r_search (PCB
->Data
->element_tree
, drawn_area
, NULL
, element_callback
, &side
);
836 r_search (PCB
->Data
->name_tree
[NAME_INDEX (PCB
)], drawn_area
, NULL
, name_callback
, &side
);
840 gui
->graphics
->use_mask (HID_MASK_CLEAR
);
841 r_search (PCB
->Data
->pin_tree
, drawn_area
, NULL
, clearPin_callback
, NULL
);
842 r_search (PCB
->Data
->via_tree
, drawn_area
, NULL
, clearPin_callback
, NULL
);
843 r_search (PCB
->Data
->pad_tree
, drawn_area
, NULL
, clearPad_callback
, &side
);
847 gui
->graphics
->use_mask (HID_MASK_AFTER
);
848 DrawLayer (LAYER_PTR (max_copper_layer
+ layer
), drawn_area
);
850 r_search (PCB
->Data
->element_tree
, drawn_area
, NULL
, element_callback
, &side
);
851 r_search (PCB
->Data
->name_tree
[NAME_INDEX (PCB
)], drawn_area
, NULL
, name_callback
, &side
);
853 gui
->graphics
->use_mask (HID_MASK_OFF
);
859 DrawMaskBoardArea (int mask_type
, const BoxType
*drawn_area
)
861 /* Skip the mask drawing if the GUI doesn't want this type */
862 if ((mask_type
== HID_MASK_BEFORE
&& !gui
->poly_before
) ||
863 (mask_type
== HID_MASK_AFTER
&& !gui
->poly_after
))
866 gui
->graphics
->use_mask (mask_type
);
867 gui
->graphics
->set_color (Output
.fgGC
, PCB
->MaskColor
);
868 if (drawn_area
== NULL
)
869 gui
->graphics
->fill_rect (Output
.fgGC
, 0, 0, PCB
->MaxWidth
, PCB
->MaxHeight
);
871 gui
->graphics
->fill_rect (Output
.fgGC
, drawn_area
->X1
, drawn_area
->Y1
,
872 drawn_area
->X2
, drawn_area
->Y2
);
876 * \brief Draws solder mask layer - this will cover nearly everything.
879 DrawMask (int side
, const BoxType
*screen
)
881 int thin
= TEST_FLAG(THINDRAWFLAG
, PCB
) || TEST_FLAG(THINDRAWPOLYFLAG
, PCB
);
884 gui
->graphics
->set_color (Output
.pmGC
, PCB
->MaskColor
);
887 DrawMaskBoardArea (HID_MASK_BEFORE
, screen
);
888 gui
->graphics
->use_mask (HID_MASK_CLEAR
);
891 r_search (PCB
->Data
->pin_tree
, screen
, NULL
, clearPin_callback
, NULL
);
892 r_search (PCB
->Data
->via_tree
, screen
, NULL
, clearPin_callback
, NULL
);
893 r_search (PCB
->Data
->pad_tree
, screen
, NULL
, clearPad_callback
, &side
);
896 gui
->graphics
->set_color (Output
.pmGC
, "erase");
899 DrawMaskBoardArea (HID_MASK_AFTER
, screen
);
900 gui
->graphics
->use_mask (HID_MASK_OFF
);
905 * \brief Draws solder paste layer for a given side of the board.
908 DrawPaste (int side
, const BoxType
*drawn_area
)
910 gui
->graphics
->set_color (Output
.fgGC
, PCB
->ElementColor
);
911 ALLPAD_LOOP (PCB
->Data
);
913 if (ON_SIDE (pad
, side
) && !TEST_FLAG (NOPASTEFLAG
, pad
) && pad
->Mask
> 0)
915 if (pad
->Mask
< pad
->Thickness
)
916 _draw_pad (Output
.fgGC
, pad
, true, true);
918 _draw_pad (Output
.fgGC
, pad
, false, false);
925 DrawRats (const BoxType
*drawn_area
)
928 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
929 * XXX gtk only allows negative drawing.
930 * XXX using the mask here is to get rat transparency
932 int can_mask
= strcmp(gui
->name
, "lesstif") == 0;
935 gui
->graphics
->use_mask (HID_MASK_CLEAR
);
936 r_search (PCB
->Data
->rat_tree
, drawn_area
, NULL
, rat_callback
, NULL
);
938 gui
->graphics
->use_mask (HID_MASK_OFF
);
942 text_callback (const BoxType
* b
, void *cl
)
944 LayerType
*layer
= cl
;
945 TextType
*text
= (TextType
*)b
;
948 if (TEST_FLAG (SELECTEDFLAG
, text
))
949 gui
->graphics
->set_color (Output
.fgGC
, layer
->SelectedColor
);
951 gui
->graphics
->set_color (Output
.fgGC
, layer
->Color
);
952 if (layer
== &PCB
->Data
->SILKLAYER
||
953 layer
== &PCB
->Data
->BACKSILKLAYER
)
954 min_silk_line
= PCB
->minSlk
;
956 min_silk_line
= PCB
->minWid
;
957 gui
->graphics
->draw_pcb_text (Output
.fgGC
, text
, min_silk_line
);
962 DrawLayer (LayerType
*Layer
, const BoxType
*screen
)
964 struct poly_info info
= {screen
, Layer
};
966 /* print the non-clearing polys */
967 r_search (Layer
->polygon_tree
, screen
, NULL
, poly_callback
, &info
);
969 if (TEST_FLAG (CHECKPLANESFLAG
, PCB
))
972 /* draw all visible lines this layer */
973 r_search (Layer
->line_tree
, screen
, NULL
, line_callback
, Layer
);
975 /* draw the layer arcs on screen */
976 r_search (Layer
->arc_tree
, screen
, NULL
, arc_callback
, Layer
);
978 /* draw the layer text on screen */
979 r_search (Layer
->text_tree
, screen
, NULL
, text_callback
, Layer
);
981 /* We should check for gui->gui here, but it's kinda cool seeing the
982 auto-outline magically disappear when you first add something to
983 the "outline" layer. */
984 if (IsLayerEmpty (Layer
)
985 && (strcmp (Layer
->Name
, "outline") == 0
986 || strcmp (Layer
->Name
, "route") == 0))
988 gui
->graphics
->set_color (Output
.fgGC
, Layer
->Color
);
989 gui
->graphics
->set_line_width (Output
.fgGC
, PCB
->minWid
);
990 gui
->graphics
->draw_rect (Output
.fgGC
,
992 PCB
->MaxWidth
, PCB
->MaxHeight
);
997 * \brief Draws one layer group.
999 * If the exporter is not a GUI, also draws the pins / pads / vias in
1003 DrawLayerGroup (int group
, const BoxType
*drawn_area
)
1008 int n_entries
= PCB
->LayerGroups
.Number
[group
];
1009 Cardinal
*layers
= PCB
->LayerGroups
.Entries
[group
];
1011 for (i
= n_entries
- 1; i
>= 0; i
--)
1013 layernum
= layers
[i
];
1014 Layer
= PCB
->Data
->Layer
+ layers
[i
];
1015 if (strcmp (Layer
->Name
, "outline") == 0 ||
1016 strcmp (Layer
->Name
, "route") == 0)
1018 if (layernum
< max_copper_layer
&& Layer
->On
)
1019 DrawLayer (Layer
, drawn_area
);
1024 if (rv
&& !gui
->gui
)
1025 DrawPPV (group
, drawn_area
);
1029 GatherPVName (PinType
*Ptr
)
1032 bool vert
= TEST_FLAG (EDGE2FLAG
, Ptr
);
1036 box
.X1
= Ptr
->X
- Ptr
->Thickness
/ 2 + Settings
.PinoutTextOffsetY
;
1037 box
.Y1
= Ptr
->Y
- Ptr
->DrillingHole
/ 2 - Settings
.PinoutTextOffsetX
;
1041 box
.X1
= Ptr
->X
+ Ptr
->DrillingHole
/ 2 + Settings
.PinoutTextOffsetX
;
1042 box
.Y1
= Ptr
->Y
- Ptr
->Thickness
/ 2 + Settings
.PinoutTextOffsetY
;
1059 GatherPadName (PadType
*Pad
)
1064 /* should text be vertical ? */
1065 vert
= (Pad
->Point1
.X
== Pad
->Point2
.X
);
1069 box
.X1
= Pad
->Point1
.X
- Pad
->Thickness
/ 2;
1070 box
.Y1
= MAX (Pad
->Point1
.Y
, Pad
->Point2
.Y
) + Pad
->Thickness
/ 2;
1071 box
.X1
+= Settings
.PinoutTextOffsetY
;
1072 box
.Y1
-= Settings
.PinoutTextOffsetX
;
1078 box
.X1
= MIN (Pad
->Point1
.X
, Pad
->Point2
.X
) - Pad
->Thickness
/ 2;
1079 box
.Y1
= Pad
->Point1
.Y
- Pad
->Thickness
/ 2;
1080 box
.X1
+= Settings
.PinoutTextOffsetX
;
1081 box
.Y1
+= Settings
.PinoutTextOffsetY
;
1091 * \brief Draw a via object.
1094 DrawVia (PinType
*Via
)
1097 if (!TEST_FLAG (HOLEFLAG
, Via
) && TEST_FLAG (DISPLAYNAMEFLAG
, Via
))
1102 * \brief Draws the name of a via.
1105 DrawViaName (PinType
*Via
)
1111 * \brief Draw a pin object.
1114 DrawPin (PinType
*Pin
)
1117 if ((!TEST_FLAG (HOLEFLAG
, Pin
) && TEST_FLAG (DISPLAYNAMEFLAG
, Pin
))
1123 * \brief Draws the name of a pin.
1126 DrawPinName (PinType
*Pin
)
1132 * \brief Draw a pad object.
1135 DrawPad (PadType
*Pad
)
1138 if (doing_pinout
|| TEST_FLAG (DISPLAYNAMEFLAG
, Pad
))
1143 * \brief Draws the name of a pad.
1146 DrawPadName (PadType
*Pad
)
1148 GatherPadName (Pad
);
1152 * \brief Draws a line on a layer.
1155 DrawLine (LayerType
*Layer
, LineType
*Line
)
1161 * \brief Draws a ratline.
1164 DrawRat (RatType
*Rat
)
1166 if (Settings
.RatThickness
< 100)
1167 Rat
->Thickness
= pixel_slop
* Settings
.RatThickness
;
1168 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1169 if (TEST_FLAG(VIAFLAG
, Rat
))
1171 Coord w
= Rat
->Thickness
;
1175 b
.X1
= Rat
->Point1
.X
- w
* 2 - w
/ 2;
1176 b
.X2
= Rat
->Point1
.X
+ w
* 2 + w
/ 2;
1177 b
.Y1
= Rat
->Point1
.Y
- w
* 2 - w
/ 2;
1178 b
.Y2
= Rat
->Point1
.Y
+ w
* 2 + w
/ 2;
1182 DrawLine (NULL
, (LineType
*)Rat
);
1186 * \brief Draws an arc on a layer.
1189 DrawArc (LayerType
*Layer
, ArcType
*Arc
)
1195 * \brief Draws a text on a layer.
1198 DrawText (LayerType
*Layer
, TextType
*Text
)
1205 * \brief Draws a polygon on a layer.
1208 DrawPolygon (LayerType
*Layer
, PolygonType
*Polygon
)
1214 * \brief Draws an element.
1217 DrawElement (ElementType
*Element
)
1219 DrawElementPackage (Element
);
1220 DrawElementName (Element
);
1221 DrawElementPinsAndPads (Element
);
1225 * \brief Draws the name of an element.
1228 DrawElementName (ElementType
*Element
)
1230 if (TEST_FLAG (HIDENAMEFLAG
, Element
))
1232 DrawText (NULL
, &ELEMENT_TEXT (PCB
, Element
));
1236 * \brief Draws the package of an element.
1239 DrawElementPackage (ElementType
*Element
)
1241 ELEMENTLINE_LOOP (Element
);
1243 DrawLine (NULL
, line
);
1248 DrawArc (NULL
, arc
);
1254 * \brief Draw pins of an element.
1257 DrawElementPinsAndPads (ElementType
*Element
)
1261 if (doing_pinout
|| doing_assy
|| FRONT (pad
) || PCB
->InvisibleObjectsOn
)
1273 * \brief Erase a via.
1276 EraseVia (PinType
*Via
)
1279 if (TEST_FLAG (DISPLAYNAMEFLAG
, Via
))
1284 * \brief Erase a ratline.
1287 EraseRat (RatType
*Rat
)
1289 if (TEST_FLAG(VIAFLAG
, Rat
))
1291 Coord w
= Rat
->Thickness
;
1295 b
.X1
= Rat
->Point1
.X
- w
* 2 - w
/ 2;
1296 b
.X2
= Rat
->Point1
.X
+ w
* 2 + w
/ 2;
1297 b
.Y1
= Rat
->Point1
.Y
- w
* 2 - w
/ 2;
1298 b
.Y2
= Rat
->Point1
.Y
+ w
* 2 + w
/ 2;
1302 EraseLine ((LineType
*)Rat
);
1307 * \brief Erase a via name.
1310 EraseViaName (PinType
*Via
)
1316 * \brief Erase a pad object.
1319 ErasePad (PadType
*Pad
)
1322 if (TEST_FLAG (DISPLAYNAMEFLAG
, Pad
))
1327 * \brief Erase a pad name.
1330 ErasePadName (PadType
*Pad
)
1332 GatherPadName (Pad
);
1336 * \brief Erase a pin object.
1339 ErasePin (PinType
*Pin
)
1342 if (TEST_FLAG (DISPLAYNAMEFLAG
, Pin
))
1347 * \brief Erase a pin name.
1350 ErasePinName (PinType
*Pin
)
1356 * \brief Erases a line on a layer.
1359 EraseLine (LineType
*Line
)
1365 * \brief Erases an arc on a layer.
1368 EraseArc (ArcType
*Arc
)
1370 if (!Arc
->Thickness
)
1376 * \brief Erases a text on a layer.
1379 EraseText (LayerType
*Layer
, TextType
*Text
)
1381 /* r_delete_entry (Layer->text_tree, (BoxType *) Text); */
1386 * \brief Erases a polygon on a layer.
1389 ErasePolygon (PolygonType
*Polygon
)
1395 * \brief Erases an element.
1398 EraseElement (ElementType
*Element
)
1400 ELEMENTLINE_LOOP (Element
);
1410 EraseElementName (Element
);
1411 EraseElementPinsAndPads (Element
);
1415 * \brief Erases all pins and pads of an element.
1418 EraseElementPinsAndPads (ElementType
*Element
)
1433 * \brief Erases the name of an element.
1436 EraseElementName (ElementType
*Element
)
1438 if (TEST_FLAG (HIDENAMEFLAG
, Element
))
1440 EraseText (NULL
, &ELEMENT_TEXT (PCB
, Element
));}
1444 EraseObject (int type
, void *lptr
, void *ptr
)
1450 ErasePin ((PinType
*) ptr
);
1453 EraseText ((LayerType
*)lptr
, (TextType
*) ptr
);
1455 case ELEMENTNAME_TYPE
:
1456 EraseElementName ((ElementType
*) ptr
);
1459 ErasePolygon ((PolygonType
*) ptr
);
1462 EraseElement ((ElementType
*) ptr
);
1465 case ELEMENTLINE_TYPE
:
1467 EraseLine ((LineType
*) ptr
);
1470 ErasePad ((PadType
*) ptr
);
1473 case ELEMENTARC_TYPE
:
1474 EraseArc ((ArcType
*) ptr
);
1477 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
1484 DrawObject (int type
, void *ptr1
, void *ptr2
)
1490 DrawVia ((PinType
*) ptr2
);
1493 if (((LayerType
*) ptr1
)->On
)
1494 DrawLine ((LayerType
*) ptr1
, (LineType
*) ptr2
);
1497 if (((LayerType
*) ptr1
)->On
)
1498 DrawArc ((LayerType
*) ptr1
, (ArcType
*) ptr2
);
1501 if (((LayerType
*) ptr1
)->On
)
1502 DrawText ((LayerType
*) ptr1
, (TextType
*) ptr2
);
1505 if (((LayerType
*) ptr1
)->On
)
1506 DrawPolygon ((LayerType
*) ptr1
, (PolygonType
*) ptr2
);
1509 if (PCB
->ElementOn
&&
1510 (FRONT ((ElementType
*) ptr2
) || PCB
->InvisibleObjectsOn
))
1511 DrawElement ((ElementType
*) ptr2
);
1515 DrawRat ((RatType
*) ptr2
);
1519 DrawPin ((PinType
*) ptr2
);
1523 DrawPad ((PadType
*) ptr2
);
1525 case ELEMENTNAME_TYPE
:
1526 if (PCB
->ElementOn
&&
1527 (FRONT ((ElementType
*) ptr2
) || PCB
->InvisibleObjectsOn
))
1528 DrawElementName ((ElementType
*) ptr1
);
1534 draw_element (ElementType
*element
)
1536 draw_element_package (element
);
1537 draw_element_name (element
);
1538 draw_element_pins_and_pads (element
);
1542 * \brief HID drawing callback.
1545 hid_expose_callback (HID
* hid
, BoxType
* region
, void *item
)
1550 Output
.fgGC
= gui
->graphics
->make_gc ();
1551 Output
.bgGC
= gui
->graphics
->make_gc ();
1552 Output
.pmGC
= gui
->graphics
->make_gc ();
1554 hid
->graphics
->set_color (Output
.pmGC
, "erase");
1555 hid
->graphics
->set_color (Output
.bgGC
, "drill");
1559 doing_pinout
= true;
1560 draw_element ((ElementType
*)item
);
1561 doing_pinout
= false;
1564 DrawEverything (region
);
1566 gui
->graphics
->destroy_gc (Output
.fgGC
);
1567 gui
->graphics
->destroy_gc (Output
.bgGC
);
1568 gui
->graphics
->destroy_gc (Output
.pmGC
);