hid/gtk: Fix strncat length when building accelerator string. (CODE!)
[geda-pcb/gde.git] / src / draw.c
blobf3bb2cbc8934d66870b43c46e0b5b3a85351b99d
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, 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 static int
354 lowvia_callback (const BoxType * b, void *cl)
356 PinTypePtr via = (PinTypePtr) b;
357 if (!via->Mask)
358 DrawPlainVia (via, False);
359 return 1;
362 /* ---------------------------------------------------------------------------
363 * prints assembly drawing.
366 static void
367 PrintAssembly (const BoxType * drawn_area, int side_group, int swap_ident)
369 int save_swap = SWAP_IDENT;
371 gui->set_draw_faded (Output.fgGC, 1);
372 SWAP_IDENT = swap_ident;
373 DrawLayerGroup (side_group, drawn_area);
374 r_search (PCB->Data->via_tree, drawn_area, NULL, lowvia_callback, NULL);
375 DrawTop (drawn_area);
376 gui->set_draw_faded (Output.fgGC, 0);
378 /* draw package */
379 DrawSilk (swap_ident,
380 swap_ident ? SOLDER_LAYER : COMPONENT_LAYER,
381 drawn_area);
382 SWAP_IDENT = save_swap;
385 /* ---------------------------------------------------------------------------
386 * initializes some identifiers for a new zoom factor and redraws whole screen
388 static void
389 DrawEverything (BoxTypePtr drawn_area)
391 int i, ngroups, side;
392 int plated;
393 int component, solder;
394 /* This is the list of layer groups we will draw. */
395 int do_group[MAX_LAYER];
396 /* This is the reverse of the order in which we draw them. */
397 int drawn_groups[MAX_LAYER];
399 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
400 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
402 memset (do_group, 0, sizeof (do_group));
403 for (ngroups = 0, i = 0; i < max_layer; i++)
405 LayerType *l = LAYER_ON_STACK (i);
406 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
407 if (l->On && !do_group[group])
409 do_group[group] = 1;
410 drawn_groups[ngroups++] = group;
414 component = GetLayerGroupNumberByNumber (max_layer + COMPONENT_LAYER);
415 solder = GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER);
418 * first draw all 'invisible' stuff
420 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
421 && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
423 r_search (PCB->Data->pad_tree, drawn_area, NULL, backPad_callback,
424 NULL);
425 if (PCB->ElementOn)
427 r_search (PCB->Data->element_tree, drawn_area, NULL, backE_callback,
428 NULL);
429 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
430 backN_callback, NULL);
431 DrawLayer (&(PCB->Data->BACKSILKLAYER), drawn_area);
435 /* draw all layers in layerstack order */
436 for (i = ngroups - 1; i >= 0; i--)
438 int group = drawn_groups[i];
440 if (gui->set_layer (0, group, 0))
442 if (DrawLayerGroup (group, drawn_area) && !gui->gui)
444 int save_swap = SWAP_IDENT;
446 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
447 continue;
448 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback,
449 NULL);
450 r_search (PCB->Data->via_tree, drawn_area, NULL, pin_callback,
451 NULL);
452 /* draw element pads */
453 if (group == component || group == solder)
455 SWAP_IDENT = (group == solder);
456 r_search (PCB->Data->pad_tree, drawn_area, NULL,
457 pad_callback, NULL);
459 SWAP_IDENT = save_swap;
461 if (!gui->gui)
463 /* draw holes */
464 plated = -1;
465 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback,
466 &plated);
467 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback,
468 &plated);
473 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
474 return;
476 /* draw vias below silk */
477 if (PCB->ViaOn && gui->gui)
478 r_search (PCB->Data->via_tree, drawn_area, NULL, lowvia_callback, NULL);
479 /* Draw the solder mask if turned on */
480 if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
482 int save_swap = SWAP_IDENT;
483 SWAP_IDENT = 0;
484 DrawMask (drawn_area);
485 SWAP_IDENT = save_swap;
487 if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
489 int save_swap = SWAP_IDENT;
490 SWAP_IDENT = 1;
491 DrawMask (drawn_area);
492 SWAP_IDENT = save_swap;
494 /* Draw pins, pads, vias below silk */
495 if (gui->gui)
496 DrawTop (drawn_area);
497 else
499 HoleCountStruct hcs;
500 hcs.nplated = hcs.nunplated = 0;
501 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_counting_callback,
502 &hcs);
503 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_counting_callback,
504 &hcs);
505 if (hcs.nplated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
507 plated = 1;
508 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback,
509 &plated);
510 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback,
511 &plated);
513 if (hcs.nunplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
515 plated = 0;
516 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback,
517 &plated);
518 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback,
519 &plated);
522 /* Draw top silkscreen */
523 if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
524 DrawSilk (0, COMPONENT_LAYER, drawn_area);
525 if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
526 DrawSilk (1, SOLDER_LAYER, drawn_area);
527 if (gui->gui)
529 /* Draw element Marks */
530 if (PCB->PinOn)
531 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
532 NULL);
533 /* Draw rat lines on top */
534 if (PCB->RatOn)
535 DrawRats(drawn_area);
538 for (side = 0; side <= 1; side++)
540 int doit;
541 Boolean NoData = True;
542 ALLPAD_LOOP (PCB->Data);
544 if ((TEST_FLAG (ONSOLDERFLAG, pad) && side == SOLDER_LAYER)
545 || (!TEST_FLAG (ONSOLDERFLAG, pad) && side == COMPONENT_LAYER))
547 NoData = False;
548 break;
551 ENDALL_LOOP;
553 if (side == SOLDER_LAYER)
554 doit = gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), NoData);
555 else
556 doit = gui->set_layer ("toppaste", SL (PASTE, TOP), NoData);
557 if (doit)
559 gui->set_color (Output.fgGC, PCB->ElementColor);
560 ALLPAD_LOOP (PCB->Data);
562 if ((TEST_FLAG (ONSOLDERFLAG, pad) && side == SOLDER_LAYER)
563 || (!TEST_FLAG (ONSOLDERFLAG, pad)
564 && side == COMPONENT_LAYER))
565 if (!TEST_FLAG (NOPASTEFLAG, pad))
566 DrawPadLowLevel (Output.fgGC, pad, False, False);
568 ENDALL_LOOP;
572 doing_assy = True;
573 if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
574 PrintAssembly (drawn_area, component, 0);
576 if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
577 PrintAssembly (drawn_area, solder, 1);
578 doing_assy = False;
580 if (gui->set_layer ("fab", SL (FAB, 0), 0))
581 PrintFab ();
584 static void
585 DrawEMark (ElementTypePtr e, LocationType X, LocationType Y,
586 Boolean invisible)
588 int mark_size = EMARK_SIZE;
589 if (!PCB->InvisibleObjectsOn && invisible)
590 return;
592 if (e->PinN && mark_size > e->Pin[0].Thickness / 2)
593 mark_size = e->Pin[0].Thickness / 2;
594 if (e->PadN && mark_size > e->Pad[0].Thickness / 2)
595 mark_size = e->Pad[0].Thickness / 2;
597 gui->set_color (Output.fgGC,
598 invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
599 gui->set_line_cap (Output.fgGC, Trace_Cap);
600 gui->set_line_width (Output.fgGC, 0);
601 gui->draw_line (Output.fgGC, X - mark_size, Y, X, Y - mark_size);
602 gui->draw_line (Output.fgGC, X + mark_size, Y, X, Y - mark_size);
603 gui->draw_line (Output.fgGC, X - mark_size, Y, X, Y + mark_size);
604 gui->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
607 * If an element is locked, place a "L" on top of the "diamond".
608 * This provides a nice visual indication that it is locked that
609 * works even for color blind users.
611 if (TEST_FLAG (LOCKFLAG, e) )
613 gui->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
614 gui->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
619 static int
620 via_callback (const BoxType * b, void *cl)
622 PinTypePtr via = (PinTypePtr) b;
623 if (via->Mask)
624 DrawPlainVia (via, False);
625 return 1;
628 static int
629 pin_callback (const BoxType * b, void *cl)
631 DrawPlainPin ((PinTypePtr) b, False);
632 return 1;
635 static int
636 pad_callback (const BoxType * b, void *cl)
638 PadTypePtr pad = (PadTypePtr) b;
639 if (FRONT (pad))
640 DrawPad (pad, 0);
641 return 1;
644 /* ---------------------------------------------------------------------------
645 * draws pins pads and vias
647 static void
648 DrawTop (const BoxType * screen)
650 if (PCB->PinOn || doing_assy)
652 /* draw element pins */
653 r_search (PCB->Data->pin_tree, screen, NULL, pin_callback, NULL);
654 /* draw element pads */
655 r_search (PCB->Data->pad_tree, screen, NULL, pad_callback, NULL);
657 /* draw vias */
658 if (PCB->ViaOn || doing_assy)
660 r_search (PCB->Data->via_tree, screen, NULL, via_callback, NULL);
661 r_search (PCB->Data->via_tree, screen, NULL, hole_callback, NULL);
663 if (PCB->PinOn || doing_assy)
664 r_search (PCB->Data->pin_tree, screen, NULL, hole_callback, NULL);
667 struct pin_info
669 Boolean arg;
670 LayerTypePtr Layer;
673 static int
674 clearPin_callback (const BoxType * b, void *cl)
676 PinTypePtr pin = (PinTypePtr) b;
677 struct pin_info *i = (struct pin_info *) cl;
678 if (i->arg)
679 ClearOnlyPin (pin, True);
680 return 1;
682 static int
683 poly_callback (const BoxType * b, void *cl)
685 struct pin_info *i = (struct pin_info *) cl;
687 DrawPlainPolygon (i->Layer, (PolygonTypePtr) b);
688 return 1;
691 static int
692 clearPad_callback (const BoxType * b, void *cl)
694 PadTypePtr pad = (PadTypePtr) b;
695 if (!XOR (TEST_FLAG (ONSOLDERFLAG, pad), SWAP_IDENT))
696 ClearPad (pad, True);
697 return 1;
700 /* ---------------------------------------------------------------------------
701 * Draws silk layer.
704 static void
705 DrawSilk (int new_swap, int layer, BoxTypePtr drawn_area)
707 #if 0
708 /* This code is used when you want to mask silk to avoid exposed
709 pins and pads. We decided it was a bad idea to do this
710 unconditionally, but the code remains. */
711 struct pin_info info;
712 #endif
713 int save_swap = SWAP_IDENT;
714 SWAP_IDENT = new_swap;
716 #if 0
717 if (gui->poly_before)
719 gui->use_mask (HID_MASK_BEFORE);
720 #endif
721 DrawLayer (LAYER_PTR (max_layer + layer), drawn_area);
722 /* draw package */
723 r_search (PCB->Data->element_tree, drawn_area, NULL, frontE_callback,
724 NULL);
725 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
726 frontN_callback, NULL);
727 #if 0
730 gui->use_mask (HID_MASK_CLEAR);
731 info.arg = True;
732 r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, &info);
733 r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, &info);
734 r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &info);
736 if (gui->poly_after)
738 gui->use_mask (HID_MASK_AFTER);
739 DrawLayer (LAYER_PTR (max_layer + layer), drawn_area);
740 /* draw package */
741 r_search (PCB->Data->element_tree, drawn_area, NULL, frontE_callback,
742 NULL);
743 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
744 frontN_callback, NULL);
746 gui->use_mask (HID_MASK_OFF);
747 #endif
748 SWAP_IDENT = save_swap;
751 /* ---------------------------------------------------------------------------
752 * draws solder mask layer - this will cover nearly everything
754 static void
755 DrawMask (BoxType * screen)
757 struct pin_info info;
758 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
760 OutputType *out = &Output;
762 info.arg = True;
764 if (thin)
765 gui->set_color (Output.pmGC, PCB->MaskColor);
766 else
768 if (gui->poly_before)
770 gui->use_mask (HID_MASK_BEFORE);
771 gui->set_color (out->fgGC, PCB->MaskColor);
772 gui->fill_rect (out->fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
774 gui->use_mask (HID_MASK_CLEAR);
777 r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, &info);
778 r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, &info);
779 r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &info);
781 if (thin)
782 gui->set_color (Output.pmGC, "erase");
783 else
785 if (gui->poly_after)
787 gui->use_mask (HID_MASK_AFTER);
788 gui->set_color (out->fgGC, PCB->MaskColor);
789 gui->fill_rect (out->fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
791 gui->use_mask (HID_MASK_OFF);
794 #if 0
795 /* Some fabs want the board outline on the solder mask layer. If
796 you need this, change the '0' above to '1', and the code below
797 will copy the outline layer to the mask layers. */
798 if (!gui->gui)
800 int i;
801 for (i=PCB->Data->LayerN; i>=0; i--)
803 LayerTypePtr Layer = PCB->Data->Layer + i;
804 if (strcasecmp (Layer->Name, "outline") == 0)
805 DrawLayer (Layer, screen);
808 #endif
811 static void
812 DrawRats (BoxTypePtr drawn_area)
815 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
816 * XXX gtk only allows negative drawing.
817 * XXX using the mask here is to get rat transparency
819 int can_mask = strcmp(gui->name, "lesstif") == 0;
821 if (can_mask)
822 gui->use_mask (HID_MASK_CLEAR);
823 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
824 if (can_mask)
825 gui->use_mask (HID_MASK_OFF);
828 static int
829 line_callback (const BoxType * b, void *cl)
831 DrawLine ((LayerTypePtr) cl, (LineTypePtr) b, 0);
832 return 1;
835 static int
836 arc_callback (const BoxType * b, void *cl)
838 DrawArc ((LayerTypePtr) cl, (ArcTypePtr) b, 0);
839 return 1;
842 static int
843 text_callback (const BoxType * b, void *cl)
845 DrawRegularText ((LayerTypePtr) cl, (TextTypePtr) b, 0);
846 return 1;
850 /* ---------------------------------------------------------------------------
851 * draws one non-copper layer
853 void
854 DrawLayer (LayerTypePtr Layer, BoxType * screen)
856 struct pin_info info;
858 /* print the non-clearing polys */
859 info.Layer = Layer;
860 info.arg = False;
861 clip_box = screen;
862 r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
864 /* draw all visible lines this layer */
865 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
867 /* draw the layer arcs on screen */
868 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
870 /* draw the layer text on screen */
871 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
872 clip_box = NULL;
875 /* ---------------------------------------------------------------------------
876 * draws one layer group. Returns non-zero if pins and pads should be
877 * drawn with this group.
879 static int
880 DrawLayerGroup (int group, const BoxType * screen)
882 int i, rv = 1;
883 int layernum;
884 struct pin_info info;
885 LayerTypePtr Layer;
886 int n_entries = PCB->LayerGroups.Number[group];
887 Cardinal *layers = PCB->LayerGroups.Entries[group];
889 clip_box = screen;
890 for (i = n_entries - 1; i >= 0; i--)
892 layernum = layers[i];
893 Layer = PCB->Data->Layer + layers[i];
894 if (strcasecmp (Layer->Name, "outline") == 0
895 || strcasecmp (Layer->Name, "route") == 0)
896 rv = 0;
897 if (layernum < max_layer && Layer->On)
899 /* draw all polygons on this layer */
900 if (Layer->PolygonN)
902 info.Layer = Layer;
903 info.arg = True;
904 r_search (Layer->polygon_tree, screen, NULL, poly_callback,
905 &info);
906 info.arg = False;
909 if (TEST_FLAG (CHECKPLANESFLAG, PCB))
910 continue;
912 /* draw all visible lines this layer */
913 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
915 /* draw the layer arcs on screen */
916 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
918 /* draw the layer text on screen */
919 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
923 if (n_entries > 1)
924 rv = 1;
925 return rv;
928 /* ---------------------------------------------------------------------------
929 * draws one polygon
930 * x and y are already in display coordinates
931 * the points are numbered:
933 * 5 --- 6
934 * / \
935 * 4 7
936 * | |
937 * 3 0
938 * \ /
939 * 2 --- 1
941 static void
942 DrawSpecialPolygon (HID * hid, hidGC DrawGC,
943 LocationType X, LocationType Y, int Thickness)
945 static FloatPolyType p[8] = {
947 0.5, -TAN_22_5_DEGREE_2},
949 TAN_22_5_DEGREE_2, -0.5},
951 -TAN_22_5_DEGREE_2, -0.5},
953 -0.5, -TAN_22_5_DEGREE_2},
955 -0.5, TAN_22_5_DEGREE_2},
957 -TAN_22_5_DEGREE_2, 0.5},
959 TAN_22_5_DEGREE_2, 0.5},
961 0.5, TAN_22_5_DEGREE_2}
963 static int special_size = 0;
964 static int scaled_x[8];
965 static int scaled_y[8];
966 int polygon_x[9];
967 int polygon_y[9];
968 int i;
971 if (Thickness != special_size)
973 special_size = Thickness;
974 for (i = 0; i < 8; i++)
976 scaled_x[i] = p[i].X * special_size;
977 scaled_y[i] = p[i].Y * special_size;
980 /* add line offset */
981 for (i = 0; i < 8; i++)
983 polygon_x[i] = X + scaled_x[i];
984 polygon_y[i] = Y + scaled_y[i];
986 if (TEST_FLAG (THINDRAWFLAG, PCB))
988 int i;
989 hid->set_line_cap (Output.fgGC, Round_Cap);
990 hid->set_line_width (Output.fgGC, 0);
991 polygon_x[8] = X + scaled_x[0];
992 polygon_y[8] = Y + scaled_y[0];
993 for (i = 0; i < 8; i++)
994 hid->draw_line (DrawGC, polygon_x[i], polygon_y[i],
995 polygon_x[i + 1], polygon_y[i + 1]);
997 else
998 hid->fill_polygon (DrawGC, 8, polygon_x, polygon_y);
1001 /* ---------------------------------------------------------------------------
1002 * lowlevel drawing routine for pins and vias
1004 static void
1005 DrawPinOrViaLowLevel (PinTypePtr Ptr, Boolean drawHole)
1007 if (Gathering)
1009 AddPart (Ptr);
1010 return;
1013 if (TEST_FLAG (HOLEFLAG, Ptr))
1015 if (drawHole)
1017 gui->fill_circle (Output.bgGC, Ptr->X, Ptr->Y, Ptr->Thickness / 2);
1018 gui->set_line_cap (Output.fgGC, Round_Cap);
1019 gui->set_line_width (Output.fgGC, 0);
1020 gui->draw_arc (Output.fgGC, Ptr->X, Ptr->Y,
1021 Ptr->Thickness / 2, Ptr->Thickness / 2, 0, 360);
1023 return;
1025 if (TEST_FLAG (SQUAREFLAG, Ptr))
1027 int l, r, t, b;
1028 l = Ptr->X - Ptr->Thickness / 2;
1029 b = Ptr->Y - Ptr->Thickness / 2;
1030 r = l + Ptr->Thickness;
1031 t = b + Ptr->Thickness;
1032 if (TEST_FLAG (THINDRAWFLAG, PCB))
1034 gui->set_line_cap (Output.fgGC, Round_Cap);
1035 gui->set_line_width (Output.fgGC, 0);
1036 gui->draw_line (Output.fgGC, r, t, r, b);
1037 gui->draw_line (Output.fgGC, l, t, l, b);
1038 gui->draw_line (Output.fgGC, r, t, l, t);
1039 gui->draw_line (Output.fgGC, r, b, l, b);
1041 else
1043 gui->fill_rect (Output.fgGC, l, b, r, t);
1046 else if (TEST_FLAG (OCTAGONFLAG, Ptr))
1048 gui->set_line_cap (Output.fgGC, Round_Cap);
1049 gui->set_line_width (Output.fgGC,
1050 (Ptr->Thickness - Ptr->DrillingHole) / 2);
1052 /* transform X11 specific coord system */
1053 DrawSpecialPolygon (gui, Output.fgGC, Ptr->X, Ptr->Y, Ptr->Thickness);
1055 else
1056 { /* draw a round pin or via */
1057 if (TEST_FLAG (THINDRAWFLAG, PCB))
1059 gui->set_line_cap (Output.fgGC, Round_Cap);
1060 gui->set_line_width (Output.fgGC, 0);
1061 gui->draw_arc (Output.fgGC, Ptr->X, Ptr->Y,
1062 Ptr->Thickness / 2, Ptr->Thickness / 2, 0, 360);
1064 else
1066 gui->fill_circle (Output.fgGC, Ptr->X, Ptr->Y, Ptr->Thickness / 2);
1070 /* and the drilling hole (which is always round */
1071 if (drawHole)
1073 if (TEST_FLAG (THINDRAWFLAG, PCB))
1075 gui->set_line_cap (Output.fgGC, Round_Cap);
1076 gui->set_line_width (Output.fgGC, 0);
1077 gui->draw_arc (Output.fgGC,
1078 Ptr->X, Ptr->Y, Ptr->DrillingHole / 2,
1079 Ptr->DrillingHole / 2, 0, 360);
1081 else
1083 gui->fill_circle (Output.bgGC, Ptr->X, Ptr->Y,
1084 Ptr->DrillingHole / 2);
1089 /**************************************************************
1090 * draw pin/via hole
1092 static void
1093 DrawHole (PinTypePtr Ptr)
1095 if (TEST_FLAG (THINDRAWFLAG, PCB))
1097 if (!TEST_FLAG (HOLEFLAG, Ptr))
1099 gui->set_line_cap (Output.fgGC, Round_Cap);
1100 gui->set_line_width (Output.fgGC, 0);
1101 gui->draw_arc (Output.fgGC,
1102 Ptr->X, Ptr->Y, Ptr->DrillingHole / 2,
1103 Ptr->DrillingHole / 2, 0, 360);
1106 else
1108 gui->fill_circle (Output.bgGC, Ptr->X, Ptr->Y, Ptr->DrillingHole / 2);
1110 if (TEST_FLAG (HOLEFLAG, Ptr))
1112 if (TEST_FLAG (WARNFLAG, Ptr))
1113 gui->set_color (Output.fgGC, PCB->WarnColor);
1114 else if (TEST_FLAG (SELECTEDFLAG, Ptr))
1115 gui->set_color (Output.fgGC, PCB->ViaSelectedColor);
1116 else
1117 gui->set_color (Output.fgGC, Settings.BlackColor);
1119 gui->set_line_cap (Output.fgGC, Round_Cap);
1120 gui->set_line_width (Output.fgGC, 0);
1121 gui->draw_arc (Output.fgGC,
1122 Ptr->X, Ptr->Y, Ptr->DrillingHole / 2,
1123 Ptr->DrillingHole / 2, 0, 360);
1127 /*******************************************************************
1128 * draw clearance in pixmask around pins and vias that pierce polygons
1130 static void
1131 ClearOnlyPin (PinTypePtr Pin, Boolean mask)
1133 BDimension half =
1134 (mask ? Pin->Mask / 2 : (Pin->Thickness + Pin->Clearance) / 2);
1136 if (!mask && TEST_FLAG (HOLEFLAG, Pin))
1137 return;
1138 if (half == 0)
1139 return;
1140 if (!mask && Pin->Clearance <= 0)
1141 return;
1143 /* Clear the area around the pin */
1144 if (TEST_FLAG (SQUAREFLAG, Pin))
1146 int l, r, t, b;
1147 l = Pin->X - half;
1148 b = Pin->Y - half;
1149 r = l + half * 2;
1150 t = b + half * 2;
1151 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
1153 gui->set_line_cap (Output.pmGC, Round_Cap);
1154 gui->set_line_width (Output.pmGC, 0);
1155 gui->draw_line (Output.pmGC, r, t, r, b);
1156 gui->draw_line (Output.pmGC, l, t, l, b);
1157 gui->draw_line (Output.pmGC, r, t, l, t);
1158 gui->draw_line (Output.pmGC, r, b, l, b);
1160 else
1161 gui->fill_rect (Output.pmGC, l, b, r, t);
1163 else if (TEST_FLAG (OCTAGONFLAG, Pin))
1165 gui->set_line_cap (Output.pmGC, Round_Cap);
1166 gui->set_line_width (Output.pmGC, (Pin->Clearance + Pin->Thickness
1167 - Pin->DrillingHole));
1169 DrawSpecialPolygon (gui, Output.pmGC, Pin->X, Pin->Y, half * 2);
1171 else
1173 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
1174 gui->draw_arc (Output.pmGC, Pin->X, Pin->Y, half, half, 0, 360);
1175 else
1176 gui->fill_circle (Output.pmGC, Pin->X, Pin->Y, half);
1180 /* ---------------------------------------------------------------------------
1181 * lowlevel drawing routine for pins and vias that pierce polygons
1183 void
1184 ClearPin (PinTypePtr Pin, int Type, int unused)
1186 BDimension half = (Pin->Thickness + Pin->Clearance) / 2;
1188 if (Gathering)
1190 AddPart (Pin);
1191 return;
1193 /* Clear the area around the pin */
1194 if (TEST_FLAG (SQUAREFLAG, Pin))
1196 int l, r, t, b;
1197 l = Pin->X - half;
1198 b = Pin->Y - half;
1199 r = l + half * 2;
1200 t = b + half * 2;
1201 gui->fill_rect (Output.pmGC, l, b, r, t);
1203 else if (TEST_FLAG (OCTAGONFLAG, Pin))
1205 gui->set_line_cap (Output.pmGC, Round_Cap);
1206 gui->set_line_width (Output.pmGC, (Pin->Clearance + Pin->Thickness
1207 - Pin->DrillingHole) / 2);
1209 DrawSpecialPolygon (gui, Output.pmGC, Pin->X, Pin->Y, half * 2);
1211 else
1213 gui->fill_circle (Output.pmGC, Pin->X, Pin->Y, half);
1215 if ((!TEST_FLAG (PINFLAG, Pin) && !PCB->ViaOn)
1216 || (TEST_FLAG (PINFLAG, Pin) && !PCB->PinOn))
1217 return;
1218 /* now draw the pin or via as appropriate */
1219 switch (Type)
1221 case VIA_TYPE:
1222 case PIN_TYPE:
1223 SetPVColor (Pin, Type);
1224 DrawPinOrViaLowLevel (Pin, True);
1225 break;
1226 case NO_TYPE:
1227 default:
1228 break;
1233 #if VERTICAL_TEXT
1234 /* vertical text handling provided by Martin Devera with fixes by harry eaton */
1236 /* draw vertical text; xywh is bounding, de is text's descend used for
1237 positioning */
1238 static void
1239 DrawVText (int x, int y, int w, int h, char *str)
1241 GdkPixmap *pm;
1242 GdkImage *im;
1243 GdkGCValues values;
1244 guint32 pixel;
1245 int i, j;
1247 if (!str || !*str)
1248 return;
1250 pm = gdk_pixmap_new (DrawingWindow, w, h, -1);
1252 /* draw into pixmap */
1253 gdk_draw_rectangle (pm, Output.bgGC, TRUE, 0, 0, w, h);
1255 gui_draw_string_markup (DrawingWindow, Output.font_desc, Output.fgGC,
1256 0, 0, str);
1258 im = gdk_drawable_get_image (pm, 0, 0, w, h);
1259 gdk_gc_get_values (Output.fgGC, &values);
1261 /* draw Transpose(im). TODO: Pango should be doing vertical text soon */
1262 for (i = 0; i < w; i++)
1263 for (j = 0; j < h; j++)
1265 pixel = gdk_image_get_pixel (im, i, j);
1266 if (pixel == values.foreground.pixel)
1267 gdk_draw_point (DrawingWindow, Output.fgGC, x + j, y + w - i - 1);
1269 g_object_unref (G_OBJECT (pm));
1271 #endif
1273 /* ---------------------------------------------------------------------------
1274 * lowlevel drawing routine for pin and via names
1276 static void
1277 DrawPinOrViaNameLowLevel (PinTypePtr Ptr)
1279 char *name;
1280 BoxType box;
1281 Boolean vert;
1282 TextType text;
1284 if (!Ptr->Name || !Ptr->Name[0])
1285 name = EMPTY (Ptr->Number);
1286 else
1287 name = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? Ptr->Number : Ptr->Name);
1289 vert = TEST_FLAG (EDGE2FLAG, Ptr);
1291 if (vert)
1293 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1294 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
1296 else
1298 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
1299 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1301 if (Gathering)
1303 if (vert)
1305 box.X2 = box.X1;
1306 box.Y2 = box.Y1;
1308 else
1310 box.X2 = box.X1;
1311 box.Y2 = box.Y1;
1313 /*printf("AddPart: x1=%d y1=%d x2=%d y2=%d\n", box.X1, box.Y1, box.X2, box.Y2);*/
1314 AddPart (&box);
1315 return;
1317 /*printf("DrawPin(%d,%d): x=%d y=%d w=%d h=%d\n",
1318 TO_DRAW_X(Ptr->X), TO_DRAW_Y(Ptr->Y), box.X1, box.Y1, width, height);*/
1320 gui->set_color (Output.fgGC, PCB->PinNameColor);
1322 text.Flags = NoFlags ();
1323 text.Scale = Ptr->Thickness / 80;
1324 text.X = box.X1;
1325 text.Y = box.Y1;
1326 text.Direction = vert ? 1 : 0;
1327 text.TextString = name;
1329 if (gui->gui)
1330 doing_pinout++;
1331 DrawTextLowLevel (&text, 0);
1332 if (gui->gui)
1333 doing_pinout--;
1336 /* ---------------------------------------------------------------------------
1337 * lowlevel drawing routine for pads
1340 static void
1341 DrawPadLowLevel (hidGC gc, PadTypePtr Pad, Boolean clear, Boolean mask)
1343 int w = clear ? (mask ? Pad->Mask : Pad->Thickness + Pad->Clearance)
1344 : Pad->Thickness;
1346 if (Gathering)
1348 AddPart (Pad);
1349 return;
1352 if (clear && !mask && Pad->Clearance <= 0)
1353 return;
1355 if (TEST_FLAG (THINDRAWFLAG, PCB) ||
1356 (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
1358 int x1, y1, x2, y2, t, t2;
1359 t = w / 2;
1360 t2 = w - t;
1361 x1 = Pad->Point1.X;
1362 y1 = Pad->Point1.Y;
1363 x2 = Pad->Point2.X;
1364 y2 = Pad->Point2.Y;
1365 if (x1 > x2 || y1 > y2)
1367 /* this is a silly way to swap the variables */
1368 x1 ^= x2;
1369 x2 ^= x1;
1370 x1 ^= x2;
1371 y1 ^= y2;
1372 y2 ^= y1;
1373 y1 ^= y2;
1375 gui->set_line_cap (gc, Round_Cap);
1376 gui->set_line_width (gc, 0);
1377 if (TEST_FLAG (SQUAREFLAG, Pad)
1378 && (x1 == x2 || y1 == y2))
1380 x1 -= t;
1381 y1 -= t;
1382 x2 += t2;
1383 y2 += t2;
1384 gui->draw_line (gc, x1, y1, x1, y2);
1385 gui->draw_line (gc, x1, y2, x2, y2);
1386 gui->draw_line (gc, x2, y2, x2, y1);
1387 gui->draw_line (gc, x2, y1, x1, y1);
1389 else if (TEST_FLAG (SQUAREFLAG, Pad))
1391 /* slanted square pad */
1392 float tx, ty, theta;
1394 theta = atan2 (y2-y1, x2-x1);
1396 /* T is a vector half a thickness long, in the direction of
1397 one of the corners. */
1398 tx = t * cos (theta + M_PI/4) * sqrt(2.0);
1399 ty = t * sin (theta + M_PI/4) * sqrt(2.0);
1401 gui->draw_line (gc, x1-tx, y1-ty, x2+ty, y2-tx);
1402 gui->draw_line (gc, x2+ty, y2-tx, x2+tx, y2+ty);
1403 gui->draw_line (gc, x2+tx, y2+ty, x1-ty, y1+tx);
1404 gui->draw_line (gc, x1-ty, y1+tx, x1-tx, y1-ty);
1406 else if (x1 == x2 && y1 == y2)
1408 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 0, 360);
1410 else if (x1 == x2)
1412 gui->draw_line (gc, x1 - t, y1, x2 - t, y2);
1413 gui->draw_line (gc, x1 + t2, y1, x2 + t2, y2);
1414 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 0, -180);
1415 gui->draw_arc (gc, x2, y2, w / 2, w / 2, 180, -180);
1417 else if (y1 == y2)
1419 gui->draw_line (gc, x1, y1 - t, x2, y2 - t);
1420 gui->draw_line (gc, x1, y1 + t2, x2, y2 + t2);
1421 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 90, -180);
1422 gui->draw_arc (gc, x2, y2, w / 2, w / 2, 270, -180);
1424 else
1426 /* Slanted round-end pads. */
1427 LocationType dx, dy, ox, oy;
1428 float h;
1430 dx = x2 - x1;
1431 dy = y2 - y1;
1432 h = t / sqrt (SQUARE (dx) + SQUARE (dy));
1433 ox = dy * h + 0.5 * SGN (dy);
1434 oy = -(dx * h + 0.5 * SGN (dx));
1436 gui->draw_line (gc, x1 + ox, y1 + oy, x2 + ox, y2 + oy);
1438 if (abs (ox) >= pixel_slop || abs (oy) >= pixel_slop)
1440 LocationType angle = atan2 ((float) dx, (float) dy) * 57.295779;
1441 gui->draw_line (gc, x1 - ox, y1 - oy, x2 - ox, y2 - oy);
1442 gui->draw_arc (gc,
1443 x1, y1, t, t, angle - 180, 180);
1444 gui->draw_arc (gc, x2, y2, t, t, angle, 180);
1448 else if (Pad->Point1.X == Pad->Point2.X
1449 && Pad->Point1.Y == Pad->Point2.Y)
1451 if (TEST_FLAG (SQUAREFLAG, Pad))
1453 int l, r, t, b;
1454 l = Pad->Point1.X - w / 2;
1455 b = Pad->Point1.Y - w / 2;
1456 r = l + w;
1457 t = b + w;
1458 gui->fill_rect (gc, l, b, r, t);
1460 else
1462 gui->fill_circle (gc, Pad->Point1.X, Pad->Point1.Y, w / 2);
1465 else
1467 gui->set_line_cap (gc,
1468 TEST_FLAG (SQUAREFLAG,
1469 Pad) ? Square_Cap : Round_Cap);
1470 gui->set_line_width (gc, w);
1472 gui->draw_line (gc,
1473 Pad->Point1.X, Pad->Point1.Y,
1474 Pad->Point2.X, Pad->Point2.Y);
1476 #if 0
1477 { /* Draw bounding box for test */
1478 BoxType *box = &Pad->BoundingBox;
1479 gui->set_line_width (gc, 0);
1480 gui->draw_line (gc, box->X1, box->Y1, box->X1, box->Y2);
1481 gui->draw_line (gc, box->X1, box->Y2, box->X2, box->Y2);
1482 gui->draw_line (gc, box->X2, box->Y2, box->X2, box->Y1);
1483 gui->draw_line (gc, box->X2, box->Y1, box->X1, box->Y1);
1485 #endif
1488 /* ---------------------------------------------------------------------------
1489 * lowlevel drawing routine for pad names
1492 static void
1493 DrawPadNameLowLevel (PadTypePtr Pad)
1495 BoxType box;
1496 char *name;
1497 Boolean vert;
1498 TextType text;
1500 if (!Pad->Name || !Pad->Name[0])
1501 name = EMPTY (Pad->Number);
1502 else
1503 name = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? Pad->Number : Pad->Name);
1505 /* should text be vertical ? */
1506 vert = (Pad->Point1.X == Pad->Point2.X);
1508 if (vert)
1510 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1511 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1513 else
1515 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1516 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1519 if (vert)
1521 box.X1 += Settings.PinoutTextOffsetY;
1522 box.Y1 -= Settings.PinoutTextOffsetX;
1524 else
1526 box.X1 += Settings.PinoutTextOffsetX;
1527 box.Y1 += Settings.PinoutTextOffsetY;
1530 if (Gathering)
1532 if (vert)
1534 box.X2 = box.X1;
1535 box.Y2 = box.Y1;
1537 else
1539 box.X2 = box.X1;
1540 box.Y2 = box.Y1;
1542 AddPart (&box);
1543 return;
1546 gui->set_color (Output.fgGC, PCB->PinNameColor);
1548 text.Flags = NoFlags ();
1549 text.Scale = Pad->Thickness / 50;
1550 text.X = box.X1;
1551 text.Y = box.Y1;
1552 text.Direction = vert ? 1 : 0;
1553 text.TextString = name;
1555 DrawTextLowLevel (&text, 0);
1559 /* ---------------------------------------------------------------------------
1560 * clearance for pads
1562 static void
1563 ClearPad (PadTypePtr Pad, Boolean mask)
1565 DrawPadLowLevel(Output.pmGC, Pad, True, mask);
1568 /* ---------------------------------------------------------------------------
1569 * lowlevel drawing routine for lines
1571 static void
1572 DrawLineLowLevel (LineTypePtr Line, Boolean HaveGathered)
1574 if (Gathering && !HaveGathered)
1576 AddPart (Line);
1577 return;
1580 gui->set_line_cap (Output.fgGC, Trace_Cap);
1581 if (TEST_FLAG (THINDRAWFLAG, PCB))
1582 gui->set_line_width (Output.fgGC, 0);
1583 else
1584 gui->set_line_width (Output.fgGC, Line->Thickness);
1586 gui->draw_line (Output.fgGC,
1587 Line->Point1.X, Line->Point1.Y,
1588 Line->Point2.X, Line->Point2.Y);
1591 /* ---------------------------------------------------------------------------
1592 * lowlevel drawing routine for text objects
1594 void
1595 DrawTextLowLevel (TextTypePtr Text, int min_line_width)
1597 LocationType x = 0;
1598 unsigned char *string = (unsigned char *) Text->TextString;
1599 Cardinal n;
1600 FontTypePtr font = &PCB->Font;
1602 if (Gathering)
1604 AddPart (Text);
1605 return;
1608 while (string && *string)
1610 /* draw lines if symbol is valid and data is present */
1611 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid)
1613 LineTypePtr line = font->Symbol[*string].Line;
1614 LineType newline;
1616 for (n = font->Symbol[*string].LineN; n; n--, line++)
1618 /* create one line, scale, move, rotate and swap it */
1619 newline = *line;
1620 newline.Point1.X = (newline.Point1.X + x) * Text->Scale / 100;
1621 newline.Point1.Y = newline.Point1.Y * Text->Scale / 100;
1622 newline.Point2.X = (newline.Point2.X + x) * Text->Scale / 100;
1623 newline.Point2.Y = newline.Point2.Y * Text->Scale / 100;
1624 newline.Thickness = newline.Thickness * Text->Scale / 200;
1625 if (newline.Thickness < min_line_width)
1626 newline.Thickness = min_line_width;
1628 RotateLineLowLevel (&newline, 0, 0, Text->Direction);
1630 /* the labels of SMD objects on the bottom
1631 * side haven't been swapped yet, only their offset
1633 if (TEST_FLAG (ONSOLDERFLAG, Text))
1635 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X);
1636 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y);
1637 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X);
1638 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y);
1640 /* add offset and draw line */
1641 newline.Point1.X += Text->X;
1642 newline.Point1.Y += Text->Y;
1643 newline.Point2.X += Text->X;
1644 newline.Point2.Y += Text->Y;
1645 DrawLineLowLevel (&newline, True);
1648 /* move on to next cursor position */
1649 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta);
1651 else
1653 /* the default symbol is a filled box */
1654 BoxType defaultsymbol = PCB->Font.DefaultSymbol;
1655 LocationType size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5;
1657 defaultsymbol.X1 = (defaultsymbol.X1 + x) * Text->Scale / 100;
1658 defaultsymbol.Y1 = defaultsymbol.Y1 * Text->Scale / 100;
1659 defaultsymbol.X2 = (defaultsymbol.X2 + x) * Text->Scale / 100;
1660 defaultsymbol.Y2 = defaultsymbol.Y2 * Text->Scale / 100;
1662 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction);
1664 /* add offset and draw box */
1665 defaultsymbol.X1 += Text->X;
1666 defaultsymbol.Y1 += Text->Y;
1667 defaultsymbol.X2 += Text->X;
1668 defaultsymbol.Y2 += Text->Y;
1669 gui->fill_rect (Output.fgGC,
1670 defaultsymbol.X1, defaultsymbol.Y1,
1671 defaultsymbol.X2, defaultsymbol.Y2);
1673 /* move on to next cursor position */
1674 x += size;
1676 string++;
1680 /* ---------------------------------------------------------------------------
1681 * lowlevel drawing routine for polygons
1683 static void
1684 DrawPolygonLowLevel (PolygonTypePtr Polygon)
1686 if (!Polygon->Clipped)
1687 return;
1689 if (Gathering)
1691 AddPart (Polygon);
1692 return;
1695 printf ("DrawPolygonLowLevel: Called without Gathering set!\n");
1698 /* ---------------------------------------------------------------------------
1699 * lowlevel routine to element arcs
1701 static void
1702 DrawArcLowLevel (ArcTypePtr Arc)
1704 if (!Arc->Thickness)
1705 return;
1706 if (Gathering)
1708 AddPart (Arc);
1709 return;
1712 if (TEST_FLAG (THINDRAWFLAG, PCB))
1713 gui->set_line_width (Output.fgGC, 0);
1714 else
1715 gui->set_line_width (Output.fgGC, Arc->Thickness);
1716 gui->set_line_cap (Output.fgGC, Trace_Cap);
1718 gui->draw_arc (Output.fgGC, Arc->X, Arc->Y, Arc->Width,
1719 Arc->Height, Arc->StartAngle, Arc->Delta);
1722 /* ---------------------------------------------------------------------------
1723 * draws the package of an element
1725 static void
1726 DrawElementPackageLowLevel (ElementTypePtr Element, int unused)
1728 /* draw lines, arcs, text and pins */
1729 ELEMENTLINE_LOOP (Element);
1731 DrawLineLowLevel (line, False);
1733 END_LOOP;
1734 ARC_LOOP (Element);
1736 DrawArcLowLevel (arc);
1738 END_LOOP;
1741 /* ---------------------------------------------------------------------------
1742 * draw a via object
1744 void
1745 DrawVia (PinTypePtr Via, int unused)
1747 if (!Gathering)
1748 SetPVColor (Via, VIA_TYPE);
1749 //if (!doing_pinout && !TEST_FLAG (HOLEFLAG, Via) && TEST_ANY_PIPS (Via))
1750 // ClearPin (Via, VIA_TYPE, 0);
1751 //else
1752 DrawPinOrViaLowLevel (Via, True);
1753 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1754 DrawPinOrViaNameLowLevel (Via);
1757 /* ---------------------------------------------------------------------------
1758 * draw a via without dealing with polygon clearance
1760 static void
1761 DrawPlainVia (PinTypePtr Via, Boolean holeToo)
1763 if (!Gathering)
1764 SetPVColor (Via, VIA_TYPE);
1765 DrawPinOrViaLowLevel (Via, holeToo);
1766 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1767 DrawPinOrViaNameLowLevel (Via);
1770 /* ---------------------------------------------------------------------------
1771 * draws the name of a via
1773 void
1774 DrawViaName (PinTypePtr Via, int unused)
1776 if (!Gathering)
1778 if (TEST_FLAG (SELECTEDFLAG, Via))
1779 gui->set_color (Output.fgGC, PCB->ViaSelectedColor);
1780 else
1781 gui->set_color (Output.fgGC, PCB->ViaColor);
1783 DrawPinOrViaNameLowLevel (Via);
1786 /* ---------------------------------------------------------------------------
1787 * draw a pin object
1789 void
1790 DrawPin (PinTypePtr Pin, int unused)
1792 //if (!doing_pinout && !TEST_FLAG (HOLEFLAG, Pin) && TEST_ANY_PIPS (Pin))
1793 // ClearPin (Pin, PIN_TYPE, 0);
1794 //else
1796 if (!Gathering)
1797 SetPVColor (Pin, PIN_TYPE);
1798 DrawPinOrViaLowLevel (Pin, True);
1800 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1801 || doing_pinout)
1802 DrawPinOrViaNameLowLevel (Pin);
1805 /* ---------------------------------------------------------------------------
1806 * draw a pin without clearing around polygons
1808 static void
1809 DrawPlainPin (PinTypePtr Pin, Boolean holeToo)
1811 if (!Gathering)
1812 SetPVColor (Pin, PIN_TYPE);
1813 DrawPinOrViaLowLevel (Pin, holeToo);
1814 if (!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1815 DrawPinOrViaNameLowLevel (Pin);
1818 /* ---------------------------------------------------------------------------
1819 * draws the name of a pin
1821 void
1822 DrawPinName (PinTypePtr Pin, int unused)
1824 if (!Gathering)
1826 if (TEST_FLAG (SELECTEDFLAG, Pin))
1827 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1828 else
1829 gui->set_color (Output.fgGC, PCB->PinColor);
1831 DrawPinOrViaNameLowLevel (Pin);
1834 /* ---------------------------------------------------------------------------
1835 * draw a pad object
1837 void
1838 DrawPad (PadTypePtr Pad, int unused)
1840 if (!Gathering)
1842 if (doing_pinout)
1843 gui->set_color (Output.fgGC, PCB->PinColor);
1844 else if (TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pad))
1846 if (TEST_FLAG (WARNFLAG, Pad))
1847 gui->set_color (Output.fgGC, PCB->WarnColor);
1848 else if (TEST_FLAG (SELECTEDFLAG, Pad))
1849 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1850 else
1851 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1853 else if (FRONT (Pad))
1854 gui->set_color (Output.fgGC, PCB->PinColor);
1855 else
1856 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
1858 DrawPadLowLevel (Output.fgGC, Pad, False, False);
1859 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1860 DrawPadNameLowLevel (Pad);
1863 /* ---------------------------------------------------------------------------
1864 * draws the name of a pad
1866 void
1867 DrawPadName (PadTypePtr Pad, int unused)
1869 if (!Gathering)
1871 if (TEST_FLAG (SELECTEDFLAG, Pad))
1872 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1873 else if (FRONT (Pad))
1874 gui->set_color (Output.fgGC, PCB->PinColor);
1875 else
1876 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
1878 DrawPadNameLowLevel (Pad);
1881 /* ---------------------------------------------------------------------------
1882 * draws a line on a layer
1884 void
1885 DrawLine (LayerTypePtr Layer, LineTypePtr Line, int unused)
1887 if (!Gathering)
1889 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Line))
1891 if (TEST_FLAG (SELECTEDFLAG, Line))
1892 gui->set_color (Output.fgGC, Layer->SelectedColor);
1893 else
1894 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1896 else
1897 gui->set_color (Output.fgGC, Layer->Color);
1899 DrawLineLowLevel (Line, False);
1902 /* ---------------------------------------------------------------------------
1903 * draws a ratline
1905 void
1906 DrawRat (RatTypePtr Line, int unused)
1908 if (!Gathering)
1910 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Line))
1912 if (TEST_FLAG (SELECTEDFLAG, Line))
1913 gui->set_color (Output.fgGC, PCB->RatSelectedColor);
1914 else
1915 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1917 else
1918 gui->set_color (Output.fgGC, PCB->RatColor);
1920 if (Settings.RatThickness < 20)
1921 Line->Thickness = pixel_slop * Settings.RatThickness;
1922 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1923 if (TEST_FLAG(VIAFLAG, Line))
1925 int w = Line->Thickness;
1927 if (Gathering)
1929 BoxType b;
1931 b.X1 = Line->Point1.X - w * 2 - w / 2;
1932 b.X2 = Line->Point1.X + w * 2 + w / 2;
1933 b.Y1 = Line->Point1.Y - w * 2 - w / 2;
1934 b.Y2 = Line->Point1.Y + w * 2 + w / 2;
1935 AddPart(&b);
1937 else
1939 if (TEST_FLAG (THINDRAWFLAG, PCB))
1940 gui->set_line_width (Output.fgGC, 0);
1941 else
1942 gui->set_line_width (Output.fgGC, w);
1943 gui->draw_arc (Output.fgGC, Line->Point1.X, Line->Point1.Y,
1944 w * 2, w * 2, 0, 360);
1947 else
1948 DrawLineLowLevel ((LineTypePtr) Line, False);
1951 /* ---------------------------------------------------------------------------
1952 * draws an arc on a layer
1954 void
1955 DrawArc (LayerTypePtr Layer, ArcTypePtr Arc, int unused)
1957 if (!Arc->Thickness)
1958 return;
1959 if (!Gathering)
1961 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Arc))
1963 if (TEST_FLAG (SELECTEDFLAG, Arc))
1964 gui->set_color (Output.fgGC, Layer->SelectedColor);
1965 else
1966 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1968 else
1969 gui->set_color (Output.fgGC, Layer->Color);
1971 DrawArcLowLevel (Arc);
1974 /* ---------------------------------------------------------------------------
1975 * draws a text on a layer
1977 void
1978 DrawText (LayerTypePtr Layer, TextTypePtr Text, int unused)
1980 int min_silk_line;
1981 if (!Layer->On)
1982 return;
1983 if (TEST_FLAG (SELECTEDFLAG, Text))
1984 gui->set_color (Output.fgGC, Layer->SelectedColor);
1985 else
1986 gui->set_color (Output.fgGC, Layer->Color);
1987 if (Layer == & PCB->Data->SILKLAYER
1988 || Layer == & PCB->Data->BACKSILKLAYER)
1989 min_silk_line = PCB->minSlk;
1990 else
1991 min_silk_line = PCB->minWid;
1992 DrawTextLowLevel (Text, min_silk_line);
1995 /* ---------------------------------------------------------------------------
1996 * draws text on a layer
1998 static void
1999 DrawRegularText (LayerTypePtr Layer, TextTypePtr Text, int unused)
2001 int min_silk_line;
2002 if (TEST_FLAG (SELECTEDFLAG, Text))
2003 gui->set_color (Output.fgGC, Layer->SelectedColor);
2004 else
2005 gui->set_color (Output.fgGC, Layer->Color);
2006 if (Layer == & PCB->Data->SILKLAYER
2007 || Layer == & PCB->Data->BACKSILKLAYER)
2008 min_silk_line = PCB->minSlk;
2009 else
2010 min_silk_line = PCB->minWid;
2011 DrawTextLowLevel (Text, min_silk_line);
2014 static int
2015 cp_callback (const BoxType * b, void *cl)
2017 ClearPin ((PinTypePtr) b, (int) (size_t) cl, 0);
2018 return 1;
2021 /* ---------------------------------------------------------------------------
2022 * draws a polygon on a layer
2024 void
2025 DrawPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon, int unused)
2027 int layernum;
2029 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Polygon))
2031 if (TEST_FLAG (SELECTEDFLAG, Polygon))
2032 gui->set_color (Output.fgGC, Layer->SelectedColor);
2033 else
2034 gui->set_color (Output.fgGC, PCB->ConnectedColor);
2036 else
2037 gui->set_color (Output.fgGC, Layer->Color);
2038 layernum = GetLayerNumber (PCB->Data, Layer);
2039 DrawPolygonLowLevel (Polygon);
2040 if (TEST_FLAG (CLEARPOLYFLAG, Polygon))
2042 r_search (PCB->Data->pin_tree, &Polygon->BoundingBox, NULL,
2043 cp_callback, (void *) PIN_TYPE);
2044 r_search (PCB->Data->via_tree, &Polygon->BoundingBox, NULL,
2045 cp_callback, (void *) VIA_TYPE);
2050 thin_callback (PLINE * pl, LayerTypePtr lay, PolygonTypePtr poly)
2052 int i, *x, *y;
2053 VNODE *v;
2055 i = 0;
2056 x = (int *) malloc (pl->Count * sizeof (int));
2057 y = (int *) malloc (pl->Count * sizeof (int));
2058 for (v = &pl->head; i < pl->Count; v = v->next)
2060 x[i] = v->point[0];
2061 y[i++] = v->point[1];
2063 gui->set_line_cap (Output.fgGC, Round_Cap);
2064 gui->set_line_width (Output.fgGC, 0);
2065 for (i = 0; i < pl->Count - 1; i++)
2067 gui->draw_line (Output.fgGC, x[i], y[i], x[i + 1], y[i + 1]);
2068 // gui->fill_circle (Output.fgGC, x[i], y[i], 30);
2070 gui->draw_line (Output.fgGC, x[pl->Count - 1], y[pl->Count - 1], x[0],
2071 y[0]);
2072 free (x);
2073 free (y);
2074 return 0;
2078 /* ---------------------------------------------------------------------------
2079 * draws a polygon
2081 static void
2082 DrawPlainPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
2084 static char *color;
2086 if (!Polygon->Clipped)
2087 return;
2089 if (Gathering)
2091 AddPart (Polygon);
2092 return;
2095 if (TEST_FLAG (SELECTEDFLAG, Polygon))
2096 color = Layer->SelectedColor;
2097 else if (TEST_FLAG (FOUNDFLAG, Polygon))
2098 color = PCB->ConnectedColor;
2099 else
2100 color = Layer->Color;
2101 gui->set_color (Output.fgGC, color);
2103 if (gui->thindraw_pcb_polygon != NULL &&
2104 (TEST_FLAG (THINDRAWFLAG, PCB) ||
2105 TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
2106 gui->thindraw_pcb_polygon (Output.fgGC, Polygon, clip_box);
2107 else
2108 gui->fill_pcb_polygon (Output.fgGC, Polygon, clip_box);
2110 /* If checking planes, thin-draw any pieces which have been clipped away */
2111 if (gui->thindraw_pcb_polygon != NULL &&
2112 TEST_FLAG (CHECKPLANESFLAG, PCB) &&
2113 !TEST_FLAG (FULLPOLYFLAG, Polygon))
2115 PolygonType poly = *Polygon;
2117 for (poly.Clipped = Polygon->Clipped->f;
2118 poly.Clipped != Polygon->Clipped;
2119 poly.Clipped = poly.Clipped->f)
2120 gui->thindraw_pcb_polygon (Output.fgGC, &poly, clip_box);
2124 /* ---------------------------------------------------------------------------
2125 * draws an element
2127 void
2128 DrawElement (ElementTypePtr Element, int unused)
2130 DrawElementPackage (Element, unused);
2131 DrawElementName (Element, unused);
2132 DrawElementPinsAndPads (Element, unused);
2135 /* ---------------------------------------------------------------------------
2136 * draws the name of an element
2138 void
2139 DrawElementName (ElementTypePtr Element, int unused)
2141 if (gui->gui && TEST_FLAG (HIDENAMESFLAG, PCB))
2142 return;
2143 if (TEST_FLAG (HIDENAMEFLAG, Element))
2144 return;
2145 if (doing_pinout || doing_assy)
2146 gui->set_color (Output.fgGC, PCB->ElementColor);
2147 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, Element)))
2148 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
2149 else if (FRONT (Element))
2150 gui->set_color (Output.fgGC, PCB->ElementColor);
2151 else
2152 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
2153 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2156 /* ---------------------------------------------------------------------------
2157 * draws the package of an element
2159 void
2160 DrawElementPackage (ElementTypePtr Element, int unused)
2162 /* set color and draw lines, arcs, text and pins */
2163 if (doing_pinout || doing_assy)
2164 gui->set_color (Output.fgGC, PCB->ElementColor);
2165 else if (TEST_FLAG (SELECTEDFLAG, Element))
2166 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
2167 else if (FRONT (Element))
2168 gui->set_color (Output.fgGC, PCB->ElementColor);
2169 else
2170 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
2171 DrawElementPackageLowLevel (Element, unused);
2174 /* ---------------------------------------------------------------------------
2175 * draw pins of an element
2177 void
2178 DrawElementPinsAndPads (ElementTypePtr Element, int unused)
2180 PAD_LOOP (Element);
2182 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
2183 DrawPad (pad, unused);
2185 END_LOOP;
2186 PIN_LOOP (Element);
2188 DrawPin (pin, unused);
2190 END_LOOP;
2193 /* ---------------------------------------------------------------------------
2194 * erase a via
2196 void
2197 EraseVia (PinTypePtr Via)
2199 Erasing++;
2200 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2201 DrawPinOrViaLowLevel (Via, False);
2202 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
2203 DrawPinOrViaNameLowLevel (Via);
2204 Erasing--;
2207 /* ---------------------------------------------------------------------------
2208 * erase a ratline
2210 void
2211 EraseRat (RatTypePtr Rat)
2213 Erasing++;
2214 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2215 if (TEST_FLAG(VIAFLAG, Rat))
2217 int w = Rat->Thickness;
2219 if (TEST_FLAG (THINDRAWFLAG, PCB))
2220 gui->set_line_width (Output.fgGC, 0);
2221 else
2222 gui->set_line_width (Output.fgGC, w);
2223 gui->draw_arc (Output.fgGC, Rat->Point1.X, Rat->Point1.Y,
2224 w * 2, w * 2, 0, 360);
2226 else
2227 DrawLineLowLevel ((LineTypePtr) Rat, False);
2228 Erasing--;
2232 /* ---------------------------------------------------------------------------
2233 * erase a via name
2235 void
2236 EraseViaName (PinTypePtr Via)
2238 Erasing++;
2239 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2240 DrawPinOrViaNameLowLevel (Via);
2241 Erasing--;
2244 /* ---------------------------------------------------------------------------
2245 * erase a pad object
2247 void
2248 ErasePad (PadTypePtr Pad)
2250 Erasing++;
2251 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2252 DrawPadLowLevel (Output.fgGC, Pad, False, False);
2253 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
2254 DrawPadNameLowLevel (Pad);
2255 Erasing--;
2258 /* ---------------------------------------------------------------------------
2259 * erase a pad name
2261 void
2262 ErasePadName (PadTypePtr Pad)
2264 Erasing++;
2265 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2266 DrawPadNameLowLevel (Pad);
2267 Erasing--;
2270 /* ---------------------------------------------------------------------------
2271 * erase a pin object
2273 void
2274 ErasePin (PinTypePtr Pin)
2276 Erasing++;
2277 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2278 DrawPinOrViaLowLevel (Pin, False);
2279 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
2280 DrawPinOrViaNameLowLevel (Pin);
2281 Erasing--;
2284 /* ---------------------------------------------------------------------------
2285 * erase a pin name
2287 void
2288 ErasePinName (PinTypePtr Pin)
2290 Erasing++;
2291 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2292 DrawPinOrViaNameLowLevel (Pin);
2293 Erasing--;
2296 /* ---------------------------------------------------------------------------
2297 * erases a line on a layer
2299 void
2300 EraseLine (LineTypePtr Line)
2302 Erasing++;
2303 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2304 DrawLineLowLevel (Line, False);
2305 Erasing--;
2308 /* ---------------------------------------------------------------------------
2309 * erases an arc on a layer
2311 void
2312 EraseArc (ArcTypePtr Arc)
2314 if (!Arc->Thickness)
2315 return;
2316 Erasing++;
2317 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2318 DrawArcLowLevel (Arc);
2319 Erasing--;
2322 /* ---------------------------------------------------------------------------
2323 * erases a text on a layer
2325 void
2326 EraseText (LayerTypePtr Layer, TextTypePtr Text)
2328 int min_silk_line;
2329 Erasing++;
2330 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2331 if (Layer == & PCB->Data->SILKLAYER
2332 || Layer == & PCB->Data->BACKSILKLAYER)
2333 min_silk_line = PCB->minSlk;
2334 else
2335 min_silk_line = PCB->minWid;
2336 DrawTextLowLevel (Text, min_silk_line);
2337 Erasing--;
2340 /* ---------------------------------------------------------------------------
2341 * erases a polygon on a layer
2343 void
2344 ErasePolygon (PolygonTypePtr Polygon)
2346 Erasing++;
2347 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2348 DrawPolygonLowLevel (Polygon);
2349 Erasing--;
2352 /* ---------------------------------------------------------------------------
2353 * erases an element
2355 void
2356 EraseElement (ElementTypePtr Element)
2358 Erasing++;
2359 /* set color and draw lines, arcs, text and pins */
2360 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2361 ELEMENTLINE_LOOP (Element);
2363 DrawLineLowLevel (line, False);
2365 END_LOOP;
2366 ARC_LOOP (Element);
2368 DrawArcLowLevel (arc);
2370 END_LOOP;
2371 if (!TEST_FLAG (HIDENAMEFLAG, Element))
2372 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2373 EraseElementPinsAndPads (Element);
2374 Erasing--;
2377 /* ---------------------------------------------------------------------------
2378 * erases all pins and pads of an element
2380 void
2381 EraseElementPinsAndPads (ElementTypePtr Element)
2383 Erasing++;
2384 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2385 PIN_LOOP (Element);
2387 /* if (TEST_ANY_PIPS (pin))
2389 ClearPin (pin, NO_TYPE, 0);
2390 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2393 DrawPinOrViaLowLevel (pin, False);
2394 if (TEST_FLAG (DISPLAYNAMEFLAG, pin))
2395 DrawPinOrViaNameLowLevel (pin);
2397 END_LOOP;
2398 PAD_LOOP (Element);
2400 DrawPadLowLevel (Output.fgGC, pad, False, False);
2401 if (TEST_FLAG (DISPLAYNAMEFLAG, pad))
2402 DrawPadNameLowLevel (pad);
2404 END_LOOP;
2405 Erasing--;
2408 /* ---------------------------------------------------------------------------
2409 * erases the name of an element
2411 void
2412 EraseElementName (ElementTypePtr Element)
2414 if (TEST_FLAG (HIDENAMEFLAG, Element))
2415 return;
2416 Erasing++;
2417 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2418 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2419 Erasing--;
2423 void
2424 EraseObject (int type, void *lptr, void *ptr)
2426 switch (type)
2428 case VIA_TYPE:
2429 case PIN_TYPE:
2430 ErasePin ((PinTypePtr) ptr);
2431 break;
2432 case TEXT_TYPE:
2433 case ELEMENTNAME_TYPE:
2434 EraseText (lptr, (TextTypePtr) ptr);
2435 break;
2436 case POLYGON_TYPE:
2437 ErasePolygon ((PolygonTypePtr) ptr);
2438 break;
2439 case ELEMENT_TYPE:
2440 EraseElement ((ElementTypePtr) ptr);
2441 break;
2442 case LINE_TYPE:
2443 case ELEMENTLINE_TYPE:
2444 case RATLINE_TYPE:
2445 EraseLine ((LineTypePtr) ptr);
2446 break;
2447 case PAD_TYPE:
2448 ErasePad ((PadTypePtr) ptr);
2449 break;
2450 case ARC_TYPE:
2451 case ELEMENTARC_TYPE:
2452 EraseArc ((ArcTypePtr) ptr);
2453 break;
2454 default:
2455 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
2461 void
2462 DrawObject (int type, void *ptr1, void *ptr2, int unused)
2464 switch (type)
2466 case VIA_TYPE:
2467 if (PCB->ViaOn)
2468 DrawVia ((PinTypePtr) ptr2, 0);
2469 break;
2470 case LINE_TYPE:
2471 if (((LayerTypePtr) ptr1)->On)
2472 DrawLine ((LayerTypePtr) ptr1, (LineTypePtr) ptr2, 0);
2473 break;
2474 case ARC_TYPE:
2475 if (((LayerTypePtr) ptr1)->On)
2476 DrawArc ((LayerTypePtr) ptr1, (ArcTypePtr) ptr2, 0);
2477 break;
2478 case TEXT_TYPE:
2479 if (((LayerTypePtr) ptr1)->On)
2480 DrawText ((LayerTypePtr) ptr1, (TextTypePtr) ptr2, 0);
2481 break;
2482 case POLYGON_TYPE:
2483 if (((LayerTypePtr) ptr1)->On)
2484 DrawPolygon ((LayerTypePtr) ptr1, (PolygonTypePtr) ptr2, 0);
2485 break;
2486 case ELEMENT_TYPE:
2487 if (PCB->ElementOn &&
2488 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
2489 DrawElement ((ElementTypePtr) ptr2, 0);
2490 break;
2491 case RATLINE_TYPE:
2492 if (PCB->RatOn)
2493 DrawRat ((RatTypePtr) ptr2, 0);
2494 break;
2495 case PIN_TYPE:
2496 if (PCB->PinOn)
2497 DrawPin ((PinTypePtr) ptr2, 0);
2498 break;
2499 case PAD_TYPE:
2500 if (PCB->PinOn)
2501 DrawPad ((PadTypePtr) ptr2, 0);
2502 break;
2503 case ELEMENTNAME_TYPE:
2504 if (PCB->ElementOn &&
2505 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
2506 DrawElementName ((ElementTypePtr) ptr1, 0);
2507 break;
2511 /* ---------------------------------------------------------------------------
2512 * HID drawing callback.
2515 void
2516 hid_expose_callback (HID * hid, BoxType * region, void *item)
2518 HID *old_gui = gui;
2519 hidGC savebg = Output.bgGC;
2520 hidGC savefg = Output.fgGC;
2521 hidGC savepm = Output.pmGC;
2523 gui = hid;
2524 Output.fgGC = gui->make_gc ();
2525 Output.bgGC = gui->make_gc ();
2526 Output.pmGC = gui->make_gc ();
2528 render = True;
2529 Gathering = False;
2531 /*printf("\033[32mhid_expose_callback, s=%p %d\033[0m\n", &(SWAP_IDENT), SWAP_IDENT); */
2533 hid->set_color (Output.pmGC, "erase");
2534 hid->set_color (Output.bgGC, "drill");
2536 if (item)
2538 doing_pinout = True;
2539 DrawElement (item, 0);
2540 doing_pinout = False;
2542 else
2543 DrawEverything (region);
2545 gui->destroy_gc (Output.fgGC);
2546 gui->destroy_gc (Output.bgGC);
2547 gui->destroy_gc (Output.pmGC);
2548 gui = old_gui;
2549 Output.fgGC = savefg;
2550 Output.bgGC = savebg;
2551 Output.pmGC = savepm;
2553 Gathering = True;