pcb 4.1.1
An interactive printed circuit board layout editor.
|
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 }