Add user_data parameter to NoHolesPolygonDicer
[geda-pcb/gde.git] / src / draw.c
blob3da0bf94916b45c07d3300b93763c97fea1ac39c
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 "polygon.h"
48 #include "rotate.h"
49 #include "rtree.h"
50 #include "search.h"
51 #include "select.h"
52 #include "print.h"
54 #ifdef HAVE_LIBDMALLOC
55 #include <dmalloc.h>
56 #endif
58 RCSID ("$Id$");
60 #define SMALL_SMALL_TEXT_SIZE 0
61 #define SMALL_TEXT_SIZE 1
62 #define NORMAL_TEXT_SIZE 2
63 #define LARGE_TEXT_SIZE 3
64 #define N_TEXT_SIZES 4
67 /* ---------------------------------------------------------------------------
68 * some local types
70 typedef struct
72 double X, Y;
74 FloatPolyType, *FloatPolyTypePtr;
76 /* ---------------------------------------------------------------------------
77 * some local identifiers
79 static BoxType Block;
80 static Boolean Gathering = True;
81 static int Erasing = False;
83 static int doing_pinout = False;
84 static int doing_assy = False;
85 static const BoxType *clip_box = NULL;
87 /* ---------------------------------------------------------------------------
88 * some local prototypes
90 static void Redraw (Boolean, BoxTypePtr);
91 static void DrawEverything (BoxTypePtr);
92 static void DrawTop (const BoxType *);
93 static int DrawLayerGroup (int, const BoxType *);
94 static void DrawPinOrViaLowLevel (PinTypePtr, Boolean);
95 static void ClearOnlyPin (PinTypePtr, Boolean);
96 static void DrawPlainPin (PinTypePtr, Boolean);
97 static void DrawPlainVia (PinTypePtr, Boolean);
98 static void DrawPinOrViaNameLowLevel (PinTypePtr);
99 static void DrawPadLowLevel (hidGC, PadTypePtr, Boolean, Boolean);
100 static void DrawPadNameLowLevel (PadTypePtr);
101 static void DrawLineLowLevel (LineTypePtr, Boolean);
102 static void DrawRegularText (LayerTypePtr, TextTypePtr, int);
103 static void DrawPolygonLowLevel (PolygonTypePtr);
104 static void DrawArcLowLevel (ArcTypePtr);
105 static void DrawElementPackageLowLevel (ElementTypePtr Element, int);
106 static void DrawPlainPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon);
107 static void AddPart (void *);
108 static void SetPVColor (PinTypePtr, int);
109 static void DrawEMark (ElementTypePtr, LocationType, LocationType, Boolean);
110 static void ClearPad (PadTypePtr, Boolean);
111 static void DrawHole (PinTypePtr);
112 static void DrawMask (BoxType *);
113 static void DrawRats (BoxType *);
114 static void DrawSilk (int, int, BoxType *);
115 static int pin_callback (const BoxType * b, void *cl);
116 static int pad_callback (const BoxType * b, void *cl);
118 /*--------------------------------------------------------------------------------------
119 * setup color for pin or via
121 static void
122 SetPVColor (PinTypePtr Pin, int Type)
124 char *color;
126 if (Type == VIA_TYPE)
128 if (!doing_pinout
129 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
131 if (TEST_FLAG (WARNFLAG, Pin))
132 color = PCB->WarnColor;
133 else if (TEST_FLAG (SELECTEDFLAG, Pin))
134 color = PCB->ViaSelectedColor;
135 else
136 color = PCB->ConnectedColor;
138 else
139 color = PCB->ViaColor;
141 else
143 if (!doing_pinout
144 && TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pin))
146 if (TEST_FLAG (WARNFLAG, Pin))
147 color = PCB->WarnColor;
148 else if (TEST_FLAG (SELECTEDFLAG, Pin))
149 color = PCB->PinSelectedColor;
150 else
151 color = PCB->ConnectedColor;
153 else
154 color = PCB->PinColor;
157 gui->set_color (Output.fgGC, color);
160 /*---------------------------------------------------------------------------
161 * Adds the update rect to the update region
163 static void
164 AddPart (void *b)
166 BoxType *box = (BoxType *) b;
168 Block.X1 = MIN (Block.X1, box->X1);
169 Block.X2 = MAX (Block.X2, box->X2);
170 Block.Y1 = MIN (Block.Y1, box->Y1);
171 Block.Y2 = MAX (Block.Y2, box->Y2);
175 * force the whole output to be updated
177 void
178 UpdateAll (void)
180 gui->invalidate_all ();
184 * initiate the actual drawing to the pixmap/screen
185 * make the update block slightly larger to handle round-off
186 * caused by the TO_SCREEN operation
188 void
189 Draw (void)
192 render = True;
194 HideCrosshair (True);
196 /* clear and create event if not drawing to a pixmap
198 gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2, 1);
200 RestoreCrosshair (True);
202 /* shrink the update block */
203 Block.X1 = Block.Y1 = Block.X2 = Block.Y2 = 0;
206 /* ---------------------------------------------------------------------------
207 * redraws the output area without clearing it
209 void
210 RedrawOutput (BoxTypePtr area)
212 Redraw (True, area);
215 /* ---------------------------------------------------------------------------
216 * redraws the output area after clearing it
218 void
219 ClearAndRedrawOutput (void)
221 render = True;
222 Gathering = False;
223 UpdateAll ();
229 /* ----------------------------------------------------------------------
230 * redraws all the data
231 * all necessary sizes are already set by the porthole widget and
232 * by the event handlers
234 static void
235 Redraw (Boolean ClearWindow, BoxTypePtr screen_area)
237 gui->invalidate_all ();
238 Gathering = True;
239 render = False;
242 static int
243 backE_callback (const BoxType * b, void *cl)
245 ElementTypePtr element = (ElementTypePtr) b;
247 if (!FRONT (element))
249 DrawElementPackage (element, 0);
251 return 1;
254 static int
255 backN_callback (const BoxType * b, void *cl)
257 TextTypePtr text = (TextTypePtr) b;
258 ElementTypePtr element = (ElementTypePtr) text->Element;
260 if (!FRONT (element) && !TEST_FLAG (HIDENAMEFLAG, element))
261 DrawElementName (element, 0);
262 return 0;
265 static int
266 backPad_callback (const BoxType * b, void *cl)
268 PadTypePtr pad = (PadTypePtr) b;
270 if (!FRONT (pad))
271 DrawPad (pad, 0);
272 return 1;
275 static int
276 frontE_callback (const BoxType * b, void *cl)
278 ElementTypePtr element = (ElementTypePtr) b;
280 if (FRONT (element))
282 DrawElementPackage (element, 0);
284 return 1;
287 static int
288 EMark_callback (const BoxType * b, void *cl)
290 ElementTypePtr element = (ElementTypePtr) b;
292 DrawEMark (element, element->MarkX, element->MarkY, !FRONT (element));
293 return 1;
296 static int
297 frontN_callback (const BoxType * b, void *cl)
299 TextTypePtr text = (TextTypePtr) b;
300 ElementTypePtr element = (ElementTypePtr) text->Element;
302 if (FRONT (element) && !TEST_FLAG (HIDENAMEFLAG, element))
303 DrawElementName (element, 0);
304 return 0;
307 static int
308 hole_callback (const BoxType * b, void *cl)
310 PinTypePtr pin = (PinTypePtr) b;
311 int plated = cl ? *(int *) cl : -1;
312 switch (plated)
314 case -1:
315 break;
316 case 0:
317 if (!TEST_FLAG (HOLEFLAG, pin))
318 return 1;
319 break;
320 case 1:
321 if (TEST_FLAG (HOLEFLAG, pin))
322 return 1;
323 break;
325 DrawHole ((PinTypePtr) b);
326 return 1;
329 typedef struct
331 int nplated;
332 int nunplated;
333 } HoleCountStruct;
335 static int
336 hole_counting_callback (const BoxType * b, void *cl)
338 PinTypePtr pin = (PinTypePtr) b;
339 HoleCountStruct *hcs = (HoleCountStruct *) cl;
340 if (TEST_FLAG (HOLEFLAG, pin))
341 hcs->nunplated++;
342 else
343 hcs->nplated++;
344 return 1;
347 static int
348 rat_callback (const BoxType * b, void *cl)
350 DrawRat ((RatTypePtr) b, 0);
351 return 1;
354 static int
355 lowvia_callback (const BoxType * b, void *cl)
357 PinTypePtr via = (PinTypePtr) b;
358 if (!via->Mask)
359 DrawPlainVia (via, False);
360 return 1;
363 /* ---------------------------------------------------------------------------
364 * prints assembly drawing.
367 static void
368 PrintAssembly (const BoxType * drawn_area, int side_group, int swap_ident)
370 int save_swap = SWAP_IDENT;
372 gui->set_draw_faded (Output.fgGC, 1);
373 SWAP_IDENT = swap_ident;
374 DrawLayerGroup (side_group, drawn_area);
375 r_search (PCB->Data->via_tree, drawn_area, NULL, lowvia_callback, NULL);
376 DrawTop (drawn_area);
377 gui->set_draw_faded (Output.fgGC, 0);
379 /* draw package */
380 DrawSilk (swap_ident,
381 swap_ident ? SOLDER_LAYER : COMPONENT_LAYER,
382 drawn_area);
383 SWAP_IDENT = save_swap;
386 /* ---------------------------------------------------------------------------
387 * initializes some identifiers for a new zoom factor and redraws whole screen
389 static void
390 DrawEverything (BoxTypePtr drawn_area)
392 int i, ngroups, side;
393 int plated;
394 int component, solder;
395 /* This is the list of layer groups we will draw. */
396 int do_group[MAX_LAYER];
397 /* This is the reverse of the order in which we draw them. */
398 int drawn_groups[MAX_LAYER];
400 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
401 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
403 memset (do_group, 0, sizeof (do_group));
404 for (ngroups = 0, i = 0; i < max_layer; i++)
406 LayerType *l = LAYER_ON_STACK (i);
407 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
408 if (l->On && !do_group[group])
410 do_group[group] = 1;
411 drawn_groups[ngroups++] = group;
415 component = GetLayerGroupNumberByNumber (max_layer + COMPONENT_LAYER);
416 solder = GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER);
419 * first draw all 'invisible' stuff
421 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
422 && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
424 r_search (PCB->Data->pad_tree, drawn_area, NULL, backPad_callback,
425 NULL);
426 if (PCB->ElementOn)
428 r_search (PCB->Data->element_tree, drawn_area, NULL, backE_callback,
429 NULL);
430 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
431 backN_callback, NULL);
432 DrawLayer (&(PCB->Data->BACKSILKLAYER), drawn_area);
436 /* draw all layers in layerstack order */
437 for (i = ngroups - 1; i >= 0; i--)
439 int group = drawn_groups[i];
441 if (gui->set_layer (0, group, 0))
443 if (DrawLayerGroup (group, drawn_area) && !gui->gui)
445 int save_swap = SWAP_IDENT;
447 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
448 continue;
449 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback,
450 NULL);
451 r_search (PCB->Data->via_tree, drawn_area, NULL, pin_callback,
452 NULL);
453 /* draw element pads */
454 if (group == component || group == solder)
456 SWAP_IDENT = (group == solder);
457 r_search (PCB->Data->pad_tree, drawn_area, NULL,
458 pad_callback, NULL);
460 SWAP_IDENT = save_swap;
462 if (!gui->gui)
464 /* draw holes */
465 plated = -1;
466 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback,
467 &plated);
468 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback,
469 &plated);
474 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
475 return;
477 /* draw vias below silk */
478 if (PCB->ViaOn && gui->gui)
479 r_search (PCB->Data->via_tree, drawn_area, NULL, lowvia_callback, NULL);
480 /* Draw the solder mask if turned on */
481 if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
483 int save_swap = SWAP_IDENT;
484 SWAP_IDENT = 0;
485 DrawMask (drawn_area);
486 SWAP_IDENT = save_swap;
488 if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
490 int save_swap = SWAP_IDENT;
491 SWAP_IDENT = 1;
492 DrawMask (drawn_area);
493 SWAP_IDENT = save_swap;
495 /* Draw pins, pads, vias below silk */
496 if (gui->gui)
497 DrawTop (drawn_area);
498 else
500 HoleCountStruct hcs;
501 hcs.nplated = hcs.nunplated = 0;
502 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_counting_callback,
503 &hcs);
504 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_counting_callback,
505 &hcs);
506 if (hcs.nplated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
508 plated = 1;
509 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback,
510 &plated);
511 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback,
512 &plated);
514 if (hcs.nunplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
516 plated = 0;
517 r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback,
518 &plated);
519 r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback,
520 &plated);
523 /* Draw top silkscreen */
524 if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
525 DrawSilk (0, COMPONENT_LAYER, drawn_area);
526 if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
527 DrawSilk (1, SOLDER_LAYER, drawn_area);
528 if (gui->gui)
530 /* Draw element Marks */
531 if (PCB->PinOn)
532 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
533 NULL);
534 /* Draw rat lines on top */
535 if (PCB->RatOn)
536 DrawRats(drawn_area);
539 for (side = 0; side <= 1; side++)
541 int doit;
542 Boolean NoData = True;
543 ALLPAD_LOOP (PCB->Data);
545 if ((TEST_FLAG (ONSOLDERFLAG, pad) && side == SOLDER_LAYER)
546 || (!TEST_FLAG (ONSOLDERFLAG, pad) && side == COMPONENT_LAYER))
548 NoData = False;
549 break;
552 ENDALL_LOOP;
554 if (side == SOLDER_LAYER)
555 doit = gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), NoData);
556 else
557 doit = gui->set_layer ("toppaste", SL (PASTE, TOP), NoData);
558 if (doit)
560 gui->set_color (Output.fgGC, PCB->ElementColor);
561 ALLPAD_LOOP (PCB->Data);
563 if ((TEST_FLAG (ONSOLDERFLAG, pad) && side == SOLDER_LAYER)
564 || (!TEST_FLAG (ONSOLDERFLAG, pad)
565 && side == COMPONENT_LAYER))
566 if (!TEST_FLAG (NOPASTEFLAG, pad))
567 DrawPadLowLevel (Output.fgGC, pad, False, False);
569 ENDALL_LOOP;
573 doing_assy = True;
574 if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
575 PrintAssembly (drawn_area, component, 0);
577 if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
578 PrintAssembly (drawn_area, solder, 1);
579 doing_assy = False;
581 if (gui->set_layer ("fab", SL (FAB, 0), 0))
582 PrintFab ();
585 static void
586 DrawEMark (ElementTypePtr e, LocationType X, LocationType Y,
587 Boolean invisible)
589 int mark_size = EMARK_SIZE;
590 if (!PCB->InvisibleObjectsOn && invisible)
591 return;
593 if (e->PinN && mark_size > e->Pin[0].Thickness / 2)
594 mark_size = e->Pin[0].Thickness / 2;
595 if (e->PadN && mark_size > e->Pad[0].Thickness / 2)
596 mark_size = e->Pad[0].Thickness / 2;
598 gui->set_color (Output.fgGC,
599 invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
600 gui->set_line_cap (Output.fgGC, Trace_Cap);
601 gui->set_line_width (Output.fgGC, 0);
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);
605 gui->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
608 * If an element is locked, place a "L" on top of the "diamond".
609 * This provides a nice visual indication that it is locked that
610 * works even for color blind users.
612 if (TEST_FLAG (LOCKFLAG, e) )
614 gui->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
615 gui->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
620 static int
621 via_callback (const BoxType * b, void *cl)
623 PinTypePtr via = (PinTypePtr) b;
624 if (via->Mask)
625 DrawPlainVia (via, False);
626 return 1;
629 static int
630 pin_callback (const BoxType * b, void *cl)
632 DrawPlainPin ((PinTypePtr) b, False);
633 return 1;
636 static int
637 pad_callback (const BoxType * b, void *cl)
639 PadTypePtr pad = (PadTypePtr) b;
640 if (FRONT (pad))
641 DrawPad (pad, 0);
642 return 1;
645 /* ---------------------------------------------------------------------------
646 * draws pins pads and vias
648 static void
649 DrawTop (const BoxType * screen)
651 if (PCB->PinOn || doing_assy)
653 /* draw element pins */
654 r_search (PCB->Data->pin_tree, screen, NULL, pin_callback, NULL);
655 /* draw element pads */
656 r_search (PCB->Data->pad_tree, screen, NULL, pad_callback, NULL);
658 /* draw vias */
659 if (PCB->ViaOn || doing_assy)
661 r_search (PCB->Data->via_tree, screen, NULL, via_callback, NULL);
662 r_search (PCB->Data->via_tree, screen, NULL, hole_callback, NULL);
664 if (PCB->PinOn || doing_assy)
665 r_search (PCB->Data->pin_tree, screen, NULL, hole_callback, NULL);
668 struct pin_info
670 Boolean arg;
671 LayerTypePtr Layer;
674 static int
675 clearPin_callback (const BoxType * b, void *cl)
677 PinTypePtr pin = (PinTypePtr) b;
678 struct pin_info *i = (struct pin_info *) cl;
679 if (i->arg)
680 ClearOnlyPin (pin, True);
681 return 1;
683 static int
684 poly_callback (const BoxType * b, void *cl)
686 struct pin_info *i = (struct pin_info *) cl;
688 DrawPlainPolygon (i->Layer, (PolygonTypePtr) b);
689 return 1;
692 static int
693 clearPad_callback (const BoxType * b, void *cl)
695 PadTypePtr pad = (PadTypePtr) b;
696 if (!XOR (TEST_FLAG (ONSOLDERFLAG, pad), SWAP_IDENT))
697 ClearPad (pad, True);
698 return 1;
701 /* ---------------------------------------------------------------------------
702 * Draws silk layer.
705 static void
706 DrawSilk (int new_swap, int layer, BoxTypePtr drawn_area)
708 #if 0
709 /* This code is used when you want to mask silk to avoid exposed
710 pins and pads. We decided it was a bad idea to do this
711 unconditionally, but the code remains. */
712 struct pin_info info;
713 #endif
714 int save_swap = SWAP_IDENT;
715 SWAP_IDENT = new_swap;
717 #if 0
718 if (gui->poly_before)
720 gui->use_mask (HID_MASK_BEFORE);
721 #endif
722 DrawLayer (LAYER_PTR (max_layer + layer), drawn_area);
723 /* draw package */
724 r_search (PCB->Data->element_tree, drawn_area, NULL, frontE_callback,
725 NULL);
726 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
727 frontN_callback, NULL);
728 #if 0
731 gui->use_mask (HID_MASK_CLEAR);
732 info.arg = True;
733 r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, &info);
734 r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, &info);
735 r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &info);
737 if (gui->poly_after)
739 gui->use_mask (HID_MASK_AFTER);
740 DrawLayer (LAYER_PTR (max_layer + layer), drawn_area);
741 /* draw package */
742 r_search (PCB->Data->element_tree, drawn_area, NULL, frontE_callback,
743 NULL);
744 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
745 frontN_callback, NULL);
747 gui->use_mask (HID_MASK_OFF);
748 #endif
749 SWAP_IDENT = save_swap;
752 /* ---------------------------------------------------------------------------
753 * draws solder mask layer - this will cover nearly everything
755 static void
756 DrawMask (BoxType * screen)
758 struct pin_info info;
759 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
761 OutputType *out = &Output;
763 info.arg = True;
765 if (thin)
766 gui->set_color (Output.pmGC, PCB->MaskColor);
767 else
769 if (gui->poly_before)
771 gui->use_mask (HID_MASK_BEFORE);
772 gui->set_color (out->fgGC, PCB->MaskColor);
773 gui->fill_rect (out->fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
775 gui->use_mask (HID_MASK_CLEAR);
778 r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, &info);
779 r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, &info);
780 r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &info);
782 if (thin)
783 gui->set_color (Output.pmGC, "erase");
784 else
786 if (gui->poly_after)
788 gui->use_mask (HID_MASK_AFTER);
789 gui->set_color (out->fgGC, PCB->MaskColor);
790 gui->fill_rect (out->fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
792 gui->use_mask (HID_MASK_OFF);
795 #if 0
796 /* Some fabs want the board outline on the solder mask layer. If
797 you need this, change the '0' above to '1', and the code below
798 will copy the outline layer to the mask layers. */
799 if (!gui->gui)
801 int i;
802 for (i=PCB->Data->LayerN; i>=0; i--)
804 LayerTypePtr Layer = PCB->Data->Layer + i;
805 if (strcasecmp (Layer->Name, "outline") == 0)
806 DrawLayer (Layer, screen);
809 #endif
812 static void
813 DrawRats (BoxTypePtr drawn_area)
816 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
817 * XXX gtk only allows negative drawing.
818 * XXX using the mask here is to get rat transparency
820 int can_mask = strcmp(gui->name, "lesstif") == 0;
822 if (can_mask)
823 gui->use_mask (HID_MASK_CLEAR);
824 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
825 if (can_mask)
826 gui->use_mask (HID_MASK_OFF);
829 static int
830 line_callback (const BoxType * b, void *cl)
832 DrawLine ((LayerTypePtr) cl, (LineTypePtr) b, 0);
833 return 1;
836 static int
837 arc_callback (const BoxType * b, void *cl)
839 DrawArc ((LayerTypePtr) cl, (ArcTypePtr) b, 0);
840 return 1;
843 static int
844 text_callback (const BoxType * b, void *cl)
846 DrawRegularText ((LayerTypePtr) cl, (TextTypePtr) b, 0);
847 return 1;
851 /* ---------------------------------------------------------------------------
852 * draws one non-copper layer
854 void
855 DrawLayer (LayerTypePtr Layer, BoxType * screen)
857 struct pin_info info;
859 /* print the non-clearing polys */
860 info.Layer = Layer;
861 info.arg = False;
862 clip_box = screen;
863 r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
865 /* draw all visible lines this layer */
866 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
868 /* draw the layer arcs on screen */
869 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
871 /* draw the layer text on screen */
872 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
873 clip_box = NULL;
876 /* ---------------------------------------------------------------------------
877 * draws one layer group. Returns non-zero if pins and pads should be
878 * drawn with this group.
880 static int
881 DrawLayerGroup (int group, const BoxType * screen)
883 int i, rv = 1;
884 int layernum;
885 struct pin_info info;
886 LayerTypePtr Layer;
887 int n_entries = PCB->LayerGroups.Number[group];
888 Cardinal *layers = PCB->LayerGroups.Entries[group];
890 clip_box = screen;
891 for (i = n_entries - 1; i >= 0; i--)
893 layernum = layers[i];
894 Layer = PCB->Data->Layer + layers[i];
895 if (strcmp (Layer->Name, "outline") == 0
896 || strcmp (Layer->Name, "route") == 0)
897 rv = 0;
898 if (layernum < max_layer && Layer->On)
900 /* draw all polygons on this layer */
901 if (Layer->PolygonN)
903 info.Layer = Layer;
904 info.arg = True;
905 r_search (Layer->polygon_tree, screen, NULL, poly_callback,
906 &info);
907 info.arg = False;
910 if (TEST_FLAG (CHECKPLANESFLAG, PCB))
911 continue;
913 /* draw all visible lines this layer */
914 r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
916 /* draw the layer arcs on screen */
917 r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
919 /* draw the layer text on screen */
920 r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
924 if (n_entries > 1)
925 rv = 1;
926 return rv;
929 /* ---------------------------------------------------------------------------
930 * draws one polygon
931 * x and y are already in display coordinates
932 * the points are numbered:
934 * 5 --- 6
935 * / \
936 * 4 7
937 * | |
938 * 3 0
939 * \ /
940 * 2 --- 1
942 static void
943 DrawSpecialPolygon (HID * hid, hidGC DrawGC,
944 LocationType X, LocationType Y, int Thickness)
946 static FloatPolyType p[8] = {
948 0.5, -TAN_22_5_DEGREE_2},
950 TAN_22_5_DEGREE_2, -0.5},
952 -TAN_22_5_DEGREE_2, -0.5},
954 -0.5, -TAN_22_5_DEGREE_2},
956 -0.5, TAN_22_5_DEGREE_2},
958 -TAN_22_5_DEGREE_2, 0.5},
960 TAN_22_5_DEGREE_2, 0.5},
962 0.5, TAN_22_5_DEGREE_2}
964 static int special_size = 0;
965 static int scaled_x[8];
966 static int scaled_y[8];
967 int polygon_x[9];
968 int polygon_y[9];
969 int i;
972 if (Thickness != special_size)
974 special_size = Thickness;
975 for (i = 0; i < 8; i++)
977 scaled_x[i] = p[i].X * special_size;
978 scaled_y[i] = p[i].Y * special_size;
981 /* add line offset */
982 for (i = 0; i < 8; i++)
984 polygon_x[i] = X + scaled_x[i];
985 polygon_y[i] = Y + scaled_y[i];
987 if (TEST_FLAG (THINDRAWFLAG, PCB))
989 int i;
990 hid->set_line_cap (Output.fgGC, Round_Cap);
991 hid->set_line_width (Output.fgGC, 0);
992 polygon_x[8] = X + scaled_x[0];
993 polygon_y[8] = Y + scaled_y[0];
994 for (i = 0; i < 8; i++)
995 hid->draw_line (DrawGC, polygon_x[i], polygon_y[i],
996 polygon_x[i + 1], polygon_y[i + 1]);
998 else
999 hid->fill_polygon (DrawGC, 8, polygon_x, polygon_y);
1002 /* ---------------------------------------------------------------------------
1003 * lowlevel drawing routine for pins and vias
1005 static void
1006 DrawPinOrViaLowLevel (PinTypePtr Ptr, Boolean drawHole)
1008 if (Gathering)
1010 AddPart (Ptr);
1011 return;
1014 if (TEST_FLAG (HOLEFLAG, Ptr))
1016 if (drawHole)
1018 gui->fill_circle (Output.bgGC, Ptr->X, Ptr->Y, Ptr->Thickness / 2);
1019 gui->set_line_cap (Output.fgGC, Round_Cap);
1020 gui->set_line_width (Output.fgGC, 0);
1021 gui->draw_arc (Output.fgGC, Ptr->X, Ptr->Y,
1022 Ptr->Thickness / 2, Ptr->Thickness / 2, 0, 360);
1024 return;
1026 if (TEST_FLAG (SQUAREFLAG, Ptr))
1028 int l, r, t, b;
1029 l = Ptr->X - Ptr->Thickness / 2;
1030 b = Ptr->Y - Ptr->Thickness / 2;
1031 r = l + Ptr->Thickness;
1032 t = b + Ptr->Thickness;
1033 if (TEST_FLAG (THINDRAWFLAG, PCB))
1035 gui->set_line_cap (Output.fgGC, Round_Cap);
1036 gui->set_line_width (Output.fgGC, 0);
1037 gui->draw_line (Output.fgGC, r, t, r, b);
1038 gui->draw_line (Output.fgGC, l, t, l, b);
1039 gui->draw_line (Output.fgGC, r, t, l, t);
1040 gui->draw_line (Output.fgGC, r, b, l, b);
1042 else
1044 gui->fill_rect (Output.fgGC, l, b, r, t);
1047 else if (TEST_FLAG (OCTAGONFLAG, Ptr))
1049 gui->set_line_cap (Output.fgGC, Round_Cap);
1050 gui->set_line_width (Output.fgGC,
1051 (Ptr->Thickness - Ptr->DrillingHole) / 2);
1053 /* transform X11 specific coord system */
1054 DrawSpecialPolygon (gui, Output.fgGC, Ptr->X, Ptr->Y, Ptr->Thickness);
1056 else
1057 { /* draw a round pin or via */
1058 if (TEST_FLAG (THINDRAWFLAG, PCB))
1060 gui->set_line_cap (Output.fgGC, Round_Cap);
1061 gui->set_line_width (Output.fgGC, 0);
1062 gui->draw_arc (Output.fgGC, Ptr->X, Ptr->Y,
1063 Ptr->Thickness / 2, Ptr->Thickness / 2, 0, 360);
1065 else
1067 gui->fill_circle (Output.fgGC, Ptr->X, Ptr->Y, Ptr->Thickness / 2);
1071 /* and the drilling hole (which is always round */
1072 if (drawHole)
1074 if (TEST_FLAG (THINDRAWFLAG, PCB))
1076 gui->set_line_cap (Output.fgGC, Round_Cap);
1077 gui->set_line_width (Output.fgGC, 0);
1078 gui->draw_arc (Output.fgGC,
1079 Ptr->X, Ptr->Y, Ptr->DrillingHole / 2,
1080 Ptr->DrillingHole / 2, 0, 360);
1082 else
1084 gui->fill_circle (Output.bgGC, Ptr->X, Ptr->Y,
1085 Ptr->DrillingHole / 2);
1090 /**************************************************************
1091 * draw pin/via hole
1093 static void
1094 DrawHole (PinTypePtr Ptr)
1096 if (TEST_FLAG (THINDRAWFLAG, PCB))
1098 if (!TEST_FLAG (HOLEFLAG, Ptr))
1100 gui->set_line_cap (Output.fgGC, Round_Cap);
1101 gui->set_line_width (Output.fgGC, 0);
1102 gui->draw_arc (Output.fgGC,
1103 Ptr->X, Ptr->Y, Ptr->DrillingHole / 2,
1104 Ptr->DrillingHole / 2, 0, 360);
1107 else
1109 gui->fill_circle (Output.bgGC, Ptr->X, Ptr->Y, Ptr->DrillingHole / 2);
1111 if (TEST_FLAG (HOLEFLAG, Ptr))
1113 if (TEST_FLAG (WARNFLAG, Ptr))
1114 gui->set_color (Output.fgGC, PCB->WarnColor);
1115 else if (TEST_FLAG (SELECTEDFLAG, Ptr))
1116 gui->set_color (Output.fgGC, PCB->ViaSelectedColor);
1117 else
1118 gui->set_color (Output.fgGC, Settings.BlackColor);
1120 gui->set_line_cap (Output.fgGC, Round_Cap);
1121 gui->set_line_width (Output.fgGC, 0);
1122 gui->draw_arc (Output.fgGC,
1123 Ptr->X, Ptr->Y, Ptr->DrillingHole / 2,
1124 Ptr->DrillingHole / 2, 0, 360);
1128 /*******************************************************************
1129 * draw clearance in pixmask around pins and vias that pierce polygons
1131 static void
1132 ClearOnlyPin (PinTypePtr Pin, Boolean mask)
1134 BDimension half =
1135 (mask ? Pin->Mask / 2 : (Pin->Thickness + Pin->Clearance) / 2);
1137 if (!mask && TEST_FLAG (HOLEFLAG, Pin))
1138 return;
1139 if (half == 0)
1140 return;
1141 if (!mask && Pin->Clearance <= 0)
1142 return;
1144 /* Clear the area around the pin */
1145 if (TEST_FLAG (SQUAREFLAG, Pin))
1147 int l, r, t, b;
1148 l = Pin->X - half;
1149 b = Pin->Y - half;
1150 r = l + half * 2;
1151 t = b + half * 2;
1152 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
1154 gui->set_line_cap (Output.pmGC, Round_Cap);
1155 gui->set_line_width (Output.pmGC, 0);
1156 gui->draw_line (Output.pmGC, r, t, r, b);
1157 gui->draw_line (Output.pmGC, l, t, l, b);
1158 gui->draw_line (Output.pmGC, r, t, l, t);
1159 gui->draw_line (Output.pmGC, r, b, l, b);
1161 else
1162 gui->fill_rect (Output.pmGC, l, b, r, t);
1164 else if (TEST_FLAG (OCTAGONFLAG, Pin))
1166 gui->set_line_cap (Output.pmGC, Round_Cap);
1167 gui->set_line_width (Output.pmGC, (Pin->Clearance + Pin->Thickness
1168 - Pin->DrillingHole));
1170 DrawSpecialPolygon (gui, Output.pmGC, Pin->X, Pin->Y, half * 2);
1172 else
1174 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
1175 gui->draw_arc (Output.pmGC, Pin->X, Pin->Y, half, half, 0, 360);
1176 else
1177 gui->fill_circle (Output.pmGC, Pin->X, Pin->Y, half);
1181 /* ---------------------------------------------------------------------------
1182 * lowlevel drawing routine for pins and vias that pierce polygons
1184 void
1185 ClearPin (PinTypePtr Pin, int Type, int unused)
1187 BDimension half = (Pin->Thickness + Pin->Clearance) / 2;
1189 if (Gathering)
1191 AddPart (Pin);
1192 return;
1194 /* Clear the area around the pin */
1195 if (TEST_FLAG (SQUAREFLAG, Pin))
1197 int l, r, t, b;
1198 l = Pin->X - half;
1199 b = Pin->Y - half;
1200 r = l + half * 2;
1201 t = b + half * 2;
1202 gui->fill_rect (Output.pmGC, l, b, r, t);
1204 else if (TEST_FLAG (OCTAGONFLAG, Pin))
1206 gui->set_line_cap (Output.pmGC, Round_Cap);
1207 gui->set_line_width (Output.pmGC, (Pin->Clearance + Pin->Thickness
1208 - Pin->DrillingHole) / 2);
1210 DrawSpecialPolygon (gui, Output.pmGC, Pin->X, Pin->Y, half * 2);
1212 else
1214 gui->fill_circle (Output.pmGC, Pin->X, Pin->Y, half);
1216 if ((!TEST_FLAG (PINFLAG, Pin) && !PCB->ViaOn)
1217 || (TEST_FLAG (PINFLAG, Pin) && !PCB->PinOn))
1218 return;
1219 /* now draw the pin or via as appropriate */
1220 switch (Type)
1222 case VIA_TYPE:
1223 case PIN_TYPE:
1224 SetPVColor (Pin, Type);
1225 DrawPinOrViaLowLevel (Pin, True);
1226 break;
1227 case NO_TYPE:
1228 default:
1229 break;
1234 #if VERTICAL_TEXT
1235 /* vertical text handling provided by Martin Devera with fixes by harry eaton */
1237 /* draw vertical text; xywh is bounding, de is text's descend used for
1238 positioning */
1239 static void
1240 DrawVText (int x, int y, int w, int h, char *str)
1242 GdkPixmap *pm;
1243 GdkImage *im;
1244 GdkGCValues values;
1245 guint32 pixel;
1246 int i, j;
1248 if (!str || !*str)
1249 return;
1251 pm = gdk_pixmap_new (DrawingWindow, w, h, -1);
1253 /* draw into pixmap */
1254 gdk_draw_rectangle (pm, Output.bgGC, TRUE, 0, 0, w, h);
1256 gui_draw_string_markup (DrawingWindow, Output.font_desc, Output.fgGC,
1257 0, 0, str);
1259 im = gdk_drawable_get_image (pm, 0, 0, w, h);
1260 gdk_gc_get_values (Output.fgGC, &values);
1262 /* draw Transpose(im). TODO: Pango should be doing vertical text soon */
1263 for (i = 0; i < w; i++)
1264 for (j = 0; j < h; j++)
1266 pixel = gdk_image_get_pixel (im, i, j);
1267 if (pixel == values.foreground.pixel)
1268 gdk_draw_point (DrawingWindow, Output.fgGC, x + j, y + w - i - 1);
1270 g_object_unref (G_OBJECT (pm));
1272 #endif
1274 /* ---------------------------------------------------------------------------
1275 * lowlevel drawing routine for pin and via names
1277 static void
1278 DrawPinOrViaNameLowLevel (PinTypePtr Ptr)
1280 char *name;
1281 BoxType box;
1282 Boolean vert;
1283 TextType text;
1285 if (!Ptr->Name || !Ptr->Name[0])
1286 name = EMPTY (Ptr->Number);
1287 else
1288 name = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? Ptr->Number : Ptr->Name);
1290 vert = TEST_FLAG (EDGE2FLAG, Ptr);
1292 if (vert)
1294 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1295 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
1297 else
1299 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
1300 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
1302 if (Gathering)
1304 if (vert)
1306 box.X2 = box.X1;
1307 box.Y2 = box.Y1;
1309 else
1311 box.X2 = box.X1;
1312 box.Y2 = box.Y1;
1314 /*printf("AddPart: x1=%d y1=%d x2=%d y2=%d\n", box.X1, box.Y1, box.X2, box.Y2);*/
1315 AddPart (&box);
1316 return;
1318 /*printf("DrawPin(%d,%d): x=%d y=%d w=%d h=%d\n",
1319 TO_DRAW_X(Ptr->X), TO_DRAW_Y(Ptr->Y), box.X1, box.Y1, width, height);*/
1321 gui->set_color (Output.fgGC, PCB->PinNameColor);
1323 text.Flags = NoFlags ();
1324 text.Scale = Ptr->Thickness / 80;
1325 text.X = box.X1;
1326 text.Y = box.Y1;
1327 text.Direction = vert ? 1 : 0;
1328 text.TextString = name;
1330 if (gui->gui)
1331 doing_pinout++;
1332 DrawTextLowLevel (&text, 0);
1333 if (gui->gui)
1334 doing_pinout--;
1337 /* ---------------------------------------------------------------------------
1338 * lowlevel drawing routine for pads
1341 static void
1342 DrawPadLowLevel (hidGC gc, PadTypePtr Pad, Boolean clear, Boolean mask)
1344 int w = clear ? (mask ? Pad->Mask : Pad->Thickness + Pad->Clearance)
1345 : Pad->Thickness;
1347 if (Gathering)
1349 AddPart (Pad);
1350 return;
1353 if (TEST_FLAG (THINDRAWFLAG, PCB) ||
1354 (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
1356 int x1, y1, x2, y2, t, t2;
1357 t = w / 2;
1358 t2 = w - t;
1359 x1 = Pad->Point1.X;
1360 y1 = Pad->Point1.Y;
1361 x2 = Pad->Point2.X;
1362 y2 = Pad->Point2.Y;
1363 if (x1 > x2 || y1 > y2)
1365 /* this is a silly way to swap the variables */
1366 x1 ^= x2;
1367 x2 ^= x1;
1368 x1 ^= x2;
1369 y1 ^= y2;
1370 y2 ^= y1;
1371 y1 ^= y2;
1373 gui->set_line_cap (gc, Round_Cap);
1374 gui->set_line_width (gc, 0);
1375 if (TEST_FLAG (SQUAREFLAG, Pad)
1376 && (x1 == x2 || y1 == y2))
1378 x1 -= t;
1379 y1 -= t;
1380 x2 += t2;
1381 y2 += t2;
1382 gui->draw_line (gc, x1, y1, x1, y2);
1383 gui->draw_line (gc, x1, y2, x2, y2);
1384 gui->draw_line (gc, x2, y2, x2, y1);
1385 gui->draw_line (gc, x2, y1, x1, y1);
1387 else if (TEST_FLAG (SQUAREFLAG, Pad))
1389 /* slanted square pad */
1390 float tx, ty, theta;
1392 theta = atan2 (y2-y1, x2-x1);
1394 /* T is a vector half a thickness long, in the direction of
1395 one of the corners. */
1396 tx = t * cos (theta + M_PI/4) * sqrt(2.0);
1397 ty = t * sin (theta + M_PI/4) * sqrt(2.0);
1399 gui->draw_line (gc, x1-tx, y1-ty, x2+ty, y2-tx);
1400 gui->draw_line (gc, x2+ty, y2-tx, x2+tx, y2+ty);
1401 gui->draw_line (gc, x2+tx, y2+ty, x1-ty, y1+tx);
1402 gui->draw_line (gc, x1-ty, y1+tx, x1-tx, y1-ty);
1404 else if (x1 == x2 && y1 == y2)
1406 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 0, 360);
1408 else if (x1 == x2)
1410 gui->draw_line (gc, x1 - t, y1, x2 - t, y2);
1411 gui->draw_line (gc, x1 + t2, y1, x2 + t2, y2);
1412 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 0, -180);
1413 gui->draw_arc (gc, x2, y2, w / 2, w / 2, 180, -180);
1415 else if (y1 == y2)
1417 gui->draw_line (gc, x1, y1 - t, x2, y2 - t);
1418 gui->draw_line (gc, x1, y1 + t2, x2, y2 + t2);
1419 gui->draw_arc (gc, x1, y1, w / 2, w / 2, 90, -180);
1420 gui->draw_arc (gc, x2, y2, w / 2, w / 2, 270, -180);
1422 else
1424 /* Slanted round-end pads. */
1425 LocationType dx, dy, ox, oy;
1426 float h;
1428 dx = x2 - x1;
1429 dy = y2 - y1;
1430 h = t / sqrt (SQUARE (dx) + SQUARE (dy));
1431 ox = dy * h + 0.5 * SGN (dy);
1432 oy = -(dx * h + 0.5 * SGN (dx));
1434 gui->draw_line (gc, x1 + ox, y1 + oy, x2 + ox, y2 + oy);
1436 if (abs (ox) >= pixel_slop || abs (oy) >= pixel_slop)
1438 LocationType angle = atan2 ((float) dx, (float) dy) * 57.295779;
1439 gui->draw_line (gc, x1 - ox, y1 - oy, x2 - ox, y2 - oy);
1440 gui->draw_arc (gc,
1441 x1, y1, t, t, angle - 180, 180);
1442 gui->draw_arc (gc, x2, y2, t, t, angle, 180);
1446 else if (Pad->Point1.X == Pad->Point2.X
1447 && Pad->Point1.Y == Pad->Point2.Y)
1449 if (TEST_FLAG (SQUAREFLAG, Pad))
1451 int l, r, t, b;
1452 l = Pad->Point1.X - w / 2;
1453 b = Pad->Point1.Y - w / 2;
1454 r = l + w;
1455 t = b + w;
1456 gui->fill_rect (gc, l, b, r, t);
1458 else
1460 gui->fill_circle (gc, Pad->Point1.X, Pad->Point1.Y, w / 2);
1463 else
1465 gui->set_line_cap (gc,
1466 TEST_FLAG (SQUAREFLAG,
1467 Pad) ? Square_Cap : Round_Cap);
1468 gui->set_line_width (gc, w);
1470 gui->draw_line (gc,
1471 Pad->Point1.X, Pad->Point1.Y,
1472 Pad->Point2.X, Pad->Point2.Y);
1474 #if 0
1475 { /* Draw bounding box for test */
1476 BoxType *box = &Pad->BoundingBox;
1477 gui->set_line_width (gc, 0);
1478 gui->draw_line (gc, box->X1, box->Y1, box->X1, box->Y2);
1479 gui->draw_line (gc, box->X1, box->Y2, box->X2, box->Y2);
1480 gui->draw_line (gc, box->X2, box->Y2, box->X2, box->Y1);
1481 gui->draw_line (gc, box->X2, box->Y1, box->X1, box->Y1);
1483 #endif
1486 /* ---------------------------------------------------------------------------
1487 * lowlevel drawing routine for pad names
1490 static void
1491 DrawPadNameLowLevel (PadTypePtr Pad)
1493 BoxType box;
1494 char *name;
1495 Boolean vert;
1496 TextType text;
1498 if (!Pad->Name || !Pad->Name[0])
1499 name = EMPTY (Pad->Number);
1500 else
1501 name = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? Pad->Number : Pad->Name);
1503 /* should text be vertical ? */
1504 vert = (Pad->Point1.X == Pad->Point2.X);
1506 if (vert)
1508 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
1509 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
1511 else
1513 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
1514 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
1517 if (vert)
1519 box.X1 += Settings.PinoutTextOffsetY;
1520 box.Y1 -= Settings.PinoutTextOffsetX;
1522 else
1524 box.X1 += Settings.PinoutTextOffsetX;
1525 box.Y1 += Settings.PinoutTextOffsetY;
1528 if (Gathering)
1530 if (vert)
1532 box.X2 = box.X1;
1533 box.Y2 = box.Y1;
1535 else
1537 box.X2 = box.X1;
1538 box.Y2 = box.Y1;
1540 AddPart (&box);
1541 return;
1544 gui->set_color (Output.fgGC, PCB->PinNameColor);
1546 text.Flags = NoFlags ();
1547 text.Scale = Pad->Thickness / 50;
1548 text.X = box.X1;
1549 text.Y = box.Y1;
1550 text.Direction = vert ? 1 : 0;
1551 text.TextString = name;
1553 DrawTextLowLevel (&text, 0);
1557 /* ---------------------------------------------------------------------------
1558 * clearance for pads
1560 static void
1561 ClearPad (PadTypePtr Pad, Boolean mask)
1563 DrawPadLowLevel(Output.pmGC, Pad, True, mask);
1566 /* ---------------------------------------------------------------------------
1567 * lowlevel drawing routine for lines
1569 static void
1570 DrawLineLowLevel (LineTypePtr Line, Boolean HaveGathered)
1572 if (Gathering && !HaveGathered)
1574 AddPart (Line);
1575 return;
1578 gui->set_line_cap (Output.fgGC, Trace_Cap);
1579 if (TEST_FLAG (THINDRAWFLAG, PCB))
1580 gui->set_line_width (Output.fgGC, 0);
1581 else
1582 gui->set_line_width (Output.fgGC, Line->Thickness);
1584 gui->draw_line (Output.fgGC,
1585 Line->Point1.X, Line->Point1.Y,
1586 Line->Point2.X, Line->Point2.Y);
1589 /* ---------------------------------------------------------------------------
1590 * lowlevel drawing routine for text objects
1592 void
1593 DrawTextLowLevel (TextTypePtr Text, int min_line_width)
1595 LocationType x = 0;
1596 unsigned char *string = (unsigned char *) Text->TextString;
1597 Cardinal n;
1598 FontTypePtr font = &PCB->Font;
1600 if (Gathering)
1602 AddPart (Text);
1603 return;
1606 while (string && *string)
1608 /* draw lines if symbol is valid and data is present */
1609 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid)
1611 LineTypePtr line = font->Symbol[*string].Line;
1612 LineType newline;
1614 for (n = font->Symbol[*string].LineN; n; n--, line++)
1616 /* create one line, scale, move, rotate and swap it */
1617 newline = *line;
1618 newline.Point1.X = (newline.Point1.X + x) * Text->Scale / 100;
1619 newline.Point1.Y = newline.Point1.Y * Text->Scale / 100;
1620 newline.Point2.X = (newline.Point2.X + x) * Text->Scale / 100;
1621 newline.Point2.Y = newline.Point2.Y * Text->Scale / 100;
1622 newline.Thickness = newline.Thickness * Text->Scale / 200;
1623 if (newline.Thickness < min_line_width)
1624 newline.Thickness = min_line_width;
1626 RotateLineLowLevel (&newline, 0, 0, Text->Direction);
1628 /* the labels of SMD objects on the bottom
1629 * side haven't been swapped yet, only their offset
1631 if (TEST_FLAG (ONSOLDERFLAG, Text))
1633 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X);
1634 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y);
1635 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X);
1636 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y);
1638 /* add offset and draw line */
1639 newline.Point1.X += Text->X;
1640 newline.Point1.Y += Text->Y;
1641 newline.Point2.X += Text->X;
1642 newline.Point2.Y += Text->Y;
1643 DrawLineLowLevel (&newline, True);
1646 /* move on to next cursor position */
1647 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta);
1649 else
1651 /* the default symbol is a filled box */
1652 BoxType defaultsymbol = PCB->Font.DefaultSymbol;
1653 LocationType size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5;
1655 defaultsymbol.X1 = (defaultsymbol.X1 + x) * Text->Scale / 100;
1656 defaultsymbol.Y1 = defaultsymbol.Y1 * Text->Scale / 100;
1657 defaultsymbol.X2 = (defaultsymbol.X2 + x) * Text->Scale / 100;
1658 defaultsymbol.Y2 = defaultsymbol.Y2 * Text->Scale / 100;
1660 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction);
1662 /* add offset and draw box */
1663 defaultsymbol.X1 += Text->X;
1664 defaultsymbol.Y1 += Text->Y;
1665 defaultsymbol.X2 += Text->X;
1666 defaultsymbol.Y2 += Text->Y;
1667 gui->fill_rect (Output.fgGC,
1668 defaultsymbol.X1, defaultsymbol.Y1,
1669 defaultsymbol.X2, defaultsymbol.Y2);
1671 /* move on to next cursor position */
1672 x += size;
1674 string++;
1678 /* ---------------------------------------------------------------------------
1679 * lowlevel drawing routine for polygons
1681 static void
1682 DrawPolygonLowLevel (PolygonTypePtr Polygon)
1684 int *x, *y, n, i = 0;
1685 PLINE *pl;
1686 VNODE *v;
1687 if (!Polygon->Clipped)
1688 return;
1689 if (Gathering)
1691 AddPart (Polygon);
1692 return;
1694 pl = Polygon->Clipped->contours;
1695 n = pl->Count;
1696 x = (int *) malloc (n * sizeof (int));
1697 y = (int *) malloc (n * sizeof (int));
1698 for (v = &pl->head; i < n; v = v->next)
1700 x[i] = v->point[0];
1701 y[i++] = v->point[1];
1703 if (TEST_FLAG (THINDRAWFLAG, PCB)
1704 || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
1706 gui->set_line_width (Output.fgGC, 0);
1707 gui->set_line_cap (Output.fgGC, Round_Cap);
1708 for (i = 0; i < n - 1; i++)
1710 gui->draw_line (Output.fgGC, x[i], y[i], x[i + 1], y[i + 1]);
1711 // gui->fill_circle (Output.fgGC, x[i], y[i], 30);
1713 gui->draw_line (Output.fgGC, x[n - 1], y[n - 1], x[0], y[0]);
1715 else
1716 gui->fill_polygon (Output.fgGC, n, x, y);
1717 free (x);
1718 free (y);
1721 /* ---------------------------------------------------------------------------
1722 * lowlevel routine to element arcs
1724 static void
1725 DrawArcLowLevel (ArcTypePtr Arc)
1727 if (!Arc->Thickness)
1728 return;
1729 if (Gathering)
1731 AddPart (Arc);
1732 return;
1735 if (TEST_FLAG (THINDRAWFLAG, PCB))
1736 gui->set_line_width (Output.fgGC, 0);
1737 else
1738 gui->set_line_width (Output.fgGC, Arc->Thickness);
1739 gui->set_line_cap (Output.fgGC, Trace_Cap);
1741 gui->draw_arc (Output.fgGC, Arc->X, Arc->Y, Arc->Width,
1742 Arc->Height, Arc->StartAngle, Arc->Delta);
1745 /* ---------------------------------------------------------------------------
1746 * draws the package of an element
1748 static void
1749 DrawElementPackageLowLevel (ElementTypePtr Element, int unused)
1751 /* draw lines, arcs, text and pins */
1752 ELEMENTLINE_LOOP (Element);
1754 DrawLineLowLevel (line, False);
1756 END_LOOP;
1757 ARC_LOOP (Element);
1759 DrawArcLowLevel (arc);
1761 END_LOOP;
1764 /* ---------------------------------------------------------------------------
1765 * draw a via object
1767 void
1768 DrawVia (PinTypePtr Via, int unused)
1770 if (!Gathering)
1771 SetPVColor (Via, VIA_TYPE);
1772 //if (!doing_pinout && !TEST_FLAG (HOLEFLAG, Via) && TEST_ANY_PIPS (Via))
1773 // ClearPin (Via, VIA_TYPE, 0);
1774 //else
1775 DrawPinOrViaLowLevel (Via, True);
1776 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1777 DrawPinOrViaNameLowLevel (Via);
1780 /* ---------------------------------------------------------------------------
1781 * draw a via without dealing with polygon clearance
1783 static void
1784 DrawPlainVia (PinTypePtr Via, Boolean holeToo)
1786 if (!Gathering)
1787 SetPVColor (Via, VIA_TYPE);
1788 DrawPinOrViaLowLevel (Via, holeToo);
1789 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
1790 DrawPinOrViaNameLowLevel (Via);
1793 /* ---------------------------------------------------------------------------
1794 * draws the name of a via
1796 void
1797 DrawViaName (PinTypePtr Via, int unused)
1799 if (!Gathering)
1801 if (TEST_FLAG (SELECTEDFLAG, Via))
1802 gui->set_color (Output.fgGC, PCB->ViaSelectedColor);
1803 else
1804 gui->set_color (Output.fgGC, PCB->ViaColor);
1806 DrawPinOrViaNameLowLevel (Via);
1809 /* ---------------------------------------------------------------------------
1810 * draw a pin object
1812 void
1813 DrawPin (PinTypePtr Pin, int unused)
1815 //if (!doing_pinout && !TEST_FLAG (HOLEFLAG, Pin) && TEST_ANY_PIPS (Pin))
1816 // ClearPin (Pin, PIN_TYPE, 0);
1817 //else
1819 if (!Gathering)
1820 SetPVColor (Pin, PIN_TYPE);
1821 DrawPinOrViaLowLevel (Pin, True);
1823 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1824 || doing_pinout)
1825 DrawPinOrViaNameLowLevel (Pin);
1828 /* ---------------------------------------------------------------------------
1829 * draw a pin without clearing around polygons
1831 static void
1832 DrawPlainPin (PinTypePtr Pin, Boolean holeToo)
1834 if (!Gathering)
1835 SetPVColor (Pin, PIN_TYPE);
1836 DrawPinOrViaLowLevel (Pin, holeToo);
1837 if (!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1838 DrawPinOrViaNameLowLevel (Pin);
1841 /* ---------------------------------------------------------------------------
1842 * draws the name of a pin
1844 void
1845 DrawPinName (PinTypePtr Pin, int unused)
1847 if (!Gathering)
1849 if (TEST_FLAG (SELECTEDFLAG, Pin))
1850 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1851 else
1852 gui->set_color (Output.fgGC, PCB->PinColor);
1854 DrawPinOrViaNameLowLevel (Pin);
1857 /* ---------------------------------------------------------------------------
1858 * draw a pad object
1860 void
1861 DrawPad (PadTypePtr Pad, int unused)
1863 if (!Gathering)
1865 if (doing_pinout)
1866 gui->set_color (Output.fgGC, PCB->PinColor);
1867 else if (TEST_FLAG (WARNFLAG | SELECTEDFLAG | FOUNDFLAG, Pad))
1869 if (TEST_FLAG (WARNFLAG, Pad))
1870 gui->set_color (Output.fgGC, PCB->WarnColor);
1871 else if (TEST_FLAG (SELECTEDFLAG, Pad))
1872 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1873 else
1874 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1876 else if (FRONT (Pad))
1877 gui->set_color (Output.fgGC, PCB->PinColor);
1878 else
1879 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
1881 DrawPadLowLevel (Output.fgGC, Pad, False, False);
1882 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1883 DrawPadNameLowLevel (Pad);
1886 /* ---------------------------------------------------------------------------
1887 * draws the name of a pad
1889 void
1890 DrawPadName (PadTypePtr Pad, int unused)
1892 if (!Gathering)
1894 if (TEST_FLAG (SELECTEDFLAG, Pad))
1895 gui->set_color (Output.fgGC, PCB->PinSelectedColor);
1896 else if (FRONT (Pad))
1897 gui->set_color (Output.fgGC, PCB->PinColor);
1898 else
1899 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
1901 DrawPadNameLowLevel (Pad);
1904 /* ---------------------------------------------------------------------------
1905 * draws a line on a layer
1907 void
1908 DrawLine (LayerTypePtr Layer, LineTypePtr Line, int unused)
1910 if (!Gathering)
1912 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Line))
1914 if (TEST_FLAG (SELECTEDFLAG, Line))
1915 gui->set_color (Output.fgGC, Layer->SelectedColor);
1916 else
1917 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1919 else
1920 gui->set_color (Output.fgGC, Layer->Color);
1922 DrawLineLowLevel (Line, False);
1925 /* ---------------------------------------------------------------------------
1926 * draws a ratline
1928 void
1929 DrawRat (RatTypePtr Line, int unused)
1931 if (!Gathering)
1933 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Line))
1935 if (TEST_FLAG (SELECTEDFLAG, Line))
1936 gui->set_color (Output.fgGC, PCB->RatSelectedColor);
1937 else
1938 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1940 else
1941 gui->set_color (Output.fgGC, PCB->RatColor);
1943 if (Settings.RatThickness < 20)
1944 Line->Thickness = pixel_slop * Settings.RatThickness;
1945 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
1946 if (TEST_FLAG(VIAFLAG, Line))
1948 int w = Line->Thickness;
1950 if (Gathering)
1952 BoxType b;
1954 b.X1 = Line->Point1.X - w * 2 - w / 2;
1955 b.X2 = Line->Point1.X + w * 2 + w / 2;
1956 b.Y1 = Line->Point1.Y - w * 2 - w / 2;
1957 b.Y2 = Line->Point1.Y + w * 2 + w / 2;
1958 AddPart(&b);
1960 else
1962 if (TEST_FLAG (THINDRAWFLAG, PCB))
1963 gui->set_line_width (Output.fgGC, 0);
1964 else
1965 gui->set_line_width (Output.fgGC, w);
1966 gui->draw_arc (Output.fgGC, Line->Point1.X, Line->Point1.Y,
1967 w * 2, w * 2, 0, 360);
1970 else
1971 DrawLineLowLevel ((LineTypePtr) Line, False);
1974 /* ---------------------------------------------------------------------------
1975 * draws an arc on a layer
1977 void
1978 DrawArc (LayerTypePtr Layer, ArcTypePtr Arc, int unused)
1980 if (!Arc->Thickness)
1981 return;
1982 if (!Gathering)
1984 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Arc))
1986 if (TEST_FLAG (SELECTEDFLAG, Arc))
1987 gui->set_color (Output.fgGC, Layer->SelectedColor);
1988 else
1989 gui->set_color (Output.fgGC, PCB->ConnectedColor);
1991 else
1992 gui->set_color (Output.fgGC, Layer->Color);
1994 DrawArcLowLevel (Arc);
1997 /* ---------------------------------------------------------------------------
1998 * draws a text on a layer
2000 void
2001 DrawText (LayerTypePtr Layer, TextTypePtr Text, int unused)
2003 int min_silk_line;
2004 if (!Layer->On)
2005 return;
2006 if (TEST_FLAG (SELECTEDFLAG, Text))
2007 gui->set_color (Output.fgGC, Layer->SelectedColor);
2008 else
2009 gui->set_color (Output.fgGC, Layer->Color);
2010 if (Layer == & PCB->Data->SILKLAYER
2011 || Layer == & PCB->Data->BACKSILKLAYER)
2012 min_silk_line = PCB->minSlk;
2013 else
2014 min_silk_line = PCB->minWid;
2015 DrawTextLowLevel (Text, min_silk_line);
2018 /* ---------------------------------------------------------------------------
2019 * draws text on a layer
2021 static void
2022 DrawRegularText (LayerTypePtr Layer, TextTypePtr Text, int unused)
2024 int min_silk_line;
2025 if (TEST_FLAG (SELECTEDFLAG, Text))
2026 gui->set_color (Output.fgGC, Layer->SelectedColor);
2027 else
2028 gui->set_color (Output.fgGC, Layer->Color);
2029 if (Layer == & PCB->Data->SILKLAYER
2030 || Layer == & PCB->Data->BACKSILKLAYER)
2031 min_silk_line = PCB->minSlk;
2032 else
2033 min_silk_line = PCB->minWid;
2034 DrawTextLowLevel (Text, min_silk_line);
2037 static int
2038 cp_callback (const BoxType * b, void *cl)
2040 ClearPin ((PinTypePtr) b, (int) (size_t) cl, 0);
2041 return 1;
2044 /* ---------------------------------------------------------------------------
2045 * draws a polygon on a layer
2047 void
2048 DrawPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon, int unused)
2050 int layernum;
2052 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Polygon))
2054 if (TEST_FLAG (SELECTEDFLAG, Polygon))
2055 gui->set_color (Output.fgGC, Layer->SelectedColor);
2056 else
2057 gui->set_color (Output.fgGC, PCB->ConnectedColor);
2059 else
2060 gui->set_color (Output.fgGC, Layer->Color);
2061 layernum = GetLayerNumber (PCB->Data, Layer);
2062 DrawPolygonLowLevel (Polygon);
2063 if (TEST_FLAG (CLEARPOLYFLAG, Polygon))
2065 r_search (PCB->Data->pin_tree, &Polygon->BoundingBox, NULL,
2066 cp_callback, (void *) PIN_TYPE);
2067 r_search (PCB->Data->via_tree, &Polygon->BoundingBox, NULL,
2068 cp_callback, (void *) VIA_TYPE);
2073 thin_callback (PLINE * pl, LayerTypePtr lay, PolygonTypePtr poly)
2075 int i, *x, *y;
2076 VNODE *v;
2078 i = 0;
2079 x = (int *) malloc (pl->Count * sizeof (int));
2080 y = (int *) malloc (pl->Count * sizeof (int));
2081 for (v = &pl->head; i < pl->Count; v = v->next)
2083 x[i] = v->point[0];
2084 y[i++] = v->point[1];
2086 gui->set_line_cap (Output.fgGC, Round_Cap);
2087 gui->set_line_width (Output.fgGC, 0);
2088 for (i = 0; i < pl->Count - 1; i++)
2090 gui->draw_line (Output.fgGC, x[i], y[i], x[i + 1], y[i + 1]);
2091 // gui->fill_circle (Output.fgGC, x[i], y[i], 30);
2093 gui->draw_line (Output.fgGC, x[pl->Count - 1], y[pl->Count - 1], x[0],
2094 y[0]);
2095 free (x);
2096 free (y);
2097 return 0;
2101 /* ---------------------------------------------------------------------------
2102 * draws a polygon
2104 static void
2105 DrawPlainPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
2107 if (TEST_FLAG (SELECTEDFLAG | FOUNDFLAG, Polygon))
2109 if (TEST_FLAG (SELECTEDFLAG, Polygon))
2110 gui->set_color (Output.fgGC, Layer->SelectedColor);
2111 else
2112 gui->set_color (Output.fgGC, PCB->ConnectedColor);
2114 else
2115 gui->set_color (Output.fgGC, Layer->Color);
2116 /* if the gui has the dicer flag set then it won't accept thin draw */
2117 if ((TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
2118 && !gui->poly_dicer)
2120 DrawPolygonLowLevel (Polygon);
2121 if (!Gathering)
2122 PolygonHoles (clip_box, Layer, Polygon, thin_callback);
2124 else if (Polygon->Clipped)
2126 NoHolesPolygonDicer (Polygon, clip_box, DrawPolygonLowLevel, NULL);
2127 /* draw other parts of the polygon if fullpoly flag is set */
2128 if (TEST_FLAG (FULLPOLYFLAG, Polygon))
2130 POLYAREA *pg;
2131 for (pg = Polygon->Clipped->f; pg != Polygon->Clipped; pg = pg->f)
2133 PolygonType poly;
2134 poly.Clipped = pg;
2135 NoHolesPolygonDicer (&poly, clip_box, DrawPolygonLowLevel, NULL);
2139 /* if the gui has the dicer flag set then it won't draw missing poly outlines */
2140 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && Polygon->Clipped && !Gathering
2141 && !gui->poly_dicer)
2143 POLYAREA *pg;
2145 for (pg = Polygon->Clipped->f; pg != Polygon->Clipped; pg = pg->f)
2147 VNODE *v;
2148 PLINE *pl = pg->contours;
2149 int i = 0;
2150 int n = pl->Count;
2151 int *x = (int *) malloc (n * sizeof (int));
2152 int *y = (int *) malloc (n * sizeof (int));
2153 for (v = &pl->head; i < n; v = v->next)
2155 x[i] = v->point[0];
2156 y[i++] = v->point[1];
2158 gui->set_line_width (Output.fgGC, 0);
2159 gui->set_line_cap (Output.fgGC, Round_Cap);
2160 for (i = 0; i < n - 1; i++)
2162 gui->draw_line (Output.fgGC, x[i], y[i], x[i + 1], y[i + 1]);
2163 /* gui->fill_circle (Output.bgGC, x[i], y[i], 10); */
2165 gui->draw_line (Output.fgGC, x[n - 1], y[n - 1], x[0], y[0]);
2166 free (x);
2167 free (y);
2172 /* ---------------------------------------------------------------------------
2173 * draws an element
2175 void
2176 DrawElement (ElementTypePtr Element, int unused)
2178 DrawElementPackage (Element, unused);
2179 DrawElementName (Element, unused);
2180 DrawElementPinsAndPads (Element, unused);
2183 /* ---------------------------------------------------------------------------
2184 * draws the name of an element
2186 void
2187 DrawElementName (ElementTypePtr Element, int unused)
2189 if (gui->gui && TEST_FLAG (HIDENAMESFLAG, PCB))
2190 return;
2191 if (TEST_FLAG (HIDENAMEFLAG, Element))
2192 return;
2193 if (doing_pinout || doing_assy)
2194 gui->set_color (Output.fgGC, PCB->ElementColor);
2195 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, Element)))
2196 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
2197 else if (FRONT (Element))
2198 gui->set_color (Output.fgGC, PCB->ElementColor);
2199 else
2200 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
2201 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2204 /* ---------------------------------------------------------------------------
2205 * draws the package of an element
2207 void
2208 DrawElementPackage (ElementTypePtr Element, int unused)
2210 /* set color and draw lines, arcs, text and pins */
2211 if (doing_pinout || doing_assy)
2212 gui->set_color (Output.fgGC, PCB->ElementColor);
2213 else if (TEST_FLAG (SELECTEDFLAG, Element))
2214 gui->set_color (Output.fgGC, PCB->ElementSelectedColor);
2215 else if (FRONT (Element))
2216 gui->set_color (Output.fgGC, PCB->ElementColor);
2217 else
2218 gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
2219 DrawElementPackageLowLevel (Element, unused);
2222 /* ---------------------------------------------------------------------------
2223 * draw pins of an element
2225 void
2226 DrawElementPinsAndPads (ElementTypePtr Element, int unused)
2228 PAD_LOOP (Element);
2230 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
2231 DrawPad (pad, unused);
2233 END_LOOP;
2234 PIN_LOOP (Element);
2236 DrawPin (pin, unused);
2238 END_LOOP;
2241 /* ---------------------------------------------------------------------------
2242 * erase a via
2244 void
2245 EraseVia (PinTypePtr Via)
2247 Erasing++;
2248 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2249 DrawPinOrViaLowLevel (Via, False);
2250 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
2251 DrawPinOrViaNameLowLevel (Via);
2252 Erasing--;
2255 /* ---------------------------------------------------------------------------
2256 * erase a ratline
2258 void
2259 EraseRat (RatTypePtr Rat)
2261 Erasing++;
2262 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2263 if (TEST_FLAG(VIAFLAG, Rat))
2265 int w = Rat->Thickness;
2267 if (TEST_FLAG (THINDRAWFLAG, PCB))
2268 gui->set_line_width (Output.fgGC, 0);
2269 else
2270 gui->set_line_width (Output.fgGC, w);
2271 gui->draw_arc (Output.fgGC, Rat->Point1.X, Rat->Point1.Y,
2272 w * 2, w * 2, 0, 360);
2274 else
2275 DrawLineLowLevel ((LineTypePtr) Rat, False);
2276 Erasing--;
2280 /* ---------------------------------------------------------------------------
2281 * erase a via name
2283 void
2284 EraseViaName (PinTypePtr Via)
2286 Erasing++;
2287 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2288 DrawPinOrViaNameLowLevel (Via);
2289 Erasing--;
2292 /* ---------------------------------------------------------------------------
2293 * erase a pad object
2295 void
2296 ErasePad (PadTypePtr Pad)
2298 Erasing++;
2299 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2300 DrawPadLowLevel (Output.fgGC, Pad, False, False);
2301 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
2302 DrawPadNameLowLevel (Pad);
2303 Erasing--;
2306 /* ---------------------------------------------------------------------------
2307 * erase a pad name
2309 void
2310 ErasePadName (PadTypePtr Pad)
2312 Erasing++;
2313 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2314 DrawPadNameLowLevel (Pad);
2315 Erasing--;
2318 /* ---------------------------------------------------------------------------
2319 * erase a pin object
2321 void
2322 ErasePin (PinTypePtr Pin)
2324 Erasing++;
2325 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2326 DrawPinOrViaLowLevel (Pin, False);
2327 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
2328 DrawPinOrViaNameLowLevel (Pin);
2329 Erasing--;
2332 /* ---------------------------------------------------------------------------
2333 * erase a pin name
2335 void
2336 ErasePinName (PinTypePtr Pin)
2338 Erasing++;
2339 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2340 DrawPinOrViaNameLowLevel (Pin);
2341 Erasing--;
2344 /* ---------------------------------------------------------------------------
2345 * erases a line on a layer
2347 void
2348 EraseLine (LineTypePtr Line)
2350 Erasing++;
2351 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2352 DrawLineLowLevel (Line, False);
2353 Erasing--;
2356 /* ---------------------------------------------------------------------------
2357 * erases an arc on a layer
2359 void
2360 EraseArc (ArcTypePtr Arc)
2362 if (!Arc->Thickness)
2363 return;
2364 Erasing++;
2365 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2366 DrawArcLowLevel (Arc);
2367 Erasing--;
2370 /* ---------------------------------------------------------------------------
2371 * erases a text on a layer
2373 void
2374 EraseText (LayerTypePtr Layer, TextTypePtr Text)
2376 int min_silk_line;
2377 Erasing++;
2378 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2379 if (Layer == & PCB->Data->SILKLAYER
2380 || Layer == & PCB->Data->BACKSILKLAYER)
2381 min_silk_line = PCB->minSlk;
2382 else
2383 min_silk_line = PCB->minWid;
2384 DrawTextLowLevel (Text, min_silk_line);
2385 Erasing--;
2388 /* ---------------------------------------------------------------------------
2389 * erases a polygon on a layer
2391 void
2392 ErasePolygon (PolygonTypePtr Polygon)
2394 Erasing++;
2395 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2396 DrawPolygonLowLevel (Polygon);
2397 Erasing--;
2400 /* ---------------------------------------------------------------------------
2401 * erases an element
2403 void
2404 EraseElement (ElementTypePtr Element)
2406 Erasing++;
2407 /* set color and draw lines, arcs, text and pins */
2408 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2409 ELEMENTLINE_LOOP (Element);
2411 DrawLineLowLevel (line, False);
2413 END_LOOP;
2414 ARC_LOOP (Element);
2416 DrawArcLowLevel (arc);
2418 END_LOOP;
2419 if (!TEST_FLAG (HIDENAMEFLAG, Element))
2420 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2421 EraseElementPinsAndPads (Element);
2422 Erasing--;
2425 /* ---------------------------------------------------------------------------
2426 * erases all pins and pads of an element
2428 void
2429 EraseElementPinsAndPads (ElementTypePtr Element)
2431 Erasing++;
2432 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2433 PIN_LOOP (Element);
2435 /* if (TEST_ANY_PIPS (pin))
2437 ClearPin (pin, NO_TYPE, 0);
2438 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2441 DrawPinOrViaLowLevel (pin, False);
2442 if (TEST_FLAG (DISPLAYNAMEFLAG, pin))
2443 DrawPinOrViaNameLowLevel (pin);
2445 END_LOOP;
2446 PAD_LOOP (Element);
2448 DrawPadLowLevel (Output.fgGC, pad, False, False);
2449 if (TEST_FLAG (DISPLAYNAMEFLAG, pad))
2450 DrawPadNameLowLevel (pad);
2452 END_LOOP;
2453 Erasing--;
2456 /* ---------------------------------------------------------------------------
2457 * erases the name of an element
2459 void
2460 EraseElementName (ElementTypePtr Element)
2462 if (TEST_FLAG (HIDENAMEFLAG, Element))
2463 return;
2464 Erasing++;
2465 gui->set_color (Output.fgGC, Settings.BackgroundColor);
2466 DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
2467 Erasing--;
2471 void
2472 EraseObject (int type, void *lptr, void *ptr)
2474 switch (type)
2476 case VIA_TYPE:
2477 case PIN_TYPE:
2478 ErasePin ((PinTypePtr) ptr);
2479 break;
2480 case TEXT_TYPE:
2481 case ELEMENTNAME_TYPE:
2482 EraseText (lptr, (TextTypePtr) ptr);
2483 break;
2484 case POLYGON_TYPE:
2485 ErasePolygon ((PolygonTypePtr) ptr);
2486 break;
2487 case ELEMENT_TYPE:
2488 EraseElement ((ElementTypePtr) ptr);
2489 break;
2490 case LINE_TYPE:
2491 case ELEMENTLINE_TYPE:
2492 case RATLINE_TYPE:
2493 EraseLine ((LineTypePtr) ptr);
2494 break;
2495 case PAD_TYPE:
2496 ErasePad ((PadTypePtr) ptr);
2497 break;
2498 case ARC_TYPE:
2499 case ELEMENTARC_TYPE:
2500 EraseArc ((ArcTypePtr) ptr);
2501 break;
2502 default:
2503 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
2509 void
2510 DrawObject (int type, void *ptr1, void *ptr2, int unused)
2512 switch (type)
2514 case VIA_TYPE:
2515 if (PCB->ViaOn)
2516 DrawVia ((PinTypePtr) ptr2, 0);
2517 break;
2518 case LINE_TYPE:
2519 if (((LayerTypePtr) ptr1)->On)
2520 DrawLine ((LayerTypePtr) ptr1, (LineTypePtr) ptr2, 0);
2521 break;
2522 case ARC_TYPE:
2523 if (((LayerTypePtr) ptr1)->On)
2524 DrawArc ((LayerTypePtr) ptr1, (ArcTypePtr) ptr2, 0);
2525 break;
2526 case TEXT_TYPE:
2527 if (((LayerTypePtr) ptr1)->On)
2528 DrawText ((LayerTypePtr) ptr1, (TextTypePtr) ptr2, 0);
2529 break;
2530 case POLYGON_TYPE:
2531 if (((LayerTypePtr) ptr1)->On)
2532 DrawPolygon ((LayerTypePtr) ptr1, (PolygonTypePtr) ptr2, 0);
2533 break;
2534 case ELEMENT_TYPE:
2535 if (PCB->ElementOn &&
2536 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
2537 DrawElement ((ElementTypePtr) ptr2, 0);
2538 break;
2539 case RATLINE_TYPE:
2540 if (PCB->RatOn)
2541 DrawRat ((RatTypePtr) ptr2, 0);
2542 break;
2543 case PIN_TYPE:
2544 if (PCB->PinOn)
2545 DrawPin ((PinTypePtr) ptr2, 0);
2546 break;
2547 case PAD_TYPE:
2548 if (PCB->PinOn)
2549 DrawPad ((PadTypePtr) ptr2, 0);
2550 break;
2551 case ELEMENTNAME_TYPE:
2552 if (PCB->ElementOn &&
2553 (FRONT ((ElementTypePtr) ptr2) || PCB->InvisibleObjectsOn))
2554 DrawElementName ((ElementTypePtr) ptr1, 0);
2555 break;
2559 /* ---------------------------------------------------------------------------
2560 * HID drawing callback.
2563 void
2564 hid_expose_callback (HID * hid, BoxType * region, void *item)
2566 HID *old_gui = gui;
2567 hidGC savebg = Output.bgGC;
2568 hidGC savefg = Output.fgGC;
2569 hidGC savepm = Output.pmGC;
2571 gui = hid;
2572 Output.fgGC = gui->make_gc ();
2573 Output.bgGC = gui->make_gc ();
2574 Output.pmGC = gui->make_gc ();
2576 render = True;
2577 Gathering = False;
2579 /*printf("\033[32mhid_expose_callback, s=%p %d\033[0m\n", &(SWAP_IDENT), SWAP_IDENT); */
2581 hid->set_color (Output.pmGC, "erase");
2582 hid->set_color (Output.bgGC, "drill");
2584 if (item)
2586 doing_pinout = True;
2587 DrawElement (item, 0);
2588 doing_pinout = False;
2590 else
2591 DrawEverything (region);
2593 gui->destroy_gc (Output.fgGC);
2594 gui->destroy_gc (Output.bgGC);
2595 gui->destroy_gc (Output.pmGC);
2596 gui = old_gui;
2597 Output.fgGC = savefg;
2598 Output.bgGC = savebg;
2599 Output.pmGC = savepm;
2601 Gathering = True;