pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 #include "global.h" 00002 #include "hid.h" 00003 #include "hid_draw.h" 00004 #include "data.h" /* For global "PCB" variable */ 00005 #include "rotate.h" /* For RotateLineLowLevel() */ 00006 #include "polygon.h" 00007 #include "draw_helpers.h" 00008 00009 00010 void 00011 common_draw_pcb_line (hidGC gc, LineType *line) 00012 { 00013 gui->graphics->set_line_cap (gc, Trace_Cap); 00014 if (TEST_FLAG (THINDRAWFLAG, PCB)) 00015 gui->graphics->set_line_width (gc, 0); 00016 else 00017 gui->graphics->set_line_width (gc, line->Thickness); 00018 00019 gui->graphics->draw_line (gc, 00020 line->Point1.X, line->Point1.Y, 00021 line->Point2.X, line->Point2.Y); 00022 } 00023 00024 void 00025 common_draw_pcb_arc (hidGC gc, ArcType *arc) 00026 { 00027 if (!arc->Thickness) 00028 return; 00029 00030 if (TEST_FLAG (THINDRAWFLAG, PCB)) 00031 gui->graphics->set_line_width (gc, 0); 00032 else 00033 gui->graphics->set_line_width (gc, arc->Thickness); 00034 gui->graphics->set_line_cap (gc, Trace_Cap); 00035 00036 gui->graphics->draw_arc (gc, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); 00037 } 00038 00039 /* --------------------------------------------------------------------------- 00040 * drawing routine for text objects 00041 */ 00042 static void 00043 common_draw_pcb_text (hidGC gc, TextType *Text, Coord min_line_width) 00044 { 00045 Coord x = 0; 00046 unsigned char *string = (unsigned char *) Text->TextString; 00047 Cardinal n; 00048 FontType *font = &PCB->Font; 00049 00050 while (string && *string) 00051 { 00052 /* draw lines if symbol is valid and data is present */ 00053 if (*string <= MAX_FONTPOSITION && font->Symbol[*string].Valid) 00054 { 00055 LineType *line = font->Symbol[*string].Line; 00056 LineType newline; 00057 00058 for (n = font->Symbol[*string].LineN; n; n--, line++) 00059 { 00060 /* create one line, scale, move, rotate and swap it */ 00061 newline = *line; 00062 newline.Point1.X = SCALE_TEXT (newline.Point1.X + x, Text->Scale); 00063 newline.Point1.Y = SCALE_TEXT (newline.Point1.Y, Text->Scale); 00064 newline.Point2.X = SCALE_TEXT (newline.Point2.X + x, Text->Scale); 00065 newline.Point2.Y = SCALE_TEXT (newline.Point2.Y, Text->Scale); 00066 newline.Thickness = SCALE_TEXT (newline.Thickness, Text->Scale / 2); 00067 if (newline.Thickness < min_line_width) 00068 newline.Thickness = min_line_width; 00069 00070 RotateLineLowLevel (&newline, 0, 0, Text->Direction); 00071 00072 /* the labels of SMD objects on the bottom 00073 * side haven't been swapped yet, only their offset 00074 */ 00075 if (TEST_FLAG (ONSOLDERFLAG, Text)) 00076 { 00077 newline.Point1.X = SWAP_SIGN_X (newline.Point1.X); 00078 newline.Point1.Y = SWAP_SIGN_Y (newline.Point1.Y); 00079 newline.Point2.X = SWAP_SIGN_X (newline.Point2.X); 00080 newline.Point2.Y = SWAP_SIGN_Y (newline.Point2.Y); 00081 } 00082 /* add offset and draw line */ 00083 newline.Point1.X += Text->X; 00084 newline.Point1.Y += Text->Y; 00085 newline.Point2.X += Text->X; 00086 newline.Point2.Y += Text->Y; 00087 gui->graphics->draw_pcb_line (gc, &newline); 00088 } 00089 00090 /* move on to next cursor position */ 00091 x += (font->Symbol[*string].Width + font->Symbol[*string].Delta); 00092 } 00093 else 00094 { 00095 /* the default symbol is a filled box */ 00096 BoxType defaultsymbol = PCB->Font.DefaultSymbol; 00097 Coord size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5; 00098 00099 defaultsymbol.X1 = SCALE_TEXT (defaultsymbol.X1 + x, Text->Scale); 00100 defaultsymbol.Y1 = SCALE_TEXT (defaultsymbol.Y1, Text->Scale); 00101 defaultsymbol.X2 = SCALE_TEXT (defaultsymbol.X2 + x, Text->Scale); 00102 defaultsymbol.Y2 = SCALE_TEXT (defaultsymbol.Y2, Text->Scale); 00103 00104 RotateBoxLowLevel (&defaultsymbol, 0, 0, Text->Direction); 00105 00106 /* add offset and draw box */ 00107 defaultsymbol.X1 += Text->X; 00108 defaultsymbol.Y1 += Text->Y; 00109 defaultsymbol.X2 += Text->X; 00110 defaultsymbol.Y2 += Text->Y; 00111 gui->graphics->fill_rect (gc, 00112 defaultsymbol.X1, defaultsymbol.Y1, 00113 defaultsymbol.X2, defaultsymbol.Y2); 00114 00115 /* move on to next cursor position */ 00116 x += size; 00117 } 00118 string++; 00119 } 00120 } 00121 00122 static void 00123 fill_contour (hidGC gc, PLINE *pl) 00124 { 00125 Coord *x, *y, n, i = 0; 00126 VNODE *v; 00127 00128 n = pl->Count; 00129 x = (Coord *)malloc (n * sizeof (*x)); 00130 y = (Coord *)malloc (n * sizeof (*y)); 00131 00132 for (v = &pl->head; i < n; v = v->next) 00133 { 00134 x[i] = v->point[0]; 00135 y[i++] = v->point[1]; 00136 } 00137 00138 gui->graphics->fill_polygon (gc, n, x, y); 00139 00140 free (x); 00141 free (y); 00142 } 00143 00144 static void 00145 thindraw_contour (hidGC gc, PLINE *pl) 00146 { 00147 VNODE *v; 00148 Coord last_x, last_y; 00149 Coord this_x, this_y; 00150 00151 gui->graphics->set_line_width (gc, 0); 00152 gui->graphics->set_line_cap (gc, Round_Cap); 00153 00154 /* If the contour is round, use an arc drawing routine. */ 00155 if (pl->is_round) 00156 { 00157 gui->graphics->draw_arc (gc, pl->cx, pl->cy, pl->radius, pl->radius, 0, 360); 00158 return; 00159 } 00160 00161 /* Need at least two points in the contour */ 00162 if (pl->head.next == NULL) 00163 return; 00164 00165 last_x = pl->head.point[0]; 00166 last_y = pl->head.point[1]; 00167 v = pl->head.next; 00168 00169 do 00170 { 00171 this_x = v->point[0]; 00172 this_y = v->point[1]; 00173 00174 gui->graphics->draw_line (gc, last_x, last_y, this_x, this_y); 00175 // gui->graphics->fill_circle (gc, this_x, this_y, 30); 00176 00177 last_x = this_x; 00178 last_y = this_y; 00179 } 00180 while ((v = v->next) != pl->head.next); 00181 } 00182 00183 static void 00184 fill_contour_cb (PLINE *pl, void *user_data) 00185 { 00186 hidGC gc = (hidGC)user_data; 00187 PLINE *local_pl = pl; 00188 00189 fill_contour (gc, pl); 00190 poly_FreeContours (&local_pl); 00191 } 00192 00193 static void 00194 fill_clipped_contour (hidGC gc, PLINE *pl, const BoxType *clip_box) 00195 { 00196 PLINE *pl_copy; 00197 POLYAREA *clip_poly; 00198 POLYAREA *piece_poly; 00199 POLYAREA *clipped_pieces; 00200 POLYAREA *draw_piece; 00201 int x; 00202 00203 clip_poly = RectPoly (clip_box->X1, clip_box->X2, 00204 clip_box->Y1, clip_box->Y2); 00205 poly_CopyContour (&pl_copy, pl); 00206 piece_poly = poly_Create (); 00207 poly_InclContour (piece_poly, pl_copy); 00208 x = poly_Boolean_free (piece_poly, clip_poly, 00209 &clipped_pieces, PBO_ISECT); 00210 if (x != err_ok || clipped_pieces == NULL) 00211 return; 00212 00213 draw_piece = clipped_pieces; 00214 do 00215 { 00216 /* NB: The polygon won't have any holes in it */ 00217 fill_contour (gc, draw_piece->contours); 00218 } 00219 while ((draw_piece = draw_piece->f) != clipped_pieces); 00220 poly_Free (&clipped_pieces); 00221 } 00222 00223 /* If at least 50% of the bounding box of the polygon is on the screen, 00224 * lets compute the complete no-holes polygon. 00225 */ 00226 #define BOUNDS_INSIDE_CLIP_THRESHOLD 0.5 00227 static int 00228 should_compute_no_holes (PolygonType *poly, const BoxType *clip_box) 00229 { 00230 Coord x1, x2, y1, y2; 00231 double poly_bounding_area; 00232 double clipped_poly_area; 00233 00234 /* If there is no passed clip box, compute the whole thing */ 00235 if (clip_box == NULL) 00236 return 1; 00237 00238 x1 = MAX (poly->BoundingBox.X1, clip_box->X1); 00239 x2 = MIN (poly->BoundingBox.X2, clip_box->X2); 00240 y1 = MAX (poly->BoundingBox.Y1, clip_box->Y1); 00241 y2 = MIN (poly->BoundingBox.Y2, clip_box->Y2); 00242 00243 /* Check if the polygon is outside the clip box */ 00244 if ((x2 <= x1) || (y2 <= y1)) 00245 return 0; 00246 00247 poly_bounding_area = (double)(poly->BoundingBox.X2 - poly->BoundingBox.X1) * 00248 (double)(poly->BoundingBox.Y2 - poly->BoundingBox.Y1); 00249 00250 clipped_poly_area = (double)(x2 - x1) * (double)(y2 - y1); 00251 00252 if (clipped_poly_area / poly_bounding_area >= BOUNDS_INSIDE_CLIP_THRESHOLD) 00253 return 1; 00254 00255 return 0; 00256 } 00257 #undef BOUNDS_INSIDE_CLIP_THRESHOLD 00258 00259 void 00260 common_gui_draw_pcb_polygon (hidGC gc, PolygonType *polygon, const BoxType *clip_box) 00261 { 00262 if (polygon->Clipped == NULL) 00263 return; 00264 00265 if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB)) 00266 gui->graphics->thindraw_pcb_polygon (gc, polygon, clip_box); 00267 else 00268 gui->graphics->fill_pcb_polygon (gc, polygon, clip_box); 00269 00270 /* If checking planes, thin-draw any pieces which have been clipped away */ 00271 if (TEST_FLAG (CHECKPLANESFLAG, PCB) && !TEST_FLAG (FULLPOLYFLAG, polygon)) 00272 { 00273 PolygonType poly = *polygon; 00274 00275 for (poly.Clipped = polygon->Clipped->f; 00276 poly.Clipped != polygon->Clipped; 00277 poly.Clipped = poly.Clipped->f) 00278 gui->graphics->thindraw_pcb_polygon (gc, &poly, clip_box); 00279 } 00280 } 00281 00282 void 00283 common_fill_pcb_polygon (hidGC gc, PolygonType *poly, const BoxType *clip_box) 00284 { 00285 if (poly->Clipped == NULL) 00286 return; 00287 00288 if (!poly->NoHolesValid) 00289 { 00290 /* If enough of the polygon is on-screen, compute the entire 00291 * NoHoles version and cache it for later rendering, otherwise 00292 * just compute what we need to render now. 00293 */ 00294 if (should_compute_no_holes (poly, clip_box)) 00295 ComputeNoHoles (poly); 00296 else 00297 NoHolesPolygonDicer (poly, clip_box, fill_contour_cb, gc); 00298 } 00299 if (poly->NoHolesValid && poly->NoHoles) 00300 { 00301 PLINE *pl; 00302 00303 for (pl = poly->NoHoles; pl != NULL; pl = pl->next) 00304 { 00305 if (clip_box == NULL) 00306 fill_contour (gc, pl); 00307 else 00308 fill_clipped_contour (gc, pl, clip_box); 00309 } 00310 } 00311 00312 /* Draw other parts of the polygon if fullpoly flag is set */ 00313 /* NB: No "NoHoles" cache for these */ 00314 if (TEST_FLAG (FULLPOLYFLAG, poly)) 00315 { 00316 PolygonType p = *poly; 00317 00318 for (p.Clipped = poly->Clipped->f; 00319 p.Clipped != poly->Clipped; 00320 p.Clipped = p.Clipped->f) 00321 NoHolesPolygonDicer (&p, clip_box, fill_contour_cb, gc); 00322 } 00323 } 00324 00325 static int 00326 thindraw_hole_cb (PLINE *pl, void *user_data) 00327 { 00328 hidGC gc = (hidGC)user_data; 00329 thindraw_contour (gc, pl); 00330 return 0; 00331 } 00332 00333 void 00334 common_thindraw_pcb_polygon (hidGC gc, PolygonType *poly, 00335 const BoxType *clip_box) 00336 { 00337 if (poly->Clipped == NULL) 00338 return; 00339 00340 thindraw_contour (gc, poly->Clipped->contours); 00341 PolygonHoles (poly, clip_box, thindraw_hole_cb, gc); 00342 00343 /* Draw other parts of the polygon if fullpoly flag is set */ 00344 if (TEST_FLAG (FULLPOLYFLAG, poly)) 00345 { 00346 PolygonType p = *poly; 00347 00348 for (p.Clipped = poly->Clipped->f; 00349 p.Clipped != poly->Clipped; 00350 p.Clipped = p.Clipped->f) 00351 { 00352 thindraw_contour (gc, p.Clipped->contours); 00353 PolygonHoles (&p, clip_box, thindraw_hole_cb, gc); 00354 } 00355 } 00356 } 00357 00358 void 00359 common_thindraw_pcb_pad (hidGC gc, PadType *pad, bool clear, bool mask) 00360 { 00361 Coord w = clear ? (mask ? pad->Mask 00362 : pad->Thickness + pad->Clearance) 00363 : pad->Thickness; 00364 Coord x1, y1, x2, y2; 00365 Coord t = w / 2; 00366 x1 = pad->Point1.X; 00367 y1 = pad->Point1.Y; 00368 x2 = pad->Point2.X; 00369 y2 = pad->Point2.Y; 00370 if (x1 > x2 || y1 > y2) 00371 { 00372 Coord temp_x = x1; 00373 Coord temp_y = y1; 00374 x1 = x2; x2 = temp_x; 00375 y1 = y2; y2 = temp_y; 00376 } 00377 gui->graphics->set_line_cap (gc, Round_Cap); 00378 gui->graphics->set_line_width (gc, 0); 00379 if (TEST_FLAG (SQUAREFLAG, pad)) 00380 { 00381 /* slanted square pad */ 00382 double tx, ty, theta; 00383 00384 if (x1 == x2 && y1 == y2) 00385 theta = 0; 00386 else 00387 theta = atan2 (y2 - y1, x2 - x1); 00388 00389 /* T is a vector half a thickness long, in the direction of 00390 one of the corners. */ 00391 tx = t * cos (theta + M_PI / 4) * sqrt (2.0); 00392 ty = t * sin (theta + M_PI / 4) * sqrt (2.0); 00393 00394 gui->graphics->draw_line (gc, x1 - tx, y1 - ty, x2 + ty, y2 - tx); 00395 gui->graphics->draw_line (gc, x2 + ty, y2 - tx, x2 + tx, y2 + ty); 00396 gui->graphics->draw_line (gc, x2 + tx, y2 + ty, x1 - ty, y1 + tx); 00397 gui->graphics->draw_line (gc, x1 - ty, y1 + tx, x1 - tx, y1 - ty); 00398 } 00399 else if (x1 == x2 && y1 == y2) 00400 { 00401 gui->graphics->draw_arc (gc, x1, y1, t, t, 0, 360); 00402 } 00403 else 00404 { 00405 /* Slanted round-end pads. */ 00406 Coord dx, dy, ox, oy; 00407 double h; 00408 00409 dx = x2 - x1; 00410 dy = y2 - y1; 00411 h = t / hypot (dx, dy); 00412 ox = dy * h + 0.5 * SGN (dy); 00413 oy = -(dx * h + 0.5 * SGN (dx)); 00414 00415 gui->graphics->draw_line (gc, x1 + ox, y1 + oy, x2 + ox, y2 + oy); 00416 00417 if (abs (ox) >= pixel_slop || abs (oy) >= pixel_slop) 00418 { 00419 Angle angle = atan2 (dx, dy) * 57.295779; 00420 gui->graphics->draw_line (gc, x1 - ox, y1 - oy, x2 - ox, y2 - oy); 00421 gui->graphics->draw_arc (gc, x1, y1, t, t, angle - 180, 180); 00422 gui->graphics->draw_arc (gc, x2, y2, t, t, angle, 180); 00423 } 00424 } 00425 } 00426 00427 /* Computes the coordinates of the corners of a squared pad. */ 00428 static void 00429 common_get_pad_polygon(Coord x[4], Coord y[4], const PadType *l, int w) 00430 { 00431 Coord dX, dY; 00432 double dwx, dwy; 00433 Coord x1, y1, x2, y2; 00434 x1 = l->Point1.X; 00435 y1 = l->Point1.Y; 00436 x2 = l->Point2.X; 00437 y2 = l->Point2.Y; 00438 if (x1 > x2 || y1 > y2) 00439 { 00440 Coord temp_x = x1; 00441 Coord temp_y = y1; 00442 x1 = x2; x2 = temp_x; 00443 y1 = y2; y2 = temp_y; 00444 } 00445 00446 dX = x2 - x1; 00447 dY = y2 - y1; 00448 00449 if (dY == 0) 00450 { 00451 dwx = w / 2; 00452 dwy = 0; 00453 } 00454 else if (dX == 0) 00455 { 00456 dwx = 0; 00457 dwy = w / 2; 00458 } 00459 else 00460 { 00461 double r; 00462 00463 r = hypot (dX, dY) * 2; 00464 dwx = w / r * dX; 00465 dwy = w / r * dY; 00466 } 00467 00468 x[0] = x1 - dwx + dwy; 00469 y[0] = y1 - dwy - dwx; 00470 00471 x[1] = x1 - dwx - dwy; 00472 y[1] = y1 - dwy + dwx; 00473 00474 x[2] = x2 + dwx - dwy; 00475 y[2] = y2 + dwy + dwx; 00476 00477 x[3] = x2 + dwx + dwy; 00478 y[3] = y2 + dwy - dwx; 00479 } 00480 00481 void 00482 common_fill_pcb_pad (hidGC gc, PadType *pad, bool clear, bool mask) 00483 { 00484 Coord w = clear ? (mask ? pad->Mask 00485 : pad->Thickness + pad->Clearance) 00486 : pad->Thickness; 00487 00488 if (pad->Point1.X == pad->Point2.X && 00489 pad->Point1.Y == pad->Point2.Y) 00490 { 00491 if (TEST_FLAG (SQUAREFLAG, pad)) 00492 { 00493 Coord l, r, t, b; 00494 l = pad->Point1.X - w / 2; 00495 b = pad->Point1.Y - w / 2; 00496 r = l + w; 00497 t = b + w; 00498 gui->graphics->fill_rect (gc, l, b, r, t); 00499 } 00500 else 00501 { 00502 gui->graphics->fill_circle (gc, pad->Point1.X, pad->Point1.Y, w / 2); 00503 } 00504 } 00505 else 00506 { 00507 gui->graphics->set_line_cap (gc, TEST_FLAG (SQUAREFLAG, pad) ? 00508 Square_Cap : Round_Cap); 00509 gui->graphics->set_line_width (gc, w); 00510 00511 if (TEST_FLAG (SQUAREFLAG, pad)) 00512 { 00513 Coord x[4], y[4]; 00514 common_get_pad_polygon (x, y, pad, w); 00515 gui->graphics->fill_polygon (gc, 4, x, y); 00516 } 00517 else 00518 gui->graphics->draw_line (gc, pad->Point1.X, pad->Point1.Y, 00519 pad->Point2.X, pad->Point2.Y); 00520 } 00521 } 00522 00523 /* --------------------------------------------------------------------------- 00524 * draws one polygon 00525 * x and y are already in display coordinates 00526 * the points are numbered: 00527 * 00528 * 5 --- 6 00529 * / \ 00530 * 4 7 00531 * | | 00532 * 3 0 00533 * \ / 00534 * 2 --- 1 00535 */ 00536 00537 typedef struct 00538 { 00539 double X, Y; 00540 } 00541 FloatPolyType; 00542 00543 static void 00544 draw_octagon_poly (hidGC gc, Coord X, Coord Y, 00545 Coord Thickness, bool thin_draw) 00546 { 00547 static FloatPolyType p[8] = { 00548 { 0.5, -TAN_22_5_DEGREE_2}, 00549 { TAN_22_5_DEGREE_2, -0.5 }, 00550 {-TAN_22_5_DEGREE_2, -0.5 }, 00551 {-0.5, -TAN_22_5_DEGREE_2}, 00552 {-0.5, TAN_22_5_DEGREE_2}, 00553 {-TAN_22_5_DEGREE_2, 0.5 }, 00554 { TAN_22_5_DEGREE_2, 0.5 }, 00555 { 0.5, TAN_22_5_DEGREE_2} 00556 }; 00557 static int special_size = 0; 00558 static int scaled_x[8]; 00559 static int scaled_y[8]; 00560 Coord polygon_x[9]; 00561 Coord polygon_y[9]; 00562 int i; 00563 00564 if (Thickness != special_size) 00565 { 00566 special_size = Thickness; 00567 for (i = 0; i < 8; i++) 00568 { 00569 scaled_x[i] = p[i].X * special_size; 00570 scaled_y[i] = p[i].Y * special_size; 00571 } 00572 } 00573 /* add line offset */ 00574 for (i = 0; i < 8; i++) 00575 { 00576 polygon_x[i] = X + scaled_x[i]; 00577 polygon_y[i] = Y + scaled_y[i]; 00578 } 00579 00580 if (thin_draw) 00581 { 00582 int i; 00583 gui->graphics->set_line_cap (gc, Round_Cap); 00584 gui->graphics->set_line_width (gc, 0); 00585 polygon_x[8] = X + scaled_x[0]; 00586 polygon_y[8] = Y + scaled_y[0]; 00587 for (i = 0; i < 8; i++) 00588 gui->graphics->draw_line (gc, polygon_x[i ], polygon_y[i ], 00589 polygon_x[i + 1], polygon_y[i + 1]); 00590 } 00591 else 00592 gui->graphics->fill_polygon (gc, 8, polygon_x, polygon_y); 00593 } 00594 00595 void 00596 common_fill_pcb_pv (hidGC fg_gc, hidGC bg_gc, PinType *pv, bool drawHole, bool mask) 00597 { 00598 Coord w = mask ? pv->Mask : pv->Thickness; 00599 Coord r = w / 2; 00600 00601 if (TEST_FLAG (HOLEFLAG, pv)) 00602 { 00603 if (mask) 00604 gui->graphics->fill_circle (bg_gc, pv->X, pv->Y, r); 00605 if (drawHole) 00606 { 00607 gui->graphics->fill_circle (bg_gc, pv->X, pv->Y, r); 00608 gui->graphics->set_line_cap (fg_gc, Round_Cap); 00609 gui->graphics->set_line_width (fg_gc, 0); 00610 gui->graphics->draw_arc (fg_gc, pv->X, pv->Y, r, r, 0, 360); 00611 } 00612 return; 00613 } 00614 00615 if (TEST_FLAG (SQUAREFLAG, pv)) 00616 { 00617 Coord l = pv->X - r; 00618 Coord b = pv->Y - r; 00619 Coord r = l + w; 00620 Coord t = b + w; 00621 00622 gui->graphics->fill_rect (fg_gc, l, b, r, t); 00623 } 00624 else if (TEST_FLAG (OCTAGONFLAG, pv)) 00625 draw_octagon_poly (fg_gc, pv->X, pv->Y, w, false); 00626 else /* draw a round pin or via */ 00627 gui->graphics->fill_circle (fg_gc, pv->X, pv->Y, r); 00628 00629 /* and the drilling hole (which is always round) */ 00630 if (drawHole) 00631 gui->graphics->fill_circle (bg_gc, pv->X, pv->Y, pv->DrillingHole / 2); 00632 } 00633 00634 void 00635 common_thindraw_pcb_pv (hidGC fg_gc, hidGC bg_gc, PinType *pv, bool drawHole, bool mask) 00636 { 00637 Coord w = mask ? pv->Mask : pv->Thickness; 00638 Coord r = w / 2; 00639 00640 if (TEST_FLAG (HOLEFLAG, pv)) 00641 { 00642 if (mask) 00643 gui->graphics->draw_arc (fg_gc, pv->X, pv->Y, r, r, 0, 360); 00644 if (drawHole) 00645 { 00646 r = pv->DrillingHole / 2; 00647 gui->graphics->set_line_cap (bg_gc, Round_Cap); 00648 gui->graphics->set_line_width (bg_gc, 0); 00649 gui->graphics->draw_arc (bg_gc, pv->X, pv->Y, r, r, 0, 360); 00650 } 00651 return; 00652 } 00653 00654 if (TEST_FLAG (SQUAREFLAG, pv)) 00655 { 00656 Coord l = pv->X - r; 00657 Coord b = pv->Y - r; 00658 Coord r = l + w; 00659 Coord t = b + w; 00660 00661 gui->graphics->set_line_cap (fg_gc, Round_Cap); 00662 gui->graphics->set_line_width (fg_gc, 0); 00663 gui->graphics->draw_line (fg_gc, r, t, r, b); 00664 gui->graphics->draw_line (fg_gc, l, t, l, b); 00665 gui->graphics->draw_line (fg_gc, r, t, l, t); 00666 gui->graphics->draw_line (fg_gc, r, b, l, b); 00667 00668 } 00669 else if (TEST_FLAG (OCTAGONFLAG, pv)) 00670 { 00671 draw_octagon_poly (fg_gc, pv->X, pv->Y, w, true); 00672 } 00673 else /* draw a round pin or via */ 00674 { 00675 gui->graphics->set_line_cap (fg_gc, Round_Cap); 00676 gui->graphics->set_line_width (fg_gc, 0); 00677 gui->graphics->draw_arc (fg_gc, pv->X, pv->Y, r, r, 0, 360); 00678 } 00679 00680 /* and the drilling hole (which is always round */ 00681 if (drawHole) 00682 { 00683 gui->graphics->set_line_cap (bg_gc, Round_Cap); 00684 gui->graphics->set_line_width (bg_gc, 0); 00685 gui->graphics->draw_arc (bg_gc, pv->X, pv->Y, pv->DrillingHole / 2, 00686 pv->DrillingHole / 2, 0, 360); 00687 } 00688 } 00689 00690 void 00691 common_draw_helpers_init (HID_DRAW *graphics) 00692 { 00693 graphics->draw_pcb_line = common_draw_pcb_line; 00694 graphics->draw_pcb_arc = common_draw_pcb_arc; 00695 graphics->draw_pcb_text = common_draw_pcb_text; 00696 graphics->draw_pcb_polygon = common_fill_pcb_polygon; /* Default is the non-GUI case */ 00697 00698 graphics->fill_pcb_polygon = common_fill_pcb_polygon; 00699 graphics->thindraw_pcb_polygon = common_thindraw_pcb_polygon; 00700 graphics->fill_pcb_pad = common_fill_pcb_pad; 00701 graphics->thindraw_pcb_pad = common_thindraw_pcb_pad; 00702 graphics->fill_pcb_pv = common_fill_pcb_pv; 00703 graphics->thindraw_pcb_pv = common_thindraw_pcb_pv; 00704 }