hid/gtk (GL): I think the polygon renderer works in mask mode now
[geda-pcb/pcjc2.git] / src / draw.c
blob73a83b0a7ce70127260da1c3fa1499164ee45b40
1 /*
2 * COPYRIGHT
4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996, 2003, 2004 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
28 /* drawing routines
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
35 #include "global.h"
36 #include "hid_draw.h"
38 /*#include "clip.h"*/
39 #include "compat.h"
40 #include "crosshair.h"
41 #include "data.h"
42 #include "draw.h"
43 #include "draw_funcs.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 #undef NDEBUG
58 #include <assert.h>
60 #ifndef MAXINT
61 #define MAXINT (((unsigned int)(~0))>>1)
62 #endif
64 #define SMALL_SMALL_TEXT_SIZE 0
65 #define SMALL_TEXT_SIZE 1
66 #define NORMAL_TEXT_SIZE 2
67 #define LARGE_TEXT_SIZE 3
68 #define N_TEXT_SIZES 4
71 /* ---------------------------------------------------------------------------
72 * some local identifiers
74 static BoxType Block = {MAXINT, MAXINT, -MAXINT, -MAXINT};
76 static int doing_pinout = 0;
77 static bool doing_assy = false;
78 static HID_DRAW *hid_draw = NULL;
80 /* ---------------------------------------------------------------------------
81 * some local prototypes
83 static void DrawEverything (const BoxType *);
84 static void AddPart (void *);
85 /* static */ void DrawEMark (ElementType *, Coord, Coord, bool);
86 /* static */ void DrawRats (HID_DRAW *hid_draw, const BoxType *);
88 static void
89 set_object_color (AnyObjectType *obj, char *warn_color, char *selected_color,
90 char *connected_color, char *found_color, char *normal_color)
92 char *color;
94 if (warn_color != NULL && TEST_FLAG (WARNFLAG, obj)) color = warn_color;
95 else if (selected_color != NULL && TEST_FLAG (SELECTEDFLAG, obj)) color = selected_color;
96 else if (connected_color != NULL && TEST_FLAG (CONNECTEDFLAG, obj)) color = connected_color;
97 else if (found_color != NULL && TEST_FLAG (FOUNDFLAG, obj)) color = found_color;
98 else color = normal_color;
100 hid_draw_set_color (Output.fgGC, color);
103 /*---------------------------------------------------------------------------
104 * Adds the update rect to the update region
106 static void
107 AddPart (void *b)
109 BoxType *box = (BoxType *) b;
111 Block.X1 = MIN (Block.X1, box->X1);
112 Block.X2 = MAX (Block.X2, box->X2);
113 Block.Y1 = MIN (Block.Y1, box->Y1);
114 Block.Y2 = MAX (Block.Y2, box->Y2);
118 * initiate the actual redrawing of the updated area
120 void
121 Draw (void)
123 if (Block.X1 <= Block.X2 && Block.Y1 <= Block.Y2)
124 gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2);
126 /* shrink the update block */
127 Block.X1 = Block.Y1 = MAXINT;
128 Block.X2 = Block.Y2 = -MAXINT;
131 /* ----------------------------------------------------------------------
132 * redraws all the data by the event handlers
134 void
135 Redraw (void)
137 gui->invalidate_all ();
140 static int
141 pad_callback (const BoxType * b, void *cl)
143 PadType *pad = (PadType *) b;
144 int *side = cl;
146 if (ON_SIDE (pad, *side))
148 set_object_color ((AnyObjectType *)pad, PCB->WarnColor,
149 PCB->PinSelectedColor, PCB->ConnectedColor, PCB->FoundColor,
150 FRONT (pad) ? PCB->PinColor : PCB->InvisibleObjectsColor);
152 dapi->draw_pad (pad, NULL, NULL);
154 return 1;
157 static void
158 draw_element_name (ElementType *element)
160 if ((TEST_FLAG (HIDENAMESFLAG, PCB) && hid_draw_is_gui (hid_draw)) ||
161 TEST_FLAG (HIDENAMEFLAG, element))
162 return;
163 if (doing_pinout || doing_assy)
164 hid_draw_set_color (Output.fgGC, PCB->ElementColor);
165 else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
166 hid_draw_set_color (Output.fgGC, PCB->ElementSelectedColor);
167 else if (FRONT (element))
168 hid_draw_set_color (Output.fgGC, PCB->ElementColor);
169 else
170 hid_draw_set_color (Output.fgGC, PCB->InvisibleObjectsColor);
171 hid_draw_pcb_text (Output.fgGC, &ELEMENT_TEXT (PCB, element), PCB->minSlk);
174 static int
175 name_callback (const BoxType * b, void *cl)
177 TextType *text = (TextType *) b;
178 ElementType *element = (ElementType *) text->Element;
179 int *side = cl;
181 if (TEST_FLAG (HIDENAMEFLAG, element))
182 return 0;
184 if (ON_SIDE (element, *side))
185 draw_element_name (element);
186 return 0;
189 static void
190 draw_element_pins_and_pads (ElementType *element)
192 PAD_LOOP (element);
194 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
196 set_object_color ((AnyObjectType *)pad, PCB->WarnColor,
197 PCB->PinSelectedColor, PCB->ConnectedColor, PCB->FoundColor,
198 FRONT (pad) ? PCB->PinColor : PCB->InvisibleObjectsColor);
200 dapi->draw_pad (pad, NULL, NULL);
203 END_LOOP;
204 PIN_LOOP (element);
206 set_object_color ((AnyObjectType *)pin, PCB->WarnColor, PCB->PinSelectedColor,
207 PCB->ConnectedColor, PCB->FoundColor, PCB->PinColor);
209 dapi->draw_pin (pin, NULL, NULL);
211 set_object_color ((AnyObjectType *)pin, PCB->WarnColor,
212 PCB->PinSelectedColor, NULL, NULL, Settings.BlackColor);
214 dapi->draw_pin_hole (pin, NULL, NULL);
216 END_LOOP;
219 static int
220 EMark_callback (const BoxType * b, void *cl)
222 ElementType *element = (ElementType *) b;
224 DrawEMark (element, element->MarkX, element->MarkY, !FRONT (element));
225 return 1;
228 static int
229 rat_callback (const BoxType * b, void *cl)
231 RatType *rat = (RatType *)b;
233 set_object_color ((AnyObjectType *) rat, NULL, PCB->RatSelectedColor,
234 PCB->ConnectedColor, PCB->FoundColor, PCB->RatColor);
236 dapi->draw_rat (rat, NULL, NULL);
237 return 1;
240 static void
241 draw_element_package (ElementType *element)
243 /* set color and draw lines, arcs, text and pins */
244 if (doing_pinout || doing_assy)
245 hid_draw_set_color (Output.fgGC, PCB->ElementColor);
246 else if (TEST_FLAG (SELECTEDFLAG, element))
247 hid_draw_set_color (Output.fgGC, PCB->ElementSelectedColor);
248 else if (FRONT (element))
249 hid_draw_set_color (Output.fgGC, PCB->ElementColor);
250 else
251 hid_draw_set_color (Output.fgGC, PCB->InvisibleObjectsColor);
253 /* draw lines, arcs, text and pins */
254 ELEMENTLINE_LOOP (element);
256 //hid_draw_pcb_line (Output.fgGC, line);
257 dapi->draw_line (line, NULL, NULL);
259 END_LOOP;
260 ARC_LOOP (element);
262 //hid_draw_pcb_arc (Output.fgGC, arc);
263 dapi->draw_arc (arc, NULL, NULL);
265 END_LOOP;
268 static int
269 element_callback (const BoxType * b, void *cl)
271 ElementType *element = (ElementType *) b;
272 int *side = cl;
274 if (ON_SIDE (element, *side))
275 draw_element_package (element);
276 return 1;
279 /* ---------------------------------------------------------------------------
280 * prints assembly drawing.
283 void
284 PrintAssembly (int side, const BoxType * drawn_area)
286 int side_group = GetLayerGroupNumberBySide (side);
288 doing_assy = true;
289 hid_draw_set_draw_faded (Output.fgGC, 1);
290 DrawLayerGroup (side_group, drawn_area);
291 hid_draw_set_draw_faded (Output.fgGC, 0);
293 /* draw package */
294 DrawSilk (hid_draw, side, drawn_area);
295 doing_assy = false;
298 /* ---------------------------------------------------------------------------
299 * initializes some identifiers for a new zoom factor and redraws whole screen
301 static void
302 DrawEverything (const BoxType *drawn_area)
304 int i, ngroups, side;
305 int top_group, bottom_group;
306 /* This is the list of layer groups we will draw. */
307 int do_group[MAX_GROUP];
308 /* This is the reverse of the order in which we draw them. */
309 int drawn_groups[MAX_GROUP];
310 int plated, unplated;
311 bool paste_empty;
313 PCB->Data->SILKLAYER.Color = PCB->ElementColor;
314 PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
316 memset (do_group, 0, sizeof (do_group));
317 for (ngroups = 0, i = 0; i < max_copper_layer; i++)
319 LayerType *l = LAYER_ON_STACK (i);
320 int group = GetLayerGroupNumberByNumber (LayerStack[i]);
321 if (l->On && !do_group[group])
323 do_group[group] = 1;
324 drawn_groups[ngroups++] = group;
328 top_group = GetLayerGroupNumberBySide (TOP_SIDE);
329 bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE);
332 * first draw all 'invisible' stuff
334 if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
335 && hid_draw_set_layer (hid_draw, "invisible", SL (INVISIBLE, 0), 0))
337 side = SWAP_IDENT ? TOP_SIDE : BOTTOM_SIDE;
338 if (PCB->ElementOn)
340 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
341 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
342 dapi->draw_layer (&(PCB->Data->Layer[max_copper_layer + side]), drawn_area, NULL);
344 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
345 hid_draw_end_layer (hid_draw);
348 /* draw all layers in layerstack order */
349 for (i = ngroups - 1; i >= 0; i--)
351 int group = drawn_groups[i];
353 if (hid_draw_set_layer (hid_draw, 0, group, 0))
355 DrawLayerGroup (group, drawn_area);
356 hid_draw_end_layer (hid_draw);
360 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && hid_draw_is_gui (hid_draw))
361 return;
363 /* Draw pins, pads, vias below silk */
364 if (hid_draw_is_gui (hid_draw))
365 dapi->draw_ppv (SWAP_IDENT ? bottom_group : top_group, drawn_area, NULL);
366 else
368 CountHoles (&plated, &unplated, drawn_area);
370 if (plated && hid_draw_set_layer (hid_draw, "plated-drill", SL (PDRILL, 0), 0))
372 dapi->draw_holes (1, drawn_area, NULL);
373 hid_draw_end_layer (hid_draw);
376 if (unplated && hid_draw_set_layer (hid_draw, "unplated-drill", SL (UDRILL, 0), 0))
378 dapi->draw_holes (0, drawn_area, NULL);
379 hid_draw_end_layer (hid_draw);
383 /* Draw the solder mask if turned on */
384 if (hid_draw_set_layer (hid_draw, "componentmask", SL (MASK, TOP), 0))
386 DrawMask (TOP_SIDE, drawn_area);
387 hid_draw_end_layer (hid_draw);
390 if (hid_draw_set_layer (hid_draw, "soldermask", SL (MASK, BOTTOM), 0))
392 DrawMask (BOTTOM_SIDE, drawn_area);
393 hid_draw_end_layer (hid_draw);
396 if (hid_draw_set_layer (hid_draw, "topsilk", SL (SILK, TOP), 0))
398 DrawSilk (hid_draw, TOP_SIDE, drawn_area);
399 hid_draw_end_layer (hid_draw);
402 if (hid_draw_set_layer (hid_draw, "bottomsilk", SL (SILK, BOTTOM), 0))
404 DrawSilk (hid_draw, BOTTOM_SIDE, drawn_area);
405 hid_draw_end_layer (hid_draw);
408 if (hid_draw_is_gui (hid_draw))
410 /* Draw element Marks */
411 if (PCB->PinOn)
412 r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
413 NULL);
414 /* Draw rat lines on top */
415 if (hid_draw_set_layer (hid_draw, "rats", SL (RATS, 0), 0))
417 DrawRats (hid_draw, drawn_area);
418 hid_draw_end_layer (hid_draw);
422 paste_empty = IsPasteEmpty (TOP_SIDE);
423 if (hid_draw_set_layer (hid_draw, "toppaste", SL (PASTE, TOP), paste_empty))
425 DrawPaste (TOP_SIDE, drawn_area);
426 hid_draw_end_layer (hid_draw);
429 paste_empty = IsPasteEmpty (BOTTOM_SIDE);
430 if (hid_draw_set_layer (hid_draw, "bottompaste", SL (PASTE, BOTTOM), paste_empty))
432 DrawPaste (BOTTOM_SIDE, drawn_area);
433 hid_draw_end_layer (hid_draw);
436 if (hid_draw_set_layer (hid_draw, "topassembly", SL (ASSY, TOP), 0))
438 PrintAssembly (TOP_SIDE, drawn_area);
439 hid_draw_end_layer (hid_draw);
442 if (hid_draw_set_layer (hid_draw, "bottomassembly", SL (ASSY, BOTTOM), 0))
444 PrintAssembly (BOTTOM_SIDE, drawn_area);
445 hid_draw_end_layer (hid_draw);
448 if (hid_draw_set_layer (hid_draw, "fab", SL (FAB, 0), 0))
450 PrintFab (Output.fgGC);
451 hid_draw_end_layer (hid_draw);
455 /* static */ void
456 DrawEMark (ElementType *e, Coord X, Coord Y, bool invisible)
458 Coord mark_size = EMARK_SIZE;
459 if (!PCB->InvisibleObjectsOn && invisible)
460 return;
462 if (e->Pin != NULL)
464 PinType *pin0 = e->Pin->data;
465 if (TEST_FLAG (HOLEFLAG, pin0))
466 mark_size = MIN (mark_size, pin0->DrillingHole / 2);
467 else
468 mark_size = MIN (mark_size, pin0->Thickness / 2);
471 if (e->Pad != NULL)
473 PadType *pad0 = e->Pad->data;
474 mark_size = MIN (mark_size, pad0->Thickness / 2);
477 hid_draw_set_color (Output.fgGC, invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
478 hid_draw_set_line_cap (Output.fgGC, Trace_Cap);
479 hid_draw_set_line_width (Output.fgGC, 0);
480 hid_draw_line (Output.fgGC, X - mark_size, Y, X, Y - mark_size);
481 hid_draw_line (Output.fgGC, X + mark_size, Y, X, Y - mark_size);
482 hid_draw_line (Output.fgGC, X - mark_size, Y, X, Y + mark_size);
483 hid_draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
486 * If an element is locked, place a "L" on top of the "diamond".
487 * This provides a nice visual indication that it is locked that
488 * works even for color blind users.
490 if (TEST_FLAG (LOCKFLAG, e) )
492 hid_draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
493 hid_draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
497 static int
498 pin_mask_callback (const BoxType * b, void *cl)
500 dapi->draw_pin_mask ((PinType *) b, NULL, NULL);
501 return 1;
504 static int
505 via_mask_callback (const BoxType * b, void *cl)
507 dapi->draw_via_mask ((PinType *) b, NULL, NULL);
508 return 1;
511 static int
512 pad_mask_callback (const BoxType * b, void *cl)
514 PadType *pad = (PadType *) b;
515 int *side = cl;
516 if (ON_SIDE (pad, *side))
517 dapi->draw_pad_mask (pad, NULL, NULL);
518 return 1;
521 /* ---------------------------------------------------------------------------
522 * Draws silk layer.
525 void
526 DrawSilk (HID_DRAW *new_hid_draw, int side, const BoxType * drawn_area)
528 HID_DRAW *old_hid_draw = hid_draw;
529 hid_draw = new_hid_draw;
531 #if 0
532 /* This code is used when you want to mask silk to avoid exposed
533 pins and pads. We decided it was a bad idea to do this
534 unconditionally, but the code remains. */
535 #endif
537 #if 0
538 if (hid_draw->poly_before)
540 hid_draw_use_mask (hid_draw, HID_MASK_BEFORE);
541 #endif
542 dapi->draw_layer (LAYER_PTR (max_copper_layer + side), drawn_area, NULL);
543 /* draw package */
544 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
545 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
546 #if 0
549 hid_draw_use_mask (hid_draw, HID_MASK_CLEAR);
550 r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_mask_callback, NULL);
551 r_search (PCB->Data->via_tree, drawn_area, NULL, via_mask_callback, NULL);
552 r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_mask_callback, &side);
554 if (hid_draw->poly_after)
556 hid_draw_use_mask (hid_draw, HID_MASK_AFTER);
557 dapi->draw_layer (LAYER_PTR (max_copper_layer + layer), drawn_area, NULL);
558 /* draw package */
559 r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
560 r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
562 hid_draw_use_mask (hid_draw, HID_MASK_OFF);
563 #endif
565 hid_draw = old_hid_draw;
569 static void
570 DrawMaskBoardArea (int mask_type, const BoxType *drawn_area)
572 /* Skip the mask drawing if the GUI doesn't want this type */
573 if ((mask_type == HID_MASK_BEFORE && !hid_draw->poly_before) ||
574 (mask_type == HID_MASK_AFTER && !hid_draw->poly_after))
575 return;
577 hid_draw_use_mask (hid_draw, mask_type);
578 hid_draw_set_color (Output.fgGC, PCB->MaskColor);
579 if (drawn_area == NULL)
580 hid_draw_fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
581 else
582 hid_draw_fill_rect (Output.fgGC, drawn_area->X1, drawn_area->Y1,
583 drawn_area->X2, drawn_area->Y2);
586 struct poly_info {
587 const const BoxType *drawn_area;
588 LayerType *layer;
591 static int
592 mask_poly_callback (const BoxType * b, void *cl)
594 struct poly_info *i = cl;
595 PolygonType *polygon = (PolygonType *)b;
597 hid_draw_pcb_polygon (Output.pmGC, polygon, i->drawn_area);
598 return 1;
601 static int
602 mask_line_callback (const BoxType * b, void *cl)
604 LineType *line = (LineType *)b;
606 hid_draw_pcb_line (Output.pmGC, line);
607 return 1;
610 static int
611 mask_arc_callback (const BoxType * b, void *cl)
613 ArcType *arc = (ArcType *)b;
615 hid_draw_pcb_arc (Output.pmGC, arc);
616 return 1;
619 static int
620 mask_text_callback (const BoxType * b, void *cl)
622 LayerType *layer = cl;
623 TextType *text = (TextType *)b;
624 int min_silk_line;
626 if (layer == &PCB->Data->SILKLAYER ||
627 layer == &PCB->Data->BACKSILKLAYER)
628 min_silk_line = PCB->minSlk;
629 else
630 min_silk_line = PCB->minWid;
631 hid_draw_pcb_text (Output.fgGC, text, min_silk_line);
632 return 1;
635 /* ---------------------------------------------------------------------------
636 * draws solder mask layer - this will cover nearly everything
638 void
639 DrawMask (int side, const BoxType *screen)
641 int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
642 LayerType *Layer = LAYER_PTR (side == TOP_SIDE ? top_soldermask_layer : bottom_soldermask_layer);
643 struct poly_info info;
645 if (thin)
646 hid_draw_set_color (Output.pmGC, PCB->MaskColor);
647 else
649 DrawMaskBoardArea (HID_MASK_BEFORE, screen);
650 hid_draw_use_mask (hid_draw, HID_MASK_CLEAR);
653 info.layer = Layer;
654 info.drawn_area = screen;
655 r_search (Layer->polygon_tree, screen, NULL, mask_poly_callback, &info);
656 r_search (Layer->line_tree, screen, NULL, mask_line_callback, Layer);
657 r_search (Layer->arc_tree, screen, NULL, mask_arc_callback, Layer);
658 r_search (Layer->text_tree, screen, NULL, mask_text_callback, Layer);
660 r_search (PCB->Data->pin_tree, screen, NULL, pin_mask_callback, NULL);
661 r_search (PCB->Data->via_tree, screen, NULL, via_mask_callback, NULL);
662 r_search (PCB->Data->pad_tree, screen, NULL, pad_mask_callback, &side);
664 if (thin)
665 hid_draw_set_color (Output.pmGC, "erase");
666 else
668 DrawMaskBoardArea (HID_MASK_AFTER, screen);
669 hid_draw_use_mask (hid_draw, HID_MASK_OFF);
673 /* ---------------------------------------------------------------------------
674 * draws solder paste layer for a given side of the board
676 void
677 DrawPaste (int side, const BoxType *drawn_area)
679 hid_draw_set_color (Output.fgGC, PCB->ElementColor);
680 ALLPAD_LOOP (PCB->Data);
682 if (ON_SIDE (pad, side))
683 dapi->draw_pad_paste (pad, NULL, NULL);
685 ENDALL_LOOP;
688 /* static */ void
689 DrawRats (HID_DRAW *new_hid_draw, const BoxType *drawn_area)
691 HID_DRAW *old_hid_draw = hid_draw;
692 hid_draw = new_hid_draw;
695 * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
696 * XXX gtk only allows negative drawing.
697 * XXX using the mask here is to get rat transparency
700 if (hid_draw_can_draw_in_mask_clear (hid_draw))
701 hid_draw_use_mask (hid_draw, HID_MASK_CLEAR);
702 r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
703 if (hid_draw_can_draw_in_mask_clear (hid_draw))
704 hid_draw_use_mask (hid_draw, HID_MASK_OFF);
706 hid_draw = old_hid_draw;
709 /* ---------------------------------------------------------------------------
710 * draws one layer group. If the exporter is not a GUI,
711 * also draws the pins / pads / vias in this layer group.
713 void
714 DrawLayerGroup (int group, const BoxType *drawn_area)
716 int i, rv = 1;
717 int layernum;
718 LayerType *Layer;
719 int n_entries = PCB->LayerGroups.Number[group];
720 Cardinal *layers = PCB->LayerGroups.Entries[group];
722 for (i = n_entries - 1; i >= 0; i--)
724 layernum = layers[i];
725 Layer = PCB->Data->Layer + layers[i];
726 if (strcmp (Layer->Name, "outline") == 0 ||
727 strcmp (Layer->Name, "route") == 0)
728 rv = 0;
729 if (layernum < max_copper_layer && Layer->On)
730 dapi->draw_layer (Layer, drawn_area, NULL);
732 if (n_entries > 1)
733 rv = 1;
735 if (rv && !hid_draw_is_gui (hid_draw))
736 dapi->draw_ppv (group, drawn_area, NULL);
739 static void
740 GatherPVName (PinType *Ptr)
742 BoxType box;
743 bool vert = TEST_FLAG (EDGE2FLAG, Ptr);
745 if (vert)
747 box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
748 box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
750 else
752 box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
753 box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
756 if (vert)
758 box.X2 = box.X1;
759 box.Y2 = box.Y1;
761 else
763 box.X2 = box.X1;
764 box.Y2 = box.Y1;
766 AddPart (&box);
769 static void
770 GatherPadName (PadType *Pad)
772 BoxType box;
773 bool vert;
775 /* should text be vertical ? */
776 vert = (Pad->Point1.X == Pad->Point2.X);
778 if (vert)
780 box.X1 = Pad->Point1.X - Pad->Thickness / 2;
781 box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
782 box.X1 += Settings.PinoutTextOffsetY;
783 box.Y1 -= Settings.PinoutTextOffsetX;
784 box.X2 = box.X1;
785 box.Y2 = box.Y1;
787 else
789 box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
790 box.Y1 = Pad->Point1.Y - Pad->Thickness / 2;
791 box.X1 += Settings.PinoutTextOffsetX;
792 box.Y1 += Settings.PinoutTextOffsetY;
793 box.X2 = box.X1;
794 box.Y2 = box.Y1;
797 AddPart (&box);
798 return;
801 /* ---------------------------------------------------------------------------
802 * draw a via object
804 void
805 DrawVia (PinType *Via)
807 AddPart (Via);
808 if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
809 DrawViaName (Via);
812 /* ---------------------------------------------------------------------------
813 * draws the name of a via
815 void
816 DrawViaName (PinType *Via)
818 GatherPVName (Via);
821 /* ---------------------------------------------------------------------------
822 * draw a pin object
824 void
825 DrawPin (PinType *Pin)
827 AddPart (Pin);
828 if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
829 || doing_pinout)
830 DrawPinName (Pin);
833 /* ---------------------------------------------------------------------------
834 * draws the name of a pin
836 void
837 DrawPinName (PinType *Pin)
839 GatherPVName (Pin);
842 /* ---------------------------------------------------------------------------
843 * draw a pad object
845 void
846 DrawPad (PadType *Pad)
848 AddPart (Pad);
849 if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
850 DrawPadName (Pad);
853 /* ---------------------------------------------------------------------------
854 * draws the name of a pad
856 void
857 DrawPadName (PadType *Pad)
859 GatherPadName (Pad);
862 /* ---------------------------------------------------------------------------
863 * draws a line on a layer
865 void
866 DrawLine (LayerType *Layer, LineType *Line)
868 AddPart (Line);
871 /* ---------------------------------------------------------------------------
872 * draws a ratline
874 void
875 DrawRat (RatType *Rat)
877 if (Settings.RatThickness < 100)
878 Rat->Thickness = pixel_slop * Settings.RatThickness;
879 /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
880 if (TEST_FLAG(VIAFLAG, Rat))
882 Coord w = Rat->Thickness;
884 BoxType b;
886 b.X1 = Rat->Point1.X - w * 2 - w / 2;
887 b.X2 = Rat->Point1.X + w * 2 + w / 2;
888 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
889 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
890 AddPart (&b);
892 else
893 DrawLine (NULL, (LineType *)Rat);
896 /* ---------------------------------------------------------------------------
897 * draws an arc on a layer
899 void
900 DrawArc (LayerType *Layer, ArcType *Arc)
902 AddPart (Arc);
905 /* ---------------------------------------------------------------------------
906 * draws a text on a layer
908 void
909 DrawText (LayerType *Layer, TextType *Text)
911 AddPart (Text);
915 /* ---------------------------------------------------------------------------
916 * draws a polygon on a layer
918 void
919 DrawPolygon (LayerType *Layer, PolygonType *Polygon)
921 AddPart (Polygon);
924 /* ---------------------------------------------------------------------------
925 * draws an element
927 void
928 DrawElement (ElementType *Element)
930 DrawElementPackage (Element);
931 DrawElementName (Element);
932 DrawElementPinsAndPads (Element);
935 /* ---------------------------------------------------------------------------
936 * draws the name of an element
938 void
939 DrawElementName (ElementType *Element)
941 if (TEST_FLAG (HIDENAMEFLAG, Element))
942 return;
943 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
946 /* ---------------------------------------------------------------------------
947 * draws the package of an element
949 void
950 DrawElementPackage (ElementType *Element)
952 ELEMENTLINE_LOOP (Element);
954 DrawLine (NULL, line);
956 END_LOOP;
957 ARC_LOOP (Element);
959 DrawArc (NULL, arc);
961 END_LOOP;
964 /* ---------------------------------------------------------------------------
965 * draw pins of an element
967 void
968 DrawElementPinsAndPads (ElementType *Element)
970 PAD_LOOP (Element);
972 if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
973 DrawPad (pad);
975 END_LOOP;
976 PIN_LOOP (Element);
978 DrawPin (pin);
980 END_LOOP;
983 /* ---------------------------------------------------------------------------
984 * erase a via
986 void
987 EraseVia (PinType *Via)
989 AddPart (Via);
990 if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
991 EraseViaName (Via);
994 /* ---------------------------------------------------------------------------
995 * erase a ratline
997 void
998 EraseRat (RatType *Rat)
1000 if (TEST_FLAG(VIAFLAG, Rat))
1002 Coord w = Rat->Thickness;
1004 BoxType b;
1006 b.X1 = Rat->Point1.X - w * 2 - w / 2;
1007 b.X2 = Rat->Point1.X + w * 2 + w / 2;
1008 b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
1009 b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
1010 AddPart (&b);
1012 else
1013 EraseLine ((LineType *)Rat);
1017 /* ---------------------------------------------------------------------------
1018 * erase a via name
1020 void
1021 EraseViaName (PinType *Via)
1023 GatherPVName (Via);
1026 /* ---------------------------------------------------------------------------
1027 * erase a pad object
1029 void
1030 ErasePad (PadType *Pad)
1032 AddPart (Pad);
1033 if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1034 ErasePadName (Pad);
1037 /* ---------------------------------------------------------------------------
1038 * erase a pad name
1040 void
1041 ErasePadName (PadType *Pad)
1043 GatherPadName (Pad);
1046 /* ---------------------------------------------------------------------------
1047 * erase a pin object
1049 void
1050 ErasePin (PinType *Pin)
1052 AddPart (Pin);
1053 if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
1054 ErasePinName (Pin);
1057 /* ---------------------------------------------------------------------------
1058 * erase a pin name
1060 void
1061 ErasePinName (PinType *Pin)
1063 GatherPVName (Pin);
1066 /* ---------------------------------------------------------------------------
1067 * erases a line on a layer
1069 void
1070 EraseLine (LineType *Line)
1072 AddPart (Line);
1075 /* ---------------------------------------------------------------------------
1076 * erases an arc on a layer
1078 void
1079 EraseArc (ArcType *Arc)
1081 if (!Arc->Thickness)
1082 return;
1083 AddPart (Arc);
1086 /* ---------------------------------------------------------------------------
1087 * erases a text on a layer
1089 void
1090 EraseText (LayerType *Layer, TextType *Text)
1092 AddPart (Text);
1095 /* ---------------------------------------------------------------------------
1096 * erases a polygon on a layer
1098 void
1099 ErasePolygon (PolygonType *Polygon)
1101 AddPart (Polygon);
1104 /* ---------------------------------------------------------------------------
1105 * erases an element
1107 void
1108 EraseElement (ElementType *Element)
1110 ELEMENTLINE_LOOP (Element);
1112 EraseLine (line);
1114 END_LOOP;
1115 ARC_LOOP (Element);
1117 EraseArc (arc);
1119 END_LOOP;
1120 EraseElementName (Element);
1121 EraseElementPinsAndPads (Element);
1124 /* ---------------------------------------------------------------------------
1125 * erases all pins and pads of an element
1127 void
1128 EraseElementPinsAndPads (ElementType *Element)
1130 PIN_LOOP (Element);
1132 ErasePin (pin);
1134 END_LOOP;
1135 PAD_LOOP (Element);
1137 ErasePad (pad);
1139 END_LOOP;
1142 /* ---------------------------------------------------------------------------
1143 * erases the name of an element
1145 void
1146 EraseElementName (ElementType *Element)
1148 if (TEST_FLAG (HIDENAMEFLAG, Element))
1149 return;
1150 DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
1154 void
1155 EraseObject (int type, void *lptr, void *ptr)
1157 switch (type)
1159 case VIA_TYPE:
1160 case PIN_TYPE:
1161 ErasePin ((PinType *) ptr);
1162 break;
1163 case TEXT_TYPE:
1164 case ELEMENTNAME_TYPE:
1165 EraseText ((LayerType *)lptr, (TextType *) ptr);
1166 break;
1167 case POLYGON_TYPE:
1168 ErasePolygon ((PolygonType *) ptr);
1169 break;
1170 case ELEMENT_TYPE:
1171 EraseElement ((ElementType *) ptr);
1172 break;
1173 case LINE_TYPE:
1174 case ELEMENTLINE_TYPE:
1175 case RATLINE_TYPE:
1176 EraseLine ((LineType *) ptr);
1177 break;
1178 case PAD_TYPE:
1179 ErasePad ((PadType *) ptr);
1180 break;
1181 case ARC_TYPE:
1182 case ELEMENTARC_TYPE:
1183 EraseArc ((ArcType *) ptr);
1184 break;
1185 default:
1186 Message ("hace: Internal ERROR, trying to erase an unknown type\n");
1192 void
1193 DrawObject (int type, void *ptr1, void *ptr2)
1195 switch (type)
1197 case VIA_TYPE:
1198 if (PCB->ViaOn)
1199 DrawVia ((PinType *) ptr2);
1200 break;
1201 case LINE_TYPE:
1202 if (((LayerType *) ptr1)->On)
1203 DrawLine ((LayerType *) ptr1, (LineType *) ptr2);
1204 break;
1205 case ARC_TYPE:
1206 if (((LayerType *) ptr1)->On)
1207 DrawArc ((LayerType *) ptr1, (ArcType *) ptr2);
1208 break;
1209 case TEXT_TYPE:
1210 if (((LayerType *) ptr1)->On)
1211 DrawText ((LayerType *) ptr1, (TextType *) ptr2);
1212 break;
1213 case POLYGON_TYPE:
1214 if (((LayerType *) ptr1)->On)
1215 DrawPolygon ((LayerType *) ptr1, (PolygonType *) ptr2);
1216 break;
1217 case ELEMENT_TYPE:
1218 if (PCB->ElementOn &&
1219 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1220 DrawElement ((ElementType *) ptr2);
1221 break;
1222 case RATLINE_TYPE:
1223 if (PCB->RatOn)
1224 DrawRat ((RatType *) ptr2);
1225 break;
1226 case PIN_TYPE:
1227 if (PCB->PinOn)
1228 DrawPin ((PinType *) ptr2);
1229 break;
1230 case PAD_TYPE:
1231 if (PCB->PinOn)
1232 DrawPad ((PadType *) ptr2);
1233 break;
1234 case ELEMENTNAME_TYPE:
1235 if (PCB->ElementOn &&
1236 (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
1237 DrawElementName ((ElementType *) ptr1);
1238 break;
1242 static void
1243 draw_element (ElementType *element)
1245 draw_element_package (element);
1246 draw_element_name (element);
1247 draw_element_pins_and_pads (element);
1250 /* ---------------------------------------------------------------------------
1251 * HID drawing callback.
1254 void
1255 hid_expose_callback (HID_DRAW *expose_hid_draw, BoxType *region, void *item)
1257 hid_draw = expose_hid_draw;
1258 Output.fgGC = hid_draw_make_gc (hid_draw);
1259 Output.bgGC = hid_draw_make_gc (hid_draw);
1260 Output.pmGC = hid_draw_make_gc (hid_draw);
1262 hid_draw_set_color (Output.pmGC, "erase");
1263 hid_draw_set_color (Output.bgGC, "drill");
1265 if (item)
1267 doing_pinout = true;
1268 draw_element ((ElementType *)item);
1269 doing_pinout = false;
1271 else
1272 DrawEverything (region);
1274 hid_draw_destroy_gc (Output.fgGC);
1275 hid_draw_destroy_gc (Output.bgGC);
1276 hid_draw_destroy_gc (Output.pmGC);
1277 hid_draw = NULL;