Repopulate route style selector on PCBChanged action
[geda-pcb/whiteaudio.git] / src / draw.c
blobdeb9e652d75afc3eef3632120cb11a8ddba638be
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 DrawLayerGroup (int, const BoxType *);
87 static void AddPart (void *);
88 static void SetPVColor (PinTypePtr, int);
89 static void DrawEMark (ElementTypePtr, Coord, Coord, bool);
90 static void DrawMask (int side, const BoxType *);
91 static void DrawPaste (int side, const BoxType *);
92 static void DrawRats (const BoxType *);
93 static void DrawSilk (int side, const BoxType *);
95 /*--------------------------------------------------------------------------------------
96 * setup color for pin or via
98 static void
99 SetPVColor (PinTypePtr Pin, int Type)
101 char *color;
103 if (Type == VIA_TYPE)
105 if (!doing_pinout
106 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
108 if (TEST_FLAG (WARNFLAG, Pin))
109 color = PCB->WarnColor;
110 else if (TEST_FLAG (SELECTEDFLAG, Pin))
111 color = PCB->ViaSelectedColor;
112 else
113 color = PCB->ConnectedColor;
115 else
116 color = PCB->ViaColor;
118 else
120 if (!doing_pinout
121 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
123 if (TEST_FLAG (WARNFLAG, Pin))
124 color = PCB->WarnColor;
125 else if (TEST_FLAG (SELECTEDFLAG, Pin))
126 color = PCB->PinSelectedColor;
127 else
128 color = PCB->ConnectedColor;
130 else
131 color = PCB->PinColor;
134 gui->set_color (Output.fgGC, color);
137 /*---------------------------------------------------------------------------
138 * Adds the update rect to the update region
140 static void
141 AddPart (void *b)
143 BoxType *box = (BoxType *) b;
145 Block.X1 = MIN (Block.X1, box->X1);
146 Block.X2 = MAX (Block.X2, box->X2);
147 Block.Y1 = MIN (Block.Y1, box->Y1);
148 Block.Y2 = MAX (Block.Y2, box->Y2);
152 * initiate the actual redrawing of the updated area
154 void
155 Draw (void)
157 if (Block.X1 <= Block.X2 && Block.Y1 <= Block.Y2)
158 gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2);
160 /* shrink the update block */
161 Block.X1 = Block.Y1 = MAXINT;
162 Block.X2 = Block.Y2 = -MAXINT;
165 /* ----------------------------------------------------------------------
166 * redraws all the data by the event handlers
168 void
169 Redraw (void)
171 gui->invalidate_all ();
174 static void
175 _draw_pv_name (PinType *pv)
177 BoxType box;
178 bool vert;
179 TextType text;
181 if (!pv->Name || !pv->Name[0])
182 text.TextString = EMPTY (pv->Number);
183 else
184 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pv->Number : pv->Name);
186 vert = TEST_FLAG (EDGE2FLAG, pv);
188 if (vert)
190 box.X1 = pv->X - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
191 box.Y1 = pv->Y - pv->DrillingHole / 2 - Settings.PinoutTextOffsetX;
193 else
195 box.X1 = pv->X + pv->DrillingHole / 2 + Settings.PinoutTextOffsetX;
196 box.Y1 = pv->Y - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
199 gui->set_color (Output.fgGC, PCB->PinNameColor);
201 text.Flags = NoFlags ();
202 /* Set font height to approx 56% of pin thickness */
203 text.Scale = 56 * pv->Thickness / FONT_CAPHEIGHT;
204 text.X = box.X1;
205 text.Y = box.Y1;
206 text.Direction = vert ? 1 : 0;
208 if (gui->gui)
209 doing_pinout++;
210 DrawTextLowLevel (&text, 0);
211 if (gui->gui)
212 doing_pinout--;
215 static void
216 _draw_pv (PinTypePtr pv, bool draw_hole)
218 if (TEST_FLAG (THINDRAWFLAG, PCB))
219 gui->thindraw_pcb_pv (Output.fgGC, Output.fgGC, pv, draw_hole, false);
220 else
221 gui->fill_pcb_pv (Output.fgGC, Output.bgGC, pv, draw_hole, false);
223 if (!TEST_FLAG (HOLEFLAG, pv) && TEST_FLAG (DISPLAYNAMEFLAG, pv))
224 _draw_pv_name (pv);
227 static void
228 draw_pin (PinTypePtr pin, bool draw_hole)
230 SetPVColor (pin, PIN_TYPE);
231 _draw_pv (pin, draw_hole);
234 static int
235 pin_callback (const BoxType * b, void *cl)
237 draw_pin ((PinType *)b, false);
238 return 1;
241 static void
242 draw_via (PinTypePtr via, bool draw_hole)
244 SetPVColor (via, VIA_TYPE);
245 _draw_pv (via, draw_hole);
248 static int
249 via_callback (const BoxType * b, void *cl)
251 draw_via ((PinType *)b, false);
252 return 1;
255 static void
256 draw_pad_name (PadType *pad)
258 BoxType box;
259 bool vert;
260 TextType text;
262 if (!pad->Name || !pad->Name[0])
263 text.TextString = EMPTY (pad->Number);
264 else
265 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pad->Number : pad->Name);
267 /* should text be vertical ? */
268 vert = (pad->Point1.X == pad->Point2.X);
270 if (vert)
272 box.X1 = pad->Point1.X - pad->Thickness / 2;
273 box.Y1 = MAX (pad->Point1.Y, pad->Point2.Y) + pad->Thickness / 2;
274 box.X1 += Settings.PinoutTextOffsetY;
275 box.Y1 -= Settings.PinoutTextOffsetX;
277 else
279 box.X1 = MIN (pad->Point1.X, pad->Point2.X) - pad->Thickness / 2;
280 box.Y1 = pad->Point1.Y - pad->Thickness / 2;
281 box.X1 += Settings.PinoutTextOffsetX;
282 box.Y1 += Settings.PinoutTextOffsetY;
285 gui->set_color (Output.fgGC, PCB->PinNameColor);
287 text.Flags = NoFlags ();
288 /* Set font height to approx 90% of pin thickness */
289 text.Scale = 90 * pad->Thickness / FONT_CAPHEIGHT;
290 text.X = box.X1;
291 text.Y = box.Y1;
292 text.Direction = vert ? 1 : 0;
294 DrawTextLowLevel (&text, 0);
297 static void
298 _draw_pad (hidGC gc, PadType *pad, bool clear, bool mask)
300 if (clear && !mask && pad->Clearance <= 0)
301 return;
303 if (TEST_FLAG (THINDRAWFLAG, PCB) ||
304 (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
305 gui->thindraw_pcb_pad (gc, pad, clear, mask);
306 else
307 gui->fill_pcb_pad (gc, pad, clear, mask);
310 static void
311 draw_pad (PadType *pad)
313 if (doing_pinout)
314 gui->set_color (Output.fgGC, PCB->PinColor);
315 else if (TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, pad))
317 if (TEST_FLAG (WARNFLAG, pad))
318 gui->set_color (Output.fgGC, PCB->WarnColor);
319 else if (TEST_FLAG (SELECTEDFLAG, pad))
320 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
321 else
322 gui->set_color (Output.fgGC, PCB->ConnectedColor);
324 else if (FRONT (pad))
325 gui->set_color (Output.fgGC, PCB->PinColor);
326 else
327 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
329 _draw_pad (Output.fgGC, pad, false, false);
331 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, pad))
332 draw_pad_name (pad);
335 static int
336 pad_callback (const BoxType * b, void *cl)
338 PadTypePtr pad = (PadTypePtr) b;
339 int *side = cl;
341 if (ON_SIDE (pad, *side))
342 draw_pad (pad);
343 return 1;
346 static void
347 draw_element_name (ElementType *element)
349 if ((TEST_FLAG (HIDENAMESFLAG, PCB) && gui->gui) ||
350 TEST_FLAG (HIDENAMEFLAG, element))
351 return;
352 if (doing_pinout || doing_assy)
353 gui->set_color (Output.fgGC, PCB->ElementColor);
354 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
355 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
356 else if (FRONT (element))
357 gui->set_color (Output.fgGC, PCB->ElementColor);
358 else
359 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
360 DrawTextLowLevel (&ELEMENT_TEXT (PCB, element), PCB->minSlk);
363 static int
364 name_callback (const BoxType * b, void *cl)
366 TextTypePtr text = (TextTypePtr) b;
367 ElementTypePtr element = (ElementTypePtr) text->Element;
368 int *side = cl;
370 if (TEST_FLAG (HIDENAMEFLAG, element))
371 return 0;
373 if (ON_SIDE (element, *side))
374 draw_element_name (element);
375 return 0;
378 static void
379 draw_element_pins_and_pads (ElementType *element)
381 PAD_LOOP (element);
383 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
384 draw_pad (pad);
386 END_LOOP;
387 PIN_LOOP (element);
389 draw_pin (pin, true);
391 END_LOOP;
394 static int
395 EMark_callback (const BoxType * b, void *cl)
397 ElementTypePtr element = (ElementTypePtr) b;
399 DrawEMark (element, element->MarkX, element->MarkY, !FRONT (element));
400 return 1;
403 static int
404 hole_callback (const BoxType * b, void *cl)
406 PinTypePtr pv = (PinTypePtr) b;
407 int plated = cl ? *(int *) cl : -1;
409 if ((plated == 0 && !TEST_FLAG (HOLEFLAG, pv)) ||
410 (plated == 1 && TEST_FLAG (HOLEFLAG, pv)))
411 return 1;
413 if (TEST_FLAG (THINDRAWFLAG, PCB))
415 if (!TEST_FLAG (HOLEFLAG, pv))
417 gui->set_line_cap (Output.fgGC, Round_Cap);
418 gui->set_line_width (Output.fgGC, 0);
419 gui->draw_arc (Output.fgGC,
420 pv->X, pv->Y, pv->DrillingHole / 2,
421 pv->DrillingHole / 2, 0, 360);
424 else
425 gui->fill_circle (Output.bgGC, pv->X, pv->Y, pv->DrillingHole / 2);
427 if (TEST_FLAG (HOLEFLAG, pv))
429 if (TEST_FLAG (WARNFLAG, pv))
430 gui->set_color (Output.fgGC, PCB->WarnColor);
431 else if (TEST_FLAG (SELECTEDFLAG, pv))
432 gui->set_color (Output.fgGC, PCB->ViaSelectedColor);
433 else
434 gui->set_color (Output.fgGC, Settings.BlackColor);
436 gui->set_line_cap (Output.fgGC, Round_Cap);
437 gui->set_line_width (Output.fgGC, 0);
438 gui->draw_arc (Output.fgGC,
439 pv->X, pv->Y, pv->DrillingHole / 2,
440 pv->DrillingHole / 2, 0, 360);
442 return 1;
445 static void
446 DrawHoles (bool draw_plated, bool draw_unplated, const BoxType *drawn_area)
448 int plated = -1;
450 if ( draw_plated && !draw_unplated) plated = 1;
451 if (!draw_plated && draw_unplated) plated = 0;
453 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, &plated);
454 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, &plated);
457 static void
458 _draw_line (LineType *line)
460 gui->set_line_cap (Output.fgGC, Trace_Cap);
461 if (TEST_FLAG (THINDRAWFLAG, PCB))
462 gui->set_line_width (Output.fgGC, 0);
463 else
464 gui->set_line_width (Output.fgGC, line->Thickness);
466 gui->draw_line (Output.fgGC,
467 line->Point1.X, line->Point1.Y,
468 line->Point2.X, line->Point2.Y);
471 static void
472 draw_line (LayerType *layer, LineType *line)
474 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, line))
476 if (TEST_FLAG (SELECTEDFLAG, line))
477 gui->set_color (Output.fgGC, layer->SelectedColor);
478 else
479 gui->set_color (Output.fgGC, PCB->ConnectedColor);
481 else
482 gui->set_color (Output.fgGC, layer->Color);
483 _draw_line (line);
486 static int
487 line_callback (const BoxType * b, void *cl)
489 draw_line ((LayerType *) cl, (LineType *) b);
490 return 1;
493 static int
494 rat_callback (const BoxType * b, void *cl)
496 RatType *rat = (RatType *)b;
498 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, rat))
500 if (TEST_FLAG (SELECTEDFLAG, rat))
501 gui->set_color (Output.fgGC, PCB->RatSelectedColor);
502 else
503 gui->set_color (Output.fgGC, PCB->ConnectedColor);
505 else
506 gui->set_color (Output.fgGC, PCB->RatColor);
508 if (Settings.RatThickness < 20)
509 rat->Thickness = pixel_slop * Settings.RatThickness;
510 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
511 if (TEST_FLAG(VIAFLAG, rat))
513 int w = rat->Thickness;
515 if (TEST_FLAG (THINDRAWFLAG, PCB))
516 gui->set_line_width (Output.fgGC, 0);
517 else
518 gui->set_line_width (Output.fgGC, w);
519 gui->draw_arc (Output.fgGC, rat->Point1.X, rat->Point1.Y,
520 w * 2, w * 2, 0, 360);
522 else
523 _draw_line ((LineType *) rat);
524 return 1;
527 static void
528 _draw_arc (ArcType *arc)
530 if (!arc->Thickness)
531 return;
533 if (TEST_FLAG (THINDRAWFLAG, PCB))
534 gui->set_line_width (Output.fgGC, 0);
535 else
536 gui->set_line_width (Output.fgGC, arc->Thickness);
537 gui->set_line_cap (Output.fgGC, Trace_Cap);
539 gui->draw_arc (Output.fgGC, arc->X, arc->Y, arc->Width,
540 arc->Height, arc->StartAngle, arc->Delta);
543 static void
544 draw_arc (LayerType *layer, ArcType *arc)
546 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, arc))
548 if (TEST_FLAG (SELECTEDFLAG, arc))
549 gui->set_color (Output.fgGC, layer->SelectedColor);
550 else
551 gui->set_color (Output.fgGC, PCB->ConnectedColor);
553 else
554 gui->set_color (Output.fgGC, layer->Color);
556 _draw_arc (arc);
559 static int
560 arc_callback (const BoxType * b, void *cl)
562 draw_arc ((LayerTypePtr) cl, (ArcTypePtr) b);
563 return 1;
566 static void
567 draw_element_package (ElementType *element)
569 /* set color and draw lines, arcs, text and pins */
570 if (doing_pinout || doing_assy)
571 gui->set_color (Output.fgGC, PCB->ElementColor);
572 else if (TEST_FLAG (SELECTEDFLAG, element))
573 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
574 else if (FRONT (element))
575 gui->set_color (Output.fgGC, PCB->ElementColor);
576 else
577 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
579 /* draw lines, arcs, text and pins */
580 ELEMENTLINE_LOOP (element);
582 _draw_line (line);
584 END_LOOP;
585 ARC_LOOP (element);
587 _draw_arc (arc);
589 END_LOOP;
592 static int
593 element_callback (const BoxType * b, void *cl)
595 ElementTypePtr element = (ElementTypePtr) b;
596 int *side = cl;
598 if (ON_SIDE (element, *side))
599 draw_element_package (element);
600 return 1;
603 /* ---------------------------------------------------------------------------
604 * prints assembly drawing.
607 static void
608 PrintAssembly (int side, const BoxType * drawn_area)
610 int side_group = GetLayerGroupNumberByNumber (max_copper_layer + side);
612 doing_assy = true;
613 gui->set_draw_faded (Output.fgGC, 1);
614 DrawLayerGroup (side_group, drawn_area);
615 gui->set_draw_faded (Output.fgGC, 0);
617 /* draw package */
618 DrawSilk (side, drawn_area);
619 doing_assy = false;
622 /* ---------------------------------------------------------------------------
623 * initializes some identifiers for a new zoom factor and redraws whole screen
625 static void
626 DrawEverything (const BoxType *drawn_area)
628 int i, ngroups, side;
629 int component, solder;
630 /* This is the list of layer groups we will draw. */
631 int do_group[MAX_LAYER];
632 /* This is the reverse of the order in which we draw them. */
633 int drawn_groups[MAX_LAYER];
634 int plated, unplated;
635 bool paste_empty;
637 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
638 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
640 memset (do_group, 0, sizeof (do_group));
641 for (ngroups = 0, i = 0; i < max_copper_layer; i++)
643 LayerType *l = LAYER_ON_STACK (i);
644 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
645 if (l->On && !do_group[group])
647 do_group[group] = 1;
648 drawn_groups[ngroups++] = group;
652 component = GetLayerGroupNumberByNumber (component_silk_layer);
653 solder = GetLayerGroupNumberByNumber (solder_silk_layer);
656 * first draw all 'invisible' stuff
658 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
659 && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
661 side = SWAP_IDENT ? COMPONENT_LAYER : SOLDER_LAYER;
662 if (PCB->ElementOn)
664 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
665 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
666 DrawLayer (&(PCB->Data->Layer[max_copper_layer + side]), drawn_area);
668 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
669 gui->end_layer ();
672 /* draw all layers in layerstack order */
673 for (i = ngroups - 1; i >= 0; i--)
675 int group = drawn_groups[i];
677 if (gui->set_layer (0, group, 0))
679 DrawLayerGroup (group, drawn_area);
680 gui->end_layer ();
684 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
685 return;
687 /* Draw pins, pads, vias below silk */
688 if (gui->gui)
689 DrawPPV (SWAP_IDENT ? solder : component, drawn_area);
690 else
692 CountHoles (&plated, &unplated, drawn_area);
694 if (plated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
696 DrawHoles (true, false, drawn_area);
697 gui->end_layer ();
700 if (unplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
702 DrawHoles (false, true, drawn_area);
703 gui->end_layer ();
707 /* Draw the solder mask if turned on */
708 if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
710 DrawMask (COMPONENT_LAYER, drawn_area);
711 gui->end_layer ();
714 if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
716 DrawMask (SOLDER_LAYER, drawn_area);
717 gui->end_layer ();
720 if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
722 DrawSilk (COMPONENT_LAYER, drawn_area);
723 gui->end_layer ();
726 if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
728 DrawSilk (SOLDER_LAYER, drawn_area);
729 gui->end_layer ();
732 if (gui->gui)
734 /* Draw element Marks */
735 if (PCB->PinOn)
736 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
737 NULL);
738 /* Draw rat lines on top */
739 if (gui->set_layer ("rats", SL (RATS, 0), 0))
741 DrawRats(drawn_area);
742 gui->end_layer ();
746 paste_empty = IsPasteEmpty (COMPONENT_LAYER);
747 if (gui->set_layer ("toppaste", SL (PASTE, TOP), paste_empty))
749 DrawPaste (COMPONENT_LAYER, drawn_area);
750 gui->end_layer ();
753 paste_empty = IsPasteEmpty (SOLDER_LAYER);
754 if (gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), paste_empty))
756 DrawPaste (SOLDER_LAYER, drawn_area);
757 gui->end_layer ();
760 if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
762 PrintAssembly (COMPONENT_LAYER, drawn_area);
763 gui->end_layer ();
766 if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
768 PrintAssembly (SOLDER_LAYER, drawn_area);
769 gui->end_layer ();
772 if (gui->set_layer ("fab", SL (FAB, 0), 0))
774 PrintFab (Output.fgGC);
775 gui->end_layer ();
779 static void
780 DrawEMark (ElementTypePtr e, Coord X, Coord Y, bool invisible)
782 Coord mark_size = EMARK_SIZE;
783 if (!PCB->InvisibleObjectsOn && invisible)
784 return;
786 if (e->Pin != NULL)
788 PinType *pin0 = e->Pin->data;
789 if (TEST_FLAG (HOLEFLAG, pin0))
790 mark_size = MIN (mark_size, pin0->DrillingHole / 2);
791 else
792 mark_size = MIN (mark_size, pin0->Thickness / 2);
795 if (e->Pad != NULL)
797 PadType *pad0 = e->Pad->data;
798 mark_size = MIN (mark_size, pad0->Thickness / 2);
801 gui->set_color (Output.fgGC,
802 invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
803 gui->set_line_cap (Output.fgGC, Trace_Cap);
804 gui->set_line_width (Output.fgGC, 0);
805 gui->draw_line (Output.fgGC, X - mark_size, Y, X, Y - mark_size);
806 gui->draw_line (Output.fgGC, X + mark_size, Y, X, Y - mark_size);
807 gui->draw_line (Output.fgGC, X - mark_size, Y, X, Y + mark_size);
808 gui->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
811 * If an element is locked, place a "L" on top of the "diamond".
812 * This provides a nice visual indication that it is locked that
813 * works even for color blind users.
815 if (TEST_FLAG (LOCKFLAG, e) )
817 gui->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
818 gui->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
822 /* ---------------------------------------------------------------------------
823 * Draws pins pads and vias - Always draws for non-gui HIDs,
824 * otherwise drawing depends on PCB->PinOn and PCB->ViaOn
826 static void
827 DrawPPV (int group, const BoxType *drawn_area)
829 int component_group = GetLayerGroupNumberByNumber (component_silk_layer);
830 int solder_group = GetLayerGroupNumberByNumber (solder_silk_layer);
831 int side;
833 if (PCB->PinOn || !gui->gui)
835 /* draw element pins */
836 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback, NULL);
838 /* draw element pads */
839 if (group == component_group)
841 side = COMPONENT_LAYER;
842 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
845 if (group == solder_group)
847 side = SOLDER_LAYER;
848 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
852 /* draw vias */
853 if (PCB->ViaOn || !gui->gui)
855 r_search (PCB->Data->via_tree, drawn_area, NULL, via_callback, NULL);
856 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, NULL);
858 if (PCB->PinOn || doing_assy)
859 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, NULL);
862 static int
863 clearPin_callback (const BoxType * b, void *cl)
865 PinType *pin = (PinTypePtr) b;
866 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
867 gui->thindraw_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
868 else
869 gui->fill_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
870 return 1;
873 struct poly_info {
874 const BoxType *drawn_area;
875 LayerType *layer;
878 static int
879 poly_callback (const BoxType * b, void *cl)
881 struct poly_info *i = cl;
882 PolygonType *polygon = (PolygonType *)b;
883 static char *color;
885 if (!polygon->Clipped)
886 return 0;
888 if (TEST_FLAG (SELECTEDFLAG, polygon))
889 color = i->layer->SelectedColor;
890 else if (TEST_FLAG (FOUNDFLAG, polygon))
891 color = PCB->ConnectedColor;
892 else
893 color = i->layer->Color;
894 gui->set_color (Output.fgGC, color);
896 if (gui->thindraw_pcb_polygon != NULL &&
897 (TEST_FLAG (THINDRAWFLAG, PCB) ||
898 TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
899 gui->thindraw_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
900 else
901 gui->fill_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
903 /* If checking planes, thin-draw any pieces which have been clipped away */
904 if (gui->thindraw_pcb_polygon != NULL &&
905 TEST_FLAG (CHECKPLANESFLAG, PCB) &&
906 !TEST_FLAG (FULLPOLYFLAG, polygon))
908 PolygonType poly = *polygon;
910 for (poly.Clipped = polygon->Clipped->f;
911 poly.Clipped != polygon->Clipped;
912 poly.Clipped = poly.Clipped->f)
913 gui->thindraw_pcb_polygon (Output.fgGC, &poly, i->drawn_area);
916 return 1;
919 static int
920 clearPad_callback (const BoxType * b, void *cl)
922 PadTypePtr pad = (PadTypePtr) b;
923 int *side = cl;
924 if (ON_SIDE (pad, *side) && pad->Mask)
925 _draw_pad (Output.pmGC, pad, true, true);
926 return 1;
929 /* ---------------------------------------------------------------------------
930 * Draws silk layer.
933 static void
934 DrawSilk (int side, const BoxType * drawn_area)
936 #if 0
937 /* This code is used when you want to mask silk to avoid exposed
938 pins and pads. We decided it was a bad idea to do this
939 unconditionally, but the code remains. */
940 #endif
942 #if 0
943 if (gui->poly_before)
945 gui->use_mask (HID_MASK_BEFORE);
946 #endif
947 DrawLayer (LAYER_PTR (max_copper_layer + side), drawn_area);
948 /* draw package */
949 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
950 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
951 #if 0
954 gui->use_mask (HID_MASK_CLEAR);
955 r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, NULL);
956 r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, NULL);
957 r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &side);
959 if (gui->poly_after)
961 gui->use_mask (HID_MASK_AFTER);
962 DrawLayer (LAYER_PTR (max_copper_layer + layer), drawn_area);
963 /* draw package */
964 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
965 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
967 gui->use_mask (HID_MASK_OFF);
968 #endif
972 static void
973 DrawMaskBoardArea (int mask_type, const BoxType *drawn_area)
975 /* Skip the mask drawing if the GUI doesn't want this type */
976 if ((mask_type == HID_MASK_BEFORE && !gui->poly_before) ||
977 (mask_type == HID_MASK_AFTER && !gui->poly_after))
978 return;
980 gui->use_mask (mask_type);
981 gui->set_color (Output.fgGC, PCB->MaskColor);
982 if (drawn_area == NULL)
983 gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
984 else
985 gui->fill_rect (Output.fgGC, drawn_area->X1, drawn_area->Y1,
986 drawn_area->X2, drawn_area->Y2);
989 /* ---------------------------------------------------------------------------
990 * draws solder mask layer - this will cover nearly everything
992 static void
993 DrawMask (int side, const BoxType *screen)
995 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
997 if (thin)
998 gui->set_color (Output.pmGC, PCB->MaskColor);
999 else
1001 DrawMaskBoardArea (HID_MASK_BEFORE, screen);
1002 gui->use_mask (HID_MASK_CLEAR);
1005 r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, NULL);
1006 r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, NULL);
1007 r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &side);
1009 if (thin)
1010 gui->set_color (Output.pmGC, "erase");
1011 else
1013 DrawMaskBoardArea (HID_MASK_AFTER, screen);
1014 gui->use_mask (HID_MASK_OFF);
1018 /* ---------------------------------------------------------------------------
1019 * draws solder paste layer for a given side of the board
1021 static void
1022 DrawPaste (int side, const BoxType *drawn_area)
1024 gui->set_color (Output.fgGC, PCB->ElementColor);
1025 ALLPAD_LOOP (PCB->Data);
1027 if (ON_SIDE (pad, side) && !TEST_FLAG (NOPASTEFLAG, pad) && pad->Mask > 0)
1029 if (pad->Mask < pad->Thickness)
1030 _draw_pad (Output.fgGC, pad, true, true);
1031 else
1032 _draw_pad (Output.fgGC, pad, false, false);
1035 ENDALL_LOOP;
1038 static void
1039 DrawRats (const BoxType *drawn_area)
1042 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
1043 * XXX gtk only allows negative drawing.
1044 * XXX using the mask here is to get rat transparency
1046 int can_mask = strcmp(gui->name, "lesstif") == 0;
1048 if (can_mask)
1049 gui->use_mask (HID_MASK_CLEAR);
1050 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
1051 if (can_mask)
1052 gui->use_mask (HID_MASK_OFF);
1055 static int
1056 text_callback (const BoxType * b, void *cl)
1058 LayerType *layer = cl;
1059 TextType *text = (TextType *)b;
1060 int min_silk_line;
1062 if (TEST_FLAG (SELECTEDFLAG, text))
1063 gui->set_color (Output.fgGC, layer->SelectedColor);
1064 else
1065 gui->set_color (Output.fgGC, layer->Color);
1066 if (layer == &PCB->Data->SILKLAYER ||
1067 layer == &PCB->Data->BACKSILKLAYER)
1068 min_silk_line = PCB->minSlk;
1069 else
1070 min_silk_line = PCB->minWid;
1071 DrawTextLowLevel (text, min_silk_line);
1072 return 1;
1075 void
1076 DrawLayer (LayerTypePtr Layer, const BoxType * screen)
1078 struct poly_info info = {screen, Layer};
1080 /* print the non-clearing polys */
1081 r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
1083 if (TEST_FLAG (CHECKPLANESFLAG, PCB))
1084 return;
1086 /* draw all visible lines this layer */
1087 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
1089 /* draw the layer arcs on screen */
1090 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
1092 /* draw the layer text on screen */
1093 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
1095 /* We should check for gui->gui here, but it's kinda cool seeing the
1096 auto-outline magically disappear when you first add something to
1097 the "outline" layer. */
1098 if (IsLayerEmpty (Layer)
1099 && (strcmp (Layer->Name, "outline") == 0
1100 || strcmp (Layer->Name, "route") == 0))
1102 gui->set_color (Output.fgGC, Layer->Color);
1103 gui->set_line_width (Output.fgGC, PCB->minWid);
1104 gui->draw_rect (Output.fgGC,
1105 0, 0,
1106 PCB->MaxWidth, PCB->MaxHeight);
1110 /* ---------------------------------------------------------------------------
1111 * draws one layer group. If the exporter is not a GUI,
1112 * also draws the pins / pads / vias in this layer group.
1114 static void
1115 DrawLayerGroup (int group, const BoxType *drawn_area)
1117 int i, rv = 1;
1118 int layernum;
1119 LayerTypePtr Layer;
1120 int n_entries = PCB->LayerGroups.Number[group];
1121 Cardinal *layers = PCB->LayerGroups.Entries[group];
1123 for (i = n_entries - 1; i >= 0; i--)
1125 layernum = layers[i];
1126 Layer = PCB->Data->Layer + layers[i];
1127 if (strcmp (Layer->Name, "outline") == 0 ||
1128 strcmp (Layer->Name, "route") == 0)
1129 rv = 0;
1130 if (layernum < max_copper_layer && Layer->On)
1131 DrawLayer (Layer, drawn_area);
1133 if (n_entries > 1)
1134 rv = 1;
1136 if (rv && !gui->gui)
1137 DrawPPV (group, drawn_area);
1140 static void
1141 GatherPVName (PinTypePtr Ptr)
1143 BoxType box;
1144 bool vert = TEST_FLAG (EDGE2FLAG, Ptr);
1146 if (vert)
1148 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1149 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
1151 else
1153 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
1154 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1157 if (vert)
1159 box.X2 = box.X1;
1160 box.Y2 = box.Y1;
1162 else
1164 box.X2 = box.X1;
1165 box.Y2 = box.Y1;
1167 AddPart (&box);
1170 static void
1171 GatherPadName (PadTypePtr Pad)
1173 BoxType box;
1174 bool vert;
1176 /* should text be vertical ? */
1177 vert = (Pad->Point1.X == Pad->Point2.X);
1179 if (vert)
1181 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1182 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1183 box.X1 += Settings.PinoutTextOffsetY;
1184 box.Y1 -= Settings.PinoutTextOffsetX;
1185 box.X2 = box.X1;
1186 box.Y2 = box.Y1;
1188 else
1190 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1191 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1192 box.X1 += Settings.PinoutTextOffsetX;
1193 box.Y1 += Settings.PinoutTextOffsetY;
1194 box.X2 = box.X1;
1195 box.Y2 = box.Y1;
1198 AddPart (&box);
1199 return;
1202 /* ---------------------------------------------------------------------------
1203 * lowlevel drawing routine for text objects
1205 void
1206 DrawTextLowLevel (TextTypePtr Text, Coord min_line_width)
1208 Coord x = 0;
1209 unsigned char *string = (unsigned char *) Text->TextString;
1210 Cardinal n;
1211 FontTypePtr font = &PCB->Font;
1213 while (string && *string)
1215 /* draw lines if symbol is valid and data is present */
1216 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid)
1218 LineTypePtr line = font->Symbol[*string].Line;
1219 LineType newline;
1221 for (n = font->Symbol[*string].LineN; n; n--, line++)
1223 /* create one line, scale, move, rotate and swap it */
1224 newline = *line;
1225 newline.Point1.X = SCALE_TEXT (newline.Point1.X + x, Text->Scale);
1226 newline.Point1.Y = SCALE_TEXT (newline.Point1.Y, Text->Scale);
1227 newline.Point2.X = SCALE_TEXT (newline.Point2.X + x, Text->Scale);
1228 newline.Point2.Y = SCALE_TEXT (newline.Point2.Y, Text->Scale);
1229 newline.Thickness = SCALE_TEXT (newline.Thickness, Text->Scale / 2);
1230 if (newline.Thickness < min_line_width)
1231 newline.Thickness = min_line_width;
1233 RotateLineLowLevel (&newline, 0, 0, Text->Direction);
1235 /* the labels of SMD objects on the bottom
1236 * side haven't been swapped yet, only their offset
1238 if (TEST_FLAG (ONSOLDERFLAG, Text))
1240 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X);
1241 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y);
1242 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X);
1243 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y);
1245 /* add offset and draw line */
1246 newline.Point1.X += Text->X;
1247 newline.Point1.Y += Text->Y;
1248 newline.Point2.X += Text->X;
1249 newline.Point2.Y += Text->Y;
1250 _draw_line (&newline);
1253 /* move on to next cursor position */
1254 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta);
1256 else
1258 /* the default symbol is a filled box */
1259 BoxType defaultsymbol = PCB->Font.DefaultSymbol;
1260 Coord size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5;
1262 defaultsymbol.X1 = SCALE_TEXT (defaultsymbol.X1 + x, Text->Scale);
1263 defaultsymbol.Y1 = SCALE_TEXT (defaultsymbol.Y1, Text->Scale);
1264 defaultsymbol.X2 = SCALE_TEXT (defaultsymbol.X2 + x, Text->Scale);
1265 defaultsymbol.Y2 = SCALE_TEXT (defaultsymbol.Y2, Text->Scale);
1267 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction);
1269 /* add offset and draw box */
1270 defaultsymbol.X1 += Text->X;
1271 defaultsymbol.Y1 += Text->Y;
1272 defaultsymbol.X2 += Text->X;
1273 defaultsymbol.Y2 += Text->Y;
1274 gui->fill_rect (Output.fgGC,
1275 defaultsymbol.X1, defaultsymbol.Y1,
1276 defaultsymbol.X2, defaultsymbol.Y2);
1278 /* move on to next cursor position */
1279 x += size;
1281 string++;
1285 /* ---------------------------------------------------------------------------
1286 * draw a via object
1288 void
1289 DrawVia (PinTypePtr Via)
1291 AddPart (Via);
1292 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1293 DrawViaName (Via);
1296 /* ---------------------------------------------------------------------------
1297 * draws the name of a via
1299 void
1300 DrawViaName (PinTypePtr Via)
1302 GatherPVName (Via);
1305 /* ---------------------------------------------------------------------------
1306 * draw a pin object
1308 void
1309 DrawPin (PinTypePtr Pin)
1311 AddPart (Pin);
1312 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1313 || doing_pinout)
1314 DrawPinName (Pin);
1317 /* ---------------------------------------------------------------------------
1318 * draws the name of a pin
1320 void
1321 DrawPinName (PinTypePtr Pin)
1323 GatherPVName (Pin);
1326 /* ---------------------------------------------------------------------------
1327 * draw a pad object
1329 void
1330 DrawPad (PadTypePtr Pad)
1332 AddPart (Pad);
1333 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1334 DrawPadName (Pad);
1337 /* ---------------------------------------------------------------------------
1338 * draws the name of a pad
1340 void
1341 DrawPadName (PadTypePtr Pad)
1343 GatherPadName (Pad);
1346 /* ---------------------------------------------------------------------------
1347 * draws a line on a layer
1349 void
1350 DrawLine (LayerTypePtr Layer, LineTypePtr Line)
1352 AddPart (Line);
1355 /* ---------------------------------------------------------------------------
1356 * draws a ratline
1358 void
1359 DrawRat (RatTypePtr Rat)
1361 if (Settings.RatThickness < 20)
1362 Rat->Thickness = pixel_slop * Settings.RatThickness;
1363 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1364 if (TEST_FLAG(VIAFLAG, Rat))
1366 Coord w = Rat->Thickness;
1368 BoxType b;
1370 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1371 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1372 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1373 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1374 AddPart (&b);
1376 else
1377 DrawLine (NULL, (LineType *)Rat);
1380 /* ---------------------------------------------------------------------------
1381 * draws an arc on a layer
1383 void
1384 DrawArc (LayerTypePtr Layer, ArcTypePtr Arc)
1386 AddPart (Arc);
1389 /* ---------------------------------------------------------------------------
1390 * draws a text on a layer
1392 void
1393 DrawText (LayerTypePtr Layer, TextTypePtr Text)
1395 AddPart (Text);
1399 /* ---------------------------------------------------------------------------
1400 * draws a polygon on a layer
1402 void
1403 DrawPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
1405 AddPart (Polygon);
1408 /* ---------------------------------------------------------------------------
1409 * draws an element
1411 void
1412 DrawElement (ElementTypePtr Element)
1414 DrawElementPackage (Element);
1415 DrawElementName (Element);
1416 DrawElementPinsAndPads (Element);
1419 /* ---------------------------------------------------------------------------
1420 * draws the name of an element
1422 void
1423 DrawElementName (ElementTypePtr Element)
1425 if (TEST_FLAG (HIDENAMEFLAG, Element))
1426 return;
1427 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1430 /* ---------------------------------------------------------------------------
1431 * draws the package of an element
1433 void
1434 DrawElementPackage (ElementTypePtr Element)
1436 ELEMENTLINE_LOOP (Element);
1438 DrawLine (NULL, line);
1440 END_LOOP;
1441 ARC_LOOP (Element);
1443 DrawArc (NULL, arc);
1445 END_LOOP;
1448 /* ---------------------------------------------------------------------------
1449 * draw pins of an element
1451 void
1452 DrawElementPinsAndPads (ElementTypePtr Element)
1454 PAD_LOOP (Element);
1456 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
1457 DrawPad (pad);
1459 END_LOOP;
1460 PIN_LOOP (Element);
1462 DrawPin (pin);
1464 END_LOOP;
1467 /* ---------------------------------------------------------------------------
1468 * erase a via
1470 void
1471 EraseVia (PinTypePtr Via)
1473 AddPart (Via);
1474 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
1475 EraseViaName (Via);
1478 /* ---------------------------------------------------------------------------
1479 * erase a ratline
1481 void
1482 EraseRat (RatTypePtr Rat)
1484 if (TEST_FLAG(VIAFLAG, Rat))
1486 Coord w = Rat->Thickness;
1488 BoxType b;
1490 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1491 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1492 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1493 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1494 AddPart (&b);
1496 else
1497 EraseLine ((LineType *)Rat);
1501 /* ---------------------------------------------------------------------------
1502 * erase a via name
1504 void
1505 EraseViaName (PinTypePtr Via)
1507 GatherPVName (Via);
1510 /* ---------------------------------------------------------------------------
1511 * erase a pad object
1513 void
1514 ErasePad (PadTypePtr Pad)
1516 AddPart (Pad);
1517 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1518 ErasePadName (Pad);
1521 /* ---------------------------------------------------------------------------
1522 * erase a pad name
1524 void
1525 ErasePadName (PadTypePtr Pad)
1527 GatherPadName (Pad);
1530 /* ---------------------------------------------------------------------------
1531 * erase a pin object
1533 void
1534 ErasePin (PinTypePtr Pin)
1536 AddPart (Pin);
1537 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1538 ErasePinName (Pin);
1541 /* ---------------------------------------------------------------------------
1542 * erase a pin name
1544 void
1545 ErasePinName (PinTypePtr Pin)
1547 GatherPVName (Pin);
1550 /* ---------------------------------------------------------------------------
1551 * erases a line on a layer
1553 void
1554 EraseLine (LineTypePtr Line)
1556 AddPart (Line);
1559 /* ---------------------------------------------------------------------------
1560 * erases an arc on a layer
1562 void
1563 EraseArc (ArcTypePtr Arc)
1565 if (!Arc->Thickness)
1566 return;
1567 AddPart (Arc);
1570 /* ---------------------------------------------------------------------------
1571 * erases a text on a layer
1573 void
1574 EraseText (LayerTypePtr Layer, TextTypePtr Text)
1576 AddPart (Text);
1579 /* ---------------------------------------------------------------------------
1580 * erases a polygon on a layer
1582 void
1583 ErasePolygon (PolygonTypePtr Polygon)
1585 AddPart (Polygon);
1588 /* ---------------------------------------------------------------------------
1589 * erases an element
1591 void
1592 EraseElement (ElementTypePtr Element)
1594 ELEMENTLINE_LOOP (Element);
1596 EraseLine (line);
1598 END_LOOP;
1599 ARC_LOOP (Element);
1601 EraseArc (arc);
1603 END_LOOP;
1604 EraseElementName (Element);
1605 EraseElementPinsAndPads (Element);
1608 /* ---------------------------------------------------------------------------
1609 * erases all pins and pads of an element
1611 void
1612 EraseElementPinsAndPads (ElementTypePtr Element)
1614 PIN_LOOP (Element);
1616 ErasePin (pin);
1618 END_LOOP;
1619 PAD_LOOP (Element);
1621 ErasePad (pad);
1623 END_LOOP;
1626 /* ---------------------------------------------------------------------------
1627 * erases the name of an element
1629 void
1630 EraseElementName (ElementTypePtr Element)
1632 if (TEST_FLAG (HIDENAMEFLAG, Element))
1633 return;
1634 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1638 void
1639 EraseObject (int type, void *lptr, void *ptr)
1641 switch (type)
1643 case VIA_TYPE:
1644 case PIN_TYPE:
1645 ErasePin ((PinTypePtr) ptr);
1646 break;
1647 case TEXT_TYPE:
1648 case ELEMENTNAME_TYPE:
1649 EraseText ((LayerTypePtr)lptr, (TextTypePtr) ptr);
1650 break;
1651 case POLYGON_TYPE:
1652 ErasePolygon ((PolygonTypePtr) ptr);
1653 break;
1654 case ELEMENT_TYPE:
1655 EraseElement ((ElementTypePtr) ptr);
1656 break;
1657 case LINE_TYPE:
1658 case ELEMENTLINE_TYPE:
1659 case RATLINE_TYPE:
1660 EraseLine ((LineTypePtr) ptr);
1661 break;
1662 case PAD_TYPE:
1663 ErasePad ((PadTypePtr) ptr);
1664 break;
1665 case ARC_TYPE:
1666 case ELEMENTARC_TYPE:
1667 EraseArc ((ArcTypePtr) ptr);
1668 break;
1669 default:
1670 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
1676 void
1677 DrawObject (int type, void *ptr1, void *ptr2)
1679 switch (type)
1681 case VIA_TYPE:
1682 if (PCB->ViaOn)
1683 DrawVia ((PinTypePtr) ptr2);
1684 break;
1685 case LINE_TYPE:
1686 if (((LayerTypePtr) ptr1)->On)
1687 DrawLine ((LayerTypePtr) ptr1, (LineTypePtr) ptr2);
1688 break;
1689 case ARC_TYPE:
1690 if (((LayerTypePtr) ptr1)->On)
1691 DrawArc ((LayerTypePtr) ptr1, (ArcTypePtr) ptr2);
1692 break;
1693 case TEXT_TYPE:
1694 if (((LayerTypePtr) ptr1)->On)
1695 DrawText ((LayerTypePtr) ptr1, (TextTypePtr) ptr2);
1696 break;
1697 case POLYGON_TYPE:
1698 if (((LayerTypePtr) ptr1)->On)
1699 DrawPolygon ((LayerTypePtr) ptr1, (PolygonTypePtr) ptr2);
1700 break;
1701 case ELEMENT_TYPE:
1702 if (PCB->ElementOn &&
1703 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
1704 DrawElement ((ElementTypePtr) ptr2);
1705 break;
1706 case RATLINE_TYPE:
1707 if (PCB->RatOn)
1708 DrawRat ((RatTypePtr) ptr2);
1709 break;
1710 case PIN_TYPE:
1711 if (PCB->PinOn)
1712 DrawPin ((PinTypePtr) ptr2);
1713 break;
1714 case PAD_TYPE:
1715 if (PCB->PinOn)
1716 DrawPad ((PadTypePtr) ptr2);
1717 break;
1718 case ELEMENTNAME_TYPE:
1719 if (PCB->ElementOn &&
1720 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
1721 DrawElementName ((ElementTypePtr) ptr1);
1722 break;
1726 static void
1727 draw_element (ElementTypePtr element)
1729 draw_element_package (element);
1730 draw_element_name (element);
1731 draw_element_pins_and_pads (element);
1734 /* ---------------------------------------------------------------------------
1735 * HID drawing callback.
1738 void
1739 hid_expose_callback (HID * hid, BoxType * region, void *item)
1741 HID *old_gui = gui;
1743 gui = hid;
1744 Output.fgGC = gui->make_gc ();
1745 Output.bgGC = gui->make_gc ();
1746 Output.pmGC = gui->make_gc ();
1748 hid->set_color (Output.pmGC, "erase");
1749 hid->set_color (Output.bgGC, "drill");
1751 if (item)
1753 doing_pinout = true;
1754 draw_element ((ElementType *)item);
1755 doing_pinout = false;
1757 else
1758 DrawEverything (region);
1760 gui->destroy_gc (Output.fgGC);
1761 gui->destroy_gc (Output.bgGC);
1762 gui->destroy_gc (Output.pmGC);
1763 gui = old_gui;