HID: Move non-PCB specific drawing calls into a separate API
[geda-pcb/pcjc2.git] / src / draw.c
blob683d3940dfeca020073c8215004cd6f876e2c9ad
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 (LineType *line)
452 gui->graphics->set_line_cap (Output.fgGC, Trace_Cap);
453 if (TEST_FLAG (THINDRAWFLAG, PCB))
454 gui->graphics->set_line_width (Output.fgGC, 0);
455 else
456 gui->graphics->set_line_width (Output.fgGC, line->Thickness);
458 gui->graphics->draw_line (Output.fgGC,
459 line->Point1.X, line->Point1.Y,
460 line->Point2.X, line->Point2.Y);
463 static void
464 draw_line (LayerType *layer, LineType *line)
466 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, line))
468 if (TEST_FLAG (SELECTEDFLAG, line))
469 gui->graphics->set_color (Output.fgGC, layer->SelectedColor);
470 else
471 gui->graphics->set_color (Output.fgGC, PCB->ConnectedColor);
473 else
474 gui->graphics->set_color (Output.fgGC, layer->Color);
475 _draw_line (line);
478 static int
479 line_callback (const BoxType * b, void *cl)
481 draw_line ((LayerType *) cl, (LineType *) b);
482 return 1;
485 static int
486 rat_callback (const BoxType * b, void *cl)
488 RatType *rat = (RatType *)b;
490 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, rat))
492 if (TEST_FLAG (SELECTEDFLAG, rat))
493 gui->graphics->set_color (Output.fgGC, PCB->RatSelectedColor);
494 else
495 gui->graphics->set_color (Output.fgGC, PCB->ConnectedColor);
497 else
498 gui->graphics->set_color (Output.fgGC, PCB->RatColor);
500 if (Settings.RatThickness < 100)
501 rat->Thickness = pixel_slop * Settings.RatThickness;
502 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
503 if (TEST_FLAG(VIAFLAG, rat))
505 int w = rat->Thickness;
507 if (TEST_FLAG (THINDRAWFLAG, PCB))
508 gui->graphics->set_line_width (Output.fgGC, 0);
509 else
510 gui->graphics->set_line_width (Output.fgGC, w);
511 gui->graphics->draw_arc (Output.fgGC, rat->Point1.X, rat->Point1.Y,
512 w * 2, w * 2, 0, 360);
514 else
515 _draw_line ((LineType *) rat);
516 return 1;
519 static void
520 _draw_arc (ArcType *arc)
522 if (!arc->Thickness)
523 return;
525 if (TEST_FLAG (THINDRAWFLAG, PCB))
526 gui->graphics->set_line_width (Output.fgGC, 0);
527 else
528 gui->graphics->set_line_width (Output.fgGC, arc->Thickness);
529 gui->graphics->set_line_cap (Output.fgGC, Trace_Cap);
531 gui->graphics->draw_arc (Output.fgGC, arc->X, arc->Y, arc->Width,
532 arc->Height, arc->StartAngle, arc->Delta);
535 static void
536 draw_arc (LayerType *layer, ArcType *arc)
538 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, arc))
540 if (TEST_FLAG (SELECTEDFLAG, arc))
541 gui->graphics->set_color (Output.fgGC, layer->SelectedColor);
542 else
543 gui->graphics->set_color (Output.fgGC, PCB->ConnectedColor);
545 else
546 gui->graphics->set_color (Output.fgGC, layer->Color);
548 _draw_arc (arc);
551 static int
552 arc_callback (const BoxType * b, void *cl)
554 draw_arc ((LayerType *) cl, (ArcType *) b);
555 return 1;
558 static void
559 draw_element_package (ElementType *element)
561 /* set color and draw lines, arcs, text and pins */
562 if (doing_pinout || doing_assy)
563 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
564 else if (TEST_FLAG (SELECTEDFLAG, element))
565 gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor);
566 else if (FRONT (element))
567 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
568 else
569 gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
571 /* draw lines, arcs, text and pins */
572 ELEMENTLINE_LOOP (element);
574 _draw_line (line);
576 END_LOOP;
577 ARC_LOOP (element);
579 _draw_arc (arc);
581 END_LOOP;
584 static int
585 element_callback (const BoxType * b, void *cl)
587 ElementType *element = (ElementType *) b;
588 int *side = cl;
590 if (ON_SIDE (element, *side))
591 draw_element_package (element);
592 return 1;
595 /* ---------------------------------------------------------------------------
596 * prints assembly drawing.
599 void
600 PrintAssembly (int side, const BoxType * drawn_area)
602 int side_group = GetLayerGroupNumberByNumber (max_copper_layer + side);
604 doing_assy = true;
605 gui->graphics->set_draw_faded (Output.fgGC, 1);
606 DrawLayerGroup (side_group, drawn_area);
607 gui->graphics->set_draw_faded (Output.fgGC, 0);
609 /* draw package */
610 DrawSilk (side, drawn_area);
611 doing_assy = false;
614 /* ---------------------------------------------------------------------------
615 * initializes some identifiers for a new zoom factor and redraws whole screen
617 static void
618 DrawEverything (const BoxType *drawn_area)
620 int i, ngroups, side;
621 int component, solder;
622 /* This is the list of layer groups we will draw. */
623 int do_group[MAX_LAYER];
624 /* This is the reverse of the order in which we draw them. */
625 int drawn_groups[MAX_LAYER];
626 int plated, unplated;
627 bool paste_empty;
629 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
630 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
632 memset (do_group, 0, sizeof (do_group));
633 for (ngroups = 0, i = 0; i < max_copper_layer; i++)
635 LayerType *l = LAYER_ON_STACK (i);
636 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
637 if (l->On && !do_group[group])
639 do_group[group] = 1;
640 drawn_groups[ngroups++] = group;
644 component = GetLayerGroupNumberByNumber (component_silk_layer);
645 solder = GetLayerGroupNumberByNumber (solder_silk_layer);
648 * first draw all 'invisible' stuff
650 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
651 && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
653 side = SWAP_IDENT ? COMPONENT_LAYER : SOLDER_LAYER;
654 if (PCB->ElementOn)
656 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
657 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
658 DrawLayer (&(PCB->Data->Layer[max_copper_layer + side]), drawn_area);
660 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
661 gui->end_layer ();
664 /* draw all layers in layerstack order */
665 for (i = ngroups - 1; i >= 0; i--)
667 int group = drawn_groups[i];
669 if (gui->set_layer (0, group, 0))
671 DrawLayerGroup (group, drawn_area);
672 gui->end_layer ();
676 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
677 return;
679 /* Draw pins, pads, vias below silk */
680 if (gui->gui)
681 DrawPPV (SWAP_IDENT ? solder : component, drawn_area);
682 else
684 CountHoles (&plated, &unplated, drawn_area);
686 if (plated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
688 DrawHoles (true, false, drawn_area);
689 gui->end_layer ();
692 if (unplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
694 DrawHoles (false, true, drawn_area);
695 gui->end_layer ();
699 /* Draw the solder mask if turned on */
700 if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
702 DrawMask (COMPONENT_LAYER, drawn_area);
703 gui->end_layer ();
706 if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
708 DrawMask (SOLDER_LAYER, drawn_area);
709 gui->end_layer ();
712 if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
714 DrawSilk (COMPONENT_LAYER, drawn_area);
715 gui->end_layer ();
718 if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
720 DrawSilk (SOLDER_LAYER, drawn_area);
721 gui->end_layer ();
724 if (gui->gui)
726 /* Draw element Marks */
727 if (PCB->PinOn)
728 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
729 NULL);
730 /* Draw rat lines on top */
731 if (gui->set_layer ("rats", SL (RATS, 0), 0))
733 DrawRats(drawn_area);
734 gui->end_layer ();
738 paste_empty = IsPasteEmpty (COMPONENT_LAYER);
739 if (gui->set_layer ("toppaste", SL (PASTE, TOP), paste_empty))
741 DrawPaste (COMPONENT_LAYER, drawn_area);
742 gui->end_layer ();
745 paste_empty = IsPasteEmpty (SOLDER_LAYER);
746 if (gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), paste_empty))
748 DrawPaste (SOLDER_LAYER, drawn_area);
749 gui->end_layer ();
752 if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
754 PrintAssembly (COMPONENT_LAYER, drawn_area);
755 gui->end_layer ();
758 if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
760 PrintAssembly (SOLDER_LAYER, drawn_area);
761 gui->end_layer ();
764 if (gui->set_layer ("fab", SL (FAB, 0), 0))
766 PrintFab (Output.fgGC);
767 gui->end_layer ();
771 static void
772 DrawEMark (ElementType *e, Coord X, Coord Y, bool invisible)
774 Coord mark_size = EMARK_SIZE;
775 if (!PCB->InvisibleObjectsOn && invisible)
776 return;
778 if (e->Pin != NULL)
780 PinType *pin0 = e->Pin->data;
781 if (TEST_FLAG (HOLEFLAG, pin0))
782 mark_size = MIN (mark_size, pin0->DrillingHole / 2);
783 else
784 mark_size = MIN (mark_size, pin0->Thickness / 2);
787 if (e->Pad != NULL)
789 PadType *pad0 = e->Pad->data;
790 mark_size = MIN (mark_size, pad0->Thickness / 2);
793 gui->graphics->set_color (Output.fgGC,
794 invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
795 gui->graphics->set_line_cap (Output.fgGC, Trace_Cap);
796 gui->graphics->set_line_width (Output.fgGC, 0);
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);
800 gui->graphics->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
803 * If an element is locked, place a "L" on top of the "diamond".
804 * This provides a nice visual indication that it is locked that
805 * works even for color blind users.
807 if (TEST_FLAG (LOCKFLAG, e) )
809 gui->graphics->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
810 gui->graphics->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
814 /* ---------------------------------------------------------------------------
815 * Draws pins pads and vias - Always draws for non-gui HIDs,
816 * otherwise drawing depends on PCB->PinOn and PCB->ViaOn
818 static void
819 DrawPPV (int group, const BoxType *drawn_area)
821 int component_group = GetLayerGroupNumberByNumber (component_silk_layer);
822 int solder_group = GetLayerGroupNumberByNumber (solder_silk_layer);
823 int side;
825 if (PCB->PinOn || !gui->gui)
827 /* draw element pins */
828 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback, NULL);
830 /* draw element pads */
831 if (group == component_group)
833 side = COMPONENT_LAYER;
834 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
837 if (group == solder_group)
839 side = SOLDER_LAYER;
840 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
844 /* draw vias */
845 if (PCB->ViaOn || !gui->gui)
847 r_search (PCB->Data->via_tree, drawn_area, NULL, via_callback, NULL);
848 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, NULL);
850 if (PCB->PinOn || doing_assy)
851 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, NULL);
854 static int
855 clearPin_callback (const BoxType * b, void *cl)
857 PinType *pin = (PinType *) b;
858 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
859 gui->thindraw_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
860 else
861 gui->fill_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
862 return 1;
865 struct poly_info {
866 const BoxType *drawn_area;
867 LayerType *layer;
870 static int
871 poly_callback (const BoxType * b, void *cl)
873 struct poly_info *i = cl;
874 PolygonType *polygon = (PolygonType *)b;
875 static char *color;
877 if (!polygon->Clipped)
878 return 0;
880 if (TEST_FLAG (SELECTEDFLAG, polygon))
881 color = i->layer->SelectedColor;
882 else if (TEST_FLAG (FOUNDFLAG, polygon))
883 color = PCB->ConnectedColor;
884 else
885 color = i->layer->Color;
886 gui->graphics->set_color (Output.fgGC, color);
888 if (gui->thindraw_pcb_polygon != NULL &&
889 (TEST_FLAG (THINDRAWFLAG, PCB) ||
890 TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
891 gui->thindraw_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
892 else
893 gui->fill_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
895 /* If checking planes, thin-draw any pieces which have been clipped away */
896 if (gui->thindraw_pcb_polygon != NULL &&
897 TEST_FLAG (CHECKPLANESFLAG, PCB) &&
898 !TEST_FLAG (FULLPOLYFLAG, polygon))
900 PolygonType poly = *polygon;
902 for (poly.Clipped = polygon->Clipped->f;
903 poly.Clipped != polygon->Clipped;
904 poly.Clipped = poly.Clipped->f)
905 gui->thindraw_pcb_polygon (Output.fgGC, &poly, i->drawn_area);
908 return 1;
911 static int
912 clearPad_callback (const BoxType * b, void *cl)
914 PadType *pad = (PadType *) b;
915 int *side = cl;
916 if (ON_SIDE (pad, *side) && pad->Mask)
917 _draw_pad (Output.pmGC, pad, true, true);
918 return 1;
921 /* ---------------------------------------------------------------------------
922 * Draws silk layer.
925 void
926 DrawSilk (int side, const BoxType * drawn_area)
928 #if 0
929 /* This code is used when you want to mask silk to avoid exposed
930 pins and pads. We decided it was a bad idea to do this
931 unconditionally, but the code remains. */
932 #endif
934 #if 0
935 if (gui->poly_before)
937 gui->graphics->use_mask (HID_MASK_BEFORE);
938 #endif
939 DrawLayer (LAYER_PTR (max_copper_layer + side), drawn_area);
940 /* draw package */
941 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
942 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
943 #if 0
946 gui->graphics->use_mask (HID_MASK_CLEAR);
947 r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, NULL);
948 r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, NULL);
949 r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &side);
951 if (gui->poly_after)
953 gui->graphics->use_mask (HID_MASK_AFTER);
954 DrawLayer (LAYER_PTR (max_copper_layer + layer), drawn_area);
955 /* draw package */
956 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
957 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
959 gui->graphics->use_mask (HID_MASK_OFF);
960 #endif
964 static void
965 DrawMaskBoardArea (int mask_type, const BoxType *drawn_area)
967 /* Skip the mask drawing if the GUI doesn't want this type */
968 if ((mask_type == HID_MASK_BEFORE && !gui->poly_before) ||
969 (mask_type == HID_MASK_AFTER && !gui->poly_after))
970 return;
972 gui->graphics->use_mask (mask_type);
973 gui->graphics->set_color (Output.fgGC, PCB->MaskColor);
974 if (drawn_area == NULL)
975 gui->graphics->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
976 else
977 gui->graphics->fill_rect (Output.fgGC, drawn_area->X1, drawn_area->Y1,
978 drawn_area->X2, drawn_area->Y2);
981 /* ---------------------------------------------------------------------------
982 * draws solder mask layer - this will cover nearly everything
984 void
985 DrawMask (int side, const BoxType *screen)
987 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
989 if (thin)
990 gui->graphics->set_color (Output.pmGC, PCB->MaskColor);
991 else
993 DrawMaskBoardArea (HID_MASK_BEFORE, screen);
994 gui->graphics->use_mask (HID_MASK_CLEAR);
997 r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, NULL);
998 r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, NULL);
999 r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &side);
1001 if (thin)
1002 gui->graphics->set_color (Output.pmGC, "erase");
1003 else
1005 DrawMaskBoardArea (HID_MASK_AFTER, screen);
1006 gui->graphics->use_mask (HID_MASK_OFF);
1010 /* ---------------------------------------------------------------------------
1011 * draws solder paste layer for a given side of the board
1013 void
1014 DrawPaste (int side, const BoxType *drawn_area)
1016 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
1017 ALLPAD_LOOP (PCB->Data);
1019 if (ON_SIDE (pad, side) && !TEST_FLAG (NOPASTEFLAG, pad) && pad->Mask > 0)
1021 if (pad->Mask < pad->Thickness)
1022 _draw_pad (Output.fgGC, pad, true, true);
1023 else
1024 _draw_pad (Output.fgGC, pad, false, false);
1027 ENDALL_LOOP;
1030 static void
1031 DrawRats (const BoxType *drawn_area)
1034 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
1035 * XXX gtk only allows negative drawing.
1036 * XXX using the mask here is to get rat transparency
1038 int can_mask = strcmp(gui->name, "lesstif") == 0;
1040 if (can_mask)
1041 gui->graphics->use_mask (HID_MASK_CLEAR);
1042 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
1043 if (can_mask)
1044 gui->graphics->use_mask (HID_MASK_OFF);
1047 static int
1048 text_callback (const BoxType * b, void *cl)
1050 LayerType *layer = cl;
1051 TextType *text = (TextType *)b;
1052 int min_silk_line;
1054 if (TEST_FLAG (SELECTEDFLAG, text))
1055 gui->graphics->set_color (Output.fgGC, layer->SelectedColor);
1056 else
1057 gui->graphics->set_color (Output.fgGC, layer->Color);
1058 if (layer == &PCB->Data->SILKLAYER ||
1059 layer == &PCB->Data->BACKSILKLAYER)
1060 min_silk_line = PCB->minSlk;
1061 else
1062 min_silk_line = PCB->minWid;
1063 DrawTextLowLevel (text, min_silk_line);
1064 return 1;
1067 void
1068 DrawLayer (LayerType *Layer, const BoxType *screen)
1070 struct poly_info info = {screen, Layer};
1072 /* print the non-clearing polys */
1073 r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
1075 if (TEST_FLAG (CHECKPLANESFLAG, PCB))
1076 return;
1078 /* draw all visible lines this layer */
1079 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
1081 /* draw the layer arcs on screen */
1082 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
1084 /* draw the layer text on screen */
1085 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
1087 /* We should check for gui->gui here, but it's kinda cool seeing the
1088 auto-outline magically disappear when you first add something to
1089 the "outline" layer. */
1090 if (IsLayerEmpty (Layer)
1091 && (strcmp (Layer->Name, "outline") == 0
1092 || strcmp (Layer->Name, "route") == 0))
1094 gui->graphics->set_color (Output.fgGC, Layer->Color);
1095 gui->graphics->set_line_width (Output.fgGC, PCB->minWid);
1096 gui->graphics->draw_rect (Output.fgGC,
1097 0, 0,
1098 PCB->MaxWidth, PCB->MaxHeight);
1102 /* ---------------------------------------------------------------------------
1103 * draws one layer group. If the exporter is not a GUI,
1104 * also draws the pins / pads / vias in this layer group.
1106 void
1107 DrawLayerGroup (int group, const BoxType *drawn_area)
1109 int i, rv = 1;
1110 int layernum;
1111 LayerType *Layer;
1112 int n_entries = PCB->LayerGroups.Number[group];
1113 Cardinal *layers = PCB->LayerGroups.Entries[group];
1115 for (i = n_entries - 1; i >= 0; i--)
1117 layernum = layers[i];
1118 Layer = PCB->Data->Layer + layers[i];
1119 if (strcmp (Layer->Name, "outline") == 0 ||
1120 strcmp (Layer->Name, "route") == 0)
1121 rv = 0;
1122 if (layernum < max_copper_layer && Layer->On)
1123 DrawLayer (Layer, drawn_area);
1125 if (n_entries > 1)
1126 rv = 1;
1128 if (rv && !gui->gui)
1129 DrawPPV (group, drawn_area);
1132 static void
1133 GatherPVName (PinType *Ptr)
1135 BoxType box;
1136 bool vert = TEST_FLAG (EDGE2FLAG, Ptr);
1138 if (vert)
1140 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1141 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
1143 else
1145 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
1146 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1149 if (vert)
1151 box.X2 = box.X1;
1152 box.Y2 = box.Y1;
1154 else
1156 box.X2 = box.X1;
1157 box.Y2 = box.Y1;
1159 AddPart (&box);
1162 static void
1163 GatherPadName (PadType *Pad)
1165 BoxType box;
1166 bool vert;
1168 /* should text be vertical ? */
1169 vert = (Pad->Point1.X == Pad->Point2.X);
1171 if (vert)
1173 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1174 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1175 box.X1 += Settings.PinoutTextOffsetY;
1176 box.Y1 -= Settings.PinoutTextOffsetX;
1177 box.X2 = box.X1;
1178 box.Y2 = box.Y1;
1180 else
1182 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1183 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1184 box.X1 += Settings.PinoutTextOffsetX;
1185 box.Y1 += Settings.PinoutTextOffsetY;
1186 box.X2 = box.X1;
1187 box.Y2 = box.Y1;
1190 AddPart (&box);
1191 return;
1194 /* ---------------------------------------------------------------------------
1195 * lowlevel drawing routine for text objects
1197 void
1198 DrawTextLowLevel (TextType *Text, Coord min_line_width)
1200 Coord x = 0;
1201 unsigned char *string = (unsigned char *) Text->TextString;
1202 Cardinal n;
1203 FontType *font = &PCB->Font;
1205 while (string && *string)
1207 /* draw lines if symbol is valid and data is present */
1208 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid)
1210 LineType *line = font->Symbol[*string].Line;
1211 LineType newline;
1213 for (n = font->Symbol[*string].LineN; n; n--, line++)
1215 /* create one line, scale, move, rotate and swap it */
1216 newline = *line;
1217 newline.Point1.X = SCALE_TEXT (newline.Point1.X + x, Text->Scale);
1218 newline.Point1.Y = SCALE_TEXT (newline.Point1.Y, Text->Scale);
1219 newline.Point2.X = SCALE_TEXT (newline.Point2.X + x, Text->Scale);
1220 newline.Point2.Y = SCALE_TEXT (newline.Point2.Y, Text->Scale);
1221 newline.Thickness = SCALE_TEXT (newline.Thickness, Text->Scale / 2);
1222 if (newline.Thickness < min_line_width)
1223 newline.Thickness = min_line_width;
1225 RotateLineLowLevel (&newline, 0, 0, Text->Direction);
1227 /* the labels of SMD objects on the bottom
1228 * side haven't been swapped yet, only their offset
1230 if (TEST_FLAG (ONSOLDERFLAG, Text))
1232 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X);
1233 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y);
1234 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X);
1235 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y);
1237 /* add offset and draw line */
1238 newline.Point1.X += Text->X;
1239 newline.Point1.Y += Text->Y;
1240 newline.Point2.X += Text->X;
1241 newline.Point2.Y += Text->Y;
1242 _draw_line (&newline);
1245 /* move on to next cursor position */
1246 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta);
1248 else
1250 /* the default symbol is a filled box */
1251 BoxType defaultsymbol = PCB->Font.DefaultSymbol;
1252 Coord size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5;
1254 defaultsymbol.X1 = SCALE_TEXT (defaultsymbol.X1 + x, Text->Scale);
1255 defaultsymbol.Y1 = SCALE_TEXT (defaultsymbol.Y1, Text->Scale);
1256 defaultsymbol.X2 = SCALE_TEXT (defaultsymbol.X2 + x, Text->Scale);
1257 defaultsymbol.Y2 = SCALE_TEXT (defaultsymbol.Y2, Text->Scale);
1259 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction);
1261 /* add offset and draw box */
1262 defaultsymbol.X1 += Text->X;
1263 defaultsymbol.Y1 += Text->Y;
1264 defaultsymbol.X2 += Text->X;
1265 defaultsymbol.Y2 += Text->Y;
1266 gui->graphics->fill_rect (Output.fgGC,
1267 defaultsymbol.X1, defaultsymbol.Y1,
1268 defaultsymbol.X2, defaultsymbol.Y2);
1270 /* move on to next cursor position */
1271 x += size;
1273 string++;
1277 /* ---------------------------------------------------------------------------
1278 * draw a via object
1280 void
1281 DrawVia (PinType *Via)
1283 AddPart (Via);
1284 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1285 DrawViaName (Via);
1288 /* ---------------------------------------------------------------------------
1289 * draws the name of a via
1291 void
1292 DrawViaName (PinType *Via)
1294 GatherPVName (Via);
1297 /* ---------------------------------------------------------------------------
1298 * draw a pin object
1300 void
1301 DrawPin (PinType *Pin)
1303 AddPart (Pin);
1304 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1305 || doing_pinout)
1306 DrawPinName (Pin);
1309 /* ---------------------------------------------------------------------------
1310 * draws the name of a pin
1312 void
1313 DrawPinName (PinType *Pin)
1315 GatherPVName (Pin);
1318 /* ---------------------------------------------------------------------------
1319 * draw a pad object
1321 void
1322 DrawPad (PadType *Pad)
1324 AddPart (Pad);
1325 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1326 DrawPadName (Pad);
1329 /* ---------------------------------------------------------------------------
1330 * draws the name of a pad
1332 void
1333 DrawPadName (PadType *Pad)
1335 GatherPadName (Pad);
1338 /* ---------------------------------------------------------------------------
1339 * draws a line on a layer
1341 void
1342 DrawLine (LayerType *Layer, LineType *Line)
1344 AddPart (Line);
1347 /* ---------------------------------------------------------------------------
1348 * draws a ratline
1350 void
1351 DrawRat (RatType *Rat)
1353 if (Settings.RatThickness < 100)
1354 Rat->Thickness = pixel_slop * Settings.RatThickness;
1355 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1356 if (TEST_FLAG(VIAFLAG, Rat))
1358 Coord w = Rat->Thickness;
1360 BoxType b;
1362 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1363 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1364 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1365 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1366 AddPart (&b);
1368 else
1369 DrawLine (NULL, (LineType *)Rat);
1372 /* ---------------------------------------------------------------------------
1373 * draws an arc on a layer
1375 void
1376 DrawArc (LayerType *Layer, ArcType *Arc)
1378 AddPart (Arc);
1381 /* ---------------------------------------------------------------------------
1382 * draws a text on a layer
1384 void
1385 DrawText (LayerType *Layer, TextType *Text)
1387 AddPart (Text);
1391 /* ---------------------------------------------------------------------------
1392 * draws a polygon on a layer
1394 void
1395 DrawPolygon (LayerType *Layer, PolygonType *Polygon)
1397 AddPart (Polygon);
1400 /* ---------------------------------------------------------------------------
1401 * draws an element
1403 void
1404 DrawElement (ElementType *Element)
1406 DrawElementPackage (Element);
1407 DrawElementName (Element);
1408 DrawElementPinsAndPads (Element);
1411 /* ---------------------------------------------------------------------------
1412 * draws the name of an element
1414 void
1415 DrawElementName (ElementType *Element)
1417 if (TEST_FLAG (HIDENAMEFLAG, Element))
1418 return;
1419 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1422 /* ---------------------------------------------------------------------------
1423 * draws the package of an element
1425 void
1426 DrawElementPackage (ElementType *Element)
1428 ELEMENTLINE_LOOP (Element);
1430 DrawLine (NULL, line);
1432 END_LOOP;
1433 ARC_LOOP (Element);
1435 DrawArc (NULL, arc);
1437 END_LOOP;
1440 /* ---------------------------------------------------------------------------
1441 * draw pins of an element
1443 void
1444 DrawElementPinsAndPads (ElementType *Element)
1446 PAD_LOOP (Element);
1448 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
1449 DrawPad (pad);
1451 END_LOOP;
1452 PIN_LOOP (Element);
1454 DrawPin (pin);
1456 END_LOOP;
1459 /* ---------------------------------------------------------------------------
1460 * erase a via
1462 void
1463 EraseVia (PinType *Via)
1465 AddPart (Via);
1466 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
1467 EraseViaName (Via);
1470 /* ---------------------------------------------------------------------------
1471 * erase a ratline
1473 void
1474 EraseRat (RatType *Rat)
1476 if (TEST_FLAG(VIAFLAG, Rat))
1478 Coord w = Rat->Thickness;
1480 BoxType b;
1482 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1483 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1484 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1485 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1486 AddPart (&b);
1488 else
1489 EraseLine ((LineType *)Rat);
1493 /* ---------------------------------------------------------------------------
1494 * erase a via name
1496 void
1497 EraseViaName (PinType *Via)
1499 GatherPVName (Via);
1502 /* ---------------------------------------------------------------------------
1503 * erase a pad object
1505 void
1506 ErasePad (PadType *Pad)
1508 AddPart (Pad);
1509 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1510 ErasePadName (Pad);
1513 /* ---------------------------------------------------------------------------
1514 * erase a pad name
1516 void
1517 ErasePadName (PadType *Pad)
1519 GatherPadName (Pad);
1522 /* ---------------------------------------------------------------------------
1523 * erase a pin object
1525 void
1526 ErasePin (PinType *Pin)
1528 AddPart (Pin);
1529 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1530 ErasePinName (Pin);
1533 /* ---------------------------------------------------------------------------
1534 * erase a pin name
1536 void
1537 ErasePinName (PinType *Pin)
1539 GatherPVName (Pin);
1542 /* ---------------------------------------------------------------------------
1543 * erases a line on a layer
1545 void
1546 EraseLine (LineType *Line)
1548 AddPart (Line);
1551 /* ---------------------------------------------------------------------------
1552 * erases an arc on a layer
1554 void
1555 EraseArc (ArcType *Arc)
1557 if (!Arc->Thickness)
1558 return;
1559 AddPart (Arc);
1562 /* ---------------------------------------------------------------------------
1563 * erases a text on a layer
1565 void
1566 EraseText (LayerType *Layer, TextType *Text)
1568 AddPart (Text);
1571 /* ---------------------------------------------------------------------------
1572 * erases a polygon on a layer
1574 void
1575 ErasePolygon (PolygonType *Polygon)
1577 AddPart (Polygon);
1580 /* ---------------------------------------------------------------------------
1581 * erases an element
1583 void
1584 EraseElement (ElementType *Element)
1586 ELEMENTLINE_LOOP (Element);
1588 EraseLine (line);
1590 END_LOOP;
1591 ARC_LOOP (Element);
1593 EraseArc (arc);
1595 END_LOOP;
1596 EraseElementName (Element);
1597 EraseElementPinsAndPads (Element);
1600 /* ---------------------------------------------------------------------------
1601 * erases all pins and pads of an element
1603 void
1604 EraseElementPinsAndPads (ElementType *Element)
1606 PIN_LOOP (Element);
1608 ErasePin (pin);
1610 END_LOOP;
1611 PAD_LOOP (Element);
1613 ErasePad (pad);
1615 END_LOOP;
1618 /* ---------------------------------------------------------------------------
1619 * erases the name of an element
1621 void
1622 EraseElementName (ElementType *Element)
1624 if (TEST_FLAG (HIDENAMEFLAG, Element))
1625 return;
1626 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1630 void
1631 EraseObject (int type, void *lptr, void *ptr)
1633 switch (type)
1635 case VIA_TYPE:
1636 case PIN_TYPE:
1637 ErasePin ((PinType *) ptr);
1638 break;
1639 case TEXT_TYPE:
1640 case ELEMENTNAME_TYPE:
1641 EraseText ((LayerType *)lptr, (TextType *) ptr);
1642 break;
1643 case POLYGON_TYPE:
1644 ErasePolygon ((PolygonType *) ptr);
1645 break;
1646 case ELEMENT_TYPE:
1647 EraseElement ((ElementType *) ptr);
1648 break;
1649 case LINE_TYPE:
1650 case ELEMENTLINE_TYPE:
1651 case RATLINE_TYPE:
1652 EraseLine ((LineType *) ptr);
1653 break;
1654 case PAD_TYPE:
1655 ErasePad ((PadType *) ptr);
1656 break;
1657 case ARC_TYPE:
1658 case ELEMENTARC_TYPE:
1659 EraseArc ((ArcType *) ptr);
1660 break;
1661 default:
1662 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
1668 void
1669 DrawObject (int type, void *ptr1, void *ptr2)
1671 switch (type)
1673 case VIA_TYPE:
1674 if (PCB->ViaOn)
1675 DrawVia ((PinType *) ptr2);
1676 break;
1677 case LINE_TYPE:
1678 if (((LayerType *) ptr1)->On)
1679 DrawLine ((LayerType *) ptr1, (LineType *) ptr2);
1680 break;
1681 case ARC_TYPE:
1682 if (((LayerType *) ptr1)->On)
1683 DrawArc ((LayerType *) ptr1, (ArcType *) ptr2);
1684 break;
1685 case TEXT_TYPE:
1686 if (((LayerType *) ptr1)->On)
1687 DrawText ((LayerType *) ptr1, (TextType *) ptr2);
1688 break;
1689 case POLYGON_TYPE:
1690 if (((LayerType *) ptr1)->On)
1691 DrawPolygon ((LayerType *) ptr1, (PolygonType *) ptr2);
1692 break;
1693 case ELEMENT_TYPE:
1694 if (PCB->ElementOn &&
1695 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1696 DrawElement ((ElementType *) ptr2);
1697 break;
1698 case RATLINE_TYPE:
1699 if (PCB->RatOn)
1700 DrawRat ((RatType *) ptr2);
1701 break;
1702 case PIN_TYPE:
1703 if (PCB->PinOn)
1704 DrawPin ((PinType *) ptr2);
1705 break;
1706 case PAD_TYPE:
1707 if (PCB->PinOn)
1708 DrawPad ((PadType *) ptr2);
1709 break;
1710 case ELEMENTNAME_TYPE:
1711 if (PCB->ElementOn &&
1712 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1713 DrawElementName ((ElementType *) ptr1);
1714 break;
1718 static void
1719 draw_element (ElementType *element)
1721 draw_element_package (element);
1722 draw_element_name (element);
1723 draw_element_pins_and_pads (element);
1726 /* ---------------------------------------------------------------------------
1727 * HID drawing callback.
1730 void
1731 hid_expose_callback (HID * hid, BoxType * region, void *item)
1733 HID *old_gui = gui;
1735 gui = hid;
1736 Output.fgGC = gui->graphics->make_gc ();
1737 Output.bgGC = gui->graphics->make_gc ();
1738 Output.pmGC = gui->graphics->make_gc ();
1740 hid->graphics->set_color (Output.pmGC, "erase");
1741 hid->graphics->set_color (Output.bgGC, "drill");
1743 if (item)
1745 doing_pinout = true;
1746 draw_element ((ElementType *)item);
1747 doing_pinout = false;
1749 else
1750 DrawEverything (region);
1752 gui->graphics->destroy_gc (Output.fgGC);
1753 gui->graphics->destroy_gc (Output.bgGC);
1754 gui->graphics->destroy_gc (Output.pmGC);
1755 gui = old_gui;