pcb 4.1.1
An interactive printed circuit board layout editor.

draw.c

Go to the documentation of this file.
00001 
00033 #ifdef HAVE_CONFIG_H
00034 #include "config.h"
00035 #endif
00036 
00037 #include "global.h"
00038 #include "hid_draw.h"
00039 
00040 /*#include "clip.h"*/
00041 #include "compat.h"
00042 #include "crosshair.h"
00043 #include "data.h"
00044 #include "draw.h"
00045 #include "error.h"
00046 #include "mymem.h"
00047 #include "misc.h"
00048 #include "rotate.h"
00049 #include "rtree.h"
00050 #include "search.h"
00051 #include "select.h"
00052 #include "print.h"
00053 
00054 #ifdef HAVE_LIBDMALLOC
00055 #include <dmalloc.h>
00056 #endif
00057 
00058 #undef NDEBUG
00059 #include <assert.h>
00060 
00061 #ifndef MAXINT
00062 #define MAXINT (((unsigned int)(~0))>>1)
00063 #endif
00064 
00065 #define SMALL_SMALL_TEXT_SIZE   0
00066 #define SMALL_TEXT_SIZE                 1
00067 #define NORMAL_TEXT_SIZE                2
00068 #define LARGE_TEXT_SIZE                 3
00069 #define N_TEXT_SIZES                    4
00070 
00071 
00072 /* ---------------------------------------------------------------------------
00073  * some local identifiers
00074  */
00075 static BoxType Block = {MAXINT, MAXINT, -MAXINT, -MAXINT};
00076 
00077 static int doing_pinout = 0;
00078 static bool doing_assy = false;
00079 
00080 static int current_layergroup; /* used by via_callback */
00081 
00082 /* ---------------------------------------------------------------------------
00083  * some local prototypes
00084  */
00085 static void DrawEverything (const BoxType *);
00086 static void DrawPPV (int group, const BoxType *);
00087 static void AddPart (void *);
00088 static void DrawEMark (ElementType *, Coord, Coord, bool);
00089 static void DrawRats (const BoxType *);
00090 
00091 static void
00092 set_object_color (AnyObjectType *obj, char *warn_color, char *selected_color,
00093                   char *connected_color, char *found_color, char *normal_color)
00094 {
00095   char *color;
00096 
00097   if      (warn_color      != NULL && TEST_FLAG (WARNFLAG,      obj)) color = warn_color;
00098   else if (selected_color  != NULL && TEST_FLAG (SELECTEDFLAG,  obj)) color = selected_color;
00099   else if (connected_color != NULL && TEST_FLAG (CONNECTEDFLAG, obj)) color = connected_color;
00100   else if (found_color     != NULL && TEST_FLAG (FOUNDFLAG,     obj)) color = found_color;
00101   else                                                                color = normal_color;
00102 
00103   gui->graphics->set_color (Output.fgGC, color);
00104 }
00105 
00106 static void
00107 set_layer_object_color (LayerType *layer, AnyObjectType *obj)
00108 {
00109   set_object_color (obj, NULL, layer->SelectedColor, PCB->ConnectedColor, PCB->FoundColor, layer->Color);
00110 }
00111 
00115 static void
00116 AddPart (void *b)
00117 {
00118   BoxType *box = (BoxType *) b;
00119 
00120   Block.X1 = MIN (Block.X1, box->X1);
00121   Block.X2 = MAX (Block.X2, box->X2);
00122   Block.Y1 = MIN (Block.Y1, box->Y1);
00123   Block.Y2 = MAX (Block.Y2, box->Y2);
00124 }
00125 
00129 void
00130 Draw (void)
00131 {
00132   if (Block.X1 <= Block.X2 && Block.Y1 <= Block.Y2)
00133     gui->invalidate_lr (Block.X1, Block.X2, Block.Y1, Block.Y2);
00134 
00135   /* shrink the update block */
00136   Block.X1 = Block.Y1 =  MAXINT;
00137   Block.X2 = Block.Y2 = -MAXINT;
00138 }
00139 
00143 void
00144 Redraw (void)
00145 {
00146   gui->invalidate_all ();
00147 }
00148 
00149 static void
00150 _draw_pv_name (PinType *pv)
00151 {
00152   BoxType box;
00153   bool vert;
00154   TextType text;
00155 
00156   if (!pv->Name || !pv->Name[0])
00157     text.TextString = EMPTY (pv->Number);
00158   else
00159     text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pv->Number : pv->Name);
00160 
00161   vert = TEST_FLAG (EDGE2FLAG, pv);
00162 
00163   if (vert)
00164     {
00165       box.X1 = pv->X - pv->Thickness    / 2 + Settings.PinoutTextOffsetY;
00166       box.Y1 = pv->Y - pv->DrillingHole / 2 - Settings.PinoutTextOffsetX;
00167     }
00168   else
00169     {
00170       box.X1 = pv->X + pv->DrillingHole / 2 + Settings.PinoutTextOffsetX;
00171       box.Y1 = pv->Y - pv->Thickness    / 2 + Settings.PinoutTextOffsetY;
00172     }
00173 
00174   gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);
00175 
00176   text.Flags = NoFlags ();
00177   /* Set font height to approx 56% of pin thickness */
00178   text.Scale = 56 * pv->Thickness / FONT_CAPHEIGHT;
00179   text.X = box.X1;
00180   text.Y = box.Y1;
00181   text.Direction = vert ? 1 : 0;
00182 
00183   if (gui->gui)
00184     doing_pinout++;
00185   gui->graphics->draw_pcb_text (Output.fgGC, &text, 0);
00186   if (gui->gui)
00187     doing_pinout--;
00188 }
00189 
00190 static void
00191 _draw_pv (PinType *pv, bool draw_hole)
00192 {
00193   if (TEST_FLAG (THINDRAWFLAG, PCB))
00194     gui->graphics->thindraw_pcb_pv (Output.fgGC, Output.fgGC, pv, draw_hole, false);
00195   else if (!ViaIsOnAnyVisibleLayer (pv))
00196     gui->graphics->thindraw_pcb_pv (Output.fgGC, Output.fgGC, pv, false, false);
00197   else
00198     {
00199       gui->graphics->fill_pcb_pv (Output.fgGC, Output.bgGC, pv, draw_hole, false);
00200       if (gui->gui
00201           && VIA_IS_BURIED (pv)
00202           && !(TEST_FLAG (SELECTEDFLAG,  pv)
00203                || TEST_FLAG (CONNECTEDFLAG, pv)
00204                || TEST_FLAG (FOUNDFLAG,     pv)))
00205         {
00206           int w = (pv->Thickness - pv->DrillingHole) / 4;
00207           int r = pv->DrillingHole / 2 + w  / 2;
00208           gui->graphics->set_line_cap (Output.fgGC, Square_Cap);
00209           gui->graphics->set_color (Output.fgGC, PCB->Data->Layer[pv->BuriedFrom].Color);
00210           gui->graphics->set_line_width (Output.fgGC, w);
00211           gui->graphics->draw_arc (Output.fgGC, pv->X, pv->Y, r, r, 270, 180);
00212           gui->graphics->set_color (Output.fgGC, PCB->Data->Layer[pv->BuriedTo].Color);
00213           gui->graphics->set_line_width (Output.fgGC, w);
00214           gui->graphics->draw_arc (Output.fgGC, pv->X, pv->Y, r, r, 90, 180);
00215         }
00216     }
00217 
00218   if ((!TEST_FLAG (HOLEFLAG, pv) && TEST_FLAG (DISPLAYNAMEFLAG, pv)) || doing_pinout)
00219     _draw_pv_name (pv);
00220 }
00221 
00222 static void
00223 draw_pin (PinType *pin, bool draw_hole)
00224 {
00225   if (doing_pinout)
00226     gui->graphics->set_color (Output.fgGC, PCB->PinColor);
00227   else
00228     set_object_color ((AnyObjectType *)pin,
00229                       PCB->WarnColor, PCB->PinSelectedColor,
00230                       PCB->ConnectedColor, PCB->FoundColor, PCB->PinColor);
00231 
00232   _draw_pv (pin, draw_hole);
00233 }
00234 
00235 static int
00236 pin_callback (const BoxType * b, void *cl)
00237 {
00238   draw_pin ((PinType *)b, false);
00239   return 1;
00240 }
00241 
00242 static void
00243 draw_via (PinType *via, bool draw_hole)
00244 {
00245   if (doing_pinout)
00246     gui->graphics->set_color (Output.fgGC, PCB->ViaColor);
00247   else
00248     set_object_color ((AnyObjectType *)via,
00249                       PCB->WarnColor, PCB->ViaSelectedColor,
00250                       PCB->ConnectedColor, PCB->FoundColor, PCB->ViaColor);
00251 
00252   _draw_pv (via, draw_hole);
00253 }
00254 
00255 static bool
00256 via_visible_on_layer_group (PinType *via)
00257 {
00258   if (current_layergroup == -1)
00259      return true;
00260   else
00261    return ViaIsOnLayerGroup (via, current_layergroup);
00262 }
00263 
00264 static int
00265 via_callback (const BoxType * b, void *cl)
00266 {
00267   PinType *via = (PinType *)b;
00268 
00269   if (via_visible_on_layer_group (via))
00270     draw_via (via, false);
00271 
00272   return 1;
00273 }
00274 
00275 static void
00276 draw_pad_name (PadType *pad)
00277 {
00278   BoxType box;
00279   bool vert;
00280   TextType text;
00281 
00282   if (!pad->Name || !pad->Name[0])
00283     text.TextString = EMPTY (pad->Number);
00284   else
00285     text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pad->Number : pad->Name);
00286 
00287   /* should text be vertical ? */
00288   vert = (pad->Point1.X == pad->Point2.X);
00289 
00290   if (vert)
00291     {
00292       box.X1 = pad->Point1.X                      - pad->Thickness / 2;
00293       box.Y1 = MAX (pad->Point1.Y, pad->Point2.Y) + pad->Thickness / 2;
00294       box.X1 += Settings.PinoutTextOffsetY;
00295       box.Y1 -= Settings.PinoutTextOffsetX;
00296     }
00297   else
00298     {
00299       box.X1 = MIN (pad->Point1.X, pad->Point2.X) - pad->Thickness / 2;
00300       box.Y1 = pad->Point1.Y                      - pad->Thickness / 2;
00301       box.X1 += Settings.PinoutTextOffsetX;
00302       box.Y1 += Settings.PinoutTextOffsetY;
00303     }
00304 
00305   gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);
00306 
00307   text.Flags = NoFlags ();
00308   /* Set font height to approx 90% of pin thickness */
00309   text.Scale = 90 * pad->Thickness / FONT_CAPHEIGHT;
00310   text.X = box.X1;
00311   text.Y = box.Y1;
00312   text.Direction = vert ? 1 : 0;
00313 
00314   gui->graphics->draw_pcb_text (Output.fgGC, &text, 0);
00315 }
00316 
00317 static void
00318 _draw_pad (hidGC gc, PadType *pad, bool clear, bool mask)
00319 {
00320   if (clear && !mask && pad->Clearance <= 0)
00321     return;
00322 
00323   if (TEST_FLAG (THINDRAWFLAG, PCB) ||
00324       (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
00325     gui->graphics->thindraw_pcb_pad (gc, pad, clear, mask);
00326   else
00327     gui->graphics->fill_pcb_pad (gc, pad, clear, mask);
00328 }
00329 
00330 static void
00331 draw_pad (PadType *pad)
00332 {
00333   if (doing_pinout)
00334     gui->graphics->set_color (Output.fgGC, PCB->PinColor);
00335   else
00336     set_object_color ((AnyObjectType *)pad, PCB->WarnColor,
00337                       PCB->PinSelectedColor, PCB->ConnectedColor, PCB->FoundColor,
00338                       FRONT (pad) ? PCB->PinColor : PCB->InvisibleObjectsColor);
00339 
00340   _draw_pad (Output.fgGC, pad, false, false);
00341 
00342   if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, pad))
00343     draw_pad_name (pad);
00344 }
00345 
00346 static int
00347 pad_callback (const BoxType * b, void *cl)
00348 {
00349   PadType *pad = (PadType *) b;
00350   int *side = cl;
00351 
00352   if (ON_SIDE (pad, *side))
00353     draw_pad (pad);
00354   return 1;
00355 }
00356 
00357 static void
00358 draw_element_name (ElementType *element)
00359 {
00360   if ((TEST_FLAG (HIDENAMESFLAG, PCB) && gui->gui) ||
00361       TEST_FLAG (HIDENAMEFLAG, element))
00362     return;
00363   if (doing_pinout || doing_assy)
00364     gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
00365   else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
00366     gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor);
00367   else if (FRONT (element))
00368     gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
00369   else
00370     gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
00371   gui->graphics->draw_pcb_text (Output.fgGC, &ELEMENT_TEXT (PCB, element), PCB->minSlk);
00372 }
00373 
00374 static int
00375 name_callback (const BoxType * b, void *cl)
00376 {
00377   TextType *text = (TextType *) b;
00378   ElementType *element = (ElementType *) text->Element;
00379   int *side = cl;
00380 
00381   if (TEST_FLAG (HIDENAMEFLAG, element))
00382     return 0;
00383 
00384   if (ON_SIDE (element, *side))
00385     draw_element_name (element);
00386   return 0;
00387 }
00388 
00389 static void
00390 draw_element_pins_and_pads (ElementType *element)
00391 {
00392   PAD_LOOP (element);
00393   {
00394     if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
00395       draw_pad (pad);
00396   }
00397   END_LOOP;
00398   PIN_LOOP (element);
00399   {
00400     draw_pin (pin, true);
00401   }
00402   END_LOOP;
00403 }
00404 
00405 static int
00406 EMark_callback (const BoxType * b, void *cl)
00407 {
00408   ElementType *element = (ElementType *) b;
00409 
00410   DrawEMark (element, element->MarkX, element->MarkY, !FRONT (element));
00411   return 1;
00412 }
00413 
00414 typedef struct
00415 {
00416   int plated;
00417   bool drill_pair;
00418   Cardinal group_from;
00419   Cardinal group_to;
00420 } hole_info;
00421 
00422 static int
00423 hole_callback (const BoxType * b, void *cl)
00424 {
00425   hole_info his = {-1, false, 0, 0};
00426   hole_info *hi = &his;
00427   PinType *pv = (PinType *) b;
00428 
00429   if (cl)
00430     hi = (hole_info *)cl;
00431 
00432   if (hi->drill_pair)
00433     {
00434       if (hi->group_from != 0
00435           || hi->group_to != 0)
00436         {
00437           if (VIA_IS_BURIED (pv))
00438             {
00439               if (hi->group_from == GetLayerGroupNumberByNumber (pv->BuriedFrom)
00440                   && hi->group_to == GetLayerGroupNumberByNumber (pv->BuriedTo))
00441                 goto via_ok;
00442             }
00443         }
00444       else
00445         if (!VIA_IS_BURIED (pv))
00446           goto via_ok;
00447 
00448       return 1;
00449     }
00450 
00451 via_ok:
00452   if ((hi->plated == 0 && !TEST_FLAG (HOLEFLAG, pv)) ||
00453       (hi->plated == 1 &&  TEST_FLAG (HOLEFLAG, pv)))
00454     return 1;
00455 
00456   if (!via_visible_on_layer_group (pv))
00457      return 1;
00458 
00459   if (TEST_FLAG (THINDRAWFLAG, PCB))
00460     {
00461       if (!TEST_FLAG (HOLEFLAG, pv))
00462         {
00463           gui->graphics->set_line_cap (Output.fgGC, Round_Cap);
00464           gui->graphics->set_line_width (Output.fgGC, 0);
00465           gui->graphics->draw_arc (Output.fgGC,
00466                                    pv->X, pv->Y, pv->DrillingHole / 2,
00467                                    pv->DrillingHole / 2, 0, 360);
00468         }
00469     }
00470   else
00471     if (ViaIsOnAnyVisibleLayer (pv))
00472       gui->graphics->fill_circle (Output.bgGC, pv->X, pv->Y, pv->DrillingHole / 2);
00473     else
00474       {
00475           gui->graphics->set_line_cap (Output.fgGC, Round_Cap);
00476           gui->graphics->set_line_width (Output.fgGC, 0);
00477           gui->graphics->draw_arc (Output.fgGC,
00478                                    pv->X, pv->Y, pv->DrillingHole / 2,
00479                                    pv->DrillingHole / 2, 0, 360);
00480       }
00481 
00482   if (TEST_FLAG (HOLEFLAG, pv))
00483     {
00484       set_object_color ((AnyObjectType *) pv,
00485                         PCB->WarnColor, PCB->ViaSelectedColor,
00486                         NULL, NULL, Settings.BlackColor);
00487 
00488       gui->graphics->set_line_cap (Output.fgGC, Round_Cap);
00489       gui->graphics->set_line_width (Output.fgGC, 0);
00490       gui->graphics->draw_arc (Output.fgGC,
00491                                pv->X, pv->Y, pv->DrillingHole / 2,
00492                                pv->DrillingHole / 2, 0, 360);
00493     }
00494   return 1;
00495 }
00496 
00497 void
00498 DrawHoles (bool draw_plated, bool draw_unplated, const BoxType *drawn_area, Cardinal g_from, Cardinal g_to)
00499 {
00500   hole_info hi = {-1, true, g_from, g_to};
00501 
00502   if ( draw_plated && !draw_unplated) hi.plated = 1;
00503   if (!draw_plated &&  draw_unplated) hi.plated = 0;
00504 
00505   current_layergroup = -1;
00506 
00507   r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, &hi);
00508   r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, &hi);
00509 }
00510 
00511 static int
00512 line_callback (const BoxType * b, void *cl)
00513 {
00514   LayerType *layer = (LayerType *) cl;
00515   LineType *line = (LineType *) b;
00516 
00517   set_layer_object_color (layer, (AnyObjectType *) line);
00518   gui->graphics->draw_pcb_line (Output.fgGC, line);
00519 
00520   return 1;
00521 }
00522 
00523 static int
00524 rat_callback (const BoxType * b, void *cl)
00525 {
00526   RatType *rat = (RatType *)b;
00527 
00528   set_object_color ((AnyObjectType *) rat, NULL, PCB->RatSelectedColor,
00529                     PCB->ConnectedColor, PCB->FoundColor, PCB->RatColor);
00530 
00531   if (Settings.RatThickness < 100)
00532     rat->Thickness = pixel_slop * Settings.RatThickness;
00533   /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
00534   if (TEST_FLAG(VIAFLAG, rat))
00535     {
00536       int w = rat->Thickness;
00537 
00538       if (TEST_FLAG (THINDRAWFLAG, PCB))
00539         gui->graphics->set_line_width (Output.fgGC, 0);
00540       else
00541         gui->graphics->set_line_width (Output.fgGC, w);
00542       gui->graphics->draw_arc (Output.fgGC, rat->Point1.X, rat->Point1.Y,
00543                                w * 2, w * 2, 0, 360);
00544     }
00545   else
00546     gui->graphics->draw_pcb_line (Output.fgGC, (LineType *) rat);
00547   return 1;
00548 }
00549 
00550 static int
00551 arc_callback (const BoxType * b, void *cl)
00552 {
00553   LayerType *layer = (LayerType *) cl;
00554   ArcType *arc =  (ArcType *) b;
00555 
00556   set_layer_object_color (layer, (AnyObjectType *) arc);
00557   gui->graphics->draw_pcb_arc (Output.fgGC, arc);
00558 
00559   return 1;
00560 }
00561 
00562 static void
00563 draw_element_package (ElementType *element)
00564 {
00565   /* set color and draw lines, arcs, text and pins */
00566   if (doing_pinout || doing_assy)
00567     gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
00568   else if (TEST_FLAG (SELECTEDFLAG, element))
00569     gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor);
00570   else if (FRONT (element))
00571     gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
00572   else
00573     gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
00574 
00575   /* draw lines, arcs, text and pins */
00576   ELEMENTLINE_LOOP (element);
00577   {
00578     gui->graphics->draw_pcb_line (Output.fgGC, line);
00579   }
00580   END_LOOP;
00581   ARC_LOOP (element);
00582   {
00583     gui->graphics->draw_pcb_arc (Output.fgGC, arc);
00584   }
00585   END_LOOP;
00586 }
00587 
00588 static int
00589 element_callback (const BoxType * b, void *cl)
00590 {
00591   ElementType *element = (ElementType *) b;
00592   int *side = cl;
00593 
00594   if (ON_SIDE (element, *side))
00595     draw_element_package (element);
00596   return 1;
00597 }
00598 
00602 void
00603 PrintAssembly (int side, const BoxType * drawn_area)
00604 {
00605   int side_group = GetLayerGroupNumberBySide (side);
00606 
00607   doing_assy = true;
00608   gui->graphics->set_draw_faded (Output.fgGC, 1);
00609   DrawLayerGroup (side_group, drawn_area);
00610   gui->graphics->set_draw_faded (Output.fgGC, 0);
00611 
00612   /* draw package */
00613   DrawSilk (side, drawn_area);
00614   doing_assy = false;
00615 }
00616 
00621 static void
00622 DrawEverything (const BoxType *drawn_area)
00623 {
00624   int i, ngroups, side;
00625   int top_group, bottom_group;
00626   /* This is the list of layer groups we will draw.  */
00627   int do_group[MAX_GROUP];
00628   /* This is the reverse of the order in which we draw them.  */
00629   int drawn_groups[MAX_GROUP];
00630   int plated, unplated;
00631   bool paste_empty;
00632   int g_from, g_to;
00633   char s[22];
00634 
00635   PCB->Data->SILKLAYER.Color = PCB->ElementColor;
00636   PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor;
00637 
00638   memset (do_group, 0, sizeof (do_group));
00639   for (ngroups = 0, i = 0; i < max_copper_layer; i++)
00640     {
00641       LayerType *l = LAYER_ON_STACK (i);
00642       int group = GetLayerGroupNumberByNumber (LayerStack[i]);
00643       if (l->On && !do_group[group])
00644         {
00645           do_group[group] = 1;
00646           drawn_groups[ngroups++] = group;
00647         }
00648     }
00649 
00650   top_group = GetLayerGroupNumberBySide (TOP_SIDE);
00651   bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE);
00652 
00653   /*
00654    * first draw all 'invisible' stuff
00655    */
00656   if (!TEST_FLAG (CHECKPLANESFLAG, PCB)
00657       && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0))
00658     {
00659       side = SWAP_IDENT ? TOP_SIDE : BOTTOM_SIDE;
00660       if (PCB->ElementOn)
00661         {
00662           r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
00663           r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
00664           DrawLayer (&(PCB->Data->Layer[max_copper_layer + side]), drawn_area);
00665         }
00666       r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
00667       gui->end_layer ();
00668     }
00669 
00670   /* draw all layers in layerstack order */
00671   for (i = ngroups - 1; i >= 0; i--)
00672     {
00673       int group = drawn_groups[i];
00674 
00675       if (gui->set_layer (0, group, 0))
00676         {
00677           DrawLayerGroup (group, drawn_area);
00678           gui->end_layer ();
00679         }
00680     }
00681 
00682   if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
00683     return;
00684 
00685   /* Draw pins, pads, vias below silk */
00686   if (gui->gui)
00687     DrawPPV (SWAP_IDENT ? bottom_group : top_group, drawn_area);
00688   else
00689     {
00690       CountHoles (&plated, &unplated, drawn_area);
00691 
00692       if (plated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0))
00693         {
00694           DrawHoles (true, false, drawn_area, 0, 0);
00695           gui->end_layer ();
00696         }
00697 
00698       if (unplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0))
00699         {
00700           DrawHoles (false, true, drawn_area, 0, 0);
00701           gui->end_layer ();
00702         }
00703 
00704       for (g_from = 0; g_from < (max_group - 1); g_from++)
00705         for (g_to = g_from+1 ; g_to < max_group; g_to++ )
00706           {
00707             CountHolesEx (&plated, &unplated, drawn_area, g_from, g_to);
00708             sprintf (s, "plated-drill_%02d-%02d", g_from+1, g_to+1);
00709             if (plated && gui->set_layer (s, SL (PDRILL, 0), 0))
00710               {
00711                 DrawHoles (true, false, drawn_area, g_from, g_to);
00712                 gui->end_layer ();
00713               }
00714 
00715             sprintf (s, "unplated-drill_%02d-%02d", g_from+1, g_to+1);
00716             if (unplated && gui->set_layer (s, SL (UDRILL, 0), 0))
00717               {
00718                 DrawHoles (false, true, drawn_area, g_from, g_to);
00719                 gui->end_layer ();
00720               }
00721           }
00722 
00723 
00724     }
00725 
00726   /* Draw the solder mask if turned on */
00727   if (gui->set_layer ("componentmask", SL (MASK, TOP), 0))
00728     {
00729       DrawMask (TOP_SIDE, drawn_area);
00730       gui->end_layer ();
00731     }
00732 
00733   if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0))
00734     {
00735       DrawMask (BOTTOM_SIDE, drawn_area);
00736       gui->end_layer ();
00737     }
00738 
00739   if (gui->set_layer ("topsilk", SL (SILK, TOP), 0))
00740     {
00741       DrawSilk (TOP_SIDE, drawn_area);
00742       gui->end_layer ();
00743     }
00744 
00745   if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0))
00746     {
00747       DrawSilk (BOTTOM_SIDE, drawn_area);
00748       gui->end_layer ();
00749     }
00750 
00751   if (gui->gui)
00752     {
00753       /* Draw element Marks */
00754       if (PCB->PinOn)
00755         r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
00756                   NULL);
00757       /* Draw rat lines on top */
00758       if (gui->set_layer ("rats", SL (RATS, 0), 0))
00759         {
00760           DrawRats(drawn_area);
00761           gui->end_layer ();
00762         }
00763     }
00764 
00765   paste_empty = IsPasteEmpty (TOP_SIDE);
00766   if (gui->set_layer ("toppaste", SL (PASTE, TOP), paste_empty))
00767     {
00768       DrawPaste (TOP_SIDE, drawn_area);
00769       gui->end_layer ();
00770     }
00771 
00772   paste_empty = IsPasteEmpty (BOTTOM_SIDE);
00773   if (gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), paste_empty))
00774     {
00775       DrawPaste (BOTTOM_SIDE, drawn_area);
00776       gui->end_layer ();
00777     }
00778 
00779   if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0))
00780     {
00781       PrintAssembly (TOP_SIDE, drawn_area);
00782       gui->end_layer ();
00783     }
00784 
00785   if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0))
00786     {
00787       PrintAssembly (BOTTOM_SIDE, drawn_area);
00788       gui->end_layer ();
00789     }
00790 
00791   if (gui->set_layer ("fab", SL (FAB, 0), 0))
00792     {
00793       PrintFab (Output.fgGC);
00794       gui->end_layer ();
00795     }
00796 }
00797 
00798 static void
00799 DrawEMark (ElementType *e, Coord X, Coord Y, bool invisible)
00800 {
00801   Coord mark_size = EMARK_SIZE;
00802   if (!PCB->InvisibleObjectsOn && invisible)
00803     return;
00804 
00805   if (e->Pin != NULL)
00806     {
00807       PinType *pin0 = e->Pin->data;
00808       if (TEST_FLAG (HOLEFLAG, pin0))
00809         mark_size = MIN (mark_size, pin0->DrillingHole / 2);
00810       else
00811         mark_size = MIN (mark_size, pin0->Thickness / 2);
00812     }
00813 
00814   if (e->Pad != NULL)
00815     {
00816       PadType *pad0 = e->Pad->data;
00817       mark_size = MIN (mark_size, pad0->Thickness / 2);
00818     }
00819 
00820   gui->graphics->set_color (Output.fgGC,
00821                   invisible ? PCB->InvisibleMarkColor : PCB->ElementColor);
00822   gui->graphics->set_line_cap (Output.fgGC, Trace_Cap);
00823   gui->graphics->set_line_width (Output.fgGC, 0);
00824   gui->graphics->draw_line (Output.fgGC, X - mark_size, Y, X, Y - mark_size);
00825   gui->graphics->draw_line (Output.fgGC, X + mark_size, Y, X, Y - mark_size);
00826   gui->graphics->draw_line (Output.fgGC, X - mark_size, Y, X, Y + mark_size);
00827   gui->graphics->draw_line (Output.fgGC, X + mark_size, Y, X, Y + mark_size);
00828 
00829   /*
00830    * If an element is locked, place a "L" on top of the "diamond".
00831    * This provides a nice visual indication that it is locked that
00832    * works even for color blind users.
00833    */
00834   if (TEST_FLAG (LOCKFLAG, e) )
00835     {
00836       gui->graphics->draw_line (Output.fgGC, X, Y, X + 2 * mark_size, Y);
00837       gui->graphics->draw_line (Output.fgGC, X, Y, X, Y - 4* mark_size);
00838     }
00839 }
00840 
00845 static void
00846 DrawPPV (int group, const BoxType *drawn_area)
00847 {
00848   int top_group = GetLayerGroupNumberBySide (TOP_SIDE);
00849   int bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE);
00850   int side;
00851 
00852   if (PCB->PinOn || !gui->gui)
00853     {
00854       /* draw element pins */
00855       r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback, NULL);
00856 
00857       /* draw element pads */
00858       if (group == top_group)
00859         {
00860           side = TOP_SIDE;
00861           r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
00862         }
00863 
00864       if (group == bottom_group)
00865         {
00866           side = BOTTOM_SIDE;
00867           r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side);
00868         }
00869     }
00870 
00871   /* draw vias */
00872   if (PCB->ViaOn || !gui->gui)
00873     {
00874 
00875       current_layergroup = (gui->gui)?(-1):group; /* Limit vias only for layer group */
00876 
00877       r_search (PCB->Data->via_tree, drawn_area, NULL, via_callback, NULL);
00878       r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, NULL);
00879     }
00880   if (PCB->PinOn || doing_assy)
00881     r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, NULL);
00882 }
00883 
00884 static int
00885 clearPin_callback (const BoxType * b, void *cl)
00886 {
00887   PinType *pin = (PinType *) b;
00888   if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
00889     gui->graphics->thindraw_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
00890   else
00891     gui->graphics->fill_pcb_pv (Output.pmGC, Output.pmGC, pin, false, true);
00892   return 1;
00893 }
00894 
00895 struct poly_info {
00896   const BoxType *drawn_area;
00897   LayerType *layer;
00898 };
00899 
00900 static int
00901 poly_callback (const BoxType * b, void *cl)
00902 {
00903   struct poly_info *i = cl;
00904   PolygonType *polygon = (PolygonType *)b;
00905 
00906   set_layer_object_color (i->layer, (AnyObjectType *) polygon);
00907 
00908   gui->graphics->draw_pcb_polygon (Output.fgGC, polygon, i->drawn_area);
00909 
00910   return 1;
00911 }
00912 
00913 static int
00914 clearPad_callback (const BoxType * b, void *cl)
00915 {
00916   PadType *pad = (PadType *) b;
00917   int *side = cl;
00918   if (ON_SIDE (pad, *side) && pad->Mask)
00919     _draw_pad (Output.pmGC, pad, true, true);
00920   return 1;
00921 }
00922 
00926 void
00927 DrawSilk (int side, const BoxType * drawn_area)
00928 {
00929 #if 0
00930   /* This code is used when you want to mask silk to avoid exposed
00931      pins and pads.  We decided it was a bad idea to do this
00932      unconditionally, but the code remains.  */
00933 #endif
00934 
00935 #if 0
00936   if (gui->poly_before)
00937     {
00938       gui->graphics->use_mask (HID_MASK_BEFORE);
00939 #endif
00940       DrawLayer (LAYER_PTR (max_copper_layer + side), drawn_area);
00941       /* draw package */
00942       r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
00943       r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
00944 #if 0
00945     }
00946 
00947   gui->graphics->use_mask (HID_MASK_CLEAR);
00948   r_search (PCB->Data->pin_tree, drawn_area, NULL, clearPin_callback, NULL);
00949   r_search (PCB->Data->via_tree, drawn_area, NULL, clearPin_callback, NULL);
00950   r_search (PCB->Data->pad_tree, drawn_area, NULL, clearPad_callback, &side);
00951 
00952   if (gui->poly_after)
00953     {
00954       gui->graphics->use_mask (HID_MASK_AFTER);
00955       DrawLayer (LAYER_PTR (max_copper_layer + layer), drawn_area);
00956       /* draw package */
00957       r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side);
00958       r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side);
00959     }
00960   gui->graphics->use_mask (HID_MASK_OFF);
00961 #endif
00962 }
00963 
00964 
00965 static void
00966 DrawMaskBoardArea (int mask_type, const BoxType *drawn_area)
00967 {
00968   /* Skip the mask drawing if the GUI doesn't want this type */
00969   if ((mask_type == HID_MASK_BEFORE && !gui->poly_before) ||
00970       (mask_type == HID_MASK_AFTER  && !gui->poly_after))
00971     return;
00972 
00973   gui->graphics->use_mask (mask_type);
00974   gui->graphics->set_color (Output.fgGC, PCB->MaskColor);
00975   if (drawn_area == NULL)
00976     gui->graphics->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
00977   else
00978     gui->graphics->fill_rect (Output.fgGC, drawn_area->X1, drawn_area->Y1,
00979                                            drawn_area->X2, drawn_area->Y2);
00980 }
00981 
00985 void
00986 DrawMask (int side, const BoxType *screen)
00987 {
00988   int thin = TEST_FLAG(THINDRAWFLAG, PCB) || TEST_FLAG(THINDRAWPOLYFLAG, PCB);
00989 
00990   if (thin)
00991     gui->graphics->set_color (Output.pmGC, PCB->MaskColor);
00992   else
00993     {
00994       DrawMaskBoardArea (HID_MASK_BEFORE, screen);
00995       gui->graphics->use_mask (HID_MASK_CLEAR);
00996     }
00997 
00998   r_search (PCB->Data->pin_tree, screen, NULL, clearPin_callback, NULL);
00999   r_search (PCB->Data->via_tree, screen, NULL, clearPin_callback, NULL);
01000   r_search (PCB->Data->pad_tree, screen, NULL, clearPad_callback, &side);
01001 
01002   if (thin)
01003     gui->graphics->set_color (Output.pmGC, "erase");
01004   else
01005     {
01006       DrawMaskBoardArea (HID_MASK_AFTER, screen);
01007       gui->graphics->use_mask (HID_MASK_OFF);
01008     }
01009 }
01010 
01014 void
01015 DrawPaste (int side, const BoxType *drawn_area)
01016 {
01017   gui->graphics->set_color (Output.fgGC, PCB->ElementColor);
01018   ALLPAD_LOOP (PCB->Data);
01019   {
01020     if (ON_SIDE (pad, side) && !TEST_FLAG (NOPASTEFLAG, pad) && pad->Mask > 0)
01021       {
01022         Coord save_thickness = pad->Thickness;
01023         Coord save_mask = pad->Mask;
01024 
01025         if (Settings.PasteAdjust != 0)
01026         {
01027           pad->Thickness = pad->Thickness + Settings.PasteAdjust;
01028           pad->Mask = pad->Mask + Settings.PasteAdjust;
01029           if (pad->Thickness < 0) {
01030           printf ("adjust thickness %8.4f -> %8.4f mask  %8.4f -> %8.4f\n",
01031                   COORD_TO_MM(save_thickness), COORD_TO_MM(pad->Thickness),
01032                   COORD_TO_MM(save_mask), COORD_TO_MM(pad->Mask));
01033             pad->Thickness = 0;
01034           }
01035           if (pad->Mask < 0)
01036             pad->Mask = 0;
01037         }
01038         if (pad->Mask < pad->Thickness)
01039           _draw_pad (Output.fgGC, pad, true, true);
01040         else
01041           _draw_pad (Output.fgGC, pad, false, false);
01042         pad->Thickness = save_thickness;
01043         pad->Mask = save_mask;
01044       }
01045   }
01046   ENDALL_LOOP;
01047 }
01048 
01049 static void
01050 DrawRats (const BoxType *drawn_area)
01051 {
01052   /*
01053    * XXX lesstif allows positive AND negative drawing in HID_MASK_CLEAR.
01054    * XXX gtk only allows negative drawing.
01055    * XXX using the mask here is to get rat transparency
01056    */
01057   int can_mask = strcmp(gui->name, "lesstif") == 0;
01058 
01059   if (can_mask)
01060     gui->graphics->use_mask (HID_MASK_CLEAR);
01061   r_search (PCB->Data->rat_tree, drawn_area, NULL, rat_callback, NULL);
01062   if (can_mask)
01063     gui->graphics->use_mask (HID_MASK_OFF);
01064 }
01065 
01066 static int
01067 text_callback (const BoxType * b, void *cl)
01068 {
01069   LayerType *layer = cl;
01070   TextType *text = (TextType *)b;
01071   int min_silk_line;
01072 
01073   if (TEST_FLAG (SELECTEDFLAG, text))
01074     gui->graphics->set_color (Output.fgGC, layer->SelectedColor);
01075   else
01076     gui->graphics->set_color (Output.fgGC, layer->Color);
01077   if (layer == &PCB->Data->SILKLAYER ||
01078       layer == &PCB->Data->BACKSILKLAYER)
01079     min_silk_line = PCB->minSlk;
01080   else
01081     min_silk_line = PCB->minWid;
01082   gui->graphics->draw_pcb_text (Output.fgGC, text, min_silk_line);
01083   return 1;
01084 }
01085 
01086 void
01087 DrawLayer (LayerType *Layer, const BoxType *screen)
01088 {
01089   struct poly_info info = {screen, Layer};
01090 
01091   /* print the non-clearing polys */
01092   r_search (Layer->polygon_tree, screen, NULL, poly_callback, &info);
01093 
01094   if (TEST_FLAG (CHECKPLANESFLAG, PCB))
01095     return;
01096 
01097   /* draw all visible lines this layer */
01098   r_search (Layer->line_tree, screen, NULL, line_callback, Layer);
01099 
01100   /* draw the layer arcs on screen */
01101   r_search (Layer->arc_tree, screen, NULL, arc_callback, Layer);
01102 
01103   /* draw the layer text on screen */
01104   r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
01105 
01106   /* We should check for gui->gui here, but it's kinda cool seeing the
01107      auto-outline magically disappear when you first add something to
01108      the "outline" layer.  */
01109   if (IsLayerEmpty (Layer)
01110       && (strcmp (Layer->Name, "outline") == 0
01111           || strcmp (Layer->Name, "route") == 0))
01112     {
01113       gui->graphics->set_color (Output.fgGC, Layer->Color);
01114       gui->graphics->set_line_width (Output.fgGC, PCB->minWid);
01115       gui->graphics->draw_rect (Output.fgGC,
01116                                 0, 0,
01117                                 PCB->MaxWidth, PCB->MaxHeight);
01118     }
01119 }
01120 
01127 void
01128 DrawLayerGroup (int group, const BoxType *drawn_area)
01129 {
01130   int i, rv = 1;
01131   int layernum;
01132   LayerType *Layer;
01133   int n_entries = PCB->LayerGroups.Number[group];
01134   Cardinal *layers = PCB->LayerGroups.Entries[group];
01135 
01136   for (i = n_entries - 1; i >= 0; i--)
01137     {
01138       layernum = layers[i];
01139       Layer = PCB->Data->Layer + layers[i];
01140       if (strcmp (Layer->Name, "outline") == 0 ||
01141           strcmp (Layer->Name, "route") == 0)
01142         rv = 0;
01143       if (layernum < max_copper_layer && Layer->On)
01144         DrawLayer (Layer, drawn_area);
01145     }
01146   if (n_entries > 1)
01147     rv = 1;
01148 
01149   if (rv && !gui->gui)
01150     DrawPPV (group, drawn_area);
01151 }
01152 
01153 static void
01154 GatherPVName (PinType *Ptr)
01155 {
01156   BoxType box;
01157   bool vert = TEST_FLAG (EDGE2FLAG, Ptr);
01158 
01159   if (vert)
01160     {
01161       box.X1 = Ptr->X - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
01162       box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - Settings.PinoutTextOffsetX;
01163     }
01164   else
01165     {
01166       box.X1 = Ptr->X + Ptr->DrillingHole / 2 + Settings.PinoutTextOffsetX;
01167       box.Y1 = Ptr->Y - Ptr->Thickness / 2 + Settings.PinoutTextOffsetY;
01168     }
01169 
01170   if (vert)
01171     {
01172       box.X2 = box.X1;
01173       box.Y2 = box.Y1;
01174     }
01175   else
01176     {
01177       box.X2 = box.X1;
01178       box.Y2 = box.Y1;
01179     }
01180   AddPart (&box);
01181 }
01182 
01183 static void
01184 GatherPadName (PadType *Pad)
01185 {
01186   BoxType box;
01187   bool vert;
01188 
01189   /* should text be vertical ? */
01190   vert = (Pad->Point1.X == Pad->Point2.X);
01191 
01192   if (vert)
01193     {
01194       box.X1 = Pad->Point1.X                      - Pad->Thickness / 2;
01195       box.Y1 = MAX (Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2;
01196       box.X1 += Settings.PinoutTextOffsetY;
01197       box.Y1 -= Settings.PinoutTextOffsetX;
01198       box.X2 = box.X1;
01199       box.Y2 = box.Y1;
01200     }
01201   else
01202     {
01203       box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2;
01204       box.Y1 = Pad->Point1.Y                      - Pad->Thickness / 2;
01205       box.X1 += Settings.PinoutTextOffsetX;
01206       box.Y1 += Settings.PinoutTextOffsetY;
01207       box.X2 = box.X1;
01208       box.Y2 = box.Y1;
01209     }
01210 
01211   AddPart (&box);
01212   return;
01213 }
01214 
01218 void
01219 DrawVia (PinType *Via)
01220 {
01221   AddPart (Via);
01222   if (!TEST_FLAG (HOLEFLAG, Via) && TEST_FLAG (DISPLAYNAMEFLAG, Via))
01223     DrawViaName (Via);
01224 }
01225 
01229 void
01230 DrawViaName (PinType *Via)
01231 {
01232   GatherPVName (Via);
01233 }
01234 
01238 void
01239 DrawPin (PinType *Pin)
01240 {
01241   AddPart (Pin);
01242   if ((!TEST_FLAG (HOLEFLAG, Pin) && TEST_FLAG (DISPLAYNAMEFLAG, Pin))
01243       || doing_pinout)
01244     DrawPinName (Pin);
01245 }
01246 
01250 void
01251 DrawPinName (PinType *Pin)
01252 {
01253   GatherPVName (Pin);
01254 }
01255 
01259 void
01260 DrawPad (PadType *Pad)
01261 {
01262   AddPart (Pad);
01263   if (doing_pinout || TEST_FLAG (DISPLAYNAMEFLAG, Pad))
01264     DrawPadName (Pad);
01265 }
01266 
01270 void
01271 DrawPadName (PadType *Pad)
01272 {
01273   GatherPadName (Pad);
01274 }
01275 
01279 void
01280 DrawLine (LayerType *Layer, LineType *Line)
01281 {
01282   AddPart (Line);
01283 }
01284 
01288 void
01289 DrawRat (RatType *Rat)
01290 {
01291   if (Settings.RatThickness < 100)
01292     Rat->Thickness = pixel_slop * Settings.RatThickness;
01293   /* rats.c set VIAFLAG if this rat goes to a containing poly: draw a donut */
01294   if (TEST_FLAG(VIAFLAG, Rat))
01295     {
01296       Coord w = Rat->Thickness;
01297 
01298       BoxType b;
01299 
01300       b.X1 = Rat->Point1.X - w * 2 - w / 2;
01301       b.X2 = Rat->Point1.X + w * 2 + w / 2;
01302       b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
01303       b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
01304       AddPart (&b);
01305     }
01306   else
01307     DrawLine (NULL, (LineType *)Rat);
01308 }
01309 
01313 void
01314 DrawArc (LayerType *Layer, ArcType *Arc)
01315 {
01316   AddPart (Arc);
01317 }
01318 
01322 void
01323 DrawText (LayerType *Layer, TextType *Text)
01324 {
01325   AddPart (Text);
01326 }
01327 
01328 
01332 void
01333 DrawPolygon (LayerType *Layer, PolygonType *Polygon)
01334 {
01335   AddPart (Polygon);
01336 }
01337 
01341 void
01342 DrawElement (ElementType *Element)
01343 {
01344   DrawElementPackage (Element);
01345   DrawElementName (Element);
01346   DrawElementPinsAndPads (Element);
01347 }
01348 
01352 void
01353 DrawElementName (ElementType *Element)
01354 {
01355   if (TEST_FLAG (HIDENAMEFLAG, Element))
01356     return;
01357   DrawText (NULL, &ELEMENT_TEXT (PCB, Element));
01358 }
01359 
01363 void
01364 DrawElementPackage (ElementType *Element)
01365 {
01366   ELEMENTLINE_LOOP (Element);
01367   {
01368     DrawLine (NULL, line);
01369   }
01370   END_LOOP;
01371   ARC_LOOP (Element);
01372   {
01373     DrawArc (NULL, arc);
01374   }
01375   END_LOOP;
01376 }
01377 
01381 void
01382 DrawElementPinsAndPads (ElementType *Element)
01383 {
01384   PAD_LOOP (Element);
01385   {
01386     if (doing_pinout || doing_assy || FRONT (pad) || PCB->InvisibleObjectsOn)
01387       DrawPad (pad);
01388   }
01389   END_LOOP;
01390   PIN_LOOP (Element);
01391   {
01392     DrawPin (pin);
01393   }
01394   END_LOOP;
01395 }
01396 
01400 void
01401 EraseVia (PinType *Via)
01402 {
01403   AddPart (Via);
01404   if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
01405     EraseViaName (Via);
01406 }
01407 
01411 void
01412 EraseRat (RatType *Rat)
01413 {
01414   if (TEST_FLAG(VIAFLAG, Rat))
01415     {
01416       Coord w = Rat->Thickness;
01417 
01418       BoxType b;
01419 
01420       b.X1 = Rat->Point1.X - w * 2 - w / 2;
01421       b.X2 = Rat->Point1.X + w * 2 + w / 2;
01422       b.Y1 = Rat->Point1.Y - w * 2 - w / 2;
01423       b.Y2 = Rat->Point1.Y + w * 2 + w / 2;
01424       AddPart (&b);
01425     }
01426   else
01427     EraseLine ((LineType *)Rat);
01428 }
01429 
01430 
01434 void
01435 EraseViaName (PinType *Via)
01436 {
01437   GatherPVName (Via);
01438 }
01439 
01443 void
01444 ErasePad (PadType *Pad)
01445 {
01446   AddPart (Pad);
01447   if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
01448     ErasePadName (Pad);
01449 }
01450 
01454 void
01455 ErasePadName (PadType *Pad)
01456 {
01457   GatherPadName (Pad);
01458 }
01459 
01463 void
01464 ErasePin (PinType *Pin)
01465 {
01466   AddPart (Pin);
01467   if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
01468     ErasePinName (Pin);
01469 }
01470 
01474 void
01475 ErasePinName (PinType *Pin)
01476 {
01477   GatherPVName (Pin);
01478 }
01479 
01483 void
01484 EraseLine (LineType *Line)
01485 {
01486   AddPart (Line);
01487 }
01488 
01492 void
01493 EraseArc (ArcType *Arc)
01494 {
01495   if (!Arc->Thickness)
01496     return;
01497   AddPart (Arc);
01498 }
01499 
01503 void
01504 EraseText (LayerType *Layer, TextType *Text)
01505 {
01506 /*  r_delete_entry (Layer->text_tree, (BoxType *) Text); */
01507   AddPart (Text);
01508 }
01509 
01513 void
01514 ErasePolygon (PolygonType *Polygon)
01515 {
01516   AddPart (Polygon);
01517 }
01518 
01522 void
01523 EraseElement (ElementType *Element)
01524 {
01525   ELEMENTLINE_LOOP (Element);
01526   {
01527     EraseLine (line);
01528   }
01529   END_LOOP;
01530   ARC_LOOP (Element);
01531   {
01532     EraseArc (arc);
01533   }
01534   END_LOOP;
01535   EraseElementName (Element);
01536   EraseElementPinsAndPads (Element);
01537 }
01538 
01542 void
01543 EraseElementPinsAndPads (ElementType *Element)
01544 {
01545   PIN_LOOP (Element);
01546   {
01547     ErasePin (pin);
01548   }
01549   END_LOOP;
01550   PAD_LOOP (Element);
01551   {
01552     ErasePad (pad);
01553   }
01554   END_LOOP;
01555 }
01556 
01560 void
01561 EraseElementName (ElementType *Element)
01562 {
01563   if (TEST_FLAG (HIDENAMEFLAG, Element))
01564     return;
01565   EraseText (NULL, &ELEMENT_TEXT (PCB, Element));}
01566 
01567 
01568 void
01569 EraseObject (int type, void *lptr, void *ptr)
01570 {
01571   switch (type)
01572     {
01573     case VIA_TYPE:
01574     case PIN_TYPE:
01575       ErasePin ((PinType *) ptr);
01576       break;
01577     case TEXT_TYPE:
01578       EraseText ((LayerType *)lptr, (TextType *) ptr);
01579       break;
01580     case ELEMENTNAME_TYPE:
01581       EraseElementName ((ElementType *) ptr);
01582       break;
01583     case POLYGON_TYPE:
01584       ErasePolygon ((PolygonType *) ptr);
01585       break;
01586     case ELEMENT_TYPE:
01587       EraseElement ((ElementType *) ptr);
01588       break;
01589     case LINE_TYPE:
01590     case ELEMENTLINE_TYPE:
01591     case RATLINE_TYPE:
01592       EraseLine ((LineType *) ptr);
01593       break;
01594     case PAD_TYPE:
01595       ErasePad ((PadType *) ptr);
01596       break;
01597     case ARC_TYPE:
01598     case ELEMENTARC_TYPE:
01599       EraseArc ((ArcType *) ptr);
01600       break;
01601     default:
01602       Message ("hace: Internal ERROR, trying to erase an unknown type\n");
01603     }
01604 }
01605 
01606 
01607 
01608 void
01609 DrawObject (int type, void *ptr1, void *ptr2)
01610 {
01611   switch (type)
01612     {
01613     case VIA_TYPE:
01614       if (PCB->ViaOn)
01615         DrawVia ((PinType *) ptr2);
01616       break;
01617     case LINE_TYPE:
01618       if (((LayerType *) ptr1)->On)
01619         DrawLine ((LayerType *) ptr1, (LineType *) ptr2);
01620       break;
01621     case ARC_TYPE:
01622       if (((LayerType *) ptr1)->On)
01623         DrawArc ((LayerType *) ptr1, (ArcType *) ptr2);
01624       break;
01625     case TEXT_TYPE:
01626       if (((LayerType *) ptr1)->On)
01627         DrawText ((LayerType *) ptr1, (TextType *) ptr2);
01628       break;
01629     case POLYGON_TYPE:
01630       if (((LayerType *) ptr1)->On)
01631         DrawPolygon ((LayerType *) ptr1, (PolygonType *) ptr2);
01632       break;
01633     case ELEMENT_TYPE:
01634       if (PCB->ElementOn &&
01635           (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
01636         DrawElement ((ElementType *) ptr2);
01637       break;
01638     case RATLINE_TYPE:
01639       if (PCB->RatOn)
01640         DrawRat ((RatType *) ptr2);
01641       break;
01642     case PIN_TYPE:
01643       if (PCB->PinOn)
01644         DrawPin ((PinType *) ptr2);
01645       break;
01646     case PAD_TYPE:
01647       if (PCB->PinOn)
01648         DrawPad ((PadType *) ptr2);
01649       break;
01650     case ELEMENTNAME_TYPE:
01651       if (PCB->ElementOn &&
01652           (FRONT ((ElementType *) ptr2) || PCB->InvisibleObjectsOn))
01653         DrawElementName ((ElementType *) ptr1);
01654       break;
01655     }
01656 }
01657 
01658 static void
01659 draw_element (ElementType *element)
01660 {
01661   draw_element_package (element);
01662   draw_element_name (element);
01663   draw_element_pins_and_pads (element);
01664 }
01665 
01669 void
01670 hid_expose_callback (HID * hid, BoxType * region, void *item)
01671 {
01672   HID *old_gui = gui;
01673 
01674   gui = hid;
01675   Output.fgGC = gui->graphics->make_gc ();
01676   Output.bgGC = gui->graphics->make_gc ();
01677   Output.pmGC = gui->graphics->make_gc ();
01678 
01679   hid->graphics->set_color (Output.pmGC, "erase");
01680   hid->graphics->set_color (Output.bgGC, "drill");
01681 
01682   if (item)
01683     {
01684       doing_pinout = true;
01685       draw_element ((ElementType *)item);
01686       doing_pinout = false;
01687     }
01688   else
01689     DrawEverything (region);
01690 
01691   gui->graphics->destroy_gc (Output.fgGC);
01692   gui->graphics->destroy_gc (Output.bgGC);
01693   gui->graphics->destroy_gc (Output.pmGC);
01694   gui = old_gui;
01695 }