Move _draw_arc() routine from draw.c into HID_DRAW API
[geda-pcb/pcjc2.git] / src / draw.c
blob1e4860297509c9ec30f80d5258acf463788216ab
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"
36 #include "hid_draw.h"
38 /*#include "clip.h"*/
39 #include "compat.h"
40 #include "crosshair.h"
41 #include "data.h"
42 #include "draw.h"
43 #include "error.h"
44 #include "mymem.h"
45 #include "misc.h"
46 #include "rotate.h"
47 #include "rtree.h"
48 #include "search.h"
49 #include "select.h"
50 #include "print.h"
52 #ifdef HAVE_LIBDMALLOC
53 #include <dmalloc.h>
54 #endif
56 #undef NDEBUG
57 #include <assert.h>
59 #ifndef MAXINT
60 #define MAXINT (((unsigned int)(~0))>>1)
61 #endif
63 #define SMALL_SMALL_TEXT_SIZE 0
64 #define SMALL_TEXT_SIZE 1
65 #define NORMAL_TEXT_SIZE 2
66 #define LARGE_TEXT_SIZE 3
67 #define N_TEXT_SIZES 4
70 /* ---------------------------------------------------------------------------
71 * some local identifiers
73 static BoxType Block = {MAXINT, MAXINT, -MAXINT, -MAXINT};
75 static int doing_pinout = 0;
76 static bool doing_assy = false;
78 /* ---------------------------------------------------------------------------
79 * some local prototypes
81 static void DrawEverything (const BoxType *);
82 static void DrawPPV (int group, const BoxType *);
83 static void AddPart (void *);
84 static void DrawEMark (ElementType *, Coord, Coord, bool);
85 static void DrawRats (const BoxType *);
87 static void
88 set_object_color (AnyObjectType *obj,
89 char *warn_color, char *selected_color,
90 char *found_color, char *normal_color)
92 char *color;
94 if (warn_color != NULL && TEST_FLAG (WARNFLAG, obj)) color = warn_color;
95 else if (selected_color != NULL && TEST_FLAG (SELECTEDFLAG, obj)) color = selected_color;
96 else if (found_color != NULL && TEST_FLAG (FOUNDFLAG, obj)) color = found_color;
97 else color = normal_color;
99 gui->graphics->set_color (Output.fgGC, color);
102 static void
103 set_layer_object_color (LayerType *layer, AnyObjectType *obj)
105 set_object_color (obj, NULL, layer->SelectedColor, PCB->ConnectedColor, layer->Color);
108 /*---------------------------------------------------------------------------
109 * Adds the update rect to the update region
111 static void
112 AddPart (void *b)
114 BoxType *box = (BoxType *) b;
116 Block.X1 = MIN (Block.X1, box->X1);
117 Block.X2 = MAX (Block.X2, box->X2);
118 Block.Y1 = MIN (Block.Y1, box->Y1);
119 Block.Y2 = MAX (Block.Y2, box->Y2);
123 * initiate the actual redrawing of the updated area
125 void
126 Draw (void)
128 if (Block.X1 <= Block.X2 && Block.Y1 <= Block.Y2)
129 gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2);
131 /* shrink the update block */
132 Block.X1 = Block.Y1 = MAXINT;
133 Block.X2 = Block.Y2 = -MAXINT;
136 /* ----------------------------------------------------------------------
137 * redraws all the data by the event handlers
139 void
140 Redraw (void)
142 gui->invalidate_all ();
145 static void
146 _draw_pv_name (PinType *pv)
148 BoxType box;
149 bool vert;
150 TextType text;
152 if (!pv->Name || !pv->Name[0])
153 text.TextString = EMPTY (pv->Number);
154 else
155 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pv->Number : pv->Name);
157 vert = TEST_FLAG (EDGE2FLAG, pv);
159 if (vert)
161 box.X1 = pv->X - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
162 box.Y1 = pv->Y - pv->DrillingHole / 2 - Settings.PinoutTextOffsetX;
164 else
166 box.X1 = pv->X + pv->DrillingHole / 2 + Settings.PinoutTextOffsetX;
167 box.Y1 = pv->Y - pv->Thickness / 2 + Settings.PinoutTextOffsetY;
170 gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);
172 text.Flags = NoFlags ();
173 /* Set font height to approx 56% of pin thickness */
174 text.Scale = 56 * pv->Thickness / FONT_CAPHEIGHT;
175 text.X = box.X1;
176 text.Y = box.Y1;
177 text.Direction = vert ? 1 : 0;
179 if (gui->gui)
180 doing_pinout++;
181 DrawTextLowLevel (Output.fgGC, &text, 0);
182 if (gui->gui)
183 doing_pinout--;
186 static void
187 _draw_pv (PinType *pv, bool draw_hole)
189 if (TEST_FLAG (THINDRAWFLAG, PCB))
190 gui->graphics->thindraw_pcb_pv (Output.fgGC, Output.fgGC, pv, draw_hole, false);
191 else
192 gui->graphics->fill_pcb_pv (Output.fgGC, Output.bgGC, pv, draw_hole, false);
194 if (!TEST_FLAG (HOLEFLAG, pv) && TEST_FLAG (DISPLAYNAMEFLAG, pv))
195 _draw_pv_name (pv);
198 static void
199 draw_pin (PinType *pin, bool draw_hole)
201 if (doing_pinout)
202 gui->graphics->set_color (Output.fgGC, PCB->PinColor);
203 else
204 set_object_color ((AnyObjectType *)pin,
205 PCB->WarnColor, PCB->PinSelectedColor,
206 PCB->ConnectedColor, PCB->PinColor);
208 _draw_pv (pin, draw_hole);
211 static int
212 pin_callback (const BoxType * b, void *cl)
214 draw_pin ((PinType *)b, false);
215 return 1;
218 static void
219 draw_via (PinType *via, bool draw_hole)
221 if (doing_pinout)
222 gui->graphics->set_color (Output.fgGC, PCB->ViaColor);
223 else
224 set_object_color ((AnyObjectType *)via,
225 PCB->WarnColor, PCB->ViaSelectedColor,
226 PCB->ConnectedColor, PCB->ViaColor);
228 _draw_pv (via, draw_hole);
231 static int
232 via_callback (const BoxType * b, void *cl)
234 draw_via ((PinType *)b, false);
235 return 1;
238 static void
239 draw_pad_name (PadType *pad)
241 BoxType box;
242 bool vert;
243 TextType text;
245 if (!pad->Name || !pad->Name[0])
246 text.TextString = EMPTY (pad->Number);
247 else
248 text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pad->Number : pad->Name);
250 /* should text be vertical ? */
251 vert = (pad->Point1.X == pad->Point2.X);
253 if (vert)
255 box.X1 = pad->Point1.X - pad->Thickness / 2;
256 box.Y1 = MAX (pad->Point1.Y, pad->Point2.Y) + pad->Thickness / 2;
257 box.X1 += Settings.PinoutTextOffsetY;
258 box.Y1 -= Settings.PinoutTextOffsetX;
260 else
262 box.X1 = MIN (pad->Point1.X, pad->Point2.X) - pad->Thickness / 2;
263 box.Y1 = pad->Point1.Y - pad->Thickness / 2;
264 box.X1 += Settings.PinoutTextOffsetX;
265 box.Y1 += Settings.PinoutTextOffsetY;
268 gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);
270 text.Flags = NoFlags ();
271 /* Set font height to approx 90% of pin thickness */
272 text.Scale = 90 * pad->Thickness / FONT_CAPHEIGHT;
273 text.X = box.X1;
274 text.Y = box.Y1;
275 text.Direction = vert ? 1 : 0;
277 DrawTextLowLevel (Output.fgGC, &text, 0);
280 static void
281 _draw_pad (hidGC gc, PadType *pad, bool clear, bool mask)
283 if (clear && !mask && pad->Clearance <= 0)
284 return;
286 if (TEST_FLAG (THINDRAWFLAG, PCB) ||
287 (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
288 gui->graphics->thindraw_pcb_pad (gc, pad, clear, mask);
289 else
290 gui->graphics->fill_pcb_pad (gc, pad, clear, mask);
293 static void
294 draw_pad (PadType *pad)
296 if (doing_pinout)
297 gui->graphics->set_color (Output.fgGC, PCB->PinColor);
298 else
299 set_object_color ((AnyObjectType *)pad, PCB->WarnColor,
300 PCB->PinSelectedColor, PCB->ConnectedColor,
301 FRONT (pad) ? PCB->PinColor : PCB->InvisibleObjectsColor);
303 _draw_pad (Output.fgGC, pad, false, false);
305 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, pad))
306 draw_pad_name (pad);
309 static int
310 pad_callback (const BoxType * b, void *cl)
312 PadType *pad = (PadType *) b;
313 int *side = cl;
315 if (ON_SIDE (pad, *side))
316 draw_pad (pad);
317 return 1;
320 static void
321 draw_element_name (ElementType *element)
323 if ((TEST_FLAG (HIDENAMESFLAG, PCB) && gui->gui) ||
324 TEST_FLAG (HIDENAMEFLAG, element))
325 return;
326 if (doing_pinout || doing_assy)
327 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
328 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
329 gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor);
330 else if (FRONT (element))
331 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
332 else
333 gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
334 DrawTextLowLevel (Output.fgGC, &ELEMENT_TEXT (PCB, element), PCB->minSlk);
337 static int
338 name_callback (const BoxType * b, void *cl)
340 TextType *text = (TextType *) b;
341 ElementType *element = (ElementType *) text->Element;
342 int *side = cl;
344 if (TEST_FLAG (HIDENAMEFLAG, element))
345 return 0;
347 if (ON_SIDE (element, *side))
348 draw_element_name (element);
349 return 0;
352 static void
353 draw_element_pins_and_pads (ElementType *element)
355 PAD_LOOP (element);
357 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
358 draw_pad (pad);
360 END_LOOP;
361 PIN_LOOP (element);
363 draw_pin (pin, true);
365 END_LOOP;
368 static int
369 EMark_callback (const BoxType * b, void *cl)
371 ElementType *element = (ElementType *) b;
373 DrawEMark (element, element->MarkX, element->MarkY, !FRONT (element));
374 return 1;
377 static int
378 hole_callback (const BoxType * b, void *cl)
380 PinType *pv = (PinType *) b;
381 int plated = cl ? *(int *) cl : -1;
383 if ((plated == 0 && !TEST_FLAG (HOLEFLAG, pv)) ||
384 (plated == 1 && TEST_FLAG (HOLEFLAG, pv)))
385 return 1;
387 if (TEST_FLAG (THINDRAWFLAG, PCB))
389 if (!TEST_FLAG (HOLEFLAG, pv))
391 gui->graphics->set_line_cap (Output.fgGC, Round_Cap);
392 gui->graphics->set_line_width (Output.fgGC, 0);
393 gui->graphics->draw_arc (Output.fgGC,
394 pv->X, pv->Y, pv->DrillingHole / 2,
395 pv->DrillingHole / 2, 0, 360);
398 else
399 gui->graphics->fill_circle (Output.bgGC, pv->X, pv->Y, pv->DrillingHole / 2);
401 if (TEST_FLAG (HOLEFLAG, pv))
403 set_object_color ((AnyObjectType *) pv,
404 PCB->WarnColor, PCB->ViaSelectedColor,
405 NULL, Settings.BlackColor);
407 gui->graphics->set_line_cap (Output.fgGC, Round_Cap);
408 gui->graphics->set_line_width (Output.fgGC, 0);
409 gui->graphics->draw_arc (Output.fgGC,
410 pv->X, pv->Y, pv->DrillingHole / 2,
411 pv->DrillingHole / 2, 0, 360);
413 return 1;
416 void
417 DrawHoles (bool draw_plated, bool draw_unplated, const BoxType *drawn_area)
419 int plated = -1;
421 if ( draw_plated && !draw_unplated) plated = 1;
422 if (!draw_plated && draw_unplated) plated = 0;
424 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, &plated);
425 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, &plated);
428 static void
429 draw_line (LayerType *layer, LineType *line)
431 set_layer_object_color (layer, (AnyObjectType *) line);
432 gui->graphics->draw_pcb_line (Output.fgGC, line);
435 static int
436 line_callback (const BoxType * b, void *cl)
438 draw_line ((LayerType *) cl, (LineType *) b);
439 return 1;
442 static int
443 rat_callback (const BoxType * b, void *cl)
445 RatType *rat = (RatType *)b;
447 set_object_color ((AnyObjectType *) rat, NULL, PCB->RatSelectedColor,
448 PCB->ConnectedColor, PCB->RatColor);
450 if (Settings.RatThickness < 100)
451 rat->Thickness = pixel_slop * Settings.RatThickness;
452 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
453 if (TEST_FLAG(VIAFLAG, rat))
455 int w = rat->Thickness;
457 if (TEST_FLAG (THINDRAWFLAG, PCB))
458 gui->graphics->set_line_width (Output.fgGC, 0);
459 else
460 gui->graphics->set_line_width (Output.fgGC, w);
461 gui->graphics->draw_arc (Output.fgGC, rat->Point1.X, rat->Point1.Y,
462 w * 2, w * 2, 0, 360);
464 else
465 gui->graphics->draw_pcb_line (Output.fgGC, (LineType *) rat);
466 return 1;
469 static void
470 draw_arc (LayerType *layer, ArcType *arc)
472 set_layer_object_color (layer, (AnyObjectType *) arc);
473 gui->graphics->draw_pcb_arc (Output.fgGC, arc);
476 static int
477 arc_callback (const BoxType * b, void *cl)
479 draw_arc ((LayerType *) cl, (ArcType *) b);
480 return 1;
483 static void
484 draw_element_package (ElementType *element)
486 /* set color and draw lines, arcs, text and pins */
487 if (doing_pinout || doing_assy)
488 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
489 else if (TEST_FLAG (SELECTEDFLAG, element))
490 gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor);
491 else if (FRONT (element))
492 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
493 else
494 gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
496 /* draw lines, arcs, text and pins */
497 ELEMENTLINE_LOOP (element);
499 gui->graphics->draw_pcb_line (Output.fgGC, line);
501 END_LOOP;
502 ARC_LOOP (element);
504 gui->graphics->draw_pcb_arc (Output.fgGC, arc);
506 END_LOOP;
509 static int
510 element_callback (const BoxType * b, void *cl)
512 ElementType *element = (ElementType *) b;
513 int *side = cl;
515 if (ON_SIDE (element, *side))
516 draw_element_package (element);
517 return 1;
520 /* ---------------------------------------------------------------------------
521 * prints assembly drawing.
524 void
525 PrintAssembly (int side, const BoxType * drawn_area)
527 int side_group = GetLayerGroupNumberByNumber (max_copper_layer + side);
529 doing_assy = true;
530 gui->graphics->set_draw_faded (Output.fgGC, 1);
531 DrawLayerGroup (side_group, drawn_area);
532 gui->graphics->set_draw_faded (Output.fgGC, 0);
534 /* draw package */
535 DrawSilk (side, drawn_area);
536 doing_assy = false;
539 /* ---------------------------------------------------------------------------
540 * initializes some identifiers for a new zoom factor and redraws whole screen
542 static void
543 DrawEverything (const BoxType *drawn_area)
545 int i, ngroups, side;
546 int component, solder;
547 /* This is the list of layer groups we will draw. */
548 int do_group[MAX_LAYER];
549 /* This is the reverse of the order in which we draw them. */
550 int drawn_groups[MAX_LAYER];
551 int plated, unplated;
552 bool paste_empty;
554 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
555 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
557 memset (do_group, 0, sizeof (do_group));
558 for (ngroups = 0, i = 0; i < max_copper_layer; i++)
560 LayerType *l = LAYER_ON_STACK (i);
561 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
562 if (l->On && !do_group[group])
564 do_group[group] = 1;
565 drawn_groups[ngroups++] = group;
569 component = GetLayerGroupNumberByNumber (component_silk_layer);
570 solder = GetLayerGroupNumberByNumber (solder_silk_layer);
573 * first draw all 'invisible' stuff
575 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
576 && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
578 side = SWAP_IDENT ? COMPONENT_LAYER : SOLDER_LAYER;
579 if (PCB->ElementOn)
581 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
582 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
583 DrawLayer (&(PCB->Data->Layer[max_copper_layer + side]), drawn_area);
585 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
586 gui->end_layer ();
589 /* draw all layers in layerstack order */
590 for (i = ngroups - 1; i >= 0; i--)
592 int group = drawn_groups[i];
594 if (gui->set_layer (0, group, 0))
596 DrawLayerGroup (group, drawn_area);
597 gui->end_layer ();
601 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
602 return;
604 /* Draw pins, pads, vias below silk */
605 if (gui->gui)
606 DrawPPV (SWAP_IDENT ? solder : component, drawn_area);
607 else
609 CountHoles (&plated, &unplated, drawn_area);
611 if (plated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
613 DrawHoles (true, false, drawn_area);
614 gui->end_layer ();
617 if (unplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
619 DrawHoles (false, true, drawn_area);
620 gui->end_layer ();
624 /* Draw the solder mask if turned on */
625 if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
627 DrawMask (COMPONENT_LAYER, drawn_area);
628 gui->end_layer ();
631 if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
633 DrawMask (SOLDER_LAYER, drawn_area);
634 gui->end_layer ();
637 if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
639 DrawSilk (COMPONENT_LAYER, drawn_area);
640 gui->end_layer ();
643 if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
645 DrawSilk (SOLDER_LAYER, drawn_area);
646 gui->end_layer ();
649 if (gui->gui)
651 /* Draw element Marks */
652 if (PCB->PinOn)
653 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
654 NULL);
655 /* Draw rat lines on top */
656 if (gui->set_layer ("rats", SL (RATS, 0), 0))
658 DrawRats(drawn_area);
659 gui->end_layer ();
663 paste_empty = IsPasteEmpty (COMPONENT_LAYER);
664 if (gui->set_layer ("toppaste", SL (PASTE, TOP), paste_empty))
666 DrawPaste (COMPONENT_LAYER, drawn_area);
667 gui->end_layer ();
670 paste_empty = IsPasteEmpty (SOLDER_LAYER);
671 if (gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), paste_empty))
673 DrawPaste (SOLDER_LAYER, drawn_area);
674 gui->end_layer ();
677 if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
679 PrintAssembly (COMPONENT_LAYER, drawn_area);
680 gui->end_layer ();
683 if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
685 PrintAssembly (SOLDER_LAYER, drawn_area);
686 gui->end_layer ();
689 if (gui->set_layer ("fab", SL (FAB, 0), 0))
691 PrintFab (Output.fgGC);
692 gui->end_layer ();
696 static void
697 DrawEMark (ElementType *e, Coord X, Coord Y, bool invisible)
699 Coord mark_size = EMARK_SIZE;
700 if (!PCB->InvisibleObjectsOn && invisible)
701 return;
703 if (e->Pin != NULL)
705 PinType *pin0 = e->Pin->data;
706 if (TEST_FLAG (HOLEFLAG, pin0))
707 mark_size = MIN (mark_size, pin0->DrillingHole / 2);
708 else
709 mark_size = MIN (mark_size, pin0->Thickness / 2);
712 if (e->Pad != NULL)
714 PadType *pad0 = e->Pad->data;
715 mark_size = MIN (mark_size, pad0->Thickness / 2);
718 gui->graphics->set_color (Output.fgGC,
719 invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
720 gui->graphics->set_line_cap (Output.fgGC, Trace_Cap);
721 gui->graphics->set_line_width (Output.fgGC, 0);
722 gui->graphics->draw_line (Output.fgGC, X - mark_size, Y, X, Y - mark_size);
723 gui->graphics->draw_line (Output.fgGC, X + mark_size, Y, X, Y - mark_size);
724 gui->graphics->draw_line (Output.fgGC, X - mark_size, Y, X, Y + mark_size);
725 gui->graphics->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
728 * If an element is locked, place a "L" on top of the "diamond".
729 * This provides a nice visual indication that it is locked that
730 * works even for color blind users.
732 if (TEST_FLAG (LOCKFLAG, e) )
734 gui->graphics->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
735 gui->graphics->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
739 /* ---------------------------------------------------------------------------
740 * Draws pins pads and vias - Always draws for non-gui HIDs,
741 * otherwise drawing depends on PCB->PinOn and PCB->ViaOn
743 static void
744 DrawPPV (int group, const BoxType *drawn_area)
746 int component_group = GetLayerGroupNumberByNumber (component_silk_layer);
747 int solder_group = GetLayerGroupNumberByNumber (solder_silk_layer);
748 int side;
750 if (PCB->PinOn || !gui->gui)
752 /* draw element pins */
753 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback, NULL);
755 /* draw element pads */
756 if (group == component_group)
758 side = COMPONENT_LAYER;
759 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
762 if (group == solder_group)
764 side = SOLDER_LAYER;
765 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
769 /* draw vias */
770 if (PCB->ViaOn || !gui->gui)
772 r_search (PCB->Data->via_tree, drawn_area, NULL, via_callback, NULL);
773 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, NULL);
775 if (PCB->PinOn || doing_assy)
776 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, NULL);
779 static int
780 clearPin_callback (const BoxType * b, void *cl)
782 PinType *pin = (PinType *) b;
783 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
784 gui->graphics->thindraw_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
785 else
786 gui->graphics->fill_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
787 return 1;
790 struct poly_info {
791 const BoxType *drawn_area;
792 LayerType *layer;
795 static int
796 poly_callback (const BoxType * b, void *cl)
798 struct poly_info *i = cl;
799 PolygonType *polygon = (PolygonType *)b;
801 if (!polygon->Clipped)
802 return 0;
804 set_layer_object_color (i->layer, (AnyObjectType *) polygon);
806 if (gui->graphics->thindraw_pcb_polygon != NULL &&
807 (TEST_FLAG (THINDRAWFLAG, PCB) ||
808 TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
809 gui->graphics->thindraw_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
810 else
811 gui->graphics->fill_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
813 /* If checking planes, thin-draw any pieces which have been clipped away */
814 if (gui->graphics->thindraw_pcb_polygon != NULL &&
815 TEST_FLAG (CHECKPLANESFLAG, PCB) &&
816 !TEST_FLAG (FULLPOLYFLAG, polygon))
818 PolygonType poly = *polygon;
820 for (poly.Clipped = polygon->Clipped->f;
821 poly.Clipped != polygon->Clipped;
822 poly.Clipped = poly.Clipped->f)
823 gui->graphics->thindraw_pcb_polygon (Output.fgGC, &poly, i->drawn_area);
826 return 1;
829 static int
830 clearPad_callback (const BoxType * b, void *cl)
832 PadType *pad = (PadType *) b;
833 int *side = cl;
834 if (ON_SIDE (pad, *side) && pad->Mask)
835 _draw_pad (Output.pmGC, pad, true, true);
836 return 1;
839 /* ---------------------------------------------------------------------------
840 * Draws silk layer.
843 void
844 DrawSilk (int side, const BoxType * drawn_area)
846 #if 0
847 /* This code is used when you want to mask silk to avoid exposed
848 pins and pads. We decided it was a bad idea to do this
849 unconditionally, but the code remains. */
850 #endif
852 #if 0
853 if (gui->poly_before)
855 gui->graphics->use_mask (HID_MASK_BEFORE);
856 #endif
857 DrawLayer (LAYER_PTR (max_copper_layer + side), drawn_area);
858 /* draw package */
859 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
860 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
861 #if 0
864 gui->graphics->use_mask (HID_MASK_CLEAR);
865 r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, NULL);
866 r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, NULL);
867 r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &side);
869 if (gui->poly_after)
871 gui->graphics->use_mask (HID_MASK_AFTER);
872 DrawLayer (LAYER_PTR (max_copper_layer + layer), drawn_area);
873 /* draw package */
874 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
875 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
877 gui->graphics->use_mask (HID_MASK_OFF);
878 #endif
882 static void
883 DrawMaskBoardArea (int mask_type, const BoxType *drawn_area)
885 /* Skip the mask drawing if the GUI doesn't want this type */
886 if ((mask_type == HID_MASK_BEFORE && !gui->poly_before) ||
887 (mask_type == HID_MASK_AFTER && !gui->poly_after))
888 return;
890 gui->graphics->use_mask (mask_type);
891 gui->graphics->set_color (Output.fgGC, PCB->MaskColor);
892 if (drawn_area == NULL)
893 gui->graphics->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
894 else
895 gui->graphics->fill_rect (Output.fgGC, drawn_area->X1, drawn_area->Y1,
896 drawn_area->X2, drawn_area->Y2);
899 /* ---------------------------------------------------------------------------
900 * draws solder mask layer - this will cover nearly everything
902 void
903 DrawMask (int side, const BoxType *screen)
905 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
907 if (thin)
908 gui->graphics->set_color (Output.pmGC, PCB->MaskColor);
909 else
911 DrawMaskBoardArea (HID_MASK_BEFORE, screen);
912 gui->graphics->use_mask (HID_MASK_CLEAR);
915 r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, NULL);
916 r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, NULL);
917 r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &side);
919 if (thin)
920 gui->graphics->set_color (Output.pmGC, "erase");
921 else
923 DrawMaskBoardArea (HID_MASK_AFTER, screen);
924 gui->graphics->use_mask (HID_MASK_OFF);
928 /* ---------------------------------------------------------------------------
929 * draws solder paste layer for a given side of the board
931 void
932 DrawPaste (int side, const BoxType *drawn_area)
934 gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
935 ALLPAD_LOOP (PCB->Data);
937 if (ON_SIDE (pad, side) && !TEST_FLAG (NOPASTEFLAG, pad) && pad->Mask > 0)
939 if (pad->Mask < pad->Thickness)
940 _draw_pad (Output.fgGC, pad, true, true);
941 else
942 _draw_pad (Output.fgGC, pad, false, false);
945 ENDALL_LOOP;
948 static void
949 DrawRats (const BoxType *drawn_area)
952 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
953 * XXX gtk only allows negative drawing.
954 * XXX using the mask here is to get rat transparency
956 int can_mask = strcmp(gui->name, "lesstif") == 0;
958 if (can_mask)
959 gui->graphics->use_mask (HID_MASK_CLEAR);
960 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
961 if (can_mask)
962 gui->graphics->use_mask (HID_MASK_OFF);
965 static int
966 text_callback (const BoxType * b, void *cl)
968 LayerType *layer = cl;
969 TextType *text = (TextType *)b;
970 int min_silk_line;
972 if (TEST_FLAG (SELECTEDFLAG, text))
973 gui->graphics->set_color (Output.fgGC, layer->SelectedColor);
974 else
975 gui->graphics->set_color (Output.fgGC, layer->Color);
976 if (layer == &PCB->Data->SILKLAYER ||
977 layer == &PCB->Data->BACKSILKLAYER)
978 min_silk_line = PCB->minSlk;
979 else
980 min_silk_line = PCB->minWid;
981 DrawTextLowLevel (Output.fgGC, text, min_silk_line);
982 return 1;
985 void
986 DrawLayer (LayerType *Layer, const BoxType *screen)
988 struct poly_info info = {screen, Layer};
990 /* print the non-clearing polys */
991 r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
993 if (TEST_FLAG (CHECKPLANESFLAG, PCB))
994 return;
996 /* draw all visible lines this layer */
997 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
999 /* draw the layer arcs on screen */
1000 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
1002 /* draw the layer text on screen */
1003 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
1005 /* We should check for gui->gui here, but it's kinda cool seeing the
1006 auto-outline magically disappear when you first add something to
1007 the "outline" layer. */
1008 if (IsLayerEmpty (Layer)
1009 && (strcmp (Layer->Name, "outline") == 0
1010 || strcmp (Layer->Name, "route") == 0))
1012 gui->graphics->set_color (Output.fgGC, Layer->Color);
1013 gui->graphics->set_line_width (Output.fgGC, PCB->minWid);
1014 gui->graphics->draw_rect (Output.fgGC,
1015 0, 0,
1016 PCB->MaxWidth, PCB->MaxHeight);
1020 /* ---------------------------------------------------------------------------
1021 * draws one layer group. If the exporter is not a GUI,
1022 * also draws the pins / pads / vias in this layer group.
1024 void
1025 DrawLayerGroup (int group, const BoxType *drawn_area)
1027 int i, rv = 1;
1028 int layernum;
1029 LayerType *Layer;
1030 int n_entries = PCB->LayerGroups.Number[group];
1031 Cardinal *layers = PCB->LayerGroups.Entries[group];
1033 for (i = n_entries - 1; i >= 0; i--)
1035 layernum = layers[i];
1036 Layer = PCB->Data->Layer + layers[i];
1037 if (strcmp (Layer->Name, "outline") == 0 ||
1038 strcmp (Layer->Name, "route") == 0)
1039 rv = 0;
1040 if (layernum < max_copper_layer && Layer->On)
1041 DrawLayer (Layer, drawn_area);
1043 if (n_entries > 1)
1044 rv = 1;
1046 if (rv && !gui->gui)
1047 DrawPPV (group, drawn_area);
1050 static void
1051 GatherPVName (PinType *Ptr)
1053 BoxType box;
1054 bool vert = TEST_FLAG (EDGE2FLAG, Ptr);
1056 if (vert)
1058 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1059 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
1061 else
1063 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
1064 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1067 if (vert)
1069 box.X2 = box.X1;
1070 box.Y2 = box.Y1;
1072 else
1074 box.X2 = box.X1;
1075 box.Y2 = box.Y1;
1077 AddPart (&box);
1080 static void
1081 GatherPadName (PadType *Pad)
1083 BoxType box;
1084 bool vert;
1086 /* should text be vertical ? */
1087 vert = (Pad->Point1.X == Pad->Point2.X);
1089 if (vert)
1091 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1092 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1093 box.X1 += Settings.PinoutTextOffsetY;
1094 box.Y1 -= Settings.PinoutTextOffsetX;
1095 box.X2 = box.X1;
1096 box.Y2 = box.Y1;
1098 else
1100 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1101 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1102 box.X1 += Settings.PinoutTextOffsetX;
1103 box.Y1 += Settings.PinoutTextOffsetY;
1104 box.X2 = box.X1;
1105 box.Y2 = box.Y1;
1108 AddPart (&box);
1109 return;
1112 /* ---------------------------------------------------------------------------
1113 * lowlevel drawing routine for text objects
1115 void
1116 DrawTextLowLevel (hidGC gc, TextType *Text, Coord min_line_width)
1118 Coord x = 0;
1119 unsigned char *string = (unsigned char *) Text->TextString;
1120 Cardinal n;
1121 FontType *font = &PCB->Font;
1123 while (string && *string)
1125 /* draw lines if symbol is valid and data is present */
1126 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid)
1128 LineType *line = font->Symbol[*string].Line;
1129 LineType newline;
1131 for (n = font->Symbol[*string].LineN; n; n--, line++)
1133 /* create one line, scale, move, rotate and swap it */
1134 newline = *line;
1135 newline.Point1.X = SCALE_TEXT (newline.Point1.X + x, Text->Scale);
1136 newline.Point1.Y = SCALE_TEXT (newline.Point1.Y, Text->Scale);
1137 newline.Point2.X = SCALE_TEXT (newline.Point2.X + x, Text->Scale);
1138 newline.Point2.Y = SCALE_TEXT (newline.Point2.Y, Text->Scale);
1139 newline.Thickness = SCALE_TEXT (newline.Thickness, Text->Scale / 2);
1140 if (newline.Thickness < min_line_width)
1141 newline.Thickness = min_line_width;
1143 RotateLineLowLevel (&newline, 0, 0, Text->Direction);
1145 /* the labels of SMD objects on the bottom
1146 * side haven't been swapped yet, only their offset
1148 if (TEST_FLAG (ONSOLDERFLAG, Text))
1150 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X);
1151 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y);
1152 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X);
1153 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y);
1155 /* add offset and draw line */
1156 newline.Point1.X += Text->X;
1157 newline.Point1.Y += Text->Y;
1158 newline.Point2.X += Text->X;
1159 newline.Point2.Y += Text->Y;
1160 gui->graphics->draw_pcb_line (gc, &newline);
1163 /* move on to next cursor position */
1164 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta);
1166 else
1168 /* the default symbol is a filled box */
1169 BoxType defaultsymbol = PCB->Font.DefaultSymbol;
1170 Coord size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5;
1172 defaultsymbol.X1 = SCALE_TEXT (defaultsymbol.X1 + x, Text->Scale);
1173 defaultsymbol.Y1 = SCALE_TEXT (defaultsymbol.Y1, Text->Scale);
1174 defaultsymbol.X2 = SCALE_TEXT (defaultsymbol.X2 + x, Text->Scale);
1175 defaultsymbol.Y2 = SCALE_TEXT (defaultsymbol.Y2, Text->Scale);
1177 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction);
1179 /* add offset and draw box */
1180 defaultsymbol.X1 += Text->X;
1181 defaultsymbol.Y1 += Text->Y;
1182 defaultsymbol.X2 += Text->X;
1183 defaultsymbol.Y2 += Text->Y;
1184 gui->graphics->fill_rect (gc,
1185 defaultsymbol.X1, defaultsymbol.Y1,
1186 defaultsymbol.X2, defaultsymbol.Y2);
1188 /* move on to next cursor position */
1189 x += size;
1191 string++;
1195 /* ---------------------------------------------------------------------------
1196 * draw a via object
1198 void
1199 DrawVia (PinType *Via)
1201 AddPart (Via);
1202 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1203 DrawViaName (Via);
1206 /* ---------------------------------------------------------------------------
1207 * draws the name of a via
1209 void
1210 DrawViaName (PinType *Via)
1212 GatherPVName (Via);
1215 /* ---------------------------------------------------------------------------
1216 * draw a pin object
1218 void
1219 DrawPin (PinType *Pin)
1221 AddPart (Pin);
1222 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1223 || doing_pinout)
1224 DrawPinName (Pin);
1227 /* ---------------------------------------------------------------------------
1228 * draws the name of a pin
1230 void
1231 DrawPinName (PinType *Pin)
1233 GatherPVName (Pin);
1236 /* ---------------------------------------------------------------------------
1237 * draw a pad object
1239 void
1240 DrawPad (PadType *Pad)
1242 AddPart (Pad);
1243 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1244 DrawPadName (Pad);
1247 /* ---------------------------------------------------------------------------
1248 * draws the name of a pad
1250 void
1251 DrawPadName (PadType *Pad)
1253 GatherPadName (Pad);
1256 /* ---------------------------------------------------------------------------
1257 * draws a line on a layer
1259 void
1260 DrawLine (LayerType *Layer, LineType *Line)
1262 AddPart (Line);
1265 /* ---------------------------------------------------------------------------
1266 * draws a ratline
1268 void
1269 DrawRat (RatType *Rat)
1271 if (Settings.RatThickness < 100)
1272 Rat->Thickness = pixel_slop * Settings.RatThickness;
1273 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1274 if (TEST_FLAG(VIAFLAG, Rat))
1276 Coord w = Rat->Thickness;
1278 BoxType b;
1280 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1281 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1282 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1283 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1284 AddPart (&b);
1286 else
1287 DrawLine (NULL, (LineType *)Rat);
1290 /* ---------------------------------------------------------------------------
1291 * draws an arc on a layer
1293 void
1294 DrawArc (LayerType *Layer, ArcType *Arc)
1296 AddPart (Arc);
1299 /* ---------------------------------------------------------------------------
1300 * draws a text on a layer
1302 void
1303 DrawText (LayerType *Layer, TextType *Text)
1305 AddPart (Text);
1309 /* ---------------------------------------------------------------------------
1310 * draws a polygon on a layer
1312 void
1313 DrawPolygon (LayerType *Layer, PolygonType *Polygon)
1315 AddPart (Polygon);
1318 /* ---------------------------------------------------------------------------
1319 * draws an element
1321 void
1322 DrawElement (ElementType *Element)
1324 DrawElementPackage (Element);
1325 DrawElementName (Element);
1326 DrawElementPinsAndPads (Element);
1329 /* ---------------------------------------------------------------------------
1330 * draws the name of an element
1332 void
1333 DrawElementName (ElementType *Element)
1335 if (TEST_FLAG (HIDENAMEFLAG, Element))
1336 return;
1337 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1340 /* ---------------------------------------------------------------------------
1341 * draws the package of an element
1343 void
1344 DrawElementPackage (ElementType *Element)
1346 ELEMENTLINE_LOOP (Element);
1348 DrawLine (NULL, line);
1350 END_LOOP;
1351 ARC_LOOP (Element);
1353 DrawArc (NULL, arc);
1355 END_LOOP;
1358 /* ---------------------------------------------------------------------------
1359 * draw pins of an element
1361 void
1362 DrawElementPinsAndPads (ElementType *Element)
1364 PAD_LOOP (Element);
1366 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
1367 DrawPad (pad);
1369 END_LOOP;
1370 PIN_LOOP (Element);
1372 DrawPin (pin);
1374 END_LOOP;
1377 /* ---------------------------------------------------------------------------
1378 * erase a via
1380 void
1381 EraseVia (PinType *Via)
1383 AddPart (Via);
1384 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
1385 EraseViaName (Via);
1388 /* ---------------------------------------------------------------------------
1389 * erase a ratline
1391 void
1392 EraseRat (RatType *Rat)
1394 if (TEST_FLAG(VIAFLAG, Rat))
1396 Coord w = Rat->Thickness;
1398 BoxType b;
1400 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1401 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1402 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1403 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1404 AddPart (&b);
1406 else
1407 EraseLine ((LineType *)Rat);
1411 /* ---------------------------------------------------------------------------
1412 * erase a via name
1414 void
1415 EraseViaName (PinType *Via)
1417 GatherPVName (Via);
1420 /* ---------------------------------------------------------------------------
1421 * erase a pad object
1423 void
1424 ErasePad (PadType *Pad)
1426 AddPart (Pad);
1427 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1428 ErasePadName (Pad);
1431 /* ---------------------------------------------------------------------------
1432 * erase a pad name
1434 void
1435 ErasePadName (PadType *Pad)
1437 GatherPadName (Pad);
1440 /* ---------------------------------------------------------------------------
1441 * erase a pin object
1443 void
1444 ErasePin (PinType *Pin)
1446 AddPart (Pin);
1447 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1448 ErasePinName (Pin);
1451 /* ---------------------------------------------------------------------------
1452 * erase a pin name
1454 void
1455 ErasePinName (PinType *Pin)
1457 GatherPVName (Pin);
1460 /* ---------------------------------------------------------------------------
1461 * erases a line on a layer
1463 void
1464 EraseLine (LineType *Line)
1466 AddPart (Line);
1469 /* ---------------------------------------------------------------------------
1470 * erases an arc on a layer
1472 void
1473 EraseArc (ArcType *Arc)
1475 if (!Arc->Thickness)
1476 return;
1477 AddPart (Arc);
1480 /* ---------------------------------------------------------------------------
1481 * erases a text on a layer
1483 void
1484 EraseText (LayerType *Layer, TextType *Text)
1486 AddPart (Text);
1489 /* ---------------------------------------------------------------------------
1490 * erases a polygon on a layer
1492 void
1493 ErasePolygon (PolygonType *Polygon)
1495 AddPart (Polygon);
1498 /* ---------------------------------------------------------------------------
1499 * erases an element
1501 void
1502 EraseElement (ElementType *Element)
1504 ELEMENTLINE_LOOP (Element);
1506 EraseLine (line);
1508 END_LOOP;
1509 ARC_LOOP (Element);
1511 EraseArc (arc);
1513 END_LOOP;
1514 EraseElementName (Element);
1515 EraseElementPinsAndPads (Element);
1518 /* ---------------------------------------------------------------------------
1519 * erases all pins and pads of an element
1521 void
1522 EraseElementPinsAndPads (ElementType *Element)
1524 PIN_LOOP (Element);
1526 ErasePin (pin);
1528 END_LOOP;
1529 PAD_LOOP (Element);
1531 ErasePad (pad);
1533 END_LOOP;
1536 /* ---------------------------------------------------------------------------
1537 * erases the name of an element
1539 void
1540 EraseElementName (ElementType *Element)
1542 if (TEST_FLAG (HIDENAMEFLAG, Element))
1543 return;
1544 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1548 void
1549 EraseObject (int type, void *lptr, void *ptr)
1551 switch (type)
1553 case VIA_TYPE:
1554 case PIN_TYPE:
1555 ErasePin ((PinType *) ptr);
1556 break;
1557 case TEXT_TYPE:
1558 case ELEMENTNAME_TYPE:
1559 EraseText ((LayerType *)lptr, (TextType *) ptr);
1560 break;
1561 case POLYGON_TYPE:
1562 ErasePolygon ((PolygonType *) ptr);
1563 break;
1564 case ELEMENT_TYPE:
1565 EraseElement ((ElementType *) ptr);
1566 break;
1567 case LINE_TYPE:
1568 case ELEMENTLINE_TYPE:
1569 case RATLINE_TYPE:
1570 EraseLine ((LineType *) ptr);
1571 break;
1572 case PAD_TYPE:
1573 ErasePad ((PadType *) ptr);
1574 break;
1575 case ARC_TYPE:
1576 case ELEMENTARC_TYPE:
1577 EraseArc ((ArcType *) ptr);
1578 break;
1579 default:
1580 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
1586 void
1587 DrawObject (int type, void *ptr1, void *ptr2)
1589 switch (type)
1591 case VIA_TYPE:
1592 if (PCB->ViaOn)
1593 DrawVia ((PinType *) ptr2);
1594 break;
1595 case LINE_TYPE:
1596 if (((LayerType *) ptr1)->On)
1597 DrawLine ((LayerType *) ptr1, (LineType *) ptr2);
1598 break;
1599 case ARC_TYPE:
1600 if (((LayerType *) ptr1)->On)
1601 DrawArc ((LayerType *) ptr1, (ArcType *) ptr2);
1602 break;
1603 case TEXT_TYPE:
1604 if (((LayerType *) ptr1)->On)
1605 DrawText ((LayerType *) ptr1, (TextType *) ptr2);
1606 break;
1607 case POLYGON_TYPE:
1608 if (((LayerType *) ptr1)->On)
1609 DrawPolygon ((LayerType *) ptr1, (PolygonType *) ptr2);
1610 break;
1611 case ELEMENT_TYPE:
1612 if (PCB->ElementOn &&
1613 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1614 DrawElement ((ElementType *) ptr2);
1615 break;
1616 case RATLINE_TYPE:
1617 if (PCB->RatOn)
1618 DrawRat ((RatType *) ptr2);
1619 break;
1620 case PIN_TYPE:
1621 if (PCB->PinOn)
1622 DrawPin ((PinType *) ptr2);
1623 break;
1624 case PAD_TYPE:
1625 if (PCB->PinOn)
1626 DrawPad ((PadType *) ptr2);
1627 break;
1628 case ELEMENTNAME_TYPE:
1629 if (PCB->ElementOn &&
1630 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1631 DrawElementName ((ElementType *) ptr1);
1632 break;
1636 static void
1637 draw_element (ElementType *element)
1639 draw_element_package (element);
1640 draw_element_name (element);
1641 draw_element_pins_and_pads (element);
1644 /* ---------------------------------------------------------------------------
1645 * HID drawing callback.
1648 void
1649 hid_expose_callback (HID * hid, BoxType * region, void *item)
1651 HID *old_gui = gui;
1653 gui = hid;
1654 Output.fgGC = gui->graphics->make_gc ();
1655 Output.bgGC = gui->graphics->make_gc ();
1656 Output.pmGC = gui->graphics->make_gc ();
1658 hid->graphics->set_color (Output.pmGC, "erase");
1659 hid->graphics->set_color (Output.bgGC, "drill");
1661 if (item)
1663 doing_pinout = true;
1664 draw_element ((ElementType *)item);
1665 doing_pinout = false;
1667 else
1668 DrawEverything (region);
1670 gui->graphics->destroy_gc (Output.fgGC);
1671 gui->graphics->destroy_gc (Output.bgGC);
1672 gui->graphics->destroy_gc (Output.pmGC);
1673 gui = old_gui;