draw.c: Add gc parameter to _draw_line() function
[geda-pcb/pcjc2.git] / src / draw.c
blobdad41a7fa628c5f7afd045af0b2674838625c685
1 /*
2 * COPYRIGHT
4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996, 2003, 2004 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
28 /* drawing routines
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
35 #include "global.h"
37 /*#include "clip.h"*/
38 #include "compat.h"
39 #include "crosshair.h"
40 #include "data.h"
41 #include "draw.h"
42 #include "error.h"
43 #include "mymem.h"
44 #include "misc.h"
45 #include "rotate.h"
46 #include "rtree.h"
47 #include "search.h"
48 #include "select.h"
49 #include "print.h"
51 #ifdef HAVE_LIBDMALLOC
52 #include <dmalloc.h>
53 #endif
55 #undef NDEBUG
56 #include <assert.h>
58 #ifndef MAXINT
59 #define MAXINT (((unsigned int)(~0))>>1)
60 #endif
62 #define SMALL_SMALL_TEXT_SIZE 0
63 #define SMALL_TEXT_SIZE 1
64 #define NORMAL_TEXT_SIZE 2
65 #define LARGE_TEXT_SIZE 3
66 #define N_TEXT_SIZES 4
69 /* ---------------------------------------------------------------------------
70 * some local identifiers
72 static BoxType Block = {MAXINT, MAXINT, -MAXINT, -MAXINT};
74 static int doing_pinout = 0;
75 static bool doing_assy = false;
77 /* ---------------------------------------------------------------------------
78 * some local prototypes
80 static void DrawEverything (const BoxType *);
81 static void DrawPPV (int group, const BoxType *);
82 static void AddPart (void *);
83 static void SetPVColor (PinType *, int);
84 static void DrawEMark (ElementType *, Coord, Coord, bool);
85 static void DrawRats (const BoxType *);
87 /*--------------------------------------------------------------------------------------
88 * setup color for pin or via
90 static void
91 SetPVColor (PinType *Pin, int Type)
93 char *color;
95 if (Type == VIA_TYPE)
97 if (!doing_pinout
98 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
100 if (TEST_FLAG (WARNFLAG, Pin))
101 color = PCB->WarnColor;
102 else if (TEST_FLAG (SELECTEDFLAG, Pin))
103 color = PCB->ViaSelectedColor;
104 else
105 color = PCB->ConnectedColor;
107 else
108 color = PCB->ViaColor;
110 else
112 if (!doing_pinout
113 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
115 if (TEST_FLAG (WARNFLAG, Pin))
116 color = PCB->WarnColor;
117 else if (TEST_FLAG (SELECTEDFLAG, Pin))
118 color = PCB->PinSelectedColor;
119 else
120 color = PCB->ConnectedColor;
122 else
123 color = PCB->PinColor;
126 gui->graphics->set_color (Output.fgGC, color);
129 /*---------------------------------------------------------------------------
130 * Adds the update rect to the update region
132 static void
133 AddPart (void *b)
135 BoxType *box = (BoxType *) b;
137 Block.X1 = MIN (Block.X1, box->X1);
138 Block.X2 = MAX (Block.X2, box->X2);
139 Block.Y1 = MIN (Block.Y1, box->Y1);
140 Block.Y2 = MAX (Block.Y2, box->Y2);
144 * initiate the actual redrawing of the updated area
146 void
147 Draw (void)
149 if (Block.X1 <= Block.X2 && Block.Y1 <= Block.Y2)
150 gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2);
152 /* shrink the update block */
153 Block.X1 = Block.Y1 = MAXINT;
154 Block.X2 = Block.Y2 = -MAXINT;
157 /* ----------------------------------------------------------------------
158 * redraws all the data by the event handlers
160 void
161 Redraw (void)
163 gui->invalidate_all ();
166 static void
167 _draw_pv_name (PinType *pv)
169 BoxType box;
170 bool vert;
171 TextType text;
173 if (!pv->Name || !pv->Name[0])
174 text.TextString = EMPTY (pv->Number);
175 else
176 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pv->Number : pv->Name);
178 vert = TEST_FLAG (EDGE2FLAG, pv);
180 if (vert)
182 box.X1 = pv->X - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
183 box.Y1 = pv->Y - pv->DrillingHole / 2 - Settings.PinoutTextOffsetX;
185 else
187 box.X1 = pv->X + pv->DrillingHole / 2 + Settings.PinoutTextOffsetX;
188 box.Y1 = pv->Y - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
191 gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);
193 text.Flags = NoFlags ();
194 /* Set font height to approx 56% of pin thickness */
195 text.Scale = 56 * pv->Thickness / FONT_CAPHEIGHT;
196 text.X = box.X1;
197 text.Y = box.Y1;
198 text.Direction = vert ? 1 : 0;
200 if (gui->gui)
201 doing_pinout++;
202 DrawTextLowLevel (&text, 0);
203 if (gui->gui)
204 doing_pinout--;
207 static void
208 _draw_pv (PinType *pv, bool draw_hole)
210 if (TEST_FLAG (THINDRAWFLAG, PCB))
211 gui->thindraw_pcb_pv (Output.fgGC, Output.fgGC, pv, draw_hole, false);
212 else
213 gui->fill_pcb_pv (Output.fgGC, Output.bgGC, pv, draw_hole, false);
215 if (!TEST_FLAG (HOLEFLAG, pv) && TEST_FLAG (DISPLAYNAMEFLAG, pv))
216 _draw_pv_name (pv);
219 static void
220 draw_pin (PinType *pin, bool draw_hole)
222 SetPVColor (pin, PIN_TYPE);
223 _draw_pv (pin, draw_hole);
226 static int
227 pin_callback (const BoxType * b, void *cl)
229 draw_pin ((PinType *)b, false);
230 return 1;
233 static void
234 draw_via (PinType *via, bool draw_hole)
236 SetPVColor (via, VIA_TYPE);
237 _draw_pv (via, draw_hole);
240 static int
241 via_callback (const BoxType * b, void *cl)
243 draw_via ((PinType *)b, false);
244 return 1;
247 static void
248 draw_pad_name (PadType *pad)
250 BoxType box;
251 bool vert;
252 TextType text;
254 if (!pad->Name || !pad->Name[0])
255 text.TextString = EMPTY (pad->Number);
256 else
257 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pad->Number : pad->Name);
259 /* should text be vertical ? */
260 vert = (pad->Point1.X == pad->Point2.X);
262 if (vert)
264 box.X1 = pad->Point1.X - pad->Thickness / 2;
265 box.Y1 = MAX (pad->Point1.Y, pad->Point2.Y) + pad->Thickness / 2;
266 box.X1 += Settings.PinoutTextOffsetY;
267 box.Y1 -= Settings.PinoutTextOffsetX;
269 else
271 box.X1 = MIN (pad->Point1.X, pad->Point2.X) - pad->Thickness / 2;
272 box.Y1 = pad->Point1.Y - pad->Thickness / 2;
273 box.X1 += Settings.PinoutTextOffsetX;
274 box.Y1 += Settings.PinoutTextOffsetY;
277 gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);
279 text.Flags = NoFlags ();
280 /* Set font height to approx 90% of pin thickness */
281 text.Scale = 90 * pad->Thickness / FONT_CAPHEIGHT;
282 text.X = box.X1;
283 text.Y = box.Y1;
284 text.Direction = vert ? 1 : 0;
286 DrawTextLowLevel (&text, 0);
289 static void
290 _draw_pad (hidGC gc, PadType *pad, bool clear, bool mask)
292 if (clear && !mask && pad->Clearance <= 0)
293 return;
295 if (TEST_FLAG (THINDRAWFLAG, PCB) ||
296 (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
297 gui->thindraw_pcb_pad (gc, pad, clear, mask);
298 else
299 gui->fill_pcb_pad (gc, pad, clear, mask);
302 static void
303 draw_pad (PadType *pad)
305 if (doing_pinout)
306 gui->graphics->set_color (Output.fgGC, PCB->PinColor);
307 else if (TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, pad))
309 if (TEST_FLAG (WARNFLAG, pad))
310 gui->graphics->set_color (Output.fgGC, PCB->WarnColor);
311 else if (TEST_FLAG (SELECTEDFLAG, pad))
312 gui->graphics->set_color (Output.fgGC, PCB->PinSelectedColor);
313 else
314 gui->graphics->set_color (Output.fgGC, PCB->ConnectedColor);
316 else if (FRONT (pad))
317 gui->graphics->set_color (Output.fgGC, PCB->PinColor);
318 else
319 gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
321 _draw_pad (Output.fgGC, pad, false, false);
323 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, pad))
324 draw_pad_name (pad);
327 static int
328 pad_callback (const BoxType * b, void *cl)
330 PadType *pad = (PadType *) b;
331 int *side = cl;
333 if (ON_SIDE (pad, *side))
334 draw_pad (pad);
335 return 1;
338 static void
339 draw_element_name (ElementType *element)
341 if ((TEST_FLAG (HIDENAMESFLAG, PCB) && gui->gui) ||
342 TEST_FLAG (HIDENAMEFLAG, element))
343 return;
344 if (doing_pinout || doing_assy)
345 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
346 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
347 gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor);
348 else if (FRONT (element))
349 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
350 else
351 gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
352 DrawTextLowLevel (&ELEMENT_TEXT (PCB, element), PCB->minSlk);
355 static int
356 name_callback (const BoxType * b, void *cl)
358 TextType *text = (TextType *) b;
359 ElementType *element = (ElementType *) text->Element;
360 int *side = cl;
362 if (TEST_FLAG (HIDENAMEFLAG, element))
363 return 0;
365 if (ON_SIDE (element, *side))
366 draw_element_name (element);
367 return 0;
370 static void
371 draw_element_pins_and_pads (ElementType *element)
373 PAD_LOOP (element);
375 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
376 draw_pad (pad);
378 END_LOOP;
379 PIN_LOOP (element);
381 draw_pin (pin, true);
383 END_LOOP;
386 static int
387 EMark_callback (const BoxType * b, void *cl)
389 ElementType *element = (ElementType *) b;
391 DrawEMark (element, element->MarkX, element->MarkY, !FRONT (element));
392 return 1;
395 static int
396 hole_callback (const BoxType * b, void *cl)
398 PinType *pv = (PinType *) b;
399 int plated = cl ? *(int *) cl : -1;
401 if ((plated == 0 && !TEST_FLAG (HOLEFLAG, pv)) ||
402 (plated == 1 && TEST_FLAG (HOLEFLAG, pv)))
403 return 1;
405 if (TEST_FLAG (THINDRAWFLAG, PCB))
407 if (!TEST_FLAG (HOLEFLAG, pv))
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);
416 else
417 gui->graphics->fill_circle (Output.bgGC, pv->X, pv->Y, pv->DrillingHole / 2);
419 if (TEST_FLAG (HOLEFLAG, pv))
421 if (TEST_FLAG (WARNFLAG, pv))
422 gui->graphics->set_color (Output.fgGC, PCB->WarnColor);
423 else if (TEST_FLAG (SELECTEDFLAG, pv))
424 gui->graphics->set_color (Output.fgGC, PCB->ViaSelectedColor);
425 else
426 gui->graphics->set_color (Output.fgGC, Settings.BlackColor);
428 gui->graphics->set_line_cap (Output.fgGC, Round_Cap);
429 gui->graphics->set_line_width (Output.fgGC, 0);
430 gui->graphics->draw_arc (Output.fgGC,
431 pv->X, pv->Y, pv->DrillingHole / 2,
432 pv->DrillingHole / 2, 0, 360);
434 return 1;
437 void
438 DrawHoles (bool draw_plated, bool draw_unplated, const BoxType *drawn_area)
440 int plated = -1;
442 if ( draw_plated && !draw_unplated) plated = 1;
443 if (!draw_plated && draw_unplated) plated = 0;
445 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, &plated);
446 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, &plated);
449 static void
450 _draw_line (hidGC gc, LineType *line)
452 gui->graphics->set_line_cap (gc, Trace_Cap);
453 if (TEST_FLAG (THINDRAWFLAG, PCB))
454 gui->graphics->set_line_width (gc, 0);
455 else
456 gui->graphics->set_line_width (gc, line->Thickness);
458 gui->graphics->draw_line (gc, line->Point1.X, line->Point1.Y,
459 line->Point2.X, line->Point2.Y);
462 static void
463 draw_line (LayerType *layer, LineType *line)
465 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, line))
467 if (TEST_FLAG (SELECTEDFLAG, line))
468 gui->graphics->set_color (Output.fgGC, layer->SelectedColor);
469 else
470 gui->graphics->set_color (Output.fgGC, PCB->ConnectedColor);
472 else
473 gui->graphics->set_color (Output.fgGC, layer->Color);
474 _draw_line (Output.fgGC, line);
477 static int
478 line_callback (const BoxType * b, void *cl)
480 draw_line ((LayerType *) cl, (LineType *) b);
481 return 1;
484 static int
485 rat_callback (const BoxType * b, void *cl)
487 RatType *rat = (RatType *)b;
489 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, rat))
491 if (TEST_FLAG (SELECTEDFLAG, rat))
492 gui->graphics->set_color (Output.fgGC, PCB->RatSelectedColor);
493 else
494 gui->graphics->set_color (Output.fgGC, PCB->ConnectedColor);
496 else
497 gui->graphics->set_color (Output.fgGC, PCB->RatColor);
499 if (Settings.RatThickness < 100)
500 rat->Thickness = pixel_slop * Settings.RatThickness;
501 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
502 if (TEST_FLAG(VIAFLAG, rat))
504 int w = rat->Thickness;
506 if (TEST_FLAG (THINDRAWFLAG, PCB))
507 gui->graphics->set_line_width (Output.fgGC, 0);
508 else
509 gui->graphics->set_line_width (Output.fgGC, w);
510 gui->graphics->draw_arc (Output.fgGC, rat->Point1.X, rat->Point1.Y,
511 w * 2, w * 2, 0, 360);
513 else
514 _draw_line (Output.fgGC, (LineType *) rat);
515 return 1;
518 static void
519 _draw_arc (ArcType *arc)
521 if (!arc->Thickness)
522 return;
524 if (TEST_FLAG (THINDRAWFLAG, PCB))
525 gui->graphics->set_line_width (Output.fgGC, 0);
526 else
527 gui->graphics->set_line_width (Output.fgGC, arc->Thickness);
528 gui->graphics->set_line_cap (Output.fgGC, Trace_Cap);
530 gui->graphics->draw_arc (Output.fgGC, arc->X, arc->Y, arc->Width,
531 arc->Height, arc->StartAngle, arc->Delta);
534 static void
535 draw_arc (LayerType *layer, ArcType *arc)
537 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, arc))
539 if (TEST_FLAG (SELECTEDFLAG, arc))
540 gui->graphics->set_color (Output.fgGC, layer->SelectedColor);
541 else
542 gui->graphics->set_color (Output.fgGC, PCB->ConnectedColor);
544 else
545 gui->graphics->set_color (Output.fgGC, layer->Color);
547 _draw_arc (arc);
550 static int
551 arc_callback (const BoxType * b, void *cl)
553 draw_arc ((LayerType *) cl, (ArcType *) b);
554 return 1;
557 static void
558 draw_element_package (ElementType *element)
560 /* set color and draw lines, arcs, text and pins */
561 if (doing_pinout || doing_assy)
562 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
563 else if (TEST_FLAG (SELECTEDFLAG, element))
564 gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor);
565 else if (FRONT (element))
566 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
567 else
568 gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
570 /* draw lines, arcs, text and pins */
571 ELEMENTLINE_LOOP (element);
573 _draw_line (Output.fgGC, line);
575 END_LOOP;
576 ARC_LOOP (element);
578 _draw_arc (arc);
580 END_LOOP;
583 static int
584 element_callback (const BoxType * b, void *cl)
586 ElementType *element = (ElementType *) b;
587 int *side = cl;
589 if (ON_SIDE (element, *side))
590 draw_element_package (element);
591 return 1;
594 /* ---------------------------------------------------------------------------
595 * prints assembly drawing.
598 void
599 PrintAssembly (int side, const BoxType * drawn_area)
601 int side_group = GetLayerGroupNumberByNumber (max_copper_layer + side);
603 doing_assy = true;
604 gui->graphics->set_draw_faded (Output.fgGC, 1);
605 DrawLayerGroup (side_group, drawn_area);
606 gui->graphics->set_draw_faded (Output.fgGC, 0);
608 /* draw package */
609 DrawSilk (side, drawn_area);
610 doing_assy = false;
613 /* ---------------------------------------------------------------------------
614 * initializes some identifiers for a new zoom factor and redraws whole screen
616 static void
617 DrawEverything (const BoxType *drawn_area)
619 int i, ngroups, side;
620 int component, solder;
621 /* This is the list of layer groups we will draw. */
622 int do_group[MAX_LAYER];
623 /* This is the reverse of the order in which we draw them. */
624 int drawn_groups[MAX_LAYER];
625 int plated, unplated;
626 bool paste_empty;
628 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
629 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
631 memset (do_group, 0, sizeof (do_group));
632 for (ngroups = 0, i = 0; i < max_copper_layer; i++)
634 LayerType *l = LAYER_ON_STACK (i);
635 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
636 if (l->On && !do_group[group])
638 do_group[group] = 1;
639 drawn_groups[ngroups++] = group;
643 component = GetLayerGroupNumberByNumber (component_silk_layer);
644 solder = GetLayerGroupNumberByNumber (solder_silk_layer);
647 * first draw all 'invisible' stuff
649 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
650 && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
652 side = SWAP_IDENT ? COMPONENT_LAYER : SOLDER_LAYER;
653 if (PCB->ElementOn)
655 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
656 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
657 DrawLayer (&(PCB->Data->Layer[max_copper_layer + side]), drawn_area);
659 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
660 gui->end_layer ();
663 /* draw all layers in layerstack order */
664 for (i = ngroups - 1; i >= 0; i--)
666 int group = drawn_groups[i];
668 if (gui->set_layer (0, group, 0))
670 DrawLayerGroup (group, drawn_area);
671 gui->end_layer ();
675 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
676 return;
678 /* Draw pins, pads, vias below silk */
679 if (gui->gui)
680 DrawPPV (SWAP_IDENT ? solder : component, drawn_area);
681 else
683 CountHoles (&plated, &unplated, drawn_area);
685 if (plated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
687 DrawHoles (true, false, drawn_area);
688 gui->end_layer ();
691 if (unplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
693 DrawHoles (false, true, drawn_area);
694 gui->end_layer ();
698 /* Draw the solder mask if turned on */
699 if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
701 DrawMask (COMPONENT_LAYER, drawn_area);
702 gui->end_layer ();
705 if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
707 DrawMask (SOLDER_LAYER, drawn_area);
708 gui->end_layer ();
711 if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
713 DrawSilk (COMPONENT_LAYER, drawn_area);
714 gui->end_layer ();
717 if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
719 DrawSilk (SOLDER_LAYER, drawn_area);
720 gui->end_layer ();
723 if (gui->gui)
725 /* Draw element Marks */
726 if (PCB->PinOn)
727 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
728 NULL);
729 /* Draw rat lines on top */
730 if (gui->set_layer ("rats", SL (RATS, 0), 0))
732 DrawRats(drawn_area);
733 gui->end_layer ();
737 paste_empty = IsPasteEmpty (COMPONENT_LAYER);
738 if (gui->set_layer ("toppaste", SL (PASTE, TOP), paste_empty))
740 DrawPaste (COMPONENT_LAYER, drawn_area);
741 gui->end_layer ();
744 paste_empty = IsPasteEmpty (SOLDER_LAYER);
745 if (gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), paste_empty))
747 DrawPaste (SOLDER_LAYER, drawn_area);
748 gui->end_layer ();
751 if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
753 PrintAssembly (COMPONENT_LAYER, drawn_area);
754 gui->end_layer ();
757 if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
759 PrintAssembly (SOLDER_LAYER, drawn_area);
760 gui->end_layer ();
763 if (gui->set_layer ("fab", SL (FAB, 0), 0))
765 PrintFab (Output.fgGC);
766 gui->end_layer ();
770 static void
771 DrawEMark (ElementType *e, Coord X, Coord Y, bool invisible)
773 Coord mark_size = EMARK_SIZE;
774 if (!PCB->InvisibleObjectsOn && invisible)
775 return;
777 if (e->Pin != NULL)
779 PinType *pin0 = e->Pin->data;
780 if (TEST_FLAG (HOLEFLAG, pin0))
781 mark_size = MIN (mark_size, pin0->DrillingHole / 2);
782 else
783 mark_size = MIN (mark_size, pin0->Thickness / 2);
786 if (e->Pad != NULL)
788 PadType *pad0 = e->Pad->data;
789 mark_size = MIN (mark_size, pad0->Thickness / 2);
792 gui->graphics->set_color (Output.fgGC,
793 invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
794 gui->graphics->set_line_cap (Output.fgGC, Trace_Cap);
795 gui->graphics->set_line_width (Output.fgGC, 0);
796 gui->graphics->draw_line (Output.fgGC, X - mark_size, Y, X, Y - mark_size);
797 gui->graphics->draw_line (Output.fgGC, X + mark_size, Y, X, Y - mark_size);
798 gui->graphics->draw_line (Output.fgGC, X - mark_size, Y, X, Y + mark_size);
799 gui->graphics->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
802 * If an element is locked, place a "L" on top of the "diamond".
803 * This provides a nice visual indication that it is locked that
804 * works even for color blind users.
806 if (TEST_FLAG (LOCKFLAG, e) )
808 gui->graphics->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
809 gui->graphics->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
813 /* ---------------------------------------------------------------------------
814 * Draws pins pads and vias - Always draws for non-gui HIDs,
815 * otherwise drawing depends on PCB->PinOn and PCB->ViaOn
817 static void
818 DrawPPV (int group, const BoxType *drawn_area)
820 int component_group = GetLayerGroupNumberByNumber (component_silk_layer);
821 int solder_group = GetLayerGroupNumberByNumber (solder_silk_layer);
822 int side;
824 if (PCB->PinOn || !gui->gui)
826 /* draw element pins */
827 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback, NULL);
829 /* draw element pads */
830 if (group == component_group)
832 side = COMPONENT_LAYER;
833 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
836 if (group == solder_group)
838 side = SOLDER_LAYER;
839 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
843 /* draw vias */
844 if (PCB->ViaOn || !gui->gui)
846 r_search (PCB->Data->via_tree, drawn_area, NULL, via_callback, NULL);
847 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, NULL);
849 if (PCB->PinOn || doing_assy)
850 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, NULL);
853 static int
854 clearPin_callback (const BoxType * b, void *cl)
856 PinType *pin = (PinType *) b;
857 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
858 gui->thindraw_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
859 else
860 gui->fill_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
861 return 1;
864 struct poly_info {
865 const BoxType *drawn_area;
866 LayerType *layer;
869 static int
870 poly_callback (const BoxType * b, void *cl)
872 struct poly_info *i = cl;
873 PolygonType *polygon = (PolygonType *)b;
874 static char *color;
876 if (!polygon->Clipped)
877 return 0;
879 if (TEST_FLAG (SELECTEDFLAG, polygon))
880 color = i->layer->SelectedColor;
881 else if (TEST_FLAG (FOUNDFLAG, polygon))
882 color = PCB->ConnectedColor;
883 else
884 color = i->layer->Color;
885 gui->graphics->set_color (Output.fgGC, color);
887 if (gui->thindraw_pcb_polygon != NULL &&
888 (TEST_FLAG (THINDRAWFLAG, PCB) ||
889 TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
890 gui->thindraw_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
891 else
892 gui->fill_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
894 /* If checking planes, thin-draw any pieces which have been clipped away */
895 if (gui->thindraw_pcb_polygon != NULL &&
896 TEST_FLAG (CHECKPLANESFLAG, PCB) &&
897 !TEST_FLAG (FULLPOLYFLAG, polygon))
899 PolygonType poly = *polygon;
901 for (poly.Clipped = polygon->Clipped->f;
902 poly.Clipped != polygon->Clipped;
903 poly.Clipped = poly.Clipped->f)
904 gui->thindraw_pcb_polygon (Output.fgGC, &poly, i->drawn_area);
907 return 1;
910 static int
911 clearPad_callback (const BoxType * b, void *cl)
913 PadType *pad = (PadType *) b;
914 int *side = cl;
915 if (ON_SIDE (pad, *side) && pad->Mask)
916 _draw_pad (Output.pmGC, pad, true, true);
917 return 1;
920 /* ---------------------------------------------------------------------------
921 * Draws silk layer.
924 void
925 DrawSilk (int side, const BoxType * drawn_area)
927 #if 0
928 /* This code is used when you want to mask silk to avoid exposed
929 pins and pads. We decided it was a bad idea to do this
930 unconditionally, but the code remains. */
931 #endif
933 #if 0
934 if (gui->poly_before)
936 gui->graphics->use_mask (HID_MASK_BEFORE);
937 #endif
938 DrawLayer (LAYER_PTR (max_copper_layer + side), drawn_area);
939 /* draw package */
940 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
941 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
942 #if 0
945 gui->graphics->use_mask (HID_MASK_CLEAR);
946 r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, NULL);
947 r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, NULL);
948 r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &side);
950 if (gui->poly_after)
952 gui->graphics->use_mask (HID_MASK_AFTER);
953 DrawLayer (LAYER_PTR (max_copper_layer + layer), drawn_area);
954 /* draw package */
955 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
956 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
958 gui->graphics->use_mask (HID_MASK_OFF);
959 #endif
963 static void
964 DrawMaskBoardArea (int mask_type, const BoxType *drawn_area)
966 /* Skip the mask drawing if the GUI doesn't want this type */
967 if ((mask_type == HID_MASK_BEFORE && !gui->poly_before) ||
968 (mask_type == HID_MASK_AFTER && !gui->poly_after))
969 return;
971 gui->graphics->use_mask (mask_type);
972 gui->graphics->set_color (Output.fgGC, PCB->MaskColor);
973 if (drawn_area == NULL)
974 gui->graphics->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
975 else
976 gui->graphics->fill_rect (Output.fgGC, drawn_area->X1, drawn_area->Y1,
977 drawn_area->X2, drawn_area->Y2);
980 /* ---------------------------------------------------------------------------
981 * draws solder mask layer - this will cover nearly everything
983 void
984 DrawMask (int side, const BoxType *screen)
986 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
988 if (thin)
989 gui->graphics->set_color (Output.pmGC, PCB->MaskColor);
990 else
992 DrawMaskBoardArea (HID_MASK_BEFORE, screen);
993 gui->graphics->use_mask (HID_MASK_CLEAR);
996 r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, NULL);
997 r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, NULL);
998 r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &side);
1000 if (thin)
1001 gui->graphics->set_color (Output.pmGC, "erase");
1002 else
1004 DrawMaskBoardArea (HID_MASK_AFTER, screen);
1005 gui->graphics->use_mask (HID_MASK_OFF);
1009 /* ---------------------------------------------------------------------------
1010 * draws solder paste layer for a given side of the board
1012 void
1013 DrawPaste (int side, const BoxType *drawn_area)
1015 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
1016 ALLPAD_LOOP (PCB->Data);
1018 if (ON_SIDE (pad, side) && !TEST_FLAG (NOPASTEFLAG, pad) && pad->Mask > 0)
1020 if (pad->Mask < pad->Thickness)
1021 _draw_pad (Output.fgGC, pad, true, true);
1022 else
1023 _draw_pad (Output.fgGC, pad, false, false);
1026 ENDALL_LOOP;
1029 static void
1030 DrawRats (const BoxType *drawn_area)
1033 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
1034 * XXX gtk only allows negative drawing.
1035 * XXX using the mask here is to get rat transparency
1037 int can_mask = strcmp(gui->name, "lesstif") == 0;
1039 if (can_mask)
1040 gui->graphics->use_mask (HID_MASK_CLEAR);
1041 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
1042 if (can_mask)
1043 gui->graphics->use_mask (HID_MASK_OFF);
1046 static int
1047 text_callback (const BoxType * b, void *cl)
1049 LayerType *layer = cl;
1050 TextType *text = (TextType *)b;
1051 int min_silk_line;
1053 if (TEST_FLAG (SELECTEDFLAG, text))
1054 gui->graphics->set_color (Output.fgGC, layer->SelectedColor);
1055 else
1056 gui->graphics->set_color (Output.fgGC, layer->Color);
1057 if (layer == &PCB->Data->SILKLAYER ||
1058 layer == &PCB->Data->BACKSILKLAYER)
1059 min_silk_line = PCB->minSlk;
1060 else
1061 min_silk_line = PCB->minWid;
1062 DrawTextLowLevel (text, min_silk_line);
1063 return 1;
1066 void
1067 DrawLayer (LayerType *Layer, const BoxType *screen)
1069 struct poly_info info = {screen, Layer};
1071 /* print the non-clearing polys */
1072 r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
1074 if (TEST_FLAG (CHECKPLANESFLAG, PCB))
1075 return;
1077 /* draw all visible lines this layer */
1078 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
1080 /* draw the layer arcs on screen */
1081 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
1083 /* draw the layer text on screen */
1084 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
1086 /* We should check for gui->gui here, but it's kinda cool seeing the
1087 auto-outline magically disappear when you first add something to
1088 the "outline" layer. */
1089 if (IsLayerEmpty (Layer)
1090 && (strcmp (Layer->Name, "outline") == 0
1091 || strcmp (Layer->Name, "route") == 0))
1093 gui->graphics->set_color (Output.fgGC, Layer->Color);
1094 gui->graphics->set_line_width (Output.fgGC, PCB->minWid);
1095 gui->graphics->draw_rect (Output.fgGC,
1096 0, 0,
1097 PCB->MaxWidth, PCB->MaxHeight);
1101 /* ---------------------------------------------------------------------------
1102 * draws one layer group. If the exporter is not a GUI,
1103 * also draws the pins / pads / vias in this layer group.
1105 void
1106 DrawLayerGroup (int group, const BoxType *drawn_area)
1108 int i, rv = 1;
1109 int layernum;
1110 LayerType *Layer;
1111 int n_entries = PCB->LayerGroups.Number[group];
1112 Cardinal *layers = PCB->LayerGroups.Entries[group];
1114 for (i = n_entries - 1; i >= 0; i--)
1116 layernum = layers[i];
1117 Layer = PCB->Data->Layer + layers[i];
1118 if (strcmp (Layer->Name, "outline") == 0 ||
1119 strcmp (Layer->Name, "route") == 0)
1120 rv = 0;
1121 if (layernum < max_copper_layer && Layer->On)
1122 DrawLayer (Layer, drawn_area);
1124 if (n_entries > 1)
1125 rv = 1;
1127 if (rv && !gui->gui)
1128 DrawPPV (group, drawn_area);
1131 static void
1132 GatherPVName (PinType *Ptr)
1134 BoxType box;
1135 bool vert = TEST_FLAG (EDGE2FLAG, Ptr);
1137 if (vert)
1139 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1140 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
1142 else
1144 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
1145 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1148 if (vert)
1150 box.X2 = box.X1;
1151 box.Y2 = box.Y1;
1153 else
1155 box.X2 = box.X1;
1156 box.Y2 = box.Y1;
1158 AddPart (&box);
1161 static void
1162 GatherPadName (PadType *Pad)
1164 BoxType box;
1165 bool vert;
1167 /* should text be vertical ? */
1168 vert = (Pad->Point1.X == Pad->Point2.X);
1170 if (vert)
1172 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1173 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1174 box.X1 += Settings.PinoutTextOffsetY;
1175 box.Y1 -= Settings.PinoutTextOffsetX;
1176 box.X2 = box.X1;
1177 box.Y2 = box.Y1;
1179 else
1181 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1182 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1183 box.X1 += Settings.PinoutTextOffsetX;
1184 box.Y1 += Settings.PinoutTextOffsetY;
1185 box.X2 = box.X1;
1186 box.Y2 = box.Y1;
1189 AddPart (&box);
1190 return;
1193 /* ---------------------------------------------------------------------------
1194 * lowlevel drawing routine for text objects
1196 void
1197 DrawTextLowLevel (TextType *Text, Coord min_line_width)
1199 Coord x = 0;
1200 unsigned char *string = (unsigned char *) Text->TextString;
1201 Cardinal n;
1202 FontType *font = &PCB->Font;
1204 while (string && *string)
1206 /* draw lines if symbol is valid and data is present */
1207 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid)
1209 LineType *line = font->Symbol[*string].Line;
1210 LineType newline;
1212 for (n = font->Symbol[*string].LineN; n; n--, line++)
1214 /* create one line, scale, move, rotate and swap it */
1215 newline = *line;
1216 newline.Point1.X = SCALE_TEXT (newline.Point1.X + x, Text->Scale);
1217 newline.Point1.Y = SCALE_TEXT (newline.Point1.Y, Text->Scale);
1218 newline.Point2.X = SCALE_TEXT (newline.Point2.X + x, Text->Scale);
1219 newline.Point2.Y = SCALE_TEXT (newline.Point2.Y, Text->Scale);
1220 newline.Thickness = SCALE_TEXT (newline.Thickness, Text->Scale / 2);
1221 if (newline.Thickness < min_line_width)
1222 newline.Thickness = min_line_width;
1224 RotateLineLowLevel (&newline, 0, 0, Text->Direction);
1226 /* the labels of SMD objects on the bottom
1227 * side haven't been swapped yet, only their offset
1229 if (TEST_FLAG (ONSOLDERFLAG, Text))
1231 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X);
1232 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y);
1233 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X);
1234 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y);
1236 /* add offset and draw line */
1237 newline.Point1.X += Text->X;
1238 newline.Point1.Y += Text->Y;
1239 newline.Point2.X += Text->X;
1240 newline.Point2.Y += Text->Y;
1241 _draw_line (Output.fgGC, &newline);
1244 /* move on to next cursor position */
1245 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta);
1247 else
1249 /* the default symbol is a filled box */
1250 BoxType defaultsymbol = PCB->Font.DefaultSymbol;
1251 Coord size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5;
1253 defaultsymbol.X1 = SCALE_TEXT (defaultsymbol.X1 + x, Text->Scale);
1254 defaultsymbol.Y1 = SCALE_TEXT (defaultsymbol.Y1, Text->Scale);
1255 defaultsymbol.X2 = SCALE_TEXT (defaultsymbol.X2 + x, Text->Scale);
1256 defaultsymbol.Y2 = SCALE_TEXT (defaultsymbol.Y2, Text->Scale);
1258 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction);
1260 /* add offset and draw box */
1261 defaultsymbol.X1 += Text->X;
1262 defaultsymbol.Y1 += Text->Y;
1263 defaultsymbol.X2 += Text->X;
1264 defaultsymbol.Y2 += Text->Y;
1265 gui->graphics->fill_rect (Output.fgGC,
1266 defaultsymbol.X1, defaultsymbol.Y1,
1267 defaultsymbol.X2, defaultsymbol.Y2);
1269 /* move on to next cursor position */
1270 x += size;
1272 string++;
1276 /* ---------------------------------------------------------------------------
1277 * draw a via object
1279 void
1280 DrawVia (PinType *Via)
1282 AddPart (Via);
1283 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1284 DrawViaName (Via);
1287 /* ---------------------------------------------------------------------------
1288 * draws the name of a via
1290 void
1291 DrawViaName (PinType *Via)
1293 GatherPVName (Via);
1296 /* ---------------------------------------------------------------------------
1297 * draw a pin object
1299 void
1300 DrawPin (PinType *Pin)
1302 AddPart (Pin);
1303 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1304 || doing_pinout)
1305 DrawPinName (Pin);
1308 /* ---------------------------------------------------------------------------
1309 * draws the name of a pin
1311 void
1312 DrawPinName (PinType *Pin)
1314 GatherPVName (Pin);
1317 /* ---------------------------------------------------------------------------
1318 * draw a pad object
1320 void
1321 DrawPad (PadType *Pad)
1323 AddPart (Pad);
1324 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1325 DrawPadName (Pad);
1328 /* ---------------------------------------------------------------------------
1329 * draws the name of a pad
1331 void
1332 DrawPadName (PadType *Pad)
1334 GatherPadName (Pad);
1337 /* ---------------------------------------------------------------------------
1338 * draws a line on a layer
1340 void
1341 DrawLine (LayerType *Layer, LineType *Line)
1343 AddPart (Line);
1346 /* ---------------------------------------------------------------------------
1347 * draws a ratline
1349 void
1350 DrawRat (RatType *Rat)
1352 if (Settings.RatThickness < 100)
1353 Rat->Thickness = pixel_slop * Settings.RatThickness;
1354 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1355 if (TEST_FLAG(VIAFLAG, Rat))
1357 Coord w = Rat->Thickness;
1359 BoxType b;
1361 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1362 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1363 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1364 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1365 AddPart (&b);
1367 else
1368 DrawLine (NULL, (LineType *)Rat);
1371 /* ---------------------------------------------------------------------------
1372 * draws an arc on a layer
1374 void
1375 DrawArc (LayerType *Layer, ArcType *Arc)
1377 AddPart (Arc);
1380 /* ---------------------------------------------------------------------------
1381 * draws a text on a layer
1383 void
1384 DrawText (LayerType *Layer, TextType *Text)
1386 AddPart (Text);
1390 /* ---------------------------------------------------------------------------
1391 * draws a polygon on a layer
1393 void
1394 DrawPolygon (LayerType *Layer, PolygonType *Polygon)
1396 AddPart (Polygon);
1399 /* ---------------------------------------------------------------------------
1400 * draws an element
1402 void
1403 DrawElement (ElementType *Element)
1405 DrawElementPackage (Element);
1406 DrawElementName (Element);
1407 DrawElementPinsAndPads (Element);
1410 /* ---------------------------------------------------------------------------
1411 * draws the name of an element
1413 void
1414 DrawElementName (ElementType *Element)
1416 if (TEST_FLAG (HIDENAMEFLAG, Element))
1417 return;
1418 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1421 /* ---------------------------------------------------------------------------
1422 * draws the package of an element
1424 void
1425 DrawElementPackage (ElementType *Element)
1427 ELEMENTLINE_LOOP (Element);
1429 DrawLine (NULL, line);
1431 END_LOOP;
1432 ARC_LOOP (Element);
1434 DrawArc (NULL, arc);
1436 END_LOOP;
1439 /* ---------------------------------------------------------------------------
1440 * draw pins of an element
1442 void
1443 DrawElementPinsAndPads (ElementType *Element)
1445 PAD_LOOP (Element);
1447 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
1448 DrawPad (pad);
1450 END_LOOP;
1451 PIN_LOOP (Element);
1453 DrawPin (pin);
1455 END_LOOP;
1458 /* ---------------------------------------------------------------------------
1459 * erase a via
1461 void
1462 EraseVia (PinType *Via)
1464 AddPart (Via);
1465 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
1466 EraseViaName (Via);
1469 /* ---------------------------------------------------------------------------
1470 * erase a ratline
1472 void
1473 EraseRat (RatType *Rat)
1475 if (TEST_FLAG(VIAFLAG, Rat))
1477 Coord w = Rat->Thickness;
1479 BoxType b;
1481 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1482 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1483 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1484 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1485 AddPart (&b);
1487 else
1488 EraseLine ((LineType *)Rat);
1492 /* ---------------------------------------------------------------------------
1493 * erase a via name
1495 void
1496 EraseViaName (PinType *Via)
1498 GatherPVName (Via);
1501 /* ---------------------------------------------------------------------------
1502 * erase a pad object
1504 void
1505 ErasePad (PadType *Pad)
1507 AddPart (Pad);
1508 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1509 ErasePadName (Pad);
1512 /* ---------------------------------------------------------------------------
1513 * erase a pad name
1515 void
1516 ErasePadName (PadType *Pad)
1518 GatherPadName (Pad);
1521 /* ---------------------------------------------------------------------------
1522 * erase a pin object
1524 void
1525 ErasePin (PinType *Pin)
1527 AddPart (Pin);
1528 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1529 ErasePinName (Pin);
1532 /* ---------------------------------------------------------------------------
1533 * erase a pin name
1535 void
1536 ErasePinName (PinType *Pin)
1538 GatherPVName (Pin);
1541 /* ---------------------------------------------------------------------------
1542 * erases a line on a layer
1544 void
1545 EraseLine (LineType *Line)
1547 AddPart (Line);
1550 /* ---------------------------------------------------------------------------
1551 * erases an arc on a layer
1553 void
1554 EraseArc (ArcType *Arc)
1556 if (!Arc->Thickness)
1557 return;
1558 AddPart (Arc);
1561 /* ---------------------------------------------------------------------------
1562 * erases a text on a layer
1564 void
1565 EraseText (LayerType *Layer, TextType *Text)
1567 AddPart (Text);
1570 /* ---------------------------------------------------------------------------
1571 * erases a polygon on a layer
1573 void
1574 ErasePolygon (PolygonType *Polygon)
1576 AddPart (Polygon);
1579 /* ---------------------------------------------------------------------------
1580 * erases an element
1582 void
1583 EraseElement (ElementType *Element)
1585 ELEMENTLINE_LOOP (Element);
1587 EraseLine (line);
1589 END_LOOP;
1590 ARC_LOOP (Element);
1592 EraseArc (arc);
1594 END_LOOP;
1595 EraseElementName (Element);
1596 EraseElementPinsAndPads (Element);
1599 /* ---------------------------------------------------------------------------
1600 * erases all pins and pads of an element
1602 void
1603 EraseElementPinsAndPads (ElementType *Element)
1605 PIN_LOOP (Element);
1607 ErasePin (pin);
1609 END_LOOP;
1610 PAD_LOOP (Element);
1612 ErasePad (pad);
1614 END_LOOP;
1617 /* ---------------------------------------------------------------------------
1618 * erases the name of an element
1620 void
1621 EraseElementName (ElementType *Element)
1623 if (TEST_FLAG (HIDENAMEFLAG, Element))
1624 return;
1625 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1629 void
1630 EraseObject (int type, void *lptr, void *ptr)
1632 switch (type)
1634 case VIA_TYPE:
1635 case PIN_TYPE:
1636 ErasePin ((PinType *) ptr);
1637 break;
1638 case TEXT_TYPE:
1639 case ELEMENTNAME_TYPE:
1640 EraseText ((LayerType *)lptr, (TextType *) ptr);
1641 break;
1642 case POLYGON_TYPE:
1643 ErasePolygon ((PolygonType *) ptr);
1644 break;
1645 case ELEMENT_TYPE:
1646 EraseElement ((ElementType *) ptr);
1647 break;
1648 case LINE_TYPE:
1649 case ELEMENTLINE_TYPE:
1650 case RATLINE_TYPE:
1651 EraseLine ((LineType *) ptr);
1652 break;
1653 case PAD_TYPE:
1654 ErasePad ((PadType *) ptr);
1655 break;
1656 case ARC_TYPE:
1657 case ELEMENTARC_TYPE:
1658 EraseArc ((ArcType *) ptr);
1659 break;
1660 default:
1661 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
1667 void
1668 DrawObject (int type, void *ptr1, void *ptr2)
1670 switch (type)
1672 case VIA_TYPE:
1673 if (PCB->ViaOn)
1674 DrawVia ((PinType *) ptr2);
1675 break;
1676 case LINE_TYPE:
1677 if (((LayerType *) ptr1)->On)
1678 DrawLine ((LayerType *) ptr1, (LineType *) ptr2);
1679 break;
1680 case ARC_TYPE:
1681 if (((LayerType *) ptr1)->On)
1682 DrawArc ((LayerType *) ptr1, (ArcType *) ptr2);
1683 break;
1684 case TEXT_TYPE:
1685 if (((LayerType *) ptr1)->On)
1686 DrawText ((LayerType *) ptr1, (TextType *) ptr2);
1687 break;
1688 case POLYGON_TYPE:
1689 if (((LayerType *) ptr1)->On)
1690 DrawPolygon ((LayerType *) ptr1, (PolygonType *) ptr2);
1691 break;
1692 case ELEMENT_TYPE:
1693 if (PCB->ElementOn &&
1694 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1695 DrawElement ((ElementType *) ptr2);
1696 break;
1697 case RATLINE_TYPE:
1698 if (PCB->RatOn)
1699 DrawRat ((RatType *) ptr2);
1700 break;
1701 case PIN_TYPE:
1702 if (PCB->PinOn)
1703 DrawPin ((PinType *) ptr2);
1704 break;
1705 case PAD_TYPE:
1706 if (PCB->PinOn)
1707 DrawPad ((PadType *) ptr2);
1708 break;
1709 case ELEMENTNAME_TYPE:
1710 if (PCB->ElementOn &&
1711 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1712 DrawElementName ((ElementType *) ptr1);
1713 break;
1717 static void
1718 draw_element (ElementType *element)
1720 draw_element_package (element);
1721 draw_element_name (element);
1722 draw_element_pins_and_pads (element);
1725 /* ---------------------------------------------------------------------------
1726 * HID drawing callback.
1729 void
1730 hid_expose_callback (HID * hid, BoxType * region, void *item)
1732 HID *old_gui = gui;
1734 gui = hid;
1735 Output.fgGC = gui->graphics->make_gc ();
1736 Output.bgGC = gui->graphics->make_gc ();
1737 Output.pmGC = gui->graphics->make_gc ();
1739 hid->graphics->set_color (Output.pmGC, "erase");
1740 hid->graphics->set_color (Output.bgGC, "drill");
1742 if (item)
1744 doing_pinout = true;
1745 draw_element ((ElementType *)item);
1746 doing_pinout = false;
1748 else
1749 DrawEverything (region);
1751 gui->graphics->destroy_gc (Output.fgGC);
1752 gui->graphics->destroy_gc (Output.bgGC);
1753 gui->graphics->destroy_gc (Output.pmGC);
1754 gui = old_gui;