Add SL_RATS layer ID to tell the GUI we're drawing rats
[geda-pcb/gde.git] / src / draw.c
blobb843da66f8ee22a10a0bf67989beffddfbb6b306
1 /* $Id$ */
3 /*
4 * COPYRIGHT
6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996, 2003, 2004 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
30 /* drawing routines
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
37 #include "global.h"
39 /*#include "clip.h"*/
40 #include "compat.h"
41 #include "crosshair.h"
42 #include "data.h"
43 #include "draw.h"
44 #include "error.h"
45 #include "mymem.h"
46 #include "misc.h"
47 #include "rotate.h"
48 #include "rtree.h"
49 #include "search.h"
50 #include "select.h"
51 #include "print.h"
53 #ifdef HAVE_LIBDMALLOC
54 #include <dmalloc.h>
55 #endif
57 RCSID ("$Id$");
59 #define SMALL_SMALL_TEXT_SIZE 0
60 #define SMALL_TEXT_SIZE 1
61 #define NORMAL_TEXT_SIZE 2
62 #define LARGE_TEXT_SIZE 3
63 #define N_TEXT_SIZES 4
66 /* ---------------------------------------------------------------------------
67 * some local types
69 typedef struct
71 double X, Y;
73 FloatPolyType, *FloatPolyTypePtr;
75 /* ---------------------------------------------------------------------------
76 * some local identifiers
78 static BoxType Block;
79 static Boolean Gathering = True;
80 static int Erasing = False;
82 static int doing_pinout = False;
83 static int doing_assy = False;
84 static const BoxType *clip_box = NULL;
86 /* ---------------------------------------------------------------------------
87 * some local prototypes
89 static void Redraw (Boolean, BoxTypePtr);
90 static void DrawEverything (BoxTypePtr);
91 static void DrawTop (const BoxType *);
92 static int DrawLayerGroup (int, const BoxType *);
93 static void DrawPinOrViaLowLevel (PinTypePtr, Boolean);
94 static void ClearOnlyPin (PinTypePtr, Boolean);
95 static void DrawPlainPin (PinTypePtr, Boolean);
96 static void DrawPlainVia (PinTypePtr, Boolean);
97 static void DrawPinOrViaNameLowLevel (PinTypePtr);
98 static void DrawPadLowLevel (hidGC, PadTypePtr, Boolean, Boolean);
99 static void DrawPadNameLowLevel (PadTypePtr);
100 static void DrawLineLowLevel (LineTypePtr, Boolean);
101 static void DrawRegularText (LayerTypePtr, TextTypePtr, int);
102 static void DrawPolygonLowLevel (PolygonTypePtr);
103 static void DrawArcLowLevel (ArcTypePtr);
104 static void DrawElementPackageLowLevel (ElementTypePtr Element, int);
105 static void DrawPlainPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon);
106 static void AddPart (void *);
107 static void SetPVColor (PinTypePtr, int);
108 static void DrawEMark (ElementTypePtr, LocationType, LocationType, Boolean);
109 static void ClearPad (PadTypePtr, Boolean);
110 static void DrawHole (PinTypePtr);
111 static void DrawMask (BoxType *);
112 static void DrawRats (BoxType *);
113 static void DrawSilk (int, int, const BoxType *);
114 static int pin_callback (const BoxType * b, void *cl);
115 static int pad_callback (const BoxType * b, void *cl);
117 /*--------------------------------------------------------------------------------------
118 * setup color for pin or via
120 static void
121 SetPVColor (PinTypePtr Pin, int Type)
123 char *color;
125 if (Type == VIA_TYPE)
127 if (!doing_pinout
128 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
130 if (TEST_FLAG (WARNFLAG, Pin))
131 color = PCB->WarnColor;
132 else if (TEST_FLAG (SELECTEDFLAG, Pin))
133 color = PCB->ViaSelectedColor;
134 else
135 color = PCB->ConnectedColor;
137 else
138 color = PCB->ViaColor;
140 else
142 if (!doing_pinout
143 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
145 if (TEST_FLAG (WARNFLAG, Pin))
146 color = PCB->WarnColor;
147 else if (TEST_FLAG (SELECTEDFLAG, Pin))
148 color = PCB->PinSelectedColor;
149 else
150 color = PCB->ConnectedColor;
152 else
153 color = PCB->PinColor;
156 gui->set_color (Output.fgGC, color);
159 /*---------------------------------------------------------------------------
160 * Adds the update rect to the update region
162 static void
163 AddPart (void *b)
165 BoxType *box = (BoxType *) b;
167 Block.X1 = MIN (Block.X1, box->X1);
168 Block.X2 = MAX (Block.X2, box->X2);
169 Block.Y1 = MIN (Block.Y1, box->Y1);
170 Block.Y2 = MAX (Block.Y2, box->Y2);
174 * force the whole output to be updated
176 void
177 UpdateAll (void)
179 gui->invalidate_all ();
183 * initiate the actual drawing to the pixmap/screen
184 * make the update block slightly larger to handle round-off
185 * caused by the TO_SCREEN operation
187 void
188 Draw (void)
191 render = True;
193 HideCrosshair (True);
195 /* clear and create event if not drawing to a pixmap
197 gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2, 1);
199 RestoreCrosshair (True);
201 /* shrink the update block */
202 Block.X1 = Block.Y1 = Block.X2 = Block.Y2 = 0;
205 /* ---------------------------------------------------------------------------
206 * redraws the output area without clearing it
208 void
209 RedrawOutput (BoxTypePtr area)
211 Redraw (True, area);
214 /* ---------------------------------------------------------------------------
215 * redraws the output area after clearing it
217 void
218 ClearAndRedrawOutput (void)
220 render = True;
221 Gathering = False;
222 UpdateAll ();
228 /* ----------------------------------------------------------------------
229 * redraws all the data
230 * all necessary sizes are already set by the porthole widget and
231 * by the event handlers
233 static void
234 Redraw (Boolean ClearWindow, BoxTypePtr screen_area)
236 gui->invalidate_all ();
237 Gathering = True;
238 render = False;
241 static int
242 backE_callback (const BoxType * b, void *cl)
244 ElementTypePtr element = (ElementTypePtr) b;
246 if (!FRONT (element))
248 DrawElementPackage (element, 0);
250 return 1;
253 static int
254 backN_callback (const BoxType * b, void *cl)
256 TextTypePtr text = (TextTypePtr) b;
257 ElementTypePtr element = (ElementTypePtr) text->Element;
259 if (!FRONT (element) && !TEST_FLAG (HIDENAMEFLAG, element))
260 DrawElementName (element, 0);
261 return 0;
264 static int
265 backPad_callback (const BoxType * b, void *cl)
267 PadTypePtr pad = (PadTypePtr) b;
269 if (!FRONT (pad))
270 DrawPad (pad, 0);
271 return 1;
274 static int
275 frontE_callback (const BoxType * b, void *cl)
277 ElementTypePtr element = (ElementTypePtr) b;
279 if (FRONT (element))
281 DrawElementPackage (element, 0);
283 return 1;
286 static int
287 EMark_callback (const BoxType * b, void *cl)
289 ElementTypePtr element = (ElementTypePtr) b;
291 DrawEMark (element, element->MarkX, element->MarkY, !FRONT (element));
292 return 1;
295 static int
296 frontN_callback (const BoxType * b, void *cl)
298 TextTypePtr text = (TextTypePtr) b;
299 ElementTypePtr element = (ElementTypePtr) text->Element;
301 if (FRONT (element) && !TEST_FLAG (HIDENAMEFLAG, element))
302 DrawElementName (element, 0);
303 return 0;
306 static int
307 hole_callback (const BoxType * b, void *cl)
309 PinTypePtr pin = (PinTypePtr) b;
310 int plated = cl ? *(int *) cl : -1;
311 switch (plated)
313 case -1:
314 break;
315 case 0:
316 if (!TEST_FLAG (HOLEFLAG, pin))
317 return 1;
318 break;
319 case 1:
320 if (TEST_FLAG (HOLEFLAG, pin))
321 return 1;
322 break;
324 DrawHole ((PinTypePtr) b);
325 return 1;
328 typedef struct
330 int nplated;
331 int nunplated;
332 } HoleCountStruct;
334 static int
335 hole_counting_callback (const BoxType * b, void *cl)
337 PinTypePtr pin = (PinTypePtr) b;
338 HoleCountStruct *hcs = (HoleCountStruct *) cl;
339 if (TEST_FLAG (HOLEFLAG, pin))
340 hcs->nunplated++;
341 else
342 hcs->nplated++;
343 return 1;
346 static int
347 rat_callback (const BoxType * b, void *cl)
349 DrawRat ((RatTypePtr) b, 0);
350 return 1;
353 /* ---------------------------------------------------------------------------
354 * prints assembly drawing.
357 static void
358 PrintAssembly (const BoxType * drawn_area, int side_group, int swap_ident)
360 int save_swap = SWAP_IDENT;
362 gui->set_draw_faded (Output.fgGC, 1);
363 SWAP_IDENT = swap_ident;
364 DrawLayerGroup (side_group, drawn_area);
365 DrawTop (drawn_area);
366 gui->set_draw_faded (Output.fgGC, 0);
368 /* draw package */
369 DrawSilk (swap_ident,
370 swap_ident ? SOLDER_LAYER : COMPONENT_LAYER,
371 drawn_area);
372 SWAP_IDENT = save_swap;
375 /* ---------------------------------------------------------------------------
376 * initializes some identifiers for a new zoom factor and redraws whole screen
378 static void
379 DrawEverything (BoxTypePtr drawn_area)
381 int i, ngroups, side;
382 int plated;
383 int component, solder;
384 /* This is the list of layer groups we will draw. */
385 int do_group[MAX_LAYER];
386 /* This is the reverse of the order in which we draw them. */
387 int drawn_groups[MAX_LAYER];
389 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
390 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
392 memset (do_group, 0, sizeof (do_group));
393 for (ngroups = 0, i = 0; i < max_layer; i++)
395 LayerType *l = LAYER_ON_STACK (i);
396 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
397 if (l->On && !do_group[group])
399 do_group[group] = 1;
400 drawn_groups[ngroups++] = group;
404 component = GetLayerGroupNumberByNumber (max_layer + COMPONENT_LAYER);
405 solder = GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER);
408 * first draw all 'invisible' stuff
410 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
411 && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
413 r_search (PCB->Data->pad_tree, drawn_area, NULL, backPad_callback,
414 NULL);
415 if (PCB->ElementOn)
417 r_search (PCB->Data->element_tree, drawn_area, NULL, backE_callback,
418 NULL);
419 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
420 backN_callback, NULL);
421 DrawLayer (&(PCB->Data->BACKSILKLAYER), drawn_area);
425 /* draw all layers in layerstack order */
426 for (i = ngroups - 1; i >= 0; i--)
428 int group = drawn_groups[i];
430 if (gui->set_layer (0, group, 0))
432 if (DrawLayerGroup (group, drawn_area) && !gui->gui)
434 int save_swap = SWAP_IDENT;
436 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
437 continue;
438 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback,
439 NULL);
440 r_search (PCB->Data->via_tree, drawn_area, NULL, pin_callback,
441 NULL);
442 /* draw element pads */
443 if (group == component || group == solder)
445 SWAP_IDENT = (group == solder);
446 r_search (PCB->Data->pad_tree, drawn_area, NULL,
447 pad_callback, NULL);
449 SWAP_IDENT = save_swap;
451 if (!gui->gui)
453 /* draw holes */
454 plated = -1;
455 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback,
456 &plated);
457 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback,
458 &plated);
463 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
464 return;
466 /* Draw pins, pads, vias below silk */
467 if (gui->gui)
468 DrawTop (drawn_area);
469 else
471 HoleCountStruct hcs;
472 hcs.nplated = hcs.nunplated = 0;
473 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_counting_callback,
474 &hcs);
475 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_counting_callback,
476 &hcs);
477 if (hcs.nplated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
479 plated = 1;
480 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback,
481 &plated);
482 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback,
483 &plated);
485 if (hcs.nunplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
487 plated = 0;
488 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback,
489 &plated);
490 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback,
491 &plated);
494 /* Draw the solder mask if turned on */
495 if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
497 int save_swap = SWAP_IDENT;
498 SWAP_IDENT = 0;
499 DrawMask (drawn_area);
500 SWAP_IDENT = save_swap;
502 if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
504 int save_swap = SWAP_IDENT;
505 SWAP_IDENT = 1;
506 DrawMask (drawn_area);
507 SWAP_IDENT = save_swap;
509 /* Draw top silkscreen */
510 if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
511 DrawSilk (0, COMPONENT_LAYER, drawn_area);
512 if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
513 DrawSilk (1, SOLDER_LAYER, drawn_area);
514 if (gui->gui)
516 /* Draw element Marks */
517 if (PCB->PinOn)
518 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
519 NULL);
520 /* Draw rat lines on top */
521 if (gui->set_layer ("rats", SL (RATS, 0), 0))
522 DrawRats(drawn_area);
525 for (side = 0; side <= 1; side++)
527 int doit;
528 Boolean NoData = True;
529 ALLPAD_LOOP (PCB->Data);
531 if ((TEST_FLAG (ONSOLDERFLAG, pad) && side == SOLDER_LAYER)
532 || (!TEST_FLAG (ONSOLDERFLAG, pad) && side == COMPONENT_LAYER))
534 NoData = False;
535 break;
538 ENDALL_LOOP;
540 if (side == SOLDER_LAYER)
541 doit = gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), NoData);
542 else
543 doit = gui->set_layer ("toppaste", SL (PASTE, TOP), NoData);
544 if (doit)
546 gui->set_color (Output.fgGC, PCB->ElementColor);
547 ALLPAD_LOOP (PCB->Data);
549 if ((TEST_FLAG (ONSOLDERFLAG, pad) && side == SOLDER_LAYER)
550 || (!TEST_FLAG (ONSOLDERFLAG, pad)
551 && side == COMPONENT_LAYER))
552 if (!TEST_FLAG (NOPASTEFLAG, pad))
553 DrawPadLowLevel (Output.fgGC, pad, False, False);
555 ENDALL_LOOP;
559 doing_assy = True;
560 if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
561 PrintAssembly (drawn_area, component, 0);
563 if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
564 PrintAssembly (drawn_area, solder, 1);
565 doing_assy = False;
567 if (gui->set_layer ("fab", SL (FAB, 0), 0))
568 PrintFab ();
571 static void
572 DrawEMark (ElementTypePtr e, LocationType X, LocationType Y,
573 Boolean invisible)
575 int mark_size = EMARK_SIZE;
576 if (!PCB->InvisibleObjectsOn && invisible)
577 return;
579 if (e->PinN && mark_size > e->Pin[0].Thickness / 2)
580 mark_size = e->Pin[0].Thickness / 2;
581 if (e->PadN && mark_size > e->Pad[0].Thickness / 2)
582 mark_size = e->Pad[0].Thickness / 2;
584 gui->set_color (Output.fgGC,
585 invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
586 gui->set_line_cap (Output.fgGC, Trace_Cap);
587 gui->set_line_width (Output.fgGC, 0);
588 gui->draw_line (Output.fgGC, X - mark_size, Y, X, Y - mark_size);
589 gui->draw_line (Output.fgGC, X + mark_size, Y, X, Y - mark_size);
590 gui->draw_line (Output.fgGC, X - mark_size, Y, X, Y + mark_size);
591 gui->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
594 * If an element is locked, place a "L" on top of the "diamond".
595 * This provides a nice visual indication that it is locked that
596 * works even for color blind users.
598 if (TEST_FLAG (LOCKFLAG, e) )
600 gui->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
601 gui->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
606 static int
607 via_callback (const BoxType * b, void *cl)
609 PinTypePtr via = (PinTypePtr) b;
610 DrawPlainVia (via, False);
611 return 1;
614 static int
615 pin_callback (const BoxType * b, void *cl)
617 DrawPlainPin ((PinTypePtr) b, False);
618 return 1;
621 static int
622 pad_callback (const BoxType * b, void *cl)
624 PadTypePtr pad = (PadTypePtr) b;
625 if (FRONT (pad))
626 DrawPad (pad, 0);
627 return 1;
630 /* ---------------------------------------------------------------------------
631 * draws pins pads and vias
633 static void
634 DrawTop (const BoxType * screen)
636 if (PCB->PinOn || doing_assy)
638 /* draw element pins */
639 r_search (PCB->Data->pin_tree, screen, NULL, pin_callback, NULL);
640 /* draw element pads */
641 r_search (PCB->Data->pad_tree, screen, NULL, pad_callback, NULL);
643 /* draw vias */
644 if (PCB->ViaOn || doing_assy)
646 r_search (PCB->Data->via_tree, screen, NULL, via_callback, NULL);
647 r_search (PCB->Data->via_tree, screen, NULL, hole_callback, NULL);
649 if (PCB->PinOn || doing_assy)
650 r_search (PCB->Data->pin_tree, screen, NULL, hole_callback, NULL);
653 struct pin_info
655 Boolean arg;
656 LayerTypePtr Layer;
659 static int
660 clearPin_callback (const BoxType * b, void *cl)
662 PinTypePtr pin = (PinTypePtr) b;
663 struct pin_info *i = (struct pin_info *) cl;
664 if (i->arg)
665 ClearOnlyPin (pin, True);
666 return 1;
668 static int
669 poly_callback (const BoxType * b, void *cl)
671 struct pin_info *i = (struct pin_info *) cl;
673 DrawPlainPolygon (i->Layer, (PolygonTypePtr) b);
674 return 1;
677 static int
678 clearPad_callback (const BoxType * b, void *cl)
680 PadTypePtr pad = (PadTypePtr) b;
681 if (!XOR (TEST_FLAG (ONSOLDERFLAG, pad), SWAP_IDENT))
682 ClearPad (pad, True);
683 return 1;
686 /* ---------------------------------------------------------------------------
687 * Draws silk layer.
690 static void
691 DrawSilk (int new_swap, int layer, const BoxType * drawn_area)
693 #if 0
694 /* This code is used when you want to mask silk to avoid exposed
695 pins and pads. We decided it was a bad idea to do this
696 unconditionally, but the code remains. */
697 struct pin_info info;
698 #endif
699 int save_swap = SWAP_IDENT;
700 SWAP_IDENT = new_swap;
702 #if 0
703 if (gui->poly_before)
705 gui->use_mask (HID_MASK_BEFORE);
706 #endif
707 DrawLayer (LAYER_PTR (max_layer + layer), drawn_area);
708 /* draw package */
709 r_search (PCB->Data->element_tree, drawn_area, NULL, frontE_callback,
710 NULL);
711 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
712 frontN_callback, NULL);
713 #if 0
716 gui->use_mask (HID_MASK_CLEAR);
717 info.arg = True;
718 r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, &info);
719 r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, &info);
720 r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &info);
722 if (gui->poly_after)
724 gui->use_mask (HID_MASK_AFTER);
725 DrawLayer (LAYER_PTR (max_layer + layer), drawn_area);
726 /* draw package */
727 r_search (PCB->Data->element_tree, drawn_area, NULL, frontE_callback,
728 NULL);
729 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
730 frontN_callback, NULL);
732 gui->use_mask (HID_MASK_OFF);
733 #endif
734 SWAP_IDENT = save_swap;
737 /* ---------------------------------------------------------------------------
738 * draws solder mask layer - this will cover nearly everything
740 static void
741 DrawMask (BoxType * screen)
743 struct pin_info info;
744 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
746 OutputType *out = &Output;
748 info.arg = True;
750 if (thin)
751 gui->set_color (Output.pmGC, PCB->MaskColor);
752 else
754 if (gui->poly_before)
756 gui->use_mask (HID_MASK_BEFORE);
757 gui->set_color (out->fgGC, PCB->MaskColor);
758 gui->fill_rect (out->fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
760 gui->use_mask (HID_MASK_CLEAR);
763 r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, &info);
764 r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, &info);
765 r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &info);
767 if (thin)
768 gui->set_color (Output.pmGC, "erase");
769 else
771 if (gui->poly_after)
773 gui->use_mask (HID_MASK_AFTER);
774 gui->set_color (out->fgGC, PCB->MaskColor);
775 gui->fill_rect (out->fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
777 gui->use_mask (HID_MASK_OFF);
780 #if 0
781 /* Some fabs want the board outline on the solder mask layer. If
782 you need this, change the '0' above to '1', and the code below
783 will copy the outline layer to the mask layers. */
784 if (!gui->gui)
786 int i;
787 for (i=PCB->Data->LayerN; i>=0; i--)
789 LayerTypePtr Layer = PCB->Data->Layer + i;
790 if (strcmp (Layer->Name, "outline") == 0)
791 DrawLayer (Layer, screen);
794 #endif
797 static void
798 DrawRats (BoxTypePtr drawn_area)
801 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
802 * XXX gtk only allows negative drawing.
803 * XXX using the mask here is to get rat transparency
805 int can_mask = strcmp(gui->name, "lesstif") == 0;
807 if (can_mask)
808 gui->use_mask (HID_MASK_CLEAR);
809 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
810 if (can_mask)
811 gui->use_mask (HID_MASK_OFF);
814 static int
815 line_callback (const BoxType * b, void *cl)
817 DrawLine ((LayerTypePtr) cl, (LineTypePtr) b, 0);
818 return 1;
821 static int
822 arc_callback (const BoxType * b, void *cl)
824 DrawArc ((LayerTypePtr) cl, (ArcTypePtr) b, 0);
825 return 1;
828 static int
829 text_callback (const BoxType * b, void *cl)
831 DrawRegularText ((LayerTypePtr) cl, (TextTypePtr) b, 0);
832 return 1;
836 /* ---------------------------------------------------------------------------
837 * draws one non-copper layer
839 void
840 DrawLayer (LayerTypePtr Layer, const BoxType * screen)
842 struct pin_info info;
844 /* print the non-clearing polys */
845 info.Layer = Layer;
846 info.arg = False;
847 clip_box = screen;
848 r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
850 /* draw all visible lines this layer */
851 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
853 /* draw the layer arcs on screen */
854 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
856 /* draw the layer text on screen */
857 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
858 clip_box = NULL;
861 /* ---------------------------------------------------------------------------
862 * draws one layer group. Returns non-zero if pins and pads should be
863 * drawn with this group.
865 static int
866 DrawLayerGroup (int group, const BoxType * screen)
868 int i, rv = 1;
869 int layernum;
870 struct pin_info info;
871 LayerTypePtr Layer;
872 int n_entries = PCB->LayerGroups.Number[group];
873 Cardinal *layers = PCB->LayerGroups.Entries[group];
875 clip_box = screen;
876 for (i = n_entries - 1; i >= 0; i--)
878 layernum = layers[i];
879 Layer = PCB->Data->Layer + layers[i];
880 if (strcmp (Layer->Name, "outline") == 0 ||
881 strcmp (Layer->Name, "route") == 0)
882 rv = 0;
883 if (layernum < max_layer && Layer->On)
885 /* draw all polygons on this layer */
886 if (Layer->PolygonN)
888 info.Layer = Layer;
889 info.arg = True;
890 r_search (Layer->polygon_tree, screen, NULL, poly_callback,
891 &info);
892 info.arg = False;
895 if (TEST_FLAG (CHECKPLANESFLAG, PCB))
896 continue;
898 /* draw all visible lines this layer */
899 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
901 /* draw the layer arcs on screen */
902 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
904 /* draw the layer text on screen */
905 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
909 if (n_entries > 1)
910 rv = 1;
911 return rv;
914 /* ---------------------------------------------------------------------------
915 * draws one polygon
916 * x and y are already in display coordinates
917 * the points are numbered:
919 * 5 --- 6
920 * / \
921 * 4 7
922 * | |
923 * 3 0
924 * \ /
925 * 2 --- 1
927 static void
928 DrawSpecialPolygon (HID * hid, hidGC DrawGC,
929 LocationType X, LocationType Y, int Thickness,
930 int thin_draw)
932 static FloatPolyType p[8] = {
934 0.5, -TAN_22_5_DEGREE_2},
936 TAN_22_5_DEGREE_2, -0.5},
938 -TAN_22_5_DEGREE_2, -0.5},
940 -0.5, -TAN_22_5_DEGREE_2},
942 -0.5, TAN_22_5_DEGREE_2},
944 -TAN_22_5_DEGREE_2, 0.5},
946 TAN_22_5_DEGREE_2, 0.5},
948 0.5, TAN_22_5_DEGREE_2}
950 static int special_size = 0;
951 static int scaled_x[8];
952 static int scaled_y[8];
953 int polygon_x[9];
954 int polygon_y[9];
955 int i;
958 if (Thickness != special_size)
960 special_size = Thickness;
961 for (i = 0; i < 8; i++)
963 scaled_x[i] = p[i].X * special_size;
964 scaled_y[i] = p[i].Y * special_size;
967 /* add line offset */
968 for (i = 0; i < 8; i++)
970 polygon_x[i] = X + scaled_x[i];
971 polygon_y[i] = Y + scaled_y[i];
973 if (thin_draw)
975 int i;
976 hid->set_line_cap (DrawGC, Round_Cap);
977 hid->set_line_width (DrawGC, 0);
978 polygon_x[8] = X + scaled_x[0];
979 polygon_y[8] = Y + scaled_y[0];
980 for (i = 0; i < 8; i++)
981 hid->draw_line (DrawGC, polygon_x[i], polygon_y[i],
982 polygon_x[i + 1], polygon_y[i + 1]);
984 else
985 hid->fill_polygon (DrawGC, 8, polygon_x, polygon_y);
988 /* ---------------------------------------------------------------------------
989 * lowlevel drawing routine for pins and vias
991 static void
992 DrawPinOrViaLowLevel (PinTypePtr Ptr, Boolean drawHole)
994 if (Gathering)
996 AddPart (Ptr);
997 return;
1000 if (TEST_FLAG (HOLEFLAG, Ptr))
1002 if (drawHole)
1004 gui->fill_circle (Output.bgGC, Ptr->X, Ptr->Y, Ptr->Thickness / 2);
1005 gui->set_line_cap (Output.fgGC, Round_Cap);
1006 gui->set_line_width (Output.fgGC, 0);
1007 gui->draw_arc (Output.fgGC, Ptr->X, Ptr->Y,
1008 Ptr->Thickness / 2, Ptr->Thickness / 2, 0, 360);
1010 return;
1012 if (TEST_FLAG (SQUAREFLAG, Ptr))
1014 int l, r, t, b;
1015 l = Ptr->X - Ptr->Thickness / 2;
1016 b = Ptr->Y - Ptr->Thickness / 2;
1017 r = l + Ptr->Thickness;
1018 t = b + Ptr->Thickness;
1019 if (TEST_FLAG (THINDRAWFLAG, PCB))
1021 gui->set_line_cap (Output.fgGC, Round_Cap);
1022 gui->set_line_width (Output.fgGC, 0);
1023 gui->draw_line (Output.fgGC, r, t, r, b);
1024 gui->draw_line (Output.fgGC, l, t, l, b);
1025 gui->draw_line (Output.fgGC, r, t, l, t);
1026 gui->draw_line (Output.fgGC, r, b, l, b);
1028 else
1030 gui->fill_rect (Output.fgGC, l, b, r, t);
1033 else if (TEST_FLAG (OCTAGONFLAG, Ptr))
1035 DrawSpecialPolygon (gui, Output.fgGC, Ptr->X, Ptr->Y, Ptr->Thickness,
1036 TEST_FLAG (THINDRAWFLAG, PCB));
1038 else
1039 { /* draw a round pin or via */
1040 if (TEST_FLAG (THINDRAWFLAG, PCB))
1042 gui->set_line_cap (Output.fgGC, Round_Cap);
1043 gui->set_line_width (Output.fgGC, 0);
1044 gui->draw_arc (Output.fgGC, Ptr->X, Ptr->Y,
1045 Ptr->Thickness / 2, Ptr->Thickness / 2, 0, 360);
1047 else
1049 gui->fill_circle (Output.fgGC, Ptr->X, Ptr->Y, Ptr->Thickness / 2);
1053 /* and the drilling hole (which is always round */
1054 if (drawHole)
1056 if (TEST_FLAG (THINDRAWFLAG, PCB))
1058 gui->set_line_cap (Output.fgGC, Round_Cap);
1059 gui->set_line_width (Output.fgGC, 0);
1060 gui->draw_arc (Output.fgGC,
1061 Ptr->X, Ptr->Y, Ptr->DrillingHole / 2,
1062 Ptr->DrillingHole / 2, 0, 360);
1064 else
1066 gui->fill_circle (Output.bgGC, Ptr->X, Ptr->Y,
1067 Ptr->DrillingHole / 2);
1072 /**************************************************************
1073 * draw pin/via hole
1075 static void
1076 DrawHole (PinTypePtr Ptr)
1078 if (TEST_FLAG (THINDRAWFLAG, PCB))
1080 if (!TEST_FLAG (HOLEFLAG, Ptr))
1082 gui->set_line_cap (Output.fgGC, Round_Cap);
1083 gui->set_line_width (Output.fgGC, 0);
1084 gui->draw_arc (Output.fgGC,
1085 Ptr->X, Ptr->Y, Ptr->DrillingHole / 2,
1086 Ptr->DrillingHole / 2, 0, 360);
1089 else
1091 gui->fill_circle (Output.bgGC, Ptr->X, Ptr->Y, Ptr->DrillingHole / 2);
1093 if (TEST_FLAG (HOLEFLAG, Ptr))
1095 if (TEST_FLAG (WARNFLAG, Ptr))
1096 gui->set_color (Output.fgGC, PCB->WarnColor);
1097 else if (TEST_FLAG (SELECTEDFLAG, Ptr))
1098 gui->set_color (Output.fgGC, PCB->ViaSelectedColor);
1099 else
1100 gui->set_color (Output.fgGC, Settings.BlackColor);
1102 gui->set_line_cap (Output.fgGC, Round_Cap);
1103 gui->set_line_width (Output.fgGC, 0);
1104 gui->draw_arc (Output.fgGC,
1105 Ptr->X, Ptr->Y, Ptr->DrillingHole / 2,
1106 Ptr->DrillingHole / 2, 0, 360);
1110 /*******************************************************************
1111 * draw clearance in pixmask around pins and vias that pierce polygons
1113 static void
1114 ClearOnlyPin (PinTypePtr Pin, Boolean mask)
1116 BDimension half =
1117 (mask ? Pin->Mask / 2 : (Pin->Thickness + Pin->Clearance) / 2);
1119 if (!mask && TEST_FLAG (HOLEFLAG, Pin))
1120 return;
1121 if (half == 0)
1122 return;
1123 if (!mask && Pin->Clearance <= 0)
1124 return;
1126 /* Clear the area around the pin */
1127 if (TEST_FLAG (SQUAREFLAG, Pin))
1129 int l, r, t, b;
1130 l = Pin->X - half;
1131 b = Pin->Y - half;
1132 r = l + half * 2;
1133 t = b + half * 2;
1134 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
1136 gui->set_line_cap (Output.pmGC, Round_Cap);
1137 gui->set_line_width (Output.pmGC, 0);
1138 gui->draw_line (Output.pmGC, r, t, r, b);
1139 gui->draw_line (Output.pmGC, l, t, l, b);
1140 gui->draw_line (Output.pmGC, r, t, l, t);
1141 gui->draw_line (Output.pmGC, r, b, l, b);
1143 else
1144 gui->fill_rect (Output.pmGC, l, b, r, t);
1146 else if (TEST_FLAG (OCTAGONFLAG, Pin))
1148 DrawSpecialPolygon (gui, Output.pmGC, Pin->X, Pin->Y, half * 2,
1149 TEST_FLAG (THINDRAWFLAG, PCB) ||
1150 TEST_FLAG (THINDRAWPOLYFLAG, PCB));
1152 else
1154 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
1156 gui->set_line_cap (Output.pmGC, Round_Cap);
1157 gui->set_line_width (Output.pmGC, 0);
1158 gui->draw_arc (Output.pmGC, Pin->X, Pin->Y, half, half, 0, 360);
1160 else
1161 gui->fill_circle (Output.pmGC, Pin->X, Pin->Y, half);
1166 #if VERTICAL_TEXT
1167 /* vertical text handling provided by Martin Devera with fixes by harry eaton */
1169 /* draw vertical text; xywh is bounding, de is text's descend used for
1170 positioning */
1171 static void
1172 DrawVText (int x, int y, int w, int h, char *str)
1174 GdkPixmap *pm;
1175 GdkImage *im;
1176 GdkGCValues values;
1177 guint32 pixel;
1178 int i, j;
1180 if (!str || !*str)
1181 return;
1183 pm = gdk_pixmap_new (DrawingWindow, w, h, -1);
1185 /* draw into pixmap */
1186 gdk_draw_rectangle (pm, Output.bgGC, TRUE, 0, 0, w, h);
1188 gui_draw_string_markup (DrawingWindow, Output.font_desc, Output.fgGC,
1189 0, 0, str);
1191 im = gdk_drawable_get_image (pm, 0, 0, w, h);
1192 gdk_gc_get_values (Output.fgGC, &values);
1194 /* draw Transpose(im). TODO: Pango should be doing vertical text soon */
1195 for (i = 0; i < w; i++)
1196 for (j = 0; j < h; j++)
1198 pixel = gdk_image_get_pixel (im, i, j);
1199 if (pixel == values.foreground.pixel)
1200 gdk_draw_point (DrawingWindow, Output.fgGC, x + j, y + w - i - 1);
1202 g_object_unref (G_OBJECT (pm));
1204 #endif
1206 /* ---------------------------------------------------------------------------
1207 * lowlevel drawing routine for pin and via names
1209 static void
1210 DrawPinOrViaNameLowLevel (PinTypePtr Ptr)
1212 char *name;
1213 BoxType box;
1214 Boolean vert;
1215 TextType text;
1217 if (!Ptr->Name || !Ptr->Name[0])
1218 name = EMPTY (Ptr->Number);
1219 else
1220 name = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? Ptr->Number : Ptr->Name);
1222 vert = TEST_FLAG (EDGE2FLAG, Ptr);
1224 if (vert)
1226 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1227 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
1229 else
1231 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
1232 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1234 if (Gathering)
1236 if (vert)
1238 box.X2 = box.X1;
1239 box.Y2 = box.Y1;
1241 else
1243 box.X2 = box.X1;
1244 box.Y2 = box.Y1;
1246 /*printf("AddPart: x1=%d y1=%d x2=%d y2=%d\n", box.X1, box.Y1, box.X2, box.Y2);*/
1247 AddPart (&box);
1248 return;
1250 /*printf("DrawPin(%d,%d): x=%d y=%d w=%d h=%d\n",
1251 TO_DRAW_X(Ptr->X), TO_DRAW_Y(Ptr->Y), box.X1, box.Y1, width, height);*/
1253 gui->set_color (Output.fgGC, PCB->PinNameColor);
1255 text.Flags = NoFlags ();
1256 text.Scale = Ptr->Thickness / 80;
1257 text.X = box.X1;
1258 text.Y = box.Y1;
1259 text.Direction = vert ? 1 : 0;
1260 text.TextString = name;
1262 if (gui->gui)
1263 doing_pinout++;
1264 DrawTextLowLevel (&text, 0);
1265 if (gui->gui)
1266 doing_pinout--;
1269 /* ---------------------------------------------------------------------------
1270 * lowlevel drawing routine for pads
1273 static void
1274 DrawPadLowLevel (hidGC gc, PadTypePtr Pad, Boolean clear, Boolean mask)
1276 int w = clear ? (mask ? Pad->Mask : Pad->Thickness + Pad->Clearance)
1277 : Pad->Thickness;
1279 if (Gathering)
1281 AddPart (Pad);
1282 return;
1285 if (clear && !mask && Pad->Clearance <= 0)
1286 return;
1288 if (TEST_FLAG (THINDRAWFLAG, PCB) ||
1289 (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
1291 int x1, y1, x2, y2, t, t2;
1292 t = w / 2;
1293 t2 = w - t;
1294 x1 = Pad->Point1.X;
1295 y1 = Pad->Point1.Y;
1296 x2 = Pad->Point2.X;
1297 y2 = Pad->Point2.Y;
1298 if (x1 > x2 || y1 > y2)
1300 /* this is a silly way to swap the variables */
1301 x1 ^= x2;
1302 x2 ^= x1;
1303 x1 ^= x2;
1304 y1 ^= y2;
1305 y2 ^= y1;
1306 y1 ^= y2;
1308 gui->set_line_cap (gc, Round_Cap);
1309 gui->set_line_width (gc, 0);
1310 if (TEST_FLAG (SQUAREFLAG, Pad)
1311 && (x1 == x2 || y1 == y2))
1313 x1 -= t;
1314 y1 -= t;
1315 x2 += t2;
1316 y2 += t2;
1317 gui->draw_line (gc, x1, y1, x1, y2);
1318 gui->draw_line (gc, x1, y2, x2, y2);
1319 gui->draw_line (gc, x2, y2, x2, y1);
1320 gui->draw_line (gc, x2, y1, x1, y1);
1322 else if (TEST_FLAG (SQUAREFLAG, Pad))
1324 /* slanted square pad */
1325 float tx, ty, theta;
1327 theta = atan2 (y2-y1, x2-x1);
1329 /* T is a vector half a thickness long, in the direction of
1330 one of the corners. */
1331 tx = t * cos (theta + M_PI/4) * sqrt(2.0);
1332 ty = t * sin (theta + M_PI/4) * sqrt(2.0);
1334 gui->draw_line (gc, x1-tx, y1-ty, x2+ty, y2-tx);
1335 gui->draw_line (gc, x2+ty, y2-tx, x2+tx, y2+ty);
1336 gui->draw_line (gc, x2+tx, y2+ty, x1-ty, y1+tx);
1337 gui->draw_line (gc, x1-ty, y1+tx, x1-tx, y1-ty);
1339 else if (x1 == x2 && y1 == y2)
1341 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 0, 360);
1343 else if (x1 == x2)
1345 gui->draw_line (gc, x1 - t, y1, x2 - t, y2);
1346 gui->draw_line (gc, x1 + t2, y1, x2 + t2, y2);
1347 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 0, -180);
1348 gui->draw_arc (gc, x2, y2, w / 2, w / 2, 180, -180);
1350 else if (y1 == y2)
1352 gui->draw_line (gc, x1, y1 - t, x2, y2 - t);
1353 gui->draw_line (gc, x1, y1 + t2, x2, y2 + t2);
1354 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 90, -180);
1355 gui->draw_arc (gc, x2, y2, w / 2, w / 2, 270, -180);
1357 else
1359 /* Slanted round-end pads. */
1360 LocationType dx, dy, ox, oy;
1361 float h;
1363 dx = x2 - x1;
1364 dy = y2 - y1;
1365 h = t / sqrt (SQUARE (dx) + SQUARE (dy));
1366 ox = dy * h + 0.5 * SGN (dy);
1367 oy = -(dx * h + 0.5 * SGN (dx));
1369 gui->draw_line (gc, x1 + ox, y1 + oy, x2 + ox, y2 + oy);
1371 if (abs (ox) >= pixel_slop || abs (oy) >= pixel_slop)
1373 LocationType angle = atan2 ((float) dx, (float) dy) * 57.295779;
1374 gui->draw_line (gc, x1 - ox, y1 - oy, x2 - ox, y2 - oy);
1375 gui->draw_arc (gc,
1376 x1, y1, t, t, angle - 180, 180);
1377 gui->draw_arc (gc, x2, y2, t, t, angle, 180);
1381 else if (Pad->Point1.X == Pad->Point2.X
1382 && Pad->Point1.Y == Pad->Point2.Y)
1384 if (TEST_FLAG (SQUAREFLAG, Pad))
1386 int l, r, t, b;
1387 l = Pad->Point1.X - w / 2;
1388 b = Pad->Point1.Y - w / 2;
1389 r = l + w;
1390 t = b + w;
1391 gui->fill_rect (gc, l, b, r, t);
1393 else
1395 gui->fill_circle (gc, Pad->Point1.X, Pad->Point1.Y, w / 2);
1398 else
1400 gui->set_line_cap (gc,
1401 TEST_FLAG (SQUAREFLAG,
1402 Pad) ? Square_Cap : Round_Cap);
1403 gui->set_line_width (gc, w);
1405 gui->draw_line (gc,
1406 Pad->Point1.X, Pad->Point1.Y,
1407 Pad->Point2.X, Pad->Point2.Y);
1409 #if 0
1410 { /* Draw bounding box for test */
1411 BoxType *box = &Pad->BoundingBox;
1412 gui->set_line_width (gc, 0);
1413 gui->draw_line (gc, box->X1, box->Y1, box->X1, box->Y2);
1414 gui->draw_line (gc, box->X1, box->Y2, box->X2, box->Y2);
1415 gui->draw_line (gc, box->X2, box->Y2, box->X2, box->Y1);
1416 gui->draw_line (gc, box->X2, box->Y1, box->X1, box->Y1);
1418 #endif
1421 /* ---------------------------------------------------------------------------
1422 * lowlevel drawing routine for pad names
1425 static void
1426 DrawPadNameLowLevel (PadTypePtr Pad)
1428 BoxType box;
1429 char *name;
1430 Boolean vert;
1431 TextType text;
1433 if (!Pad->Name || !Pad->Name[0])
1434 name = EMPTY (Pad->Number);
1435 else
1436 name = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? Pad->Number : Pad->Name);
1438 /* should text be vertical ? */
1439 vert = (Pad->Point1.X == Pad->Point2.X);
1441 if (vert)
1443 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1444 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1446 else
1448 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1449 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1452 if (vert)
1454 box.X1 += Settings.PinoutTextOffsetY;
1455 box.Y1 -= Settings.PinoutTextOffsetX;
1457 else
1459 box.X1 += Settings.PinoutTextOffsetX;
1460 box.Y1 += Settings.PinoutTextOffsetY;
1463 if (Gathering)
1465 if (vert)
1467 box.X2 = box.X1;
1468 box.Y2 = box.Y1;
1470 else
1472 box.X2 = box.X1;
1473 box.Y2 = box.Y1;
1475 AddPart (&box);
1476 return;
1479 gui->set_color (Output.fgGC, PCB->PinNameColor);
1481 text.Flags = NoFlags ();
1482 text.Scale = Pad->Thickness / 50;
1483 text.X = box.X1;
1484 text.Y = box.Y1;
1485 text.Direction = vert ? 1 : 0;
1486 text.TextString = name;
1488 DrawTextLowLevel (&text, 0);
1492 /* ---------------------------------------------------------------------------
1493 * clearance for pads
1495 static void
1496 ClearPad (PadTypePtr Pad, Boolean mask)
1498 DrawPadLowLevel(Output.pmGC, Pad, True, mask);
1501 /* ---------------------------------------------------------------------------
1502 * lowlevel drawing routine for lines
1504 static void
1505 DrawLineLowLevel (LineTypePtr Line, Boolean HaveGathered)
1507 if (Gathering && !HaveGathered)
1509 AddPart (Line);
1510 return;
1513 gui->set_line_cap (Output.fgGC, Trace_Cap);
1514 if (TEST_FLAG (THINDRAWFLAG, PCB))
1515 gui->set_line_width (Output.fgGC, 0);
1516 else
1517 gui->set_line_width (Output.fgGC, Line->Thickness);
1519 gui->draw_line (Output.fgGC,
1520 Line->Point1.X, Line->Point1.Y,
1521 Line->Point2.X, Line->Point2.Y);
1524 /* ---------------------------------------------------------------------------
1525 * lowlevel drawing routine for text objects
1527 void
1528 DrawTextLowLevel (TextTypePtr Text, int min_line_width)
1530 LocationType x = 0;
1531 unsigned char *string = (unsigned char *) Text->TextString;
1532 Cardinal n;
1533 FontTypePtr font = &PCB->Font;
1535 if (Gathering)
1537 AddPart (Text);
1538 return;
1541 while (string && *string)
1543 /* draw lines if symbol is valid and data is present */
1544 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid)
1546 LineTypePtr line = font->Symbol[*string].Line;
1547 LineType newline;
1549 for (n = font->Symbol[*string].LineN; n; n--, line++)
1551 /* create one line, scale, move, rotate and swap it */
1552 newline = *line;
1553 newline.Point1.X = (newline.Point1.X + x) * Text->Scale / 100;
1554 newline.Point1.Y = newline.Point1.Y * Text->Scale / 100;
1555 newline.Point2.X = (newline.Point2.X + x) * Text->Scale / 100;
1556 newline.Point2.Y = newline.Point2.Y * Text->Scale / 100;
1557 newline.Thickness = newline.Thickness * Text->Scale / 200;
1558 if (newline.Thickness < min_line_width)
1559 newline.Thickness = min_line_width;
1561 RotateLineLowLevel (&newline, 0, 0, Text->Direction);
1563 /* the labels of SMD objects on the bottom
1564 * side haven't been swapped yet, only their offset
1566 if (TEST_FLAG (ONSOLDERFLAG, Text))
1568 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X);
1569 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y);
1570 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X);
1571 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y);
1573 /* add offset and draw line */
1574 newline.Point1.X += Text->X;
1575 newline.Point1.Y += Text->Y;
1576 newline.Point2.X += Text->X;
1577 newline.Point2.Y += Text->Y;
1578 DrawLineLowLevel (&newline, True);
1581 /* move on to next cursor position */
1582 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta);
1584 else
1586 /* the default symbol is a filled box */
1587 BoxType defaultsymbol = PCB->Font.DefaultSymbol;
1588 LocationType size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5;
1590 defaultsymbol.X1 = (defaultsymbol.X1 + x) * Text->Scale / 100;
1591 defaultsymbol.Y1 = defaultsymbol.Y1 * Text->Scale / 100;
1592 defaultsymbol.X2 = (defaultsymbol.X2 + x) * Text->Scale / 100;
1593 defaultsymbol.Y2 = defaultsymbol.Y2 * Text->Scale / 100;
1595 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction);
1597 /* add offset and draw box */
1598 defaultsymbol.X1 += Text->X;
1599 defaultsymbol.Y1 += Text->Y;
1600 defaultsymbol.X2 += Text->X;
1601 defaultsymbol.Y2 += Text->Y;
1602 gui->fill_rect (Output.fgGC,
1603 defaultsymbol.X1, defaultsymbol.Y1,
1604 defaultsymbol.X2, defaultsymbol.Y2);
1606 /* move on to next cursor position */
1607 x += size;
1609 string++;
1613 /* ---------------------------------------------------------------------------
1614 * lowlevel drawing routine for polygons
1616 static void
1617 DrawPolygonLowLevel (PolygonTypePtr Polygon)
1619 if (!Polygon->Clipped)
1620 return;
1622 if (Gathering)
1624 AddPart (Polygon);
1625 return;
1628 printf ("DrawPolygonLowLevel: Called without Gathering set!\n");
1631 /* ---------------------------------------------------------------------------
1632 * lowlevel routine to element arcs
1634 static void
1635 DrawArcLowLevel (ArcTypePtr Arc)
1637 if (!Arc->Thickness)
1638 return;
1639 if (Gathering)
1641 AddPart (Arc);
1642 return;
1645 if (TEST_FLAG (THINDRAWFLAG, PCB))
1646 gui->set_line_width (Output.fgGC, 0);
1647 else
1648 gui->set_line_width (Output.fgGC, Arc->Thickness);
1649 gui->set_line_cap (Output.fgGC, Trace_Cap);
1651 gui->draw_arc (Output.fgGC, Arc->X, Arc->Y, Arc->Width,
1652 Arc->Height, Arc->StartAngle, Arc->Delta);
1655 /* ---------------------------------------------------------------------------
1656 * draws the package of an element
1658 static void
1659 DrawElementPackageLowLevel (ElementTypePtr Element, int unused)
1661 /* draw lines, arcs, text and pins */
1662 ELEMENTLINE_LOOP (Element);
1664 DrawLineLowLevel (line, False);
1666 END_LOOP;
1667 ARC_LOOP (Element);
1669 DrawArcLowLevel (arc);
1671 END_LOOP;
1674 /* ---------------------------------------------------------------------------
1675 * draw a via object
1677 void
1678 DrawVia (PinTypePtr Via, int unused)
1680 if (!Gathering)
1681 SetPVColor (Via, VIA_TYPE);
1682 DrawPinOrViaLowLevel (Via, True);
1683 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1684 DrawPinOrViaNameLowLevel (Via);
1687 /* ---------------------------------------------------------------------------
1688 * draw a via without dealing with polygon clearance
1690 static void
1691 DrawPlainVia (PinTypePtr Via, Boolean holeToo)
1693 if (!Gathering)
1694 SetPVColor (Via, VIA_TYPE);
1695 DrawPinOrViaLowLevel (Via, holeToo);
1696 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1697 DrawPinOrViaNameLowLevel (Via);
1700 /* ---------------------------------------------------------------------------
1701 * draws the name of a via
1703 void
1704 DrawViaName (PinTypePtr Via, int unused)
1706 if (!Gathering)
1708 if (TEST_FLAG (SELECTEDFLAG, Via))
1709 gui->set_color (Output.fgGC, PCB->ViaSelectedColor);
1710 else
1711 gui->set_color (Output.fgGC, PCB->ViaColor);
1713 DrawPinOrViaNameLowLevel (Via);
1716 /* ---------------------------------------------------------------------------
1717 * draw a pin object
1719 void
1720 DrawPin (PinTypePtr Pin, int unused)
1723 if (!Gathering)
1724 SetPVColor (Pin, PIN_TYPE);
1725 DrawPinOrViaLowLevel (Pin, True);
1727 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1728 || doing_pinout)
1729 DrawPinOrViaNameLowLevel (Pin);
1732 /* ---------------------------------------------------------------------------
1733 * draw a pin without clearing around polygons
1735 static void
1736 DrawPlainPin (PinTypePtr Pin, Boolean holeToo)
1738 if (!Gathering)
1739 SetPVColor (Pin, PIN_TYPE);
1740 DrawPinOrViaLowLevel (Pin, holeToo);
1741 if (!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1742 DrawPinOrViaNameLowLevel (Pin);
1745 /* ---------------------------------------------------------------------------
1746 * draws the name of a pin
1748 void
1749 DrawPinName (PinTypePtr Pin, int unused)
1751 if (!Gathering)
1753 if (TEST_FLAG (SELECTEDFLAG, Pin))
1754 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1755 else
1756 gui->set_color (Output.fgGC, PCB->PinColor);
1758 DrawPinOrViaNameLowLevel (Pin);
1761 /* ---------------------------------------------------------------------------
1762 * draw a pad object
1764 void
1765 DrawPad (PadTypePtr Pad, int unused)
1767 if (!Gathering)
1769 if (doing_pinout)
1770 gui->set_color (Output.fgGC, PCB->PinColor);
1771 else if (TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pad))
1773 if (TEST_FLAG (WARNFLAG, Pad))
1774 gui->set_color (Output.fgGC, PCB->WarnColor);
1775 else if (TEST_FLAG (SELECTEDFLAG, Pad))
1776 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1777 else
1778 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1780 else if (FRONT (Pad))
1781 gui->set_color (Output.fgGC, PCB->PinColor);
1782 else
1783 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
1785 DrawPadLowLevel (Output.fgGC, Pad, False, False);
1786 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1787 DrawPadNameLowLevel (Pad);
1790 /* ---------------------------------------------------------------------------
1791 * draws the name of a pad
1793 void
1794 DrawPadName (PadTypePtr Pad, int unused)
1796 if (!Gathering)
1798 if (TEST_FLAG (SELECTEDFLAG, Pad))
1799 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1800 else if (FRONT (Pad))
1801 gui->set_color (Output.fgGC, PCB->PinColor);
1802 else
1803 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
1805 DrawPadNameLowLevel (Pad);
1808 /* ---------------------------------------------------------------------------
1809 * draws a line on a layer
1811 void
1812 DrawLine (LayerTypePtr Layer, LineTypePtr Line, int unused)
1814 if (!Gathering)
1816 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Line))
1818 if (TEST_FLAG (SELECTEDFLAG, Line))
1819 gui->set_color (Output.fgGC, Layer->SelectedColor);
1820 else
1821 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1823 else
1824 gui->set_color (Output.fgGC, Layer->Color);
1826 DrawLineLowLevel (Line, False);
1829 /* ---------------------------------------------------------------------------
1830 * draws a ratline
1832 void
1833 DrawRat (RatTypePtr Line, int unused)
1835 if (!Gathering)
1837 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Line))
1839 if (TEST_FLAG (SELECTEDFLAG, Line))
1840 gui->set_color (Output.fgGC, PCB->RatSelectedColor);
1841 else
1842 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1844 else
1845 gui->set_color (Output.fgGC, PCB->RatColor);
1847 if (Settings.RatThickness < 20)
1848 Line->Thickness = pixel_slop * Settings.RatThickness;
1849 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1850 if (TEST_FLAG(VIAFLAG, Line))
1852 int w = Line->Thickness;
1854 if (Gathering)
1856 BoxType b;
1858 b.X1 = Line->Point1.X - w * 2 - w / 2;
1859 b.X2 = Line->Point1.X + w * 2 + w / 2;
1860 b.Y1 = Line->Point1.Y - w * 2 - w / 2;
1861 b.Y2 = Line->Point1.Y + w * 2 + w / 2;
1862 AddPart(&b);
1864 else
1866 if (TEST_FLAG (THINDRAWFLAG, PCB))
1867 gui->set_line_width (Output.fgGC, 0);
1868 else
1869 gui->set_line_width (Output.fgGC, w);
1870 gui->draw_arc (Output.fgGC, Line->Point1.X, Line->Point1.Y,
1871 w * 2, w * 2, 0, 360);
1874 else
1875 DrawLineLowLevel ((LineTypePtr) Line, False);
1878 /* ---------------------------------------------------------------------------
1879 * draws an arc on a layer
1881 void
1882 DrawArc (LayerTypePtr Layer, ArcTypePtr Arc, int unused)
1884 if (!Arc->Thickness)
1885 return;
1886 if (!Gathering)
1888 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Arc))
1890 if (TEST_FLAG (SELECTEDFLAG, Arc))
1891 gui->set_color (Output.fgGC, Layer->SelectedColor);
1892 else
1893 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1895 else
1896 gui->set_color (Output.fgGC, Layer->Color);
1898 DrawArcLowLevel (Arc);
1901 /* ---------------------------------------------------------------------------
1902 * draws a text on a layer
1904 void
1905 DrawText (LayerTypePtr Layer, TextTypePtr Text, int unused)
1907 int min_silk_line;
1908 if (!Layer->On)
1909 return;
1910 if (TEST_FLAG (SELECTEDFLAG, Text))
1911 gui->set_color (Output.fgGC, Layer->SelectedColor);
1912 else
1913 gui->set_color (Output.fgGC, Layer->Color);
1914 if (Layer == & PCB->Data->SILKLAYER
1915 || Layer == & PCB->Data->BACKSILKLAYER)
1916 min_silk_line = PCB->minSlk;
1917 else
1918 min_silk_line = PCB->minWid;
1919 DrawTextLowLevel (Text, min_silk_line);
1922 /* ---------------------------------------------------------------------------
1923 * draws text on a layer
1925 static void
1926 DrawRegularText (LayerTypePtr Layer, TextTypePtr Text, int unused)
1928 int min_silk_line;
1929 if (TEST_FLAG (SELECTEDFLAG, Text))
1930 gui->set_color (Output.fgGC, Layer->SelectedColor);
1931 else
1932 gui->set_color (Output.fgGC, Layer->Color);
1933 if (Layer == & PCB->Data->SILKLAYER
1934 || Layer == & PCB->Data->BACKSILKLAYER)
1935 min_silk_line = PCB->minSlk;
1936 else
1937 min_silk_line = PCB->minWid;
1938 DrawTextLowLevel (Text, min_silk_line);
1941 /* ---------------------------------------------------------------------------
1942 * draws a polygon on a layer
1944 void
1945 DrawPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon, int unused)
1947 DrawPolygonLowLevel (Polygon);
1951 thin_callback (PLINE * pl, LayerTypePtr lay, PolygonTypePtr poly)
1953 int i, *x, *y;
1954 VNODE *v;
1956 i = 0;
1957 x = (int *) malloc (pl->Count * sizeof (int));
1958 y = (int *) malloc (pl->Count * sizeof (int));
1959 for (v = &pl->head; i < pl->Count; v = v->next)
1961 x[i] = v->point[0];
1962 y[i++] = v->point[1];
1964 gui->set_line_cap (Output.fgGC, Round_Cap);
1965 gui->set_line_width (Output.fgGC, 0);
1966 for (i = 0; i < pl->Count - 1; i++)
1968 gui->draw_line (Output.fgGC, x[i], y[i], x[i + 1], y[i + 1]);
1969 // gui->fill_circle (Output.fgGC, x[i], y[i], 30);
1971 gui->draw_line (Output.fgGC, x[pl->Count - 1], y[pl->Count - 1], x[0],
1972 y[0]);
1973 free (x);
1974 free (y);
1975 return 0;
1979 /* ---------------------------------------------------------------------------
1980 * draws a polygon
1982 static void
1983 DrawPlainPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
1985 static char *color;
1987 if (!Polygon->Clipped)
1988 return;
1990 if (Gathering)
1992 AddPart (Polygon);
1993 return;
1996 if (TEST_FLAG (SELECTEDFLAG, Polygon))
1997 color = Layer->SelectedColor;
1998 else if (TEST_FLAG (FOUNDFLAG, Polygon))
1999 color = PCB->ConnectedColor;
2000 else
2001 color = Layer->Color;
2002 gui->set_color (Output.fgGC, color);
2004 if (gui->thindraw_pcb_polygon != NULL &&
2005 (TEST_FLAG (THINDRAWFLAG, PCB) ||
2006 TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
2007 gui->thindraw_pcb_polygon (Output.fgGC, Polygon, clip_box);
2008 else
2009 gui->fill_pcb_polygon (Output.fgGC, Polygon, clip_box);
2011 /* If checking planes, thin-draw any pieces which have been clipped away */
2012 if (gui->thindraw_pcb_polygon != NULL &&
2013 TEST_FLAG (CHECKPLANESFLAG, PCB) &&
2014 !TEST_FLAG (FULLPOLYFLAG, Polygon))
2016 PolygonType poly = *Polygon;
2018 for (poly.Clipped = Polygon->Clipped->f;
2019 poly.Clipped != Polygon->Clipped;
2020 poly.Clipped = poly.Clipped->f)
2021 gui->thindraw_pcb_polygon (Output.fgGC, &poly, clip_box);
2025 /* ---------------------------------------------------------------------------
2026 * draws an element
2028 void
2029 DrawElement (ElementTypePtr Element, int unused)
2031 DrawElementPackage (Element, unused);
2032 DrawElementName (Element, unused);
2033 DrawElementPinsAndPads (Element, unused);
2036 /* ---------------------------------------------------------------------------
2037 * draws the name of an element
2039 void
2040 DrawElementName (ElementTypePtr Element, int unused)
2042 if (gui->gui && TEST_FLAG (HIDENAMESFLAG, PCB))
2043 return;
2044 if (TEST_FLAG (HIDENAMEFLAG, Element))
2045 return;
2046 if (doing_pinout || doing_assy)
2047 gui->set_color (Output.fgGC, PCB->ElementColor);
2048 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, Element)))
2049 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
2050 else if (FRONT (Element))
2051 gui->set_color (Output.fgGC, PCB->ElementColor);
2052 else
2053 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
2054 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2057 /* ---------------------------------------------------------------------------
2058 * draws the package of an element
2060 void
2061 DrawElementPackage (ElementTypePtr Element, int unused)
2063 /* set color and draw lines, arcs, text and pins */
2064 if (doing_pinout || doing_assy)
2065 gui->set_color (Output.fgGC, PCB->ElementColor);
2066 else if (TEST_FLAG (SELECTEDFLAG, Element))
2067 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
2068 else if (FRONT (Element))
2069 gui->set_color (Output.fgGC, PCB->ElementColor);
2070 else
2071 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
2072 DrawElementPackageLowLevel (Element, unused);
2075 /* ---------------------------------------------------------------------------
2076 * draw pins of an element
2078 void
2079 DrawElementPinsAndPads (ElementTypePtr Element, int unused)
2081 PAD_LOOP (Element);
2083 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
2084 DrawPad (pad, unused);
2086 END_LOOP;
2087 PIN_LOOP (Element);
2089 DrawPin (pin, unused);
2091 END_LOOP;
2094 /* ---------------------------------------------------------------------------
2095 * erase a via
2097 void
2098 EraseVia (PinTypePtr Via)
2100 Erasing++;
2101 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2102 DrawPinOrViaLowLevel (Via, False);
2103 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
2104 DrawPinOrViaNameLowLevel (Via);
2105 Erasing--;
2108 /* ---------------------------------------------------------------------------
2109 * erase a ratline
2111 void
2112 EraseRat (RatTypePtr Rat)
2114 Erasing++;
2115 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2116 if (TEST_FLAG(VIAFLAG, Rat))
2118 int w = Rat->Thickness;
2120 if (TEST_FLAG (THINDRAWFLAG, PCB))
2121 gui->set_line_width (Output.fgGC, 0);
2122 else
2123 gui->set_line_width (Output.fgGC, w);
2124 gui->draw_arc (Output.fgGC, Rat->Point1.X, Rat->Point1.Y,
2125 w * 2, w * 2, 0, 360);
2127 else
2128 DrawLineLowLevel ((LineTypePtr) Rat, False);
2129 Erasing--;
2133 /* ---------------------------------------------------------------------------
2134 * erase a via name
2136 void
2137 EraseViaName (PinTypePtr Via)
2139 Erasing++;
2140 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2141 DrawPinOrViaNameLowLevel (Via);
2142 Erasing--;
2145 /* ---------------------------------------------------------------------------
2146 * erase a pad object
2148 void
2149 ErasePad (PadTypePtr Pad)
2151 Erasing++;
2152 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2153 DrawPadLowLevel (Output.fgGC, Pad, False, False);
2154 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
2155 DrawPadNameLowLevel (Pad);
2156 Erasing--;
2159 /* ---------------------------------------------------------------------------
2160 * erase a pad name
2162 void
2163 ErasePadName (PadTypePtr Pad)
2165 Erasing++;
2166 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2167 DrawPadNameLowLevel (Pad);
2168 Erasing--;
2171 /* ---------------------------------------------------------------------------
2172 * erase a pin object
2174 void
2175 ErasePin (PinTypePtr Pin)
2177 Erasing++;
2178 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2179 DrawPinOrViaLowLevel (Pin, False);
2180 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
2181 DrawPinOrViaNameLowLevel (Pin);
2182 Erasing--;
2185 /* ---------------------------------------------------------------------------
2186 * erase a pin name
2188 void
2189 ErasePinName (PinTypePtr Pin)
2191 Erasing++;
2192 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2193 DrawPinOrViaNameLowLevel (Pin);
2194 Erasing--;
2197 /* ---------------------------------------------------------------------------
2198 * erases a line on a layer
2200 void
2201 EraseLine (LineTypePtr Line)
2203 Erasing++;
2204 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2205 DrawLineLowLevel (Line, False);
2206 Erasing--;
2209 /* ---------------------------------------------------------------------------
2210 * erases an arc on a layer
2212 void
2213 EraseArc (ArcTypePtr Arc)
2215 if (!Arc->Thickness)
2216 return;
2217 Erasing++;
2218 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2219 DrawArcLowLevel (Arc);
2220 Erasing--;
2223 /* ---------------------------------------------------------------------------
2224 * erases a text on a layer
2226 void
2227 EraseText (LayerTypePtr Layer, TextTypePtr Text)
2229 int min_silk_line;
2230 Erasing++;
2231 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2232 if (Layer == & PCB->Data->SILKLAYER
2233 || Layer == & PCB->Data->BACKSILKLAYER)
2234 min_silk_line = PCB->minSlk;
2235 else
2236 min_silk_line = PCB->minWid;
2237 DrawTextLowLevel (Text, min_silk_line);
2238 Erasing--;
2241 /* ---------------------------------------------------------------------------
2242 * erases a polygon on a layer
2244 void
2245 ErasePolygon (PolygonTypePtr Polygon)
2247 Erasing++;
2248 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2249 DrawPolygonLowLevel (Polygon);
2250 Erasing--;
2253 /* ---------------------------------------------------------------------------
2254 * erases an element
2256 void
2257 EraseElement (ElementTypePtr Element)
2259 Erasing++;
2260 /* set color and draw lines, arcs, text and pins */
2261 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2262 ELEMENTLINE_LOOP (Element);
2264 DrawLineLowLevel (line, False);
2266 END_LOOP;
2267 ARC_LOOP (Element);
2269 DrawArcLowLevel (arc);
2271 END_LOOP;
2272 if (!TEST_FLAG (HIDENAMEFLAG, Element))
2273 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2274 EraseElementPinsAndPads (Element);
2275 Erasing--;
2278 /* ---------------------------------------------------------------------------
2279 * erases all pins and pads of an element
2281 void
2282 EraseElementPinsAndPads (ElementTypePtr Element)
2284 Erasing++;
2285 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2286 PIN_LOOP (Element);
2288 DrawPinOrViaLowLevel (pin, False);
2289 if (TEST_FLAG (DISPLAYNAMEFLAG, pin))
2290 DrawPinOrViaNameLowLevel (pin);
2292 END_LOOP;
2293 PAD_LOOP (Element);
2295 DrawPadLowLevel (Output.fgGC, pad, False, False);
2296 if (TEST_FLAG (DISPLAYNAMEFLAG, pad))
2297 DrawPadNameLowLevel (pad);
2299 END_LOOP;
2300 Erasing--;
2303 /* ---------------------------------------------------------------------------
2304 * erases the name of an element
2306 void
2307 EraseElementName (ElementTypePtr Element)
2309 if (TEST_FLAG (HIDENAMEFLAG, Element))
2310 return;
2311 Erasing++;
2312 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2313 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2314 Erasing--;
2318 void
2319 EraseObject (int type, void *lptr, void *ptr)
2321 switch (type)
2323 case VIA_TYPE:
2324 case PIN_TYPE:
2325 ErasePin ((PinTypePtr) ptr);
2326 break;
2327 case TEXT_TYPE:
2328 case ELEMENTNAME_TYPE:
2329 EraseText (lptr, (TextTypePtr) ptr);
2330 break;
2331 case POLYGON_TYPE:
2332 ErasePolygon ((PolygonTypePtr) ptr);
2333 break;
2334 case ELEMENT_TYPE:
2335 EraseElement ((ElementTypePtr) ptr);
2336 break;
2337 case LINE_TYPE:
2338 case ELEMENTLINE_TYPE:
2339 case RATLINE_TYPE:
2340 EraseLine ((LineTypePtr) ptr);
2341 break;
2342 case PAD_TYPE:
2343 ErasePad ((PadTypePtr) ptr);
2344 break;
2345 case ARC_TYPE:
2346 case ELEMENTARC_TYPE:
2347 EraseArc ((ArcTypePtr) ptr);
2348 break;
2349 default:
2350 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
2356 void
2357 DrawObject (int type, void *ptr1, void *ptr2, int unused)
2359 switch (type)
2361 case VIA_TYPE:
2362 if (PCB->ViaOn)
2363 DrawVia ((PinTypePtr) ptr2, 0);
2364 break;
2365 case LINE_TYPE:
2366 if (((LayerTypePtr) ptr1)->On)
2367 DrawLine ((LayerTypePtr) ptr1, (LineTypePtr) ptr2, 0);
2368 break;
2369 case ARC_TYPE:
2370 if (((LayerTypePtr) ptr1)->On)
2371 DrawArc ((LayerTypePtr) ptr1, (ArcTypePtr) ptr2, 0);
2372 break;
2373 case TEXT_TYPE:
2374 if (((LayerTypePtr) ptr1)->On)
2375 DrawText ((LayerTypePtr) ptr1, (TextTypePtr) ptr2, 0);
2376 break;
2377 case POLYGON_TYPE:
2378 if (((LayerTypePtr) ptr1)->On)
2379 DrawPolygon ((LayerTypePtr) ptr1, (PolygonTypePtr) ptr2, 0);
2380 break;
2381 case ELEMENT_TYPE:
2382 if (PCB->ElementOn &&
2383 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
2384 DrawElement ((ElementTypePtr) ptr2, 0);
2385 break;
2386 case RATLINE_TYPE:
2387 if (PCB->RatOn)
2388 DrawRat ((RatTypePtr) ptr2, 0);
2389 break;
2390 case PIN_TYPE:
2391 if (PCB->PinOn)
2392 DrawPin ((PinTypePtr) ptr2, 0);
2393 break;
2394 case PAD_TYPE:
2395 if (PCB->PinOn)
2396 DrawPad ((PadTypePtr) ptr2, 0);
2397 break;
2398 case ELEMENTNAME_TYPE:
2399 if (PCB->ElementOn &&
2400 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
2401 DrawElementName ((ElementTypePtr) ptr1, 0);
2402 break;
2406 /* ---------------------------------------------------------------------------
2407 * HID drawing callback.
2410 void
2411 hid_expose_callback (HID * hid, BoxType * region, void *item)
2413 HID *old_gui = gui;
2414 hidGC savebg = Output.bgGC;
2415 hidGC savefg = Output.fgGC;
2416 hidGC savepm = Output.pmGC;
2418 gui = hid;
2419 Output.fgGC = gui->make_gc ();
2420 Output.bgGC = gui->make_gc ();
2421 Output.pmGC = gui->make_gc ();
2423 render = True;
2424 Gathering = False;
2426 /*printf("\033[32mhid_expose_callback, s=%p %d\033[0m\n", &(SWAP_IDENT), SWAP_IDENT); */
2428 hid->set_color (Output.pmGC, "erase");
2429 hid->set_color (Output.bgGC, "drill");
2431 if (item)
2433 doing_pinout = True;
2434 DrawElement (item, 0);
2435 doing_pinout = False;
2437 else
2438 DrawEverything (region);
2440 gui->destroy_gc (Output.fgGC);
2441 gui->destroy_gc (Output.bgGC);
2442 gui->destroy_gc (Output.pmGC);
2443 gui = old_gui;
2444 Output.fgGC = savefg;
2445 Output.bgGC = savebg;
2446 Output.pmGC = savepm;
2448 Gathering = True;