Add support for filling / thindrawing raw polygons to the HID interface
[geda-pcb/gde.git] / src / draw.c
blob1d902b245552eabcc4e0154dd681e7c3c9aa2461
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 (strcmp (Layer->Name, "outline") == 0
895 || strcmp (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 (TEST_FLAG (THINDRAWFLAG, PCB) ||
1353 (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
1355 int x1, y1, x2, y2, t, t2;
1356 t = w / 2;
1357 t2 = w - t;
1358 x1 = Pad->Point1.X;
1359 y1 = Pad->Point1.Y;
1360 x2 = Pad->Point2.X;
1361 y2 = Pad->Point2.Y;
1362 if (x1 > x2 || y1 > y2)
1364 /* this is a silly way to swap the variables */
1365 x1 ^= x2;
1366 x2 ^= x1;
1367 x1 ^= x2;
1368 y1 ^= y2;
1369 y2 ^= y1;
1370 y1 ^= y2;
1372 gui->set_line_cap (gc, Round_Cap);
1373 gui->set_line_width (gc, 0);
1374 if (TEST_FLAG (SQUAREFLAG, Pad)
1375 && (x1 == x2 || y1 == y2))
1377 x1 -= t;
1378 y1 -= t;
1379 x2 += t2;
1380 y2 += t2;
1381 gui->draw_line (gc, x1, y1, x1, y2);
1382 gui->draw_line (gc, x1, y2, x2, y2);
1383 gui->draw_line (gc, x2, y2, x2, y1);
1384 gui->draw_line (gc, x2, y1, x1, y1);
1386 else if (TEST_FLAG (SQUAREFLAG, Pad))
1388 /* slanted square pad */
1389 float tx, ty, theta;
1391 theta = atan2 (y2-y1, x2-x1);
1393 /* T is a vector half a thickness long, in the direction of
1394 one of the corners. */
1395 tx = t * cos (theta + M_PI/4) * sqrt(2.0);
1396 ty = t * sin (theta + M_PI/4) * sqrt(2.0);
1398 gui->draw_line (gc, x1-tx, y1-ty, x2+ty, y2-tx);
1399 gui->draw_line (gc, x2+ty, y2-tx, x2+tx, y2+ty);
1400 gui->draw_line (gc, x2+tx, y2+ty, x1-ty, y1+tx);
1401 gui->draw_line (gc, x1-ty, y1+tx, x1-tx, y1-ty);
1403 else if (x1 == x2 && y1 == y2)
1405 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 0, 360);
1407 else if (x1 == x2)
1409 gui->draw_line (gc, x1 - t, y1, x2 - t, y2);
1410 gui->draw_line (gc, x1 + t2, y1, x2 + t2, y2);
1411 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 0, -180);
1412 gui->draw_arc (gc, x2, y2, w / 2, w / 2, 180, -180);
1414 else if (y1 == y2)
1416 gui->draw_line (gc, x1, y1 - t, x2, y2 - t);
1417 gui->draw_line (gc, x1, y1 + t2, x2, y2 + t2);
1418 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 90, -180);
1419 gui->draw_arc (gc, x2, y2, w / 2, w / 2, 270, -180);
1421 else
1423 /* Slanted round-end pads. */
1424 LocationType dx, dy, ox, oy;
1425 float h;
1427 dx = x2 - x1;
1428 dy = y2 - y1;
1429 h = t / sqrt (SQUARE (dx) + SQUARE (dy));
1430 ox = dy * h + 0.5 * SGN (dy);
1431 oy = -(dx * h + 0.5 * SGN (dx));
1433 gui->draw_line (gc, x1 + ox, y1 + oy, x2 + ox, y2 + oy);
1435 if (abs (ox) >= pixel_slop || abs (oy) >= pixel_slop)
1437 LocationType angle = atan2 ((float) dx, (float) dy) * 57.295779;
1438 gui->draw_line (gc, x1 - ox, y1 - oy, x2 - ox, y2 - oy);
1439 gui->draw_arc (gc,
1440 x1, y1, t, t, angle - 180, 180);
1441 gui->draw_arc (gc, x2, y2, t, t, angle, 180);
1445 else if (Pad->Point1.X == Pad->Point2.X
1446 && Pad->Point1.Y == Pad->Point2.Y)
1448 if (TEST_FLAG (SQUAREFLAG, Pad))
1450 int l, r, t, b;
1451 l = Pad->Point1.X - w / 2;
1452 b = Pad->Point1.Y - w / 2;
1453 r = l + w;
1454 t = b + w;
1455 gui->fill_rect (gc, l, b, r, t);
1457 else
1459 gui->fill_circle (gc, Pad->Point1.X, Pad->Point1.Y, w / 2);
1462 else
1464 gui->set_line_cap (gc,
1465 TEST_FLAG (SQUAREFLAG,
1466 Pad) ? Square_Cap : Round_Cap);
1467 gui->set_line_width (gc, w);
1469 gui->draw_line (gc,
1470 Pad->Point1.X, Pad->Point1.Y,
1471 Pad->Point2.X, Pad->Point2.Y);
1473 #if 0
1474 { /* Draw bounding box for test */
1475 BoxType *box = &Pad->BoundingBox;
1476 gui->set_line_width (gc, 0);
1477 gui->draw_line (gc, box->X1, box->Y1, box->X1, box->Y2);
1478 gui->draw_line (gc, box->X1, box->Y2, box->X2, box->Y2);
1479 gui->draw_line (gc, box->X2, box->Y2, box->X2, box->Y1);
1480 gui->draw_line (gc, box->X2, box->Y1, box->X1, box->Y1);
1482 #endif
1485 /* ---------------------------------------------------------------------------
1486 * lowlevel drawing routine for pad names
1489 static void
1490 DrawPadNameLowLevel (PadTypePtr Pad)
1492 BoxType box;
1493 char *name;
1494 Boolean vert;
1495 TextType text;
1497 if (!Pad->Name || !Pad->Name[0])
1498 name = EMPTY (Pad->Number);
1499 else
1500 name = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? Pad->Number : Pad->Name);
1502 /* should text be vertical ? */
1503 vert = (Pad->Point1.X == Pad->Point2.X);
1505 if (vert)
1507 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1508 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1510 else
1512 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1513 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1516 if (vert)
1518 box.X1 += Settings.PinoutTextOffsetY;
1519 box.Y1 -= Settings.PinoutTextOffsetX;
1521 else
1523 box.X1 += Settings.PinoutTextOffsetX;
1524 box.Y1 += Settings.PinoutTextOffsetY;
1527 if (Gathering)
1529 if (vert)
1531 box.X2 = box.X1;
1532 box.Y2 = box.Y1;
1534 else
1536 box.X2 = box.X1;
1537 box.Y2 = box.Y1;
1539 AddPart (&box);
1540 return;
1543 gui->set_color (Output.fgGC, PCB->PinNameColor);
1545 text.Flags = NoFlags ();
1546 text.Scale = Pad->Thickness / 50;
1547 text.X = box.X1;
1548 text.Y = box.Y1;
1549 text.Direction = vert ? 1 : 0;
1550 text.TextString = name;
1552 DrawTextLowLevel (&text, 0);
1556 /* ---------------------------------------------------------------------------
1557 * clearance for pads
1559 static void
1560 ClearPad (PadTypePtr Pad, Boolean mask)
1562 DrawPadLowLevel(Output.pmGC, Pad, True, mask);
1565 /* ---------------------------------------------------------------------------
1566 * lowlevel drawing routine for lines
1568 static void
1569 DrawLineLowLevel (LineTypePtr Line, Boolean HaveGathered)
1571 if (Gathering && !HaveGathered)
1573 AddPart (Line);
1574 return;
1577 gui->set_line_cap (Output.fgGC, Trace_Cap);
1578 if (TEST_FLAG (THINDRAWFLAG, PCB))
1579 gui->set_line_width (Output.fgGC, 0);
1580 else
1581 gui->set_line_width (Output.fgGC, Line->Thickness);
1583 gui->draw_line (Output.fgGC,
1584 Line->Point1.X, Line->Point1.Y,
1585 Line->Point2.X, Line->Point2.Y);
1588 /* ---------------------------------------------------------------------------
1589 * lowlevel drawing routine for text objects
1591 void
1592 DrawTextLowLevel (TextTypePtr Text, int min_line_width)
1594 LocationType x = 0;
1595 unsigned char *string = (unsigned char *) Text->TextString;
1596 Cardinal n;
1597 FontTypePtr font = &PCB->Font;
1599 if (Gathering)
1601 AddPart (Text);
1602 return;
1605 while (string && *string)
1607 /* draw lines if symbol is valid and data is present */
1608 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid)
1610 LineTypePtr line = font->Symbol[*string].Line;
1611 LineType newline;
1613 for (n = font->Symbol[*string].LineN; n; n--, line++)
1615 /* create one line, scale, move, rotate and swap it */
1616 newline = *line;
1617 newline.Point1.X = (newline.Point1.X + x) * Text->Scale / 100;
1618 newline.Point1.Y = newline.Point1.Y * Text->Scale / 100;
1619 newline.Point2.X = (newline.Point2.X + x) * Text->Scale / 100;
1620 newline.Point2.Y = newline.Point2.Y * Text->Scale / 100;
1621 newline.Thickness = newline.Thickness * Text->Scale / 200;
1622 if (newline.Thickness < min_line_width)
1623 newline.Thickness = min_line_width;
1625 RotateLineLowLevel (&newline, 0, 0, Text->Direction);
1627 /* the labels of SMD objects on the bottom
1628 * side haven't been swapped yet, only their offset
1630 if (TEST_FLAG (ONSOLDERFLAG, Text))
1632 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X);
1633 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y);
1634 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X);
1635 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y);
1637 /* add offset and draw line */
1638 newline.Point1.X += Text->X;
1639 newline.Point1.Y += Text->Y;
1640 newline.Point2.X += Text->X;
1641 newline.Point2.Y += Text->Y;
1642 DrawLineLowLevel (&newline, True);
1645 /* move on to next cursor position */
1646 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta);
1648 else
1650 /* the default symbol is a filled box */
1651 BoxType defaultsymbol = PCB->Font.DefaultSymbol;
1652 LocationType size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5;
1654 defaultsymbol.X1 = (defaultsymbol.X1 + x) * Text->Scale / 100;
1655 defaultsymbol.Y1 = defaultsymbol.Y1 * Text->Scale / 100;
1656 defaultsymbol.X2 = (defaultsymbol.X2 + x) * Text->Scale / 100;
1657 defaultsymbol.Y2 = defaultsymbol.Y2 * Text->Scale / 100;
1659 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction);
1661 /* add offset and draw box */
1662 defaultsymbol.X1 += Text->X;
1663 defaultsymbol.Y1 += Text->Y;
1664 defaultsymbol.X2 += Text->X;
1665 defaultsymbol.Y2 += Text->Y;
1666 gui->fill_rect (Output.fgGC,
1667 defaultsymbol.X1, defaultsymbol.Y1,
1668 defaultsymbol.X2, defaultsymbol.Y2);
1670 /* move on to next cursor position */
1671 x += size;
1673 string++;
1677 /* ---------------------------------------------------------------------------
1678 * lowlevel drawing routine for polygons
1680 static void
1681 DrawPolygonLowLevel (PolygonTypePtr Polygon)
1683 if (!Polygon->Clipped)
1684 return;
1686 if (Gathering)
1688 AddPart (Polygon);
1689 return;
1692 printf ("DrawPolygonLowLevel: Called without Gathering set!\n");
1695 /* ---------------------------------------------------------------------------
1696 * lowlevel routine to element arcs
1698 static void
1699 DrawArcLowLevel (ArcTypePtr Arc)
1701 if (!Arc->Thickness)
1702 return;
1703 if (Gathering)
1705 AddPart (Arc);
1706 return;
1709 if (TEST_FLAG (THINDRAWFLAG, PCB))
1710 gui->set_line_width (Output.fgGC, 0);
1711 else
1712 gui->set_line_width (Output.fgGC, Arc->Thickness);
1713 gui->set_line_cap (Output.fgGC, Trace_Cap);
1715 gui->draw_arc (Output.fgGC, Arc->X, Arc->Y, Arc->Width,
1716 Arc->Height, Arc->StartAngle, Arc->Delta);
1719 /* ---------------------------------------------------------------------------
1720 * draws the package of an element
1722 static void
1723 DrawElementPackageLowLevel (ElementTypePtr Element, int unused)
1725 /* draw lines, arcs, text and pins */
1726 ELEMENTLINE_LOOP (Element);
1728 DrawLineLowLevel (line, False);
1730 END_LOOP;
1731 ARC_LOOP (Element);
1733 DrawArcLowLevel (arc);
1735 END_LOOP;
1738 /* ---------------------------------------------------------------------------
1739 * draw a via object
1741 void
1742 DrawVia (PinTypePtr Via, int unused)
1744 if (!Gathering)
1745 SetPVColor (Via, VIA_TYPE);
1746 //if (!doing_pinout && !TEST_FLAG (HOLEFLAG, Via) && TEST_ANY_PIPS (Via))
1747 // ClearPin (Via, VIA_TYPE, 0);
1748 //else
1749 DrawPinOrViaLowLevel (Via, True);
1750 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1751 DrawPinOrViaNameLowLevel (Via);
1754 /* ---------------------------------------------------------------------------
1755 * draw a via without dealing with polygon clearance
1757 static void
1758 DrawPlainVia (PinTypePtr Via, Boolean holeToo)
1760 if (!Gathering)
1761 SetPVColor (Via, VIA_TYPE);
1762 DrawPinOrViaLowLevel (Via, holeToo);
1763 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1764 DrawPinOrViaNameLowLevel (Via);
1767 /* ---------------------------------------------------------------------------
1768 * draws the name of a via
1770 void
1771 DrawViaName (PinTypePtr Via, int unused)
1773 if (!Gathering)
1775 if (TEST_FLAG (SELECTEDFLAG, Via))
1776 gui->set_color (Output.fgGC, PCB->ViaSelectedColor);
1777 else
1778 gui->set_color (Output.fgGC, PCB->ViaColor);
1780 DrawPinOrViaNameLowLevel (Via);
1783 /* ---------------------------------------------------------------------------
1784 * draw a pin object
1786 void
1787 DrawPin (PinTypePtr Pin, int unused)
1789 //if (!doing_pinout && !TEST_FLAG (HOLEFLAG, Pin) && TEST_ANY_PIPS (Pin))
1790 // ClearPin (Pin, PIN_TYPE, 0);
1791 //else
1793 if (!Gathering)
1794 SetPVColor (Pin, PIN_TYPE);
1795 DrawPinOrViaLowLevel (Pin, True);
1797 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1798 || doing_pinout)
1799 DrawPinOrViaNameLowLevel (Pin);
1802 /* ---------------------------------------------------------------------------
1803 * draw a pin without clearing around polygons
1805 static void
1806 DrawPlainPin (PinTypePtr Pin, Boolean holeToo)
1808 if (!Gathering)
1809 SetPVColor (Pin, PIN_TYPE);
1810 DrawPinOrViaLowLevel (Pin, holeToo);
1811 if (!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1812 DrawPinOrViaNameLowLevel (Pin);
1815 /* ---------------------------------------------------------------------------
1816 * draws the name of a pin
1818 void
1819 DrawPinName (PinTypePtr Pin, int unused)
1821 if (!Gathering)
1823 if (TEST_FLAG (SELECTEDFLAG, Pin))
1824 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1825 else
1826 gui->set_color (Output.fgGC, PCB->PinColor);
1828 DrawPinOrViaNameLowLevel (Pin);
1831 /* ---------------------------------------------------------------------------
1832 * draw a pad object
1834 void
1835 DrawPad (PadTypePtr Pad, int unused)
1837 if (!Gathering)
1839 if (doing_pinout)
1840 gui->set_color (Output.fgGC, PCB->PinColor);
1841 else if (TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pad))
1843 if (TEST_FLAG (WARNFLAG, Pad))
1844 gui->set_color (Output.fgGC, PCB->WarnColor);
1845 else if (TEST_FLAG (SELECTEDFLAG, Pad))
1846 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1847 else
1848 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1850 else if (FRONT (Pad))
1851 gui->set_color (Output.fgGC, PCB->PinColor);
1852 else
1853 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
1855 DrawPadLowLevel (Output.fgGC, Pad, False, False);
1856 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1857 DrawPadNameLowLevel (Pad);
1860 /* ---------------------------------------------------------------------------
1861 * draws the name of a pad
1863 void
1864 DrawPadName (PadTypePtr Pad, int unused)
1866 if (!Gathering)
1868 if (TEST_FLAG (SELECTEDFLAG, Pad))
1869 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1870 else if (FRONT (Pad))
1871 gui->set_color (Output.fgGC, PCB->PinColor);
1872 else
1873 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
1875 DrawPadNameLowLevel (Pad);
1878 /* ---------------------------------------------------------------------------
1879 * draws a line on a layer
1881 void
1882 DrawLine (LayerTypePtr Layer, LineTypePtr Line, int unused)
1884 if (!Gathering)
1886 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Line))
1888 if (TEST_FLAG (SELECTEDFLAG, Line))
1889 gui->set_color (Output.fgGC, Layer->SelectedColor);
1890 else
1891 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1893 else
1894 gui->set_color (Output.fgGC, Layer->Color);
1896 DrawLineLowLevel (Line, False);
1899 /* ---------------------------------------------------------------------------
1900 * draws a ratline
1902 void
1903 DrawRat (RatTypePtr Line, int unused)
1905 if (!Gathering)
1907 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Line))
1909 if (TEST_FLAG (SELECTEDFLAG, Line))
1910 gui->set_color (Output.fgGC, PCB->RatSelectedColor);
1911 else
1912 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1914 else
1915 gui->set_color (Output.fgGC, PCB->RatColor);
1917 if (Settings.RatThickness < 20)
1918 Line->Thickness = pixel_slop * Settings.RatThickness;
1919 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1920 if (TEST_FLAG(VIAFLAG, Line))
1922 int w = Line->Thickness;
1924 if (Gathering)
1926 BoxType b;
1928 b.X1 = Line->Point1.X - w * 2 - w / 2;
1929 b.X2 = Line->Point1.X + w * 2 + w / 2;
1930 b.Y1 = Line->Point1.Y - w * 2 - w / 2;
1931 b.Y2 = Line->Point1.Y + w * 2 + w / 2;
1932 AddPart(&b);
1934 else
1936 if (TEST_FLAG (THINDRAWFLAG, PCB))
1937 gui->set_line_width (Output.fgGC, 0);
1938 else
1939 gui->set_line_width (Output.fgGC, w);
1940 gui->draw_arc (Output.fgGC, Line->Point1.X, Line->Point1.Y,
1941 w * 2, w * 2, 0, 360);
1944 else
1945 DrawLineLowLevel ((LineTypePtr) Line, False);
1948 /* ---------------------------------------------------------------------------
1949 * draws an arc on a layer
1951 void
1952 DrawArc (LayerTypePtr Layer, ArcTypePtr Arc, int unused)
1954 if (!Arc->Thickness)
1955 return;
1956 if (!Gathering)
1958 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Arc))
1960 if (TEST_FLAG (SELECTEDFLAG, Arc))
1961 gui->set_color (Output.fgGC, Layer->SelectedColor);
1962 else
1963 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1965 else
1966 gui->set_color (Output.fgGC, Layer->Color);
1968 DrawArcLowLevel (Arc);
1971 /* ---------------------------------------------------------------------------
1972 * draws a text on a layer
1974 void
1975 DrawText (LayerTypePtr Layer, TextTypePtr Text, int unused)
1977 int min_silk_line;
1978 if (!Layer->On)
1979 return;
1980 if (TEST_FLAG (SELECTEDFLAG, Text))
1981 gui->set_color (Output.fgGC, Layer->SelectedColor);
1982 else
1983 gui->set_color (Output.fgGC, Layer->Color);
1984 if (Layer == & PCB->Data->SILKLAYER
1985 || Layer == & PCB->Data->BACKSILKLAYER)
1986 min_silk_line = PCB->minSlk;
1987 else
1988 min_silk_line = PCB->minWid;
1989 DrawTextLowLevel (Text, min_silk_line);
1992 /* ---------------------------------------------------------------------------
1993 * draws text on a layer
1995 static void
1996 DrawRegularText (LayerTypePtr Layer, TextTypePtr Text, int unused)
1998 int min_silk_line;
1999 if (TEST_FLAG (SELECTEDFLAG, Text))
2000 gui->set_color (Output.fgGC, Layer->SelectedColor);
2001 else
2002 gui->set_color (Output.fgGC, Layer->Color);
2003 if (Layer == & PCB->Data->SILKLAYER
2004 || Layer == & PCB->Data->BACKSILKLAYER)
2005 min_silk_line = PCB->minSlk;
2006 else
2007 min_silk_line = PCB->minWid;
2008 DrawTextLowLevel (Text, min_silk_line);
2011 static int
2012 cp_callback (const BoxType * b, void *cl)
2014 ClearPin ((PinTypePtr) b, (int) (size_t) cl, 0);
2015 return 1;
2018 /* ---------------------------------------------------------------------------
2019 * draws a polygon on a layer
2021 void
2022 DrawPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon, int unused)
2024 int layernum;
2026 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Polygon))
2028 if (TEST_FLAG (SELECTEDFLAG, Polygon))
2029 gui->set_color (Output.fgGC, Layer->SelectedColor);
2030 else
2031 gui->set_color (Output.fgGC, PCB->ConnectedColor);
2033 else
2034 gui->set_color (Output.fgGC, Layer->Color);
2035 layernum = GetLayerNumber (PCB->Data, Layer);
2036 DrawPolygonLowLevel (Polygon);
2037 if (TEST_FLAG (CLEARPOLYFLAG, Polygon))
2039 r_search (PCB->Data->pin_tree, &Polygon->BoundingBox, NULL,
2040 cp_callback, (void *) PIN_TYPE);
2041 r_search (PCB->Data->via_tree, &Polygon->BoundingBox, NULL,
2042 cp_callback, (void *) VIA_TYPE);
2047 thin_callback (PLINE * pl, LayerTypePtr lay, PolygonTypePtr poly)
2049 int i, *x, *y;
2050 VNODE *v;
2052 i = 0;
2053 x = (int *) malloc (pl->Count * sizeof (int));
2054 y = (int *) malloc (pl->Count * sizeof (int));
2055 for (v = &pl->head; i < pl->Count; v = v->next)
2057 x[i] = v->point[0];
2058 y[i++] = v->point[1];
2060 gui->set_line_cap (Output.fgGC, Round_Cap);
2061 gui->set_line_width (Output.fgGC, 0);
2062 for (i = 0; i < pl->Count - 1; i++)
2064 gui->draw_line (Output.fgGC, x[i], y[i], x[i + 1], y[i + 1]);
2065 // gui->fill_circle (Output.fgGC, x[i], y[i], 30);
2067 gui->draw_line (Output.fgGC, x[pl->Count - 1], y[pl->Count - 1], x[0],
2068 y[0]);
2069 free (x);
2070 free (y);
2071 return 0;
2075 /* ---------------------------------------------------------------------------
2076 * draws a polygon
2078 static void
2079 DrawPlainPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
2081 static char *color;
2083 if (!Polygon->Clipped)
2084 return;
2086 if (Gathering)
2088 AddPart (Polygon);
2089 return;
2092 if (TEST_FLAG (SELECTEDFLAG, Polygon))
2093 color = Layer->SelectedColor;
2094 else if (TEST_FLAG (FOUNDFLAG, Polygon))
2095 color = PCB->ConnectedColor;
2096 else
2097 color = Layer->Color;
2098 gui->set_color (Output.fgGC, color);
2100 if (gui->thindraw_pcb_polygon != NULL &&
2101 (TEST_FLAG (THINDRAWFLAG, PCB) ||
2102 TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
2103 gui->thindraw_pcb_polygon (Output.fgGC, Polygon, clip_box);
2104 else
2105 gui->fill_pcb_polygon (Output.fgGC, Polygon, clip_box);
2107 /* If checking planes, thin-draw any pieces which have been clipped away */
2108 if (gui->thindraw_pcb_polygon != NULL &&
2109 TEST_FLAG (CHECKPLANESFLAG, PCB) &&
2110 !TEST_FLAG (FULLPOLYFLAG, Polygon))
2112 PolygonType poly = *Polygon;
2114 for (poly.Clipped = Polygon->Clipped->f;
2115 poly.Clipped != Polygon->Clipped;
2116 poly.Clipped = poly.Clipped->f)
2117 gui->thindraw_pcb_polygon (Output.fgGC, &poly, clip_box);
2121 /* ---------------------------------------------------------------------------
2122 * draws an element
2124 void
2125 DrawElement (ElementTypePtr Element, int unused)
2127 DrawElementPackage (Element, unused);
2128 DrawElementName (Element, unused);
2129 DrawElementPinsAndPads (Element, unused);
2132 /* ---------------------------------------------------------------------------
2133 * draws the name of an element
2135 void
2136 DrawElementName (ElementTypePtr Element, int unused)
2138 if (gui->gui && TEST_FLAG (HIDENAMESFLAG, PCB))
2139 return;
2140 if (TEST_FLAG (HIDENAMEFLAG, Element))
2141 return;
2142 if (doing_pinout || doing_assy)
2143 gui->set_color (Output.fgGC, PCB->ElementColor);
2144 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, Element)))
2145 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
2146 else if (FRONT (Element))
2147 gui->set_color (Output.fgGC, PCB->ElementColor);
2148 else
2149 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
2150 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2153 /* ---------------------------------------------------------------------------
2154 * draws the package of an element
2156 void
2157 DrawElementPackage (ElementTypePtr Element, int unused)
2159 /* set color and draw lines, arcs, text and pins */
2160 if (doing_pinout || doing_assy)
2161 gui->set_color (Output.fgGC, PCB->ElementColor);
2162 else if (TEST_FLAG (SELECTEDFLAG, Element))
2163 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
2164 else if (FRONT (Element))
2165 gui->set_color (Output.fgGC, PCB->ElementColor);
2166 else
2167 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
2168 DrawElementPackageLowLevel (Element, unused);
2171 /* ---------------------------------------------------------------------------
2172 * draw pins of an element
2174 void
2175 DrawElementPinsAndPads (ElementTypePtr Element, int unused)
2177 PAD_LOOP (Element);
2179 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
2180 DrawPad (pad, unused);
2182 END_LOOP;
2183 PIN_LOOP (Element);
2185 DrawPin (pin, unused);
2187 END_LOOP;
2190 /* ---------------------------------------------------------------------------
2191 * erase a via
2193 void
2194 EraseVia (PinTypePtr Via)
2196 Erasing++;
2197 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2198 DrawPinOrViaLowLevel (Via, False);
2199 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
2200 DrawPinOrViaNameLowLevel (Via);
2201 Erasing--;
2204 /* ---------------------------------------------------------------------------
2205 * erase a ratline
2207 void
2208 EraseRat (RatTypePtr Rat)
2210 Erasing++;
2211 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2212 if (TEST_FLAG(VIAFLAG, Rat))
2214 int w = Rat->Thickness;
2216 if (TEST_FLAG (THINDRAWFLAG, PCB))
2217 gui->set_line_width (Output.fgGC, 0);
2218 else
2219 gui->set_line_width (Output.fgGC, w);
2220 gui->draw_arc (Output.fgGC, Rat->Point1.X, Rat->Point1.Y,
2221 w * 2, w * 2, 0, 360);
2223 else
2224 DrawLineLowLevel ((LineTypePtr) Rat, False);
2225 Erasing--;
2229 /* ---------------------------------------------------------------------------
2230 * erase a via name
2232 void
2233 EraseViaName (PinTypePtr Via)
2235 Erasing++;
2236 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2237 DrawPinOrViaNameLowLevel (Via);
2238 Erasing--;
2241 /* ---------------------------------------------------------------------------
2242 * erase a pad object
2244 void
2245 ErasePad (PadTypePtr Pad)
2247 Erasing++;
2248 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2249 DrawPadLowLevel (Output.fgGC, Pad, False, False);
2250 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
2251 DrawPadNameLowLevel (Pad);
2252 Erasing--;
2255 /* ---------------------------------------------------------------------------
2256 * erase a pad name
2258 void
2259 ErasePadName (PadTypePtr Pad)
2261 Erasing++;
2262 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2263 DrawPadNameLowLevel (Pad);
2264 Erasing--;
2267 /* ---------------------------------------------------------------------------
2268 * erase a pin object
2270 void
2271 ErasePin (PinTypePtr Pin)
2273 Erasing++;
2274 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2275 DrawPinOrViaLowLevel (Pin, False);
2276 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
2277 DrawPinOrViaNameLowLevel (Pin);
2278 Erasing--;
2281 /* ---------------------------------------------------------------------------
2282 * erase a pin name
2284 void
2285 ErasePinName (PinTypePtr Pin)
2287 Erasing++;
2288 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2289 DrawPinOrViaNameLowLevel (Pin);
2290 Erasing--;
2293 /* ---------------------------------------------------------------------------
2294 * erases a line on a layer
2296 void
2297 EraseLine (LineTypePtr Line)
2299 Erasing++;
2300 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2301 DrawLineLowLevel (Line, False);
2302 Erasing--;
2305 /* ---------------------------------------------------------------------------
2306 * erases an arc on a layer
2308 void
2309 EraseArc (ArcTypePtr Arc)
2311 if (!Arc->Thickness)
2312 return;
2313 Erasing++;
2314 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2315 DrawArcLowLevel (Arc);
2316 Erasing--;
2319 /* ---------------------------------------------------------------------------
2320 * erases a text on a layer
2322 void
2323 EraseText (LayerTypePtr Layer, TextTypePtr Text)
2325 int min_silk_line;
2326 Erasing++;
2327 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2328 if (Layer == & PCB->Data->SILKLAYER
2329 || Layer == & PCB->Data->BACKSILKLAYER)
2330 min_silk_line = PCB->minSlk;
2331 else
2332 min_silk_line = PCB->minWid;
2333 DrawTextLowLevel (Text, min_silk_line);
2334 Erasing--;
2337 /* ---------------------------------------------------------------------------
2338 * erases a polygon on a layer
2340 void
2341 ErasePolygon (PolygonTypePtr Polygon)
2343 Erasing++;
2344 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2345 DrawPolygonLowLevel (Polygon);
2346 Erasing--;
2349 /* ---------------------------------------------------------------------------
2350 * erases an element
2352 void
2353 EraseElement (ElementTypePtr Element)
2355 Erasing++;
2356 /* set color and draw lines, arcs, text and pins */
2357 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2358 ELEMENTLINE_LOOP (Element);
2360 DrawLineLowLevel (line, False);
2362 END_LOOP;
2363 ARC_LOOP (Element);
2365 DrawArcLowLevel (arc);
2367 END_LOOP;
2368 if (!TEST_FLAG (HIDENAMEFLAG, Element))
2369 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2370 EraseElementPinsAndPads (Element);
2371 Erasing--;
2374 /* ---------------------------------------------------------------------------
2375 * erases all pins and pads of an element
2377 void
2378 EraseElementPinsAndPads (ElementTypePtr Element)
2380 Erasing++;
2381 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2382 PIN_LOOP (Element);
2384 /* if (TEST_ANY_PIPS (pin))
2386 ClearPin (pin, NO_TYPE, 0);
2387 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2390 DrawPinOrViaLowLevel (pin, False);
2391 if (TEST_FLAG (DISPLAYNAMEFLAG, pin))
2392 DrawPinOrViaNameLowLevel (pin);
2394 END_LOOP;
2395 PAD_LOOP (Element);
2397 DrawPadLowLevel (Output.fgGC, pad, False, False);
2398 if (TEST_FLAG (DISPLAYNAMEFLAG, pad))
2399 DrawPadNameLowLevel (pad);
2401 END_LOOP;
2402 Erasing--;
2405 /* ---------------------------------------------------------------------------
2406 * erases the name of an element
2408 void
2409 EraseElementName (ElementTypePtr Element)
2411 if (TEST_FLAG (HIDENAMEFLAG, Element))
2412 return;
2413 Erasing++;
2414 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2415 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2416 Erasing--;
2420 void
2421 EraseObject (int type, void *lptr, void *ptr)
2423 switch (type)
2425 case VIA_TYPE:
2426 case PIN_TYPE:
2427 ErasePin ((PinTypePtr) ptr);
2428 break;
2429 case TEXT_TYPE:
2430 case ELEMENTNAME_TYPE:
2431 EraseText (lptr, (TextTypePtr) ptr);
2432 break;
2433 case POLYGON_TYPE:
2434 ErasePolygon ((PolygonTypePtr) ptr);
2435 break;
2436 case ELEMENT_TYPE:
2437 EraseElement ((ElementTypePtr) ptr);
2438 break;
2439 case LINE_TYPE:
2440 case ELEMENTLINE_TYPE:
2441 case RATLINE_TYPE:
2442 EraseLine ((LineTypePtr) ptr);
2443 break;
2444 case PAD_TYPE:
2445 ErasePad ((PadTypePtr) ptr);
2446 break;
2447 case ARC_TYPE:
2448 case ELEMENTARC_TYPE:
2449 EraseArc ((ArcTypePtr) ptr);
2450 break;
2451 default:
2452 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
2458 void
2459 DrawObject (int type, void *ptr1, void *ptr2, int unused)
2461 switch (type)
2463 case VIA_TYPE:
2464 if (PCB->ViaOn)
2465 DrawVia ((PinTypePtr) ptr2, 0);
2466 break;
2467 case LINE_TYPE:
2468 if (((LayerTypePtr) ptr1)->On)
2469 DrawLine ((LayerTypePtr) ptr1, (LineTypePtr) ptr2, 0);
2470 break;
2471 case ARC_TYPE:
2472 if (((LayerTypePtr) ptr1)->On)
2473 DrawArc ((LayerTypePtr) ptr1, (ArcTypePtr) ptr2, 0);
2474 break;
2475 case TEXT_TYPE:
2476 if (((LayerTypePtr) ptr1)->On)
2477 DrawText ((LayerTypePtr) ptr1, (TextTypePtr) ptr2, 0);
2478 break;
2479 case POLYGON_TYPE:
2480 if (((LayerTypePtr) ptr1)->On)
2481 DrawPolygon ((LayerTypePtr) ptr1, (PolygonTypePtr) ptr2, 0);
2482 break;
2483 case ELEMENT_TYPE:
2484 if (PCB->ElementOn &&
2485 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
2486 DrawElement ((ElementTypePtr) ptr2, 0);
2487 break;
2488 case RATLINE_TYPE:
2489 if (PCB->RatOn)
2490 DrawRat ((RatTypePtr) ptr2, 0);
2491 break;
2492 case PIN_TYPE:
2493 if (PCB->PinOn)
2494 DrawPin ((PinTypePtr) ptr2, 0);
2495 break;
2496 case PAD_TYPE:
2497 if (PCB->PinOn)
2498 DrawPad ((PadTypePtr) ptr2, 0);
2499 break;
2500 case ELEMENTNAME_TYPE:
2501 if (PCB->ElementOn &&
2502 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
2503 DrawElementName ((ElementTypePtr) ptr1, 0);
2504 break;
2508 /* ---------------------------------------------------------------------------
2509 * HID drawing callback.
2512 void
2513 hid_expose_callback (HID * hid, BoxType * region, void *item)
2515 HID *old_gui = gui;
2516 hidGC savebg = Output.bgGC;
2517 hidGC savefg = Output.fgGC;
2518 hidGC savepm = Output.pmGC;
2520 gui = hid;
2521 Output.fgGC = gui->make_gc ();
2522 Output.bgGC = gui->make_gc ();
2523 Output.pmGC = gui->make_gc ();
2525 render = True;
2526 Gathering = False;
2528 /*printf("\033[32mhid_expose_callback, s=%p %d\033[0m\n", &(SWAP_IDENT), SWAP_IDENT); */
2530 hid->set_color (Output.pmGC, "erase");
2531 hid->set_color (Output.bgGC, "drill");
2533 if (item)
2535 doing_pinout = True;
2536 DrawElement (item, 0);
2537 doing_pinout = False;
2539 else
2540 DrawEverything (region);
2542 gui->destroy_gc (Output.fgGC);
2543 gui->destroy_gc (Output.bgGC);
2544 gui->destroy_gc (Output.pmGC);
2545 gui = old_gui;
2546 Output.fgGC = savefg;
2547 Output.bgGC = savebg;
2548 Output.pmGC = savepm;
2550 Gathering = True;