gerber.c: Use ` modifier in pcb-printf to fix internationalization bug
[geda-pcb/whiteaudio.git] / src / draw.c
bloba06dde184e767a871d3b4967e87b8fb334f3a92f
1 /* $Id$ */
3 /*
4 * COPYRIGHT
6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996, 2003, 2004 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
30 /* drawing routines
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
37 #include "global.h"
39 /*#include "clip.h"*/
40 #include "compat.h"
41 #include "crosshair.h"
42 #include "data.h"
43 #include "draw.h"
44 #include "error.h"
45 #include "mymem.h"
46 #include "misc.h"
47 #include "rotate.h"
48 #include "rtree.h"
49 #include "search.h"
50 #include "select.h"
51 #include "print.h"
53 #ifdef HAVE_LIBDMALLOC
54 #include <dmalloc.h>
55 #endif
57 #undef NDEBUG
58 #include <assert.h>
60 #ifndef MAXINT
61 #define MAXINT (((unsigned int)(~0))>>1)
62 #endif
64 RCSID ("$Id$");
66 #define SMALL_SMALL_TEXT_SIZE 0
67 #define SMALL_TEXT_SIZE 1
68 #define NORMAL_TEXT_SIZE 2
69 #define LARGE_TEXT_SIZE 3
70 #define N_TEXT_SIZES 4
73 /* ---------------------------------------------------------------------------
74 * some local identifiers
76 static BoxType Block = {MAXINT, MAXINT, -MAXINT, -MAXINT};
78 static int doing_pinout = 0;
79 static bool doing_assy = false;
81 /* ---------------------------------------------------------------------------
82 * some local prototypes
84 static void DrawEverything (const BoxType *);
85 static void DrawPPV (int group, const BoxType *);
86 static void AddPart (void *);
87 static void SetPVColor (PinTypePtr, int);
88 static void DrawEMark (ElementTypePtr, Coord, Coord, bool);
89 static void DrawRats (const BoxType *);
91 /*--------------------------------------------------------------------------------------
92 * setup color for pin or via
94 static void
95 SetPVColor (PinTypePtr Pin, int Type)
97 char *color;
99 if (Type == VIA_TYPE)
101 if (!doing_pinout
102 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
104 if (TEST_FLAG (WARNFLAG, Pin))
105 color = PCB->WarnColor;
106 else if (TEST_FLAG (SELECTEDFLAG, Pin))
107 color = PCB->ViaSelectedColor;
108 else
109 color = PCB->ConnectedColor;
111 else
112 color = PCB->ViaColor;
114 else
116 if (!doing_pinout
117 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
119 if (TEST_FLAG (WARNFLAG, Pin))
120 color = PCB->WarnColor;
121 else if (TEST_FLAG (SELECTEDFLAG, Pin))
122 color = PCB->PinSelectedColor;
123 else
124 color = PCB->ConnectedColor;
126 else
127 color = PCB->PinColor;
130 gui->set_color (Output.fgGC, color);
133 /*---------------------------------------------------------------------------
134 * Adds the update rect to the update region
136 static void
137 AddPart (void *b)
139 BoxType *box = (BoxType *) b;
141 Block.X1 = MIN (Block.X1, box->X1);
142 Block.X2 = MAX (Block.X2, box->X2);
143 Block.Y1 = MIN (Block.Y1, box->Y1);
144 Block.Y2 = MAX (Block.Y2, box->Y2);
148 * initiate the actual redrawing of the updated area
150 void
151 Draw (void)
153 if (Block.X1 <= Block.X2 && Block.Y1 <= Block.Y2)
154 gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2);
156 /* shrink the update block */
157 Block.X1 = Block.Y1 = MAXINT;
158 Block.X2 = Block.Y2 = -MAXINT;
161 /* ----------------------------------------------------------------------
162 * redraws all the data by the event handlers
164 void
165 Redraw (void)
167 gui->invalidate_all ();
170 static void
171 _draw_pv_name (PinType *pv)
173 BoxType box;
174 bool vert;
175 TextType text;
177 if (!pv->Name || !pv->Name[0])
178 text.TextString = EMPTY (pv->Number);
179 else
180 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pv->Number : pv->Name);
182 vert = TEST_FLAG (EDGE2FLAG, pv);
184 if (vert)
186 box.X1 = pv->X - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
187 box.Y1 = pv->Y - pv->DrillingHole / 2 - Settings.PinoutTextOffsetX;
189 else
191 box.X1 = pv->X + pv->DrillingHole / 2 + Settings.PinoutTextOffsetX;
192 box.Y1 = pv->Y - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
195 gui->set_color (Output.fgGC, PCB->PinNameColor);
197 text.Flags = NoFlags ();
198 /* Set font height to approx 56% of pin thickness */
199 text.Scale = 56 * pv->Thickness / FONT_CAPHEIGHT;
200 text.X = box.X1;
201 text.Y = box.Y1;
202 text.Direction = vert ? 1 : 0;
204 if (gui->gui)
205 doing_pinout++;
206 DrawTextLowLevel (&text, 0);
207 if (gui->gui)
208 doing_pinout--;
211 static void
212 _draw_pv (PinTypePtr pv, bool draw_hole)
214 if (TEST_FLAG (THINDRAWFLAG, PCB))
215 gui->thindraw_pcb_pv (Output.fgGC, Output.fgGC, pv, draw_hole, false);
216 else
217 gui->fill_pcb_pv (Output.fgGC, Output.bgGC, pv, draw_hole, false);
219 if (!TEST_FLAG (HOLEFLAG, pv) && TEST_FLAG (DISPLAYNAMEFLAG, pv))
220 _draw_pv_name (pv);
223 static void
224 draw_pin (PinTypePtr pin, bool draw_hole)
226 SetPVColor (pin, PIN_TYPE);
227 _draw_pv (pin, draw_hole);
230 static int
231 pin_callback (const BoxType * b, void *cl)
233 draw_pin ((PinType *)b, false);
234 return 1;
237 static void
238 draw_via (PinTypePtr via, bool draw_hole)
240 SetPVColor (via, VIA_TYPE);
241 _draw_pv (via, draw_hole);
244 static int
245 via_callback (const BoxType * b, void *cl)
247 draw_via ((PinType *)b, false);
248 return 1;
251 static void
252 draw_pad_name (PadType *pad)
254 BoxType box;
255 bool vert;
256 TextType text;
258 if (!pad->Name || !pad->Name[0])
259 text.TextString = EMPTY (pad->Number);
260 else
261 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pad->Number : pad->Name);
263 /* should text be vertical ? */
264 vert = (pad->Point1.X == pad->Point2.X);
266 if (vert)
268 box.X1 = pad->Point1.X - pad->Thickness / 2;
269 box.Y1 = MAX (pad->Point1.Y, pad->Point2.Y) + pad->Thickness / 2;
270 box.X1 += Settings.PinoutTextOffsetY;
271 box.Y1 -= Settings.PinoutTextOffsetX;
273 else
275 box.X1 = MIN (pad->Point1.X, pad->Point2.X) - pad->Thickness / 2;
276 box.Y1 = pad->Point1.Y - pad->Thickness / 2;
277 box.X1 += Settings.PinoutTextOffsetX;
278 box.Y1 += Settings.PinoutTextOffsetY;
281 gui->set_color (Output.fgGC, PCB->PinNameColor);
283 text.Flags = NoFlags ();
284 /* Set font height to approx 90% of pin thickness */
285 text.Scale = 90 * pad->Thickness / FONT_CAPHEIGHT;
286 text.X = box.X1;
287 text.Y = box.Y1;
288 text.Direction = vert ? 1 : 0;
290 DrawTextLowLevel (&text, 0);
293 static void
294 _draw_pad (hidGC gc, PadType *pad, bool clear, bool mask)
296 if (clear && !mask && pad->Clearance <= 0)
297 return;
299 if (TEST_FLAG (THINDRAWFLAG, PCB) ||
300 (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
301 gui->thindraw_pcb_pad (gc, pad, clear, mask);
302 else
303 gui->fill_pcb_pad (gc, pad, clear, mask);
306 static void
307 draw_pad (PadType *pad)
309 if (doing_pinout)
310 gui->set_color (Output.fgGC, PCB->PinColor);
311 else if (TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, pad))
313 if (TEST_FLAG (WARNFLAG, pad))
314 gui->set_color (Output.fgGC, PCB->WarnColor);
315 else if (TEST_FLAG (SELECTEDFLAG, pad))
316 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
317 else
318 gui->set_color (Output.fgGC, PCB->ConnectedColor);
320 else if (FRONT (pad))
321 gui->set_color (Output.fgGC, PCB->PinColor);
322 else
323 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
325 _draw_pad (Output.fgGC, pad, false, false);
327 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, pad))
328 draw_pad_name (pad);
331 static int
332 pad_callback (const BoxType * b, void *cl)
334 PadTypePtr pad = (PadTypePtr) b;
335 int *side = cl;
337 if (ON_SIDE (pad, *side))
338 draw_pad (pad);
339 return 1;
342 static void
343 draw_element_name (ElementType *element)
345 if ((TEST_FLAG (HIDENAMESFLAG, PCB) && gui->gui) ||
346 TEST_FLAG (HIDENAMEFLAG, element))
347 return;
348 if (doing_pinout || doing_assy)
349 gui->set_color (Output.fgGC, PCB->ElementColor);
350 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
351 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
352 else if (FRONT (element))
353 gui->set_color (Output.fgGC, PCB->ElementColor);
354 else
355 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
356 DrawTextLowLevel (&ELEMENT_TEXT (PCB, element), PCB->minSlk);
359 static int
360 name_callback (const BoxType * b, void *cl)
362 TextTypePtr text = (TextTypePtr) b;
363 ElementTypePtr element = (ElementTypePtr) text->Element;
364 int *side = cl;
366 if (TEST_FLAG (HIDENAMEFLAG, element))
367 return 0;
369 if (ON_SIDE (element, *side))
370 draw_element_name (element);
371 return 0;
374 static void
375 draw_element_pins_and_pads (ElementType *element)
377 PAD_LOOP (element);
379 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
380 draw_pad (pad);
382 END_LOOP;
383 PIN_LOOP (element);
385 draw_pin (pin, true);
387 END_LOOP;
390 static int
391 EMark_callback (const BoxType * b, void *cl)
393 ElementTypePtr element = (ElementTypePtr) b;
395 DrawEMark (element, element->MarkX, element->MarkY, !FRONT (element));
396 return 1;
399 static int
400 hole_callback (const BoxType * b, void *cl)
402 PinTypePtr pv = (PinTypePtr) b;
403 int plated = cl ? *(int *) cl : -1;
405 if ((plated == 0 && !TEST_FLAG (HOLEFLAG, pv)) ||
406 (plated == 1 && TEST_FLAG (HOLEFLAG, pv)))
407 return 1;
409 if (TEST_FLAG (THINDRAWFLAG, PCB))
411 if (!TEST_FLAG (HOLEFLAG, pv))
413 gui->set_line_cap (Output.fgGC, Round_Cap);
414 gui->set_line_width (Output.fgGC, 0);
415 gui->draw_arc (Output.fgGC,
416 pv->X, pv->Y, pv->DrillingHole / 2,
417 pv->DrillingHole / 2, 0, 360);
420 else
421 gui->fill_circle (Output.bgGC, pv->X, pv->Y, pv->DrillingHole / 2);
423 if (TEST_FLAG (HOLEFLAG, pv))
425 if (TEST_FLAG (WARNFLAG, pv))
426 gui->set_color (Output.fgGC, PCB->WarnColor);
427 else if (TEST_FLAG (SELECTEDFLAG, pv))
428 gui->set_color (Output.fgGC, PCB->ViaSelectedColor);
429 else
430 gui->set_color (Output.fgGC, Settings.BlackColor);
432 gui->set_line_cap (Output.fgGC, Round_Cap);
433 gui->set_line_width (Output.fgGC, 0);
434 gui->draw_arc (Output.fgGC,
435 pv->X, pv->Y, pv->DrillingHole / 2,
436 pv->DrillingHole / 2, 0, 360);
438 return 1;
441 void
442 DrawHoles (bool draw_plated, bool draw_unplated, const BoxType *drawn_area)
444 int plated = -1;
446 if ( draw_plated && !draw_unplated) plated = 1;
447 if (!draw_plated && draw_unplated) plated = 0;
449 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, &plated);
450 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, &plated);
453 static void
454 _draw_line (LineType *line)
456 gui->set_line_cap (Output.fgGC, Trace_Cap);
457 if (TEST_FLAG (THINDRAWFLAG, PCB))
458 gui->set_line_width (Output.fgGC, 0);
459 else
460 gui->set_line_width (Output.fgGC, line->Thickness);
462 gui->draw_line (Output.fgGC,
463 line->Point1.X, line->Point1.Y,
464 line->Point2.X, line->Point2.Y);
467 static void
468 draw_line (LayerType *layer, LineType *line)
470 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, line))
472 if (TEST_FLAG (SELECTEDFLAG, line))
473 gui->set_color (Output.fgGC, layer->SelectedColor);
474 else
475 gui->set_color (Output.fgGC, PCB->ConnectedColor);
477 else
478 gui->set_color (Output.fgGC, layer->Color);
479 _draw_line (line);
482 static int
483 line_callback (const BoxType * b, void *cl)
485 draw_line ((LayerType *) cl, (LineType *) b);
486 return 1;
489 static int
490 rat_callback (const BoxType * b, void *cl)
492 RatType *rat = (RatType *)b;
494 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, rat))
496 if (TEST_FLAG (SELECTEDFLAG, rat))
497 gui->set_color (Output.fgGC, PCB->RatSelectedColor);
498 else
499 gui->set_color (Output.fgGC, PCB->ConnectedColor);
501 else
502 gui->set_color (Output.fgGC, PCB->RatColor);
504 if (Settings.RatThickness < 20)
505 rat->Thickness = pixel_slop * Settings.RatThickness;
506 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
507 if (TEST_FLAG(VIAFLAG, rat))
509 int w = rat->Thickness;
511 if (TEST_FLAG (THINDRAWFLAG, PCB))
512 gui->set_line_width (Output.fgGC, 0);
513 else
514 gui->set_line_width (Output.fgGC, w);
515 gui->draw_arc (Output.fgGC, rat->Point1.X, rat->Point1.Y,
516 w * 2, w * 2, 0, 360);
518 else
519 _draw_line ((LineType *) rat);
520 return 1;
523 static void
524 _draw_arc (ArcType *arc)
526 if (!arc->Thickness)
527 return;
529 if (TEST_FLAG (THINDRAWFLAG, PCB))
530 gui->set_line_width (Output.fgGC, 0);
531 else
532 gui->set_line_width (Output.fgGC, arc->Thickness);
533 gui->set_line_cap (Output.fgGC, Trace_Cap);
535 gui->draw_arc (Output.fgGC, arc->X, arc->Y, arc->Width,
536 arc->Height, arc->StartAngle, arc->Delta);
539 static void
540 draw_arc (LayerType *layer, ArcType *arc)
542 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, arc))
544 if (TEST_FLAG (SELECTEDFLAG, arc))
545 gui->set_color (Output.fgGC, layer->SelectedColor);
546 else
547 gui->set_color (Output.fgGC, PCB->ConnectedColor);
549 else
550 gui->set_color (Output.fgGC, layer->Color);
552 _draw_arc (arc);
555 static int
556 arc_callback (const BoxType * b, void *cl)
558 draw_arc ((LayerTypePtr) cl, (ArcTypePtr) b);
559 return 1;
562 static void
563 draw_element_package (ElementType *element)
565 /* set color and draw lines, arcs, text and pins */
566 if (doing_pinout || doing_assy)
567 gui->set_color (Output.fgGC, PCB->ElementColor);
568 else if (TEST_FLAG (SELECTEDFLAG, element))
569 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
570 else if (FRONT (element))
571 gui->set_color (Output.fgGC, PCB->ElementColor);
572 else
573 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
575 /* draw lines, arcs, text and pins */
576 ELEMENTLINE_LOOP (element);
578 _draw_line (line);
580 END_LOOP;
581 ARC_LOOP (element);
583 _draw_arc (arc);
585 END_LOOP;
588 static int
589 element_callback (const BoxType * b, void *cl)
591 ElementTypePtr element = (ElementTypePtr) b;
592 int *side = cl;
594 if (ON_SIDE (element, *side))
595 draw_element_package (element);
596 return 1;
599 /* ---------------------------------------------------------------------------
600 * prints assembly drawing.
603 void
604 PrintAssembly (int side, const BoxType * drawn_area)
606 int side_group = GetLayerGroupNumberByNumber (max_copper_layer + side);
608 doing_assy = true;
609 gui->set_draw_faded (Output.fgGC, 1);
610 DrawLayerGroup (side_group, drawn_area);
611 gui->set_draw_faded (Output.fgGC, 0);
613 /* draw package */
614 DrawSilk (side, drawn_area);
615 doing_assy = false;
618 /* ---------------------------------------------------------------------------
619 * initializes some identifiers for a new zoom factor and redraws whole screen
621 static void
622 DrawEverything (const BoxType *drawn_area)
624 int i, ngroups, side;
625 int component, solder;
626 /* This is the list of layer groups we will draw. */
627 int do_group[MAX_LAYER];
628 /* This is the reverse of the order in which we draw them. */
629 int drawn_groups[MAX_LAYER];
630 int plated, unplated;
631 bool paste_empty;
633 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
634 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
636 memset (do_group, 0, sizeof (do_group));
637 for (ngroups = 0, i = 0; i < max_copper_layer; i++)
639 LayerType *l = LAYER_ON_STACK (i);
640 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
641 if (l->On && !do_group[group])
643 do_group[group] = 1;
644 drawn_groups[ngroups++] = group;
648 component = GetLayerGroupNumberByNumber (component_silk_layer);
649 solder = GetLayerGroupNumberByNumber (solder_silk_layer);
652 * first draw all 'invisible' stuff
654 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
655 && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
657 side = SWAP_IDENT ? COMPONENT_LAYER : SOLDER_LAYER;
658 if (PCB->ElementOn)
660 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
661 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
662 DrawLayer (&(PCB->Data->Layer[max_copper_layer + side]), drawn_area);
664 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
665 gui->end_layer ();
668 /* draw all layers in layerstack order */
669 for (i = ngroups - 1; i >= 0; i--)
671 int group = drawn_groups[i];
673 if (gui->set_layer (0, group, 0))
675 DrawLayerGroup (group, drawn_area);
676 gui->end_layer ();
680 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
681 return;
683 /* Draw pins, pads, vias below silk */
684 if (gui->gui)
685 DrawPPV (SWAP_IDENT ? solder : component, drawn_area);
686 else
688 CountHoles (&plated, &unplated, drawn_area);
690 if (plated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
692 DrawHoles (true, false, drawn_area);
693 gui->end_layer ();
696 if (unplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
698 DrawHoles (false, true, drawn_area);
699 gui->end_layer ();
703 /* Draw the solder mask if turned on */
704 if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
706 DrawMask (COMPONENT_LAYER, drawn_area);
707 gui->end_layer ();
710 if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
712 DrawMask (SOLDER_LAYER, drawn_area);
713 gui->end_layer ();
716 if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
718 DrawSilk (COMPONENT_LAYER, drawn_area);
719 gui->end_layer ();
722 if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
724 DrawSilk (SOLDER_LAYER, drawn_area);
725 gui->end_layer ();
728 if (gui->gui)
730 /* Draw element Marks */
731 if (PCB->PinOn)
732 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
733 NULL);
734 /* Draw rat lines on top */
735 if (gui->set_layer ("rats", SL (RATS, 0), 0))
737 DrawRats(drawn_area);
738 gui->end_layer ();
742 paste_empty = IsPasteEmpty (COMPONENT_LAYER);
743 if (gui->set_layer ("toppaste", SL (PASTE, TOP), paste_empty))
745 DrawPaste (COMPONENT_LAYER, drawn_area);
746 gui->end_layer ();
749 paste_empty = IsPasteEmpty (SOLDER_LAYER);
750 if (gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), paste_empty))
752 DrawPaste (SOLDER_LAYER, drawn_area);
753 gui->end_layer ();
756 if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
758 PrintAssembly (COMPONENT_LAYER, drawn_area);
759 gui->end_layer ();
762 if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
764 PrintAssembly (SOLDER_LAYER, drawn_area);
765 gui->end_layer ();
768 if (gui->set_layer ("fab", SL (FAB, 0), 0))
770 PrintFab (Output.fgGC);
771 gui->end_layer ();
775 static void
776 DrawEMark (ElementTypePtr e, Coord X, Coord Y, bool invisible)
778 Coord mark_size = EMARK_SIZE;
779 if (!PCB->InvisibleObjectsOn && invisible)
780 return;
782 if (e->Pin != NULL)
784 PinType *pin0 = e->Pin->data;
785 if (TEST_FLAG (HOLEFLAG, pin0))
786 mark_size = MIN (mark_size, pin0->DrillingHole / 2);
787 else
788 mark_size = MIN (mark_size, pin0->Thickness / 2);
791 if (e->Pad != NULL)
793 PadType *pad0 = e->Pad->data;
794 mark_size = MIN (mark_size, pad0->Thickness / 2);
797 gui->set_color (Output.fgGC,
798 invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
799 gui->set_line_cap (Output.fgGC, Trace_Cap);
800 gui->set_line_width (Output.fgGC, 0);
801 gui->draw_line (Output.fgGC, X - mark_size, Y, X, Y - mark_size);
802 gui->draw_line (Output.fgGC, X + mark_size, Y, X, Y - mark_size);
803 gui->draw_line (Output.fgGC, X - mark_size, Y, X, Y + mark_size);
804 gui->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
807 * If an element is locked, place a "L" on top of the "diamond".
808 * This provides a nice visual indication that it is locked that
809 * works even for color blind users.
811 if (TEST_FLAG (LOCKFLAG, e) )
813 gui->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
814 gui->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
818 /* ---------------------------------------------------------------------------
819 * Draws pins pads and vias - Always draws for non-gui HIDs,
820 * otherwise drawing depends on PCB->PinOn and PCB->ViaOn
822 static void
823 DrawPPV (int group, const BoxType *drawn_area)
825 int component_group = GetLayerGroupNumberByNumber (component_silk_layer);
826 int solder_group = GetLayerGroupNumberByNumber (solder_silk_layer);
827 int side;
829 if (PCB->PinOn || !gui->gui)
831 /* draw element pins */
832 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback, NULL);
834 /* draw element pads */
835 if (group == component_group)
837 side = COMPONENT_LAYER;
838 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
841 if (group == solder_group)
843 side = SOLDER_LAYER;
844 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
848 /* draw vias */
849 if (PCB->ViaOn || !gui->gui)
851 r_search (PCB->Data->via_tree, drawn_area, NULL, via_callback, NULL);
852 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, NULL);
854 if (PCB->PinOn || doing_assy)
855 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, NULL);
858 static int
859 clearPin_callback (const BoxType * b, void *cl)
861 PinType *pin = (PinTypePtr) b;
862 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
863 gui->thindraw_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
864 else
865 gui->fill_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
866 return 1;
869 struct poly_info {
870 const BoxType *drawn_area;
871 LayerType *layer;
874 static int
875 poly_callback (const BoxType * b, void *cl)
877 struct poly_info *i = cl;
878 PolygonType *polygon = (PolygonType *)b;
879 static char *color;
881 if (!polygon->Clipped)
882 return 0;
884 if (TEST_FLAG (SELECTEDFLAG, polygon))
885 color = i->layer->SelectedColor;
886 else if (TEST_FLAG (FOUNDFLAG, polygon))
887 color = PCB->ConnectedColor;
888 else
889 color = i->layer->Color;
890 gui->set_color (Output.fgGC, color);
892 if (gui->thindraw_pcb_polygon != NULL &&
893 (TEST_FLAG (THINDRAWFLAG, PCB) ||
894 TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
895 gui->thindraw_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
896 else
897 gui->fill_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
899 /* If checking planes, thin-draw any pieces which have been clipped away */
900 if (gui->thindraw_pcb_polygon != NULL &&
901 TEST_FLAG (CHECKPLANESFLAG, PCB) &&
902 !TEST_FLAG (FULLPOLYFLAG, polygon))
904 PolygonType poly = *polygon;
906 for (poly.Clipped = polygon->Clipped->f;
907 poly.Clipped != polygon->Clipped;
908 poly.Clipped = poly.Clipped->f)
909 gui->thindraw_pcb_polygon (Output.fgGC, &poly, i->drawn_area);
912 return 1;
915 static int
916 clearPad_callback (const BoxType * b, void *cl)
918 PadTypePtr pad = (PadTypePtr) b;
919 int *side = cl;
920 if (ON_SIDE (pad, *side) && pad->Mask)
921 _draw_pad (Output.pmGC, pad, true, true);
922 return 1;
925 /* ---------------------------------------------------------------------------
926 * Draws silk layer.
929 void
930 DrawSilk (int side, const BoxType * drawn_area)
932 #if 0
933 /* This code is used when you want to mask silk to avoid exposed
934 pins and pads. We decided it was a bad idea to do this
935 unconditionally, but the code remains. */
936 #endif
938 #if 0
939 if (gui->poly_before)
941 gui->use_mask (HID_MASK_BEFORE);
942 #endif
943 DrawLayer (LAYER_PTR (max_copper_layer + side), drawn_area);
944 /* draw package */
945 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
946 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
947 #if 0
950 gui->use_mask (HID_MASK_CLEAR);
951 r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, NULL);
952 r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, NULL);
953 r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &side);
955 if (gui->poly_after)
957 gui->use_mask (HID_MASK_AFTER);
958 DrawLayer (LAYER_PTR (max_copper_layer + layer), drawn_area);
959 /* draw package */
960 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
961 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
963 gui->use_mask (HID_MASK_OFF);
964 #endif
968 static void
969 DrawMaskBoardArea (int mask_type, const BoxType *drawn_area)
971 /* Skip the mask drawing if the GUI doesn't want this type */
972 if ((mask_type == HID_MASK_BEFORE && !gui->poly_before) ||
973 (mask_type == HID_MASK_AFTER && !gui->poly_after))
974 return;
976 gui->use_mask (mask_type);
977 gui->set_color (Output.fgGC, PCB->MaskColor);
978 if (drawn_area == NULL)
979 gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
980 else
981 gui->fill_rect (Output.fgGC, drawn_area->X1, drawn_area->Y1,
982 drawn_area->X2, drawn_area->Y2);
985 /* ---------------------------------------------------------------------------
986 * draws solder mask layer - this will cover nearly everything
988 void
989 DrawMask (int side, const BoxType *screen)
991 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
993 if (thin)
994 gui->set_color (Output.pmGC, PCB->MaskColor);
995 else
997 DrawMaskBoardArea (HID_MASK_BEFORE, screen);
998 gui->use_mask (HID_MASK_CLEAR);
1001 r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, NULL);
1002 r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, NULL);
1003 r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &side);
1005 if (thin)
1006 gui->set_color (Output.pmGC, "erase");
1007 else
1009 DrawMaskBoardArea (HID_MASK_AFTER, screen);
1010 gui->use_mask (HID_MASK_OFF);
1014 /* ---------------------------------------------------------------------------
1015 * draws solder paste layer for a given side of the board
1017 void
1018 DrawPaste (int side, const BoxType *drawn_area)
1020 gui->set_color (Output.fgGC, PCB->ElementColor);
1021 ALLPAD_LOOP (PCB->Data);
1023 if (ON_SIDE (pad, side) && !TEST_FLAG (NOPASTEFLAG, pad) && pad->Mask > 0)
1025 if (pad->Mask < pad->Thickness)
1026 _draw_pad (Output.fgGC, pad, true, true);
1027 else
1028 _draw_pad (Output.fgGC, pad, false, false);
1031 ENDALL_LOOP;
1034 static void
1035 DrawRats (const BoxType *drawn_area)
1038 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
1039 * XXX gtk only allows negative drawing.
1040 * XXX using the mask here is to get rat transparency
1042 int can_mask = strcmp(gui->name, "lesstif") == 0;
1044 if (can_mask)
1045 gui->use_mask (HID_MASK_CLEAR);
1046 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
1047 if (can_mask)
1048 gui->use_mask (HID_MASK_OFF);
1051 static int
1052 text_callback (const BoxType * b, void *cl)
1054 LayerType *layer = cl;
1055 TextType *text = (TextType *)b;
1056 int min_silk_line;
1058 if (TEST_FLAG (SELECTEDFLAG, text))
1059 gui->set_color (Output.fgGC, layer->SelectedColor);
1060 else
1061 gui->set_color (Output.fgGC, layer->Color);
1062 if (layer == &PCB->Data->SILKLAYER ||
1063 layer == &PCB->Data->BACKSILKLAYER)
1064 min_silk_line = PCB->minSlk;
1065 else
1066 min_silk_line = PCB->minWid;
1067 DrawTextLowLevel (text, min_silk_line);
1068 return 1;
1071 void
1072 DrawLayer (LayerTypePtr Layer, const BoxType * screen)
1074 struct poly_info info = {screen, Layer};
1076 /* print the non-clearing polys */
1077 r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
1079 if (TEST_FLAG (CHECKPLANESFLAG, PCB))
1080 return;
1082 /* draw all visible lines this layer */
1083 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
1085 /* draw the layer arcs on screen */
1086 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
1088 /* draw the layer text on screen */
1089 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
1091 /* We should check for gui->gui here, but it's kinda cool seeing the
1092 auto-outline magically disappear when you first add something to
1093 the "outline" layer. */
1094 if (IsLayerEmpty (Layer)
1095 && (strcmp (Layer->Name, "outline") == 0
1096 || strcmp (Layer->Name, "route") == 0))
1098 gui->set_color (Output.fgGC, Layer->Color);
1099 gui->set_line_width (Output.fgGC, PCB->minWid);
1100 gui->draw_rect (Output.fgGC,
1101 0, 0,
1102 PCB->MaxWidth, PCB->MaxHeight);
1106 /* ---------------------------------------------------------------------------
1107 * draws one layer group. If the exporter is not a GUI,
1108 * also draws the pins / pads / vias in this layer group.
1110 void
1111 DrawLayerGroup (int group, const BoxType *drawn_area)
1113 int i, rv = 1;
1114 int layernum;
1115 LayerTypePtr Layer;
1116 int n_entries = PCB->LayerGroups.Number[group];
1117 Cardinal *layers = PCB->LayerGroups.Entries[group];
1119 for (i = n_entries - 1; i >= 0; i--)
1121 layernum = layers[i];
1122 Layer = PCB->Data->Layer + layers[i];
1123 if (strcmp (Layer->Name, "outline") == 0 ||
1124 strcmp (Layer->Name, "route") == 0)
1125 rv = 0;
1126 if (layernum < max_copper_layer && Layer->On)
1127 DrawLayer (Layer, drawn_area);
1129 if (n_entries > 1)
1130 rv = 1;
1132 if (rv && !gui->gui)
1133 DrawPPV (group, drawn_area);
1136 static void
1137 GatherPVName (PinTypePtr Ptr)
1139 BoxType box;
1140 bool vert = TEST_FLAG (EDGE2FLAG, Ptr);
1142 if (vert)
1144 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1145 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
1147 else
1149 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
1150 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1153 if (vert)
1155 box.X2 = box.X1;
1156 box.Y2 = box.Y1;
1158 else
1160 box.X2 = box.X1;
1161 box.Y2 = box.Y1;
1163 AddPart (&box);
1166 static void
1167 GatherPadName (PadTypePtr Pad)
1169 BoxType box;
1170 bool vert;
1172 /* should text be vertical ? */
1173 vert = (Pad->Point1.X == Pad->Point2.X);
1175 if (vert)
1177 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1178 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1179 box.X1 += Settings.PinoutTextOffsetY;
1180 box.Y1 -= Settings.PinoutTextOffsetX;
1181 box.X2 = box.X1;
1182 box.Y2 = box.Y1;
1184 else
1186 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1187 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1188 box.X1 += Settings.PinoutTextOffsetX;
1189 box.Y1 += Settings.PinoutTextOffsetY;
1190 box.X2 = box.X1;
1191 box.Y2 = box.Y1;
1194 AddPart (&box);
1195 return;
1198 /* ---------------------------------------------------------------------------
1199 * lowlevel drawing routine for text objects
1201 void
1202 DrawTextLowLevel (TextTypePtr Text, Coord min_line_width)
1204 Coord x = 0;
1205 unsigned char *string = (unsigned char *) Text->TextString;
1206 Cardinal n;
1207 FontTypePtr font = &PCB->Font;
1209 while (string && *string)
1211 /* draw lines if symbol is valid and data is present */
1212 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid)
1214 LineTypePtr line = font->Symbol[*string].Line;
1215 LineType newline;
1217 for (n = font->Symbol[*string].LineN; n; n--, line++)
1219 /* create one line, scale, move, rotate and swap it */
1220 newline = *line;
1221 newline.Point1.X = SCALE_TEXT (newline.Point1.X + x, Text->Scale);
1222 newline.Point1.Y = SCALE_TEXT (newline.Point1.Y, Text->Scale);
1223 newline.Point2.X = SCALE_TEXT (newline.Point2.X + x, Text->Scale);
1224 newline.Point2.Y = SCALE_TEXT (newline.Point2.Y, Text->Scale);
1225 newline.Thickness = SCALE_TEXT (newline.Thickness, Text->Scale / 2);
1226 if (newline.Thickness < min_line_width)
1227 newline.Thickness = min_line_width;
1229 RotateLineLowLevel (&newline, 0, 0, Text->Direction);
1231 /* the labels of SMD objects on the bottom
1232 * side haven't been swapped yet, only their offset
1234 if (TEST_FLAG (ONSOLDERFLAG, Text))
1236 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X);
1237 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y);
1238 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X);
1239 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y);
1241 /* add offset and draw line */
1242 newline.Point1.X += Text->X;
1243 newline.Point1.Y += Text->Y;
1244 newline.Point2.X += Text->X;
1245 newline.Point2.Y += Text->Y;
1246 _draw_line (&newline);
1249 /* move on to next cursor position */
1250 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta);
1252 else
1254 /* the default symbol is a filled box */
1255 BoxType defaultsymbol = PCB->Font.DefaultSymbol;
1256 Coord size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5;
1258 defaultsymbol.X1 = SCALE_TEXT (defaultsymbol.X1 + x, Text->Scale);
1259 defaultsymbol.Y1 = SCALE_TEXT (defaultsymbol.Y1, Text->Scale);
1260 defaultsymbol.X2 = SCALE_TEXT (defaultsymbol.X2 + x, Text->Scale);
1261 defaultsymbol.Y2 = SCALE_TEXT (defaultsymbol.Y2, Text->Scale);
1263 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction);
1265 /* add offset and draw box */
1266 defaultsymbol.X1 += Text->X;
1267 defaultsymbol.Y1 += Text->Y;
1268 defaultsymbol.X2 += Text->X;
1269 defaultsymbol.Y2 += Text->Y;
1270 gui->fill_rect (Output.fgGC,
1271 defaultsymbol.X1, defaultsymbol.Y1,
1272 defaultsymbol.X2, defaultsymbol.Y2);
1274 /* move on to next cursor position */
1275 x += size;
1277 string++;
1281 /* ---------------------------------------------------------------------------
1282 * draw a via object
1284 void
1285 DrawVia (PinTypePtr Via)
1287 AddPart (Via);
1288 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1289 DrawViaName (Via);
1292 /* ---------------------------------------------------------------------------
1293 * draws the name of a via
1295 void
1296 DrawViaName (PinTypePtr Via)
1298 GatherPVName (Via);
1301 /* ---------------------------------------------------------------------------
1302 * draw a pin object
1304 void
1305 DrawPin (PinTypePtr Pin)
1307 AddPart (Pin);
1308 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1309 || doing_pinout)
1310 DrawPinName (Pin);
1313 /* ---------------------------------------------------------------------------
1314 * draws the name of a pin
1316 void
1317 DrawPinName (PinTypePtr Pin)
1319 GatherPVName (Pin);
1322 /* ---------------------------------------------------------------------------
1323 * draw a pad object
1325 void
1326 DrawPad (PadTypePtr Pad)
1328 AddPart (Pad);
1329 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1330 DrawPadName (Pad);
1333 /* ---------------------------------------------------------------------------
1334 * draws the name of a pad
1336 void
1337 DrawPadName (PadTypePtr Pad)
1339 GatherPadName (Pad);
1342 /* ---------------------------------------------------------------------------
1343 * draws a line on a layer
1345 void
1346 DrawLine (LayerTypePtr Layer, LineTypePtr Line)
1348 AddPart (Line);
1351 /* ---------------------------------------------------------------------------
1352 * draws a ratline
1354 void
1355 DrawRat (RatTypePtr Rat)
1357 if (Settings.RatThickness < 20)
1358 Rat->Thickness = pixel_slop * Settings.RatThickness;
1359 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1360 if (TEST_FLAG(VIAFLAG, Rat))
1362 Coord w = Rat->Thickness;
1364 BoxType b;
1366 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1367 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1368 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1369 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1370 AddPart (&b);
1372 else
1373 DrawLine (NULL, (LineType *)Rat);
1376 /* ---------------------------------------------------------------------------
1377 * draws an arc on a layer
1379 void
1380 DrawArc (LayerTypePtr Layer, ArcTypePtr Arc)
1382 AddPart (Arc);
1385 /* ---------------------------------------------------------------------------
1386 * draws a text on a layer
1388 void
1389 DrawText (LayerTypePtr Layer, TextTypePtr Text)
1391 AddPart (Text);
1395 /* ---------------------------------------------------------------------------
1396 * draws a polygon on a layer
1398 void
1399 DrawPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
1401 AddPart (Polygon);
1404 /* ---------------------------------------------------------------------------
1405 * draws an element
1407 void
1408 DrawElement (ElementTypePtr Element)
1410 DrawElementPackage (Element);
1411 DrawElementName (Element);
1412 DrawElementPinsAndPads (Element);
1415 /* ---------------------------------------------------------------------------
1416 * draws the name of an element
1418 void
1419 DrawElementName (ElementTypePtr Element)
1421 if (TEST_FLAG (HIDENAMEFLAG, Element))
1422 return;
1423 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1426 /* ---------------------------------------------------------------------------
1427 * draws the package of an element
1429 void
1430 DrawElementPackage (ElementTypePtr Element)
1432 ELEMENTLINE_LOOP (Element);
1434 DrawLine (NULL, line);
1436 END_LOOP;
1437 ARC_LOOP (Element);
1439 DrawArc (NULL, arc);
1441 END_LOOP;
1444 /* ---------------------------------------------------------------------------
1445 * draw pins of an element
1447 void
1448 DrawElementPinsAndPads (ElementTypePtr Element)
1450 PAD_LOOP (Element);
1452 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
1453 DrawPad (pad);
1455 END_LOOP;
1456 PIN_LOOP (Element);
1458 DrawPin (pin);
1460 END_LOOP;
1463 /* ---------------------------------------------------------------------------
1464 * erase a via
1466 void
1467 EraseVia (PinTypePtr Via)
1469 AddPart (Via);
1470 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
1471 EraseViaName (Via);
1474 /* ---------------------------------------------------------------------------
1475 * erase a ratline
1477 void
1478 EraseRat (RatTypePtr Rat)
1480 if (TEST_FLAG(VIAFLAG, Rat))
1482 Coord w = Rat->Thickness;
1484 BoxType b;
1486 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1487 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1488 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1489 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1490 AddPart (&b);
1492 else
1493 EraseLine ((LineType *)Rat);
1497 /* ---------------------------------------------------------------------------
1498 * erase a via name
1500 void
1501 EraseViaName (PinTypePtr Via)
1503 GatherPVName (Via);
1506 /* ---------------------------------------------------------------------------
1507 * erase a pad object
1509 void
1510 ErasePad (PadTypePtr Pad)
1512 AddPart (Pad);
1513 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1514 ErasePadName (Pad);
1517 /* ---------------------------------------------------------------------------
1518 * erase a pad name
1520 void
1521 ErasePadName (PadTypePtr Pad)
1523 GatherPadName (Pad);
1526 /* ---------------------------------------------------------------------------
1527 * erase a pin object
1529 void
1530 ErasePin (PinTypePtr Pin)
1532 AddPart (Pin);
1533 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1534 ErasePinName (Pin);
1537 /* ---------------------------------------------------------------------------
1538 * erase a pin name
1540 void
1541 ErasePinName (PinTypePtr Pin)
1543 GatherPVName (Pin);
1546 /* ---------------------------------------------------------------------------
1547 * erases a line on a layer
1549 void
1550 EraseLine (LineTypePtr Line)
1552 AddPart (Line);
1555 /* ---------------------------------------------------------------------------
1556 * erases an arc on a layer
1558 void
1559 EraseArc (ArcTypePtr Arc)
1561 if (!Arc->Thickness)
1562 return;
1563 AddPart (Arc);
1566 /* ---------------------------------------------------------------------------
1567 * erases a text on a layer
1569 void
1570 EraseText (LayerTypePtr Layer, TextTypePtr Text)
1572 AddPart (Text);
1575 /* ---------------------------------------------------------------------------
1576 * erases a polygon on a layer
1578 void
1579 ErasePolygon (PolygonTypePtr Polygon)
1581 AddPart (Polygon);
1584 /* ---------------------------------------------------------------------------
1585 * erases an element
1587 void
1588 EraseElement (ElementTypePtr Element)
1590 ELEMENTLINE_LOOP (Element);
1592 EraseLine (line);
1594 END_LOOP;
1595 ARC_LOOP (Element);
1597 EraseArc (arc);
1599 END_LOOP;
1600 EraseElementName (Element);
1601 EraseElementPinsAndPads (Element);
1604 /* ---------------------------------------------------------------------------
1605 * erases all pins and pads of an element
1607 void
1608 EraseElementPinsAndPads (ElementTypePtr Element)
1610 PIN_LOOP (Element);
1612 ErasePin (pin);
1614 END_LOOP;
1615 PAD_LOOP (Element);
1617 ErasePad (pad);
1619 END_LOOP;
1622 /* ---------------------------------------------------------------------------
1623 * erases the name of an element
1625 void
1626 EraseElementName (ElementTypePtr Element)
1628 if (TEST_FLAG (HIDENAMEFLAG, Element))
1629 return;
1630 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1634 void
1635 EraseObject (int type, void *lptr, void *ptr)
1637 switch (type)
1639 case VIA_TYPE:
1640 case PIN_TYPE:
1641 ErasePin ((PinTypePtr) ptr);
1642 break;
1643 case TEXT_TYPE:
1644 case ELEMENTNAME_TYPE:
1645 EraseText ((LayerTypePtr)lptr, (TextTypePtr) ptr);
1646 break;
1647 case POLYGON_TYPE:
1648 ErasePolygon ((PolygonTypePtr) ptr);
1649 break;
1650 case ELEMENT_TYPE:
1651 EraseElement ((ElementTypePtr) ptr);
1652 break;
1653 case LINE_TYPE:
1654 case ELEMENTLINE_TYPE:
1655 case RATLINE_TYPE:
1656 EraseLine ((LineTypePtr) ptr);
1657 break;
1658 case PAD_TYPE:
1659 ErasePad ((PadTypePtr) ptr);
1660 break;
1661 case ARC_TYPE:
1662 case ELEMENTARC_TYPE:
1663 EraseArc ((ArcTypePtr) ptr);
1664 break;
1665 default:
1666 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
1672 void
1673 DrawObject (int type, void *ptr1, void *ptr2)
1675 switch (type)
1677 case VIA_TYPE:
1678 if (PCB->ViaOn)
1679 DrawVia ((PinTypePtr) ptr2);
1680 break;
1681 case LINE_TYPE:
1682 if (((LayerTypePtr) ptr1)->On)
1683 DrawLine ((LayerTypePtr) ptr1, (LineTypePtr) ptr2);
1684 break;
1685 case ARC_TYPE:
1686 if (((LayerTypePtr) ptr1)->On)
1687 DrawArc ((LayerTypePtr) ptr1, (ArcTypePtr) ptr2);
1688 break;
1689 case TEXT_TYPE:
1690 if (((LayerTypePtr) ptr1)->On)
1691 DrawText ((LayerTypePtr) ptr1, (TextTypePtr) ptr2);
1692 break;
1693 case POLYGON_TYPE:
1694 if (((LayerTypePtr) ptr1)->On)
1695 DrawPolygon ((LayerTypePtr) ptr1, (PolygonTypePtr) ptr2);
1696 break;
1697 case ELEMENT_TYPE:
1698 if (PCB->ElementOn &&
1699 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
1700 DrawElement ((ElementTypePtr) ptr2);
1701 break;
1702 case RATLINE_TYPE:
1703 if (PCB->RatOn)
1704 DrawRat ((RatTypePtr) ptr2);
1705 break;
1706 case PIN_TYPE:
1707 if (PCB->PinOn)
1708 DrawPin ((PinTypePtr) ptr2);
1709 break;
1710 case PAD_TYPE:
1711 if (PCB->PinOn)
1712 DrawPad ((PadTypePtr) ptr2);
1713 break;
1714 case ELEMENTNAME_TYPE:
1715 if (PCB->ElementOn &&
1716 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
1717 DrawElementName ((ElementTypePtr) ptr1);
1718 break;
1722 static void
1723 draw_element (ElementTypePtr element)
1725 draw_element_package (element);
1726 draw_element_name (element);
1727 draw_element_pins_and_pads (element);
1730 /* ---------------------------------------------------------------------------
1731 * HID drawing callback.
1734 void
1735 hid_expose_callback (HID * hid, BoxType * region, void *item)
1737 HID *old_gui = gui;
1739 gui = hid;
1740 Output.fgGC = gui->make_gc ();
1741 Output.bgGC = gui->make_gc ();
1742 Output.pmGC = gui->make_gc ();
1744 hid->set_color (Output.pmGC, "erase");
1745 hid->set_color (Output.bgGC, "drill");
1747 if (item)
1749 doing_pinout = true;
1750 draw_element ((ElementType *)item);
1751 doing_pinout = false;
1753 else
1754 DrawEverything (region);
1756 gui->destroy_gc (Output.fgGC);
1757 gui->destroy_gc (Output.bgGC);
1758 gui->destroy_gc (Output.pmGC);
1759 gui = old_gui;