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 <assert.h> 00038 #include <memory.h> 00039 #include <setjmp.h> 00040 #include <stdlib.h> 00041 00042 #include "global.h" 00043 00044 #include "create.h" 00045 #include "data.h" 00046 #include "draw.h" 00047 #include "error.h" 00048 #include "mymem.h" 00049 #include "misc.h" 00050 #include "parse_l.h" 00051 #include "pcb-printf.h" 00052 #include "polygon.h" 00053 #include "rtree.h" 00054 #include "search.h" 00055 #include "set.h" 00056 #include "undo.h" 00057 #include "vendor.h" 00058 00059 #ifdef HAVE_LIBDMALLOC 00060 #include <dmalloc.h> 00061 #endif 00062 00063 /* --------------------------------------------------------------------------- 00064 * some local identifiers 00065 */ 00066 static long int ID = 1; 00069 static bool be_lenient = false; 00070 00071 /* ---------------------------------------------------------------------- 00072 * some local prototypes 00073 */ 00074 static void AddTextToElement (TextType *, FontType *, 00075 Coord, Coord, unsigned, char *, int, 00076 FlagType); 00077 00085 void 00086 CreateBeLenient (bool v) 00087 { 00088 be_lenient = v; 00089 } 00090 00094 DataType * 00095 CreateNewBuffer (void) 00096 { 00097 DataType *data; 00098 data = (DataType *) calloc (1, sizeof (DataType)); 00099 data->pcb = (PCBType *) PCB; 00100 return data; 00101 } 00102 00109 void 00110 pcb_colors_from_settings (PCBType *ptr) 00111 { 00112 int i; 00113 00114 /* copy default settings */ 00115 ptr->ConnectedColor = Settings.ConnectedColor; 00116 ptr->FoundColor = Settings.FoundColor; 00117 ptr->ElementColor = Settings.ElementColor; 00118 ptr->RatColor = Settings.RatColor; 00119 ptr->InvisibleObjectsColor = Settings.InvisibleObjectsColor; 00120 ptr->InvisibleMarkColor = Settings.InvisibleMarkColor; 00121 ptr->ElementSelectedColor = Settings.ElementSelectedColor; 00122 ptr->RatSelectedColor = Settings.RatSelectedColor; 00123 ptr->PinColor = Settings.PinColor; 00124 ptr->PinSelectedColor = Settings.PinSelectedColor; 00125 ptr->PinNameColor = Settings.PinNameColor; 00126 ptr->ViaColor = Settings.ViaColor; 00127 ptr->ViaSelectedColor = Settings.ViaSelectedColor; 00128 ptr->WarnColor = Settings.WarnColor; 00129 ptr->MaskColor = Settings.MaskColor; 00130 for (i = 0; i < MAX_LAYER; i++) 00131 { 00132 ptr->Data->Layer[i].Color = Settings.LayerColor[i]; 00133 ptr->Data->Layer[i].SelectedColor = Settings.LayerSelectedColor[i]; 00134 } 00135 ptr->Data->Layer[top_silk_layer].Color = 00136 Settings.ShowBottomSide ? 00137 Settings.InvisibleObjectsColor : Settings.ElementColor; 00138 ptr->Data->Layer[top_silk_layer].SelectedColor = 00139 Settings.ElementSelectedColor; 00140 ptr->Data->Layer[bottom_silk_layer].Color = 00141 Settings.ShowBottomSide ? 00142 Settings.ElementColor : Settings.InvisibleObjectsColor; 00143 ptr->Data->Layer[bottom_silk_layer].SelectedColor = 00144 Settings.ElementSelectedColor; 00145 } 00146 00150 PCBType * 00151 CreateNewPCB (void) 00152 { 00153 PCBType *ptr; 00154 int i; 00155 00156 /* allocate memory, switch all layers on and copy resources */ 00157 ptr = (PCBType *)calloc (1, sizeof (PCBType)); 00158 ptr->Data = CreateNewBuffer (); 00159 ptr->Data->pcb = (PCBType *) ptr; 00160 ptr->Data->polyClip = 1; 00161 00162 ptr->ThermStyle = 4; 00163 ptr->IsleArea = 2.e8; 00164 ptr->SilkActive = false; 00165 ptr->RatDraw = false; 00166 SET_FLAG (NAMEONPCBFLAG, ptr); 00167 if (Settings.ShowNumber) 00168 SET_FLAG (SHOWNUMBERFLAG, ptr); 00169 if (Settings.AllDirectionLines) 00170 SET_FLAG (ALLDIRECTIONFLAG, ptr); 00171 ptr->Clipping = 1; /* this is the most useful starting point for now */ 00172 if (Settings.RubberBandMode) 00173 SET_FLAG (RUBBERBANDFLAG, ptr); 00174 if (Settings.SwapStartDirection) 00175 SET_FLAG (SWAPSTARTDIRFLAG, ptr); 00176 if (Settings.UniqueNames) 00177 SET_FLAG (UNIQUENAMEFLAG, ptr); 00178 if (Settings.SnapPin) 00179 SET_FLAG (SNAPPINFLAG, ptr); 00180 if (Settings.ClearLine) 00181 SET_FLAG (CLEARNEWFLAG, ptr); 00182 if (Settings.FullPoly) 00183 SET_FLAG (NEWFULLPOLYFLAG, ptr); 00184 if (Settings.OrthogonalMoves) 00185 SET_FLAG (ORTHOMOVEFLAG, ptr); 00186 if (Settings.liveRouting) 00187 SET_FLAG (LIVEROUTEFLAG, ptr); 00188 if (Settings.ShowDRC) 00189 SET_FLAG (SHOWDRCFLAG, ptr); 00190 if (Settings.AutoDRC) 00191 SET_FLAG (AUTODRCFLAG, ptr); 00192 if (Settings.AutoBuriedVias) 00193 SET_FLAG (AUTOBURIEDVIASFLAG, ptr); 00194 ptr->Grid = Settings.Grid; 00195 ptr->LayerGroups = Settings.LayerGroups; 00196 STYLE_LOOP (ptr); 00197 { 00198 *style = Settings.RouteStyle[n]; 00199 style->index = n; 00200 } 00201 END_LOOP; 00202 ptr->MaxWidth = Settings.MaxWidth; 00203 ptr->MaxHeight = Settings.MaxHeight; 00204 ptr->ID = ID++; 00205 ptr->ThermScale = 0.5; 00206 00207 ptr->Bloat = Settings.Bloat; 00208 ptr->Shrink = Settings.Shrink; 00209 ptr->minWid = Settings.minWid; 00210 ptr->minSlk = Settings.minSlk; 00211 ptr->minDrill = Settings.minDrill; 00212 ptr->minRing = Settings.minRing; 00213 00214 for (i = 0; i < MAX_LAYER; i++) 00215 ptr->Data->Layer[i].Name = strdup (Settings.DefaultLayerName[i]); 00216 00217 CreateDefaultFont (ptr); 00218 00219 return (ptr); 00220 } 00221 00230 int 00231 CreateNewPCBPost (PCBType *pcb, int use_defaults) 00232 { 00233 /* copy default settings */ 00234 pcb_colors_from_settings (pcb); 00235 00236 if (use_defaults) 00237 { 00238 if (ParseGroupString (Settings.Groups, &pcb->LayerGroups, &pcb->Data->LayerN)) 00239 return 1; 00240 } 00241 00242 pcb->Data->Layer[top_silk_layer].Name = strdup ("top silk"); 00243 pcb->Data->Layer[top_silk_layer].Type = LT_SILK; 00244 pcb->Data->Layer[bottom_silk_layer].Name = strdup ("bottom silk"); 00245 pcb->Data->Layer[bottom_silk_layer].Type = LT_SILK; 00246 00247 return 0; 00248 } 00249 00253 PinType * 00254 CreateNewVia (DataType *Data, 00255 Coord X, Coord Y, 00256 Coord Thickness, Coord Clearance, Coord Mask, 00257 Coord DrillingHole, char *Name, FlagType Flags) 00258 { 00259 PinType *Via; 00260 00261 if (!be_lenient) 00262 { 00263 VIA_LOOP (Data); 00264 { 00265 if (Distance (X, Y, via->X, via->Y) <= 00266 via->DrillingHole / 2 + DrillingHole / 2) 00267 { 00268 Message (_("%m+Dropping via at %$mD because it's hole would overlap with the via " 00269 "at %$mD\n"), Settings.grid_unit->allow, X, Y, via->X, via->Y); 00270 return (NULL); /* don't allow via stacking */ 00271 } 00272 } 00273 END_LOOP; 00274 } 00275 00276 Via = GetViaMemory (Data); 00277 00278 if (!Via) 00279 return (Via); 00280 /* copy values */ 00281 Via->X = X; 00282 Via->Y = Y; 00283 Via->Thickness = Thickness; 00284 Via->Clearance = Clearance; 00285 Via->Mask = Mask; 00286 Via->DrillingHole = vendorDrillMap (DrillingHole); 00287 if (Via->DrillingHole != DrillingHole) 00288 { 00289 Message (_("%m+Mapped via drill hole to %$mS from %$mS per vendor table\n"), 00290 Settings.grid_unit->allow, Via->DrillingHole, DrillingHole); 00291 } 00292 00293 Via->Name = STRDUP (Name); 00294 Via->Flags = Flags; 00295 Via->BuriedFrom = 0; 00296 Via->BuriedTo = 0; 00297 CLEAR_FLAG (WARNFLAG, Via); 00298 SET_FLAG (VIAFLAG, Via); 00299 Via->ID = ID++; 00300 00301 /* 00302 * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure 00303 * hole) 00304 */ 00305 if (!TEST_FLAG (HOLEFLAG, Via) && 00306 (Via->Thickness < Via->DrillingHole + MIN_PINORVIACOPPER)) 00307 { 00308 Via->Thickness = Via->DrillingHole + MIN_PINORVIACOPPER; 00309 Message (_("%m+Increased via thickness to %$mS to allow enough copper" 00310 " at %$mD.\n"), 00311 Settings.grid_unit->allow, Via->Thickness, Via->X, Via->Y); 00312 } 00313 00314 SetPinBoundingBox (Via); 00315 if (!Data->via_tree) 00316 Data->via_tree = r_create_tree (NULL, 0, 0); 00317 r_insert_entry (Data->via_tree, (BoxType *) Via, 0); 00318 return (Via); 00319 } 00320 00324 PinType * 00325 CreateNewViaEx (DataType *Data, 00326 Coord X, Coord Y, 00327 Coord Thickness, Coord Clearance, Coord Mask, 00328 Coord DrillingHole, char *Name, FlagType Flags, 00329 Cardinal buried_from, Cardinal buried_to) 00330 { 00331 PinType *Via; 00332 00333 Via = CreateNewVia (Data, X, Y, Thickness, Clearance, Mask, 00334 DrillingHole, Name, Flags); 00335 if (Via) 00336 { 00337 if (buried_from == buried_to) 00338 { 00339 Via->BuriedFrom = 0; 00340 Via->BuriedTo = 0; 00341 } 00342 else if (buried_from <= buried_to) 00343 { 00344 Via->BuriedFrom = buried_from; 00345 Via->BuriedTo = buried_to; 00346 } 00347 else 00348 { 00349 Via->BuriedFrom = buried_to; 00350 Via->BuriedTo = buried_from; 00351 } 00352 } 00353 return Via; 00354 } 00355 00356 00357 struct line_info 00358 { 00359 Coord X1, X2, Y1, Y2; 00360 Coord Thickness; 00361 Coord Clearance; 00362 FlagType Flags; 00363 LineType test, *ans; 00364 jmp_buf env; 00365 }; 00366 00367 static int 00368 line_callback (const BoxType * b, void *cl) 00369 { 00370 LineType *line = (LineType *) b; 00371 struct line_info *i = (struct line_info *) cl; 00372 00373 if (line->Point1.X == i->X1 && 00374 line->Point2.X == i->X2 && 00375 line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2) 00376 { 00377 i->ans = (LineType *) (-1); 00378 longjmp (i->env, 1); 00379 } 00380 /* check the other point order */ 00381 if (line->Point1.X == i->X1 && 00382 line->Point2.X == i->X2 && 00383 line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2) 00384 { 00385 i->ans = (LineType *) (-1); 00386 longjmp (i->env, 1); 00387 } 00388 if (line->Point2.X == i->X1 && 00389 line->Point1.X == i->X2 && 00390 line->Point2.Y == i->Y1 && line->Point1.Y == i->Y2) 00391 { 00392 i->ans = (LineType *) - 1; 00393 longjmp (i->env, 1); 00394 } 00395 /* remove unnecessary line points */ 00396 if (line->Thickness == i->Thickness && 00397 /* don't merge lines if the clearances differ */ 00398 line->Clearance == i->Clearance && 00399 /* don't merge lines if the clear flags differ */ 00400 TEST_FLAG (CLEARLINEFLAG, line) == TEST_FLAG (CLEARLINEFLAG, i)) 00401 { 00402 if (line->Point1.X == i->X1 && line->Point1.Y == i->Y1) 00403 { 00404 i->test.Point1.X = line->Point2.X; 00405 i->test.Point1.Y = line->Point2.Y; 00406 i->test.Point2.X = i->X2; 00407 i->test.Point2.Y = i->Y2; 00408 if (IsPointOnLine (i->X1, i->Y1, 0.0, &i->test)) 00409 { 00410 i->ans = line; 00411 longjmp (i->env, 1); 00412 } 00413 } 00414 else if (line->Point2.X == i->X1 && line->Point2.Y == i->Y1) 00415 { 00416 i->test.Point1.X = line->Point1.X; 00417 i->test.Point1.Y = line->Point1.Y; 00418 i->test.Point2.X = i->X2; 00419 i->test.Point2.Y = i->Y2; 00420 if (IsPointOnLine (i->X1, i->Y1, 0.0, &i->test)) 00421 { 00422 i->ans = line; 00423 longjmp (i->env, 1); 00424 } 00425 } 00426 else if (line->Point1.X == i->X2 && line->Point1.Y == i->Y2) 00427 { 00428 i->test.Point1.X = line->Point2.X; 00429 i->test.Point1.Y = line->Point2.Y; 00430 i->test.Point2.X = i->X1; 00431 i->test.Point2.Y = i->Y1; 00432 if (IsPointOnLine (i->X2, i->Y2, 0.0, &i->test)) 00433 { 00434 i->ans = line; 00435 longjmp (i->env, 1); 00436 } 00437 } 00438 else if (line->Point2.X == i->X2 && line->Point2.Y == i->Y2) 00439 { 00440 i->test.Point1.X = line->Point1.X; 00441 i->test.Point1.Y = line->Point1.Y; 00442 i->test.Point2.X = i->X1; 00443 i->test.Point2.Y = i->Y1; 00444 if (IsPointOnLine (i->X2, i->Y2, 0.0, &i->test)) 00445 { 00446 i->ans = line; 00447 longjmp (i->env, 1); 00448 } 00449 } 00450 } 00451 return 0; 00452 } 00453 00454 00459 LineType * 00460 CreateDrawnLineOnLayer (LayerType *Layer, 00461 Coord X1, Coord Y1, 00462 Coord X2, Coord Y2, 00463 Coord Thickness, Coord Clearance, 00464 FlagType Flags) 00465 { 00466 struct line_info info; 00467 BoxType search; 00468 00469 search.X1 = MIN (X1, X2); 00470 search.X2 = MAX (X1, X2); 00471 search.Y1 = MIN (Y1, Y2); 00472 search.Y2 = MAX (Y1, Y2); 00473 if (search.Y2 == search.Y1) 00474 search.Y2++; 00475 if (search.X2 == search.X1) 00476 search.X2++; 00477 info.X1 = X1; 00478 info.X2 = X2; 00479 info.Y1 = Y1; 00480 info.Y2 = Y2; 00481 info.Thickness = Thickness; 00482 info.Clearance = Clearance; 00483 info.Flags = Flags; 00484 info.test.Thickness = 0; 00485 info.test.Flags = NoFlags (); 00486 info.ans = NULL; 00487 /* prevent stacking of duplicate lines 00488 * and remove needless intermediate points 00489 * verify that the layer is on the board first! 00490 */ 00491 if (setjmp (info.env) == 0) 00492 { 00493 r_search (Layer->line_tree, &search, NULL, line_callback, &info); 00494 return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2, 00495 Thickness, Clearance, Flags); 00496 } 00497 00498 if ((void *) info.ans == (void *) (-1)) 00499 return NULL; /* stacked line */ 00500 /* remove unnecessary points */ 00501 if (info.ans) 00502 { 00503 /* must do this BEFORE getting new line memory */ 00504 MoveObjectToRemoveUndoList (LINE_TYPE, Layer, info.ans, info.ans); 00505 X1 = info.test.Point1.X; 00506 X2 = info.test.Point2.X; 00507 Y1 = info.test.Point1.Y; 00508 Y2 = info.test.Point2.Y; 00509 } 00510 return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2, 00511 Thickness, Clearance, Flags); 00512 } 00513 00514 LineType * 00515 CreateNewLineOnLayer (LayerType *Layer, 00516 Coord X1, Coord Y1, 00517 Coord X2, Coord Y2, 00518 Coord Thickness, Coord Clearance, 00519 FlagType Flags) 00520 { 00521 LineType *Line; 00522 00523 Line = GetLineMemory (Layer); 00524 if (!Line) 00525 return (Line); 00526 Line->ID = ID++; 00527 Line->Flags = Flags; 00528 CLEAR_FLAG (RATFLAG, Line); 00529 Line->Thickness = Thickness; 00530 Line->Clearance = Clearance; 00531 Line->Point1.X = X1; 00532 Line->Point1.Y = Y1; 00533 Line->Point1.ID = ID++; 00534 Line->Point2.X = X2; 00535 Line->Point2.Y = Y2; 00536 Line->Point2.ID = ID++; 00537 SetLineBoundingBox (Line); 00538 if (!Layer->line_tree) 00539 Layer->line_tree = r_create_tree (NULL, 0, 0); 00540 r_insert_entry (Layer->line_tree, (BoxType *) Line, 0); 00541 return (Line); 00542 } 00543 00547 RatType * 00548 CreateNewRat (DataType *Data, Coord X1, Coord Y1, 00549 Coord X2, Coord Y2, Cardinal group1, 00550 Cardinal group2, Coord Thickness, FlagType Flags) 00551 { 00552 RatType *Line = GetRatMemory (Data); 00553 00554 if (!Line) 00555 return (Line); 00556 00557 Line->ID = ID++; 00558 Line->Flags = Flags; 00559 SET_FLAG (RATFLAG, Line); 00560 Line->Thickness = Thickness; 00561 Line->Point1.X = X1; 00562 Line->Point1.Y = Y1; 00563 Line->Point1.ID = ID++; 00564 Line->Point2.X = X2; 00565 Line->Point2.Y = Y2; 00566 Line->Point2.ID = ID++; 00567 Line->group1 = group1; 00568 Line->group2 = group2; 00569 SetLineBoundingBox ((LineType *) Line); 00570 if (!Data->rat_tree) 00571 Data->rat_tree = r_create_tree (NULL, 0, 0); 00572 r_insert_entry (Data->rat_tree, &Line->BoundingBox, 0); 00573 return (Line); 00574 } 00575 00579 ArcType * 00580 CreateNewArcOnLayer (LayerType *Layer, 00581 Coord X1, Coord Y1, 00582 Coord width, 00583 Coord height, 00584 Angle sa, 00585 Angle dir, Coord Thickness, 00586 Coord Clearance, FlagType Flags) 00587 { 00588 ArcType *Arc; 00589 00590 ARC_LOOP (Layer); 00591 { 00592 if (arc->X == X1 && arc->Y == Y1 && arc->Width == width && 00593 NormalizeAngle (arc->StartAngle) == NormalizeAngle (sa) && 00594 arc->Delta == dir) 00595 return (NULL); /* prevent stacked arcs */ 00596 } 00597 END_LOOP; 00598 Arc = GetArcMemory (Layer); 00599 if (!Arc) 00600 return (Arc); 00601 00602 Arc->ID = ID++; 00603 Arc->Flags = Flags; 00604 Arc->Thickness = Thickness; 00605 Arc->Clearance = Clearance; 00606 Arc->X = X1; 00607 Arc->Y = Y1; 00608 Arc->Width = width; 00609 Arc->Height = height; 00610 Arc->StartAngle = sa; 00611 Arc->Delta = dir; 00612 SetArcBoundingBox (Arc); 00613 if (!Layer->arc_tree) 00614 Layer->arc_tree = r_create_tree (NULL, 0, 0); 00615 r_insert_entry (Layer->arc_tree, (BoxType *) Arc, 0); 00616 return (Arc); 00617 } 00618 00619 00623 PolygonType * 00624 CreateNewPolygonFromRectangle (LayerType *Layer, 00625 Coord X1, Coord Y1, 00626 Coord X2, Coord Y2, 00627 FlagType Flags) 00628 { 00629 PolygonType *polygon = CreateNewPolygon (Layer, Flags); 00630 if (!polygon) 00631 return (polygon); 00632 00633 CreateNewPointInPolygon (polygon, X1, Y1); 00634 CreateNewPointInPolygon (polygon, X2, Y1); 00635 CreateNewPointInPolygon (polygon, X2, Y2); 00636 CreateNewPointInPolygon (polygon, X1, Y2); 00637 SetPolygonBoundingBox (polygon); 00638 if (!Layer->polygon_tree) 00639 Layer->polygon_tree = r_create_tree (NULL, 0, 0); 00640 r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0); 00641 return (polygon); 00642 } 00643 00647 TextType * 00648 CreateNewText (LayerType *Layer, FontType *PCBFont, 00649 Coord X, Coord Y, 00650 unsigned Direction, int Scale, char *TextString, FlagType Flags) 00651 { 00652 TextType *text; 00653 00654 if (TextString == NULL) 00655 return NULL; 00656 00657 text = GetTextMemory (Layer); 00658 if (text == NULL) 00659 return NULL; 00660 00661 /* copy values, width and height are set by drawing routine 00662 * because at this point we don't know which symbols are available 00663 */ 00664 text->X = X; 00665 text->Y = Y; 00666 text->Direction = Direction; 00667 text->Flags = Flags; 00668 text->Scale = Scale; 00669 text->TextString = strdup (TextString); 00670 00671 /* calculate size of the bounding box */ 00672 SetTextBoundingBox (PCBFont, text); 00673 text->ID = ID++; 00674 if (!Layer->text_tree) 00675 Layer->text_tree = r_create_tree (NULL, 0, 0); 00676 r_insert_entry (Layer->text_tree, (BoxType *) text, 0); 00677 return (text); 00678 } 00679 00683 PolygonType * 00684 CreateNewPolygon (LayerType *Layer, FlagType Flags) 00685 { 00686 PolygonType *polygon = GetPolygonMemory (Layer); 00687 00688 /* copy values */ 00689 polygon->Flags = Flags; 00690 polygon->ID = ID++; 00691 polygon->Clipped = NULL; 00692 polygon->NoHoles = NULL; 00693 polygon->NoHolesValid = 0; 00694 return (polygon); 00695 } 00696 00700 PointType * 00701 CreateNewPointInPolygon (PolygonType *Polygon, Coord X, Coord Y) 00702 { 00703 PointType *point = GetPointMemoryInPolygon (Polygon); 00704 00705 /* copy values */ 00706 point->X = X; 00707 point->Y = Y; 00708 point->ID = ID++; 00709 return (point); 00710 } 00711 00715 PolygonType * 00716 CreateNewHoleInPolygon (PolygonType *Polygon) 00717 { 00718 Cardinal *holeindex = GetHoleIndexMemoryInPolygon (Polygon); 00719 *holeindex = Polygon->PointN; 00720 return Polygon; 00721 } 00722 00728 ElementType * 00729 CreateNewElement (DataType *Data, FontType *PCBFont, FlagType Flags, 00730 char *Description, char *NameOnPCB, char *Value, 00731 Coord TextX, Coord TextY, BYTE Direction, 00732 int TextScale, FlagType TextFlags, bool uniqueName) 00733 { 00734 ElementType *Element; 00735 00736 #ifdef DEBUG 00737 printf("Entered CreateNewElement.....\n"); 00738 #endif 00739 00740 Element = GetElementMemory (Data); 00741 00742 /* copy values and set additional information */ 00743 TextScale = MAX (MIN_TEXTSCALE, TextScale); 00744 AddTextToElement (&DESCRIPTION_TEXT (Element), PCBFont, TextX, TextY, 00745 Direction, Description, TextScale, TextFlags); 00746 if (uniqueName) 00747 NameOnPCB = UniqueElementName (Data, NameOnPCB); 00748 AddTextToElement (&NAMEONPCB_TEXT (Element), PCBFont, TextX, TextY, 00749 Direction, NameOnPCB, TextScale, TextFlags); 00750 AddTextToElement (&VALUE_TEXT (Element), PCBFont, TextX, TextY, 00751 Direction, Value, TextScale, TextFlags); 00752 DESCRIPTION_TEXT (Element).Element = Element; 00753 NAMEONPCB_TEXT (Element).Element = Element; 00754 VALUE_TEXT (Element).Element = Element; 00755 Element->Flags = Flags; 00756 Element->ID = ID++; 00757 00758 #ifdef DEBUG 00759 printf(" .... Leaving CreateNewElement.\n"); 00760 #endif 00761 00762 return (Element); 00763 } 00764 00768 ArcType * 00769 CreateNewArcInElement (ElementType *Element, 00770 Coord X, Coord Y, 00771 Coord Width, Coord Height, 00772 Angle angle, Angle delta, Coord Thickness) 00773 { 00774 ArcType *arc; 00775 00776 arc = g_slice_new0 (ArcType); 00777 Element->Arc = g_list_append (Element->Arc, arc); 00778 Element->ArcN ++; 00779 00780 /* set Delta (0,360], StartAngle in [0,360) */ 00781 if (delta < 0) 00782 { 00783 delta = -delta; 00784 angle -= delta; 00785 } 00786 angle = NormalizeAngle (angle); 00787 delta = NormalizeAngle (delta); 00788 if (delta == 0) 00789 delta = 360; 00790 00791 /* copy values */ 00792 arc->X = X; 00793 arc->Y = Y; 00794 arc->Width = Width; 00795 arc->Height = Height; 00796 arc->StartAngle = angle; 00797 arc->Delta = delta; 00798 arc->Thickness = Thickness; 00799 arc->ID = ID++; 00800 return arc; 00801 } 00802 00806 LineType * 00807 CreateNewLineInElement (ElementType *Element, 00808 Coord X1, Coord Y1, 00809 Coord X2, Coord Y2, 00810 Coord Thickness) 00811 { 00812 LineType *line; 00813 00814 if (Thickness == 0) 00815 return NULL; 00816 00817 line = g_slice_new0 (LineType); 00818 Element->Line = g_list_append (Element->Line, line); 00819 Element->LineN ++; 00820 00821 /* copy values */ 00822 line->Point1.X = X1; 00823 line->Point1.Y = Y1; 00824 line->Point2.X = X2; 00825 line->Point2.Y = Y2; 00826 line->Thickness = Thickness; 00827 line->Flags = NoFlags (); 00828 line->ID = ID++; 00829 return line; 00830 } 00831 00835 PinType * 00836 CreateNewPin (ElementType *Element, 00837 Coord X, Coord Y, 00838 Coord Thickness, Coord Clearance, Coord Mask, 00839 Coord DrillingHole, char *Name, char *Number, 00840 FlagType Flags) 00841 { 00842 PinType *pin = GetPinMemory (Element); 00843 00844 /* copy values */ 00845 pin->X = X; 00846 pin->Y = Y; 00847 pin->Thickness = Thickness; 00848 pin->Clearance = Clearance; 00849 pin->Mask = Mask; 00850 pin->Name = STRDUP (Name); 00851 pin->Number = STRDUP (Number); 00852 pin->Flags = Flags; 00853 CLEAR_FLAG (WARNFLAG, pin); 00854 SET_FLAG (PINFLAG, pin); 00855 pin->ID = ID++; 00856 pin->Element = Element; 00857 00858 /* 00859 * If there is no vendor drill map installed, this will simply 00860 * return DrillingHole. 00861 */ 00862 pin->DrillingHole = vendorDrillMap (DrillingHole); 00863 00864 /* Unless we should not map drills on this element, map them! */ 00865 if (vendorIsElementMappable (Element)) 00866 { 00867 if (pin->DrillingHole < MIN_PINORVIASIZE) 00868 { 00869 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is below the minimum allowed size\n"), 00870 Settings.grid_unit->allow, UNKNOWN (Number), UNKNOWN (Name), pin->DrillingHole); 00871 pin->DrillingHole = DrillingHole; 00872 } 00873 else if (pin->DrillingHole > MAX_PINORVIASIZE) 00874 { 00875 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is above the maximum allowed size\n"), 00876 Settings.grid_unit->allow, UNKNOWN (Number), UNKNOWN (Name), pin->DrillingHole); 00877 pin->DrillingHole = DrillingHole; 00878 } 00879 else if (!TEST_FLAG (HOLEFLAG, pin) 00880 && (pin->DrillingHole > pin->Thickness - MIN_PINORVIACOPPER)) 00881 { 00882 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS does not leave enough copper\n"), 00883 Settings.grid_unit->allow, UNKNOWN (Number), UNKNOWN (Name), pin->DrillingHole); 00884 pin->DrillingHole = DrillingHole; 00885 } 00886 } 00887 else 00888 { 00889 pin->DrillingHole = DrillingHole; 00890 } 00891 00892 if (pin->DrillingHole != DrillingHole) 00893 { 00894 Message (_("%m+Mapped pin drill hole to %$mS from %$mS per vendor table\n"), 00895 Settings.grid_unit->allow, pin->DrillingHole, DrillingHole); 00896 } 00897 00898 return (pin); 00899 } 00900 00904 PadType * 00905 CreateNewPad (ElementType *Element, 00906 Coord X1, Coord Y1, Coord X2, 00907 Coord Y2, Coord Thickness, Coord Clearance, 00908 Coord Mask, char *Name, char *Number, FlagType Flags) 00909 { 00910 PadType *pad = GetPadMemory (Element); 00911 00912 /* copy values */ 00913 if (X1 > X2 || (X1 == X2 && Y1 > Y2)) 00914 { 00915 pad->Point1.X = X2; 00916 pad->Point1.Y = Y2; 00917 pad->Point2.X = X1; 00918 pad->Point2.Y = Y1; 00919 } 00920 else 00921 { 00922 pad->Point1.X = X1; 00923 pad->Point1.Y = Y1; 00924 pad->Point2.X = X2; 00925 pad->Point2.Y = Y2; 00926 } 00927 pad->Thickness = Thickness; 00928 pad->Clearance = Clearance; 00929 pad->Mask = Mask; 00930 pad->Name = STRDUP (Name); 00931 pad->Number = STRDUP (Number); 00932 pad->Flags = Flags; 00933 CLEAR_FLAG (WARNFLAG, pad); 00934 pad->ID = ID++; 00935 pad->Element = Element; 00936 return (pad); 00937 } 00938 00944 static void 00945 AddTextToElement (TextType *Text, FontType *PCBFont, 00946 Coord X, Coord Y, 00947 unsigned Direction, char *TextString, int Scale, FlagType Flags) 00948 { 00949 free (Text->TextString); 00950 Text->TextString = (TextString && *TextString) ? strdup (TextString) : NULL; 00951 Text->X = X; 00952 Text->Y = Y; 00953 Text->Direction = Direction; 00954 Text->Flags = Flags; 00955 Text->Scale = Scale; 00956 00957 /* calculate size of the bounding box */ 00958 SetTextBoundingBox (PCBFont, Text); 00959 Text->ID = ID++; 00960 } 00961 00965 LineType * 00966 CreateNewLineInSymbol (SymbolType *Symbol, 00967 Coord X1, Coord Y1, 00968 Coord X2, Coord Y2, Coord Thickness) 00969 { 00970 LineType *line = Symbol->Line; 00971 00972 /* realloc new memory if necessary and clear it */ 00973 if (Symbol->LineN >= Symbol->LineMax) 00974 { 00975 Symbol->LineMax += STEP_SYMBOLLINE; 00976 line = (LineType *)realloc (line, Symbol->LineMax * sizeof (LineType)); 00977 Symbol->Line = line; 00978 memset (line + Symbol->LineN, 0, STEP_SYMBOLLINE * sizeof (LineType)); 00979 } 00980 00981 /* copy values */ 00982 line = line + Symbol->LineN++; 00983 line->Point1.X = X1; 00984 line->Point1.Y = Y1; 00985 line->Point2.X = X2; 00986 line->Point2.Y = Y2; 00987 line->Thickness = Thickness; 00988 return (line); 00989 } 00990 00998 void 00999 CreateDefaultFont (PCBType *pcb) 01000 { 01001 if (ParseFont (&pcb->Font, Settings.FontFile)) 01002 Message (_("Can't find font-symbol-file '%s'\n"), Settings.FontFile); 01003 } 01004 01011 RubberbandType * 01012 CreateNewRubberbandEntry (LayerType *Layer, 01013 LineType *Line, PointType *MovedPoint) 01014 { 01015 RubberbandType *ptr = GetRubberbandMemory (); 01016 01017 /* we toggle the RUBBERENDFLAG of the line to determine if */ 01018 /* both points are being moved. */ 01019 TOGGLE_FLAG (RUBBERENDFLAG, Line); 01020 ptr->Layer = Layer; 01021 ptr->Line = Line; 01022 ptr->MovedPoint = MovedPoint; 01023 return (ptr); 01024 } 01025 01029 LibraryMenuType * 01030 CreateNewNet (LibraryType *lib, char *name, char *style) 01031 { 01032 LibraryMenuType *menu; 01033 char temp[64]; 01034 01035 sprintf (temp, " %s", name); 01036 menu = GetLibraryMenuMemory (lib); 01037 menu->Name = strdup (temp); 01038 menu->flag = 1; /* net is enabled by default */ 01039 if (style == NULL || NSTRCMP ("(unknown)", style) == 0) 01040 menu->Style = NULL; 01041 else 01042 menu->Style = strdup (style); 01043 return (menu); 01044 } 01045 01049 LibraryEntryType * 01050 CreateNewConnection (LibraryMenuType *net, char *conn) 01051 { 01052 LibraryEntryType *entry = GetLibraryEntryMemory (net); 01053 01054 entry->ListEntry = STRDUP (conn); 01055 return (entry); 01056 } 01057 01061 AttributeType * 01062 CreateNewAttribute (AttributeListType *list, char *name, char *value) 01063 { 01064 if (list->Number >= list->Max) 01065 { 01066 list->Max += 10; 01067 list->List = (AttributeType *)realloc (list->List, list->Max * sizeof (AttributeType)); 01068 } 01069 list->List[list->Number].name = STRDUP (name); 01070 list->List[list->Number].value = STRDUP (value); 01071 list->Number++; 01072 return &list->List[list->Number - 1]; 01073 }