hid/common: Clip no-holes polygon pieces before calling fill_contour
[geda-pcb/gde.git] / src / create.c
blob500d0a0b2d842729702dfdc891d869b29030d9aa
1 /* $Id$ */
3 /*
4 * COPYRIGHT
6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996, 2005 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
29 /* functions used to create vias, pins ...
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include <assert.h>
37 #include <memory.h>
38 #include <setjmp.h>
39 #include <stdlib.h>
41 #include "global.h"
43 #include "create.h"
44 #include "data.h"
45 #include "draw.h"
46 #include "error.h"
47 #include "mymem.h"
48 #include "misc.h"
49 #include "parse_l.h"
50 #include "polygon.h"
51 #include "rtree.h"
52 #include "search.h"
53 #include "set.h"
54 #include "undo.h"
55 #include "vendor.h"
57 #ifdef HAVE_LIBDMALLOC
58 #include <dmalloc.h>
59 #endif
61 RCSID ("$Id$");
63 /* ---------------------------------------------------------------------------
64 * some local identifiers
66 static int ID = 1; /* current object ID; incremented after */
67 /* each creation of an object */
69 /* ----------------------------------------------------------------------
70 * some local prototypes
72 static void AddTextToElement (TextTypePtr, FontTypePtr,
73 LocationType, LocationType, BYTE, char *, int,
74 FlagType);
76 /* ---------------------------------------------------------------------------
77 * creates a new paste buffer
79 DataTypePtr
80 CreateNewBuffer (void)
82 DataTypePtr data;
83 data = (DataTypePtr) MyCalloc (1, sizeof (DataType), "CreateNewBuffer()");
84 data->pcb = (void *) PCB;
85 return data;
88 /* ---------------------------------------------------------------------------
89 * Perhaps PCB should internally just use the Settings colors? For now,
90 * use this to set PCB colors so the config can reassign PCB colors.
92 void
93 pcb_colors_from_settings (PCBTypePtr ptr)
95 int i;
97 /* copy default settings */
98 ptr->ConnectedColor = Settings.ConnectedColor;
99 ptr->ElementColor = Settings.ElementColor;
100 ptr->RatColor = Settings.RatColor;
101 ptr->InvisibleObjectsColor = Settings.InvisibleObjectsColor;
102 ptr->InvisibleMarkColor = Settings.InvisibleMarkColor;
103 ptr->ElementSelectedColor = Settings.ElementSelectedColor;
104 ptr->RatSelectedColor = Settings.RatSelectedColor;
105 ptr->PinColor = Settings.PinColor;
106 ptr->PinSelectedColor = Settings.PinSelectedColor;
107 ptr->PinNameColor = Settings.PinNameColor;
108 ptr->ViaColor = Settings.ViaColor;
109 ptr->ViaSelectedColor = Settings.ViaSelectedColor;
110 ptr->WarnColor = Settings.WarnColor;
111 ptr->MaskColor = Settings.MaskColor;
112 for (i = 0; i < MAX_LAYER; i++)
114 ptr->Data->Layer[i].Color = Settings.LayerColor[i];
115 ptr->Data->Layer[i].SelectedColor = Settings.LayerSelectedColor[i];
117 ptr->Data->Layer[max_layer + COMPONENT_LAYER].Color =
118 Settings.ShowSolderSide ?
119 Settings.InvisibleObjectsColor : Settings.ElementColor;
120 ptr->Data->Layer[max_layer + COMPONENT_LAYER].SelectedColor =
121 Settings.ElementSelectedColor;
122 ptr->Data->Layer[max_layer + SOLDER_LAYER].Color =
123 Settings.ShowSolderSide ?
124 Settings.ElementColor : Settings.InvisibleObjectsColor;
125 ptr->Data->Layer[max_layer + SOLDER_LAYER].SelectedColor =
126 Settings.ElementSelectedColor;
129 /* ---------------------------------------------------------------------------
130 * creates a new PCB
132 PCBTypePtr
133 CreateNewPCB (Boolean SetDefaultNames)
135 PCBTypePtr ptr;
136 int i;
138 /* allocate memory, switch all layers on and copy resources */
139 ptr = MyCalloc (1, sizeof (PCBType), "CreateNewPCB()");
140 ptr->Data = CreateNewBuffer ();
141 ptr->Data->pcb = (void *) ptr;
143 ptr->ThermStyle = 4;
144 ptr->IsleArea = 2.e8;
145 ptr->SilkActive = False;
146 ptr->RatDraw = False;
147 SET_FLAG (NAMEONPCBFLAG, ptr);
148 if (Settings.ShowNumber)
149 SET_FLAG (SHOWNUMBERFLAG, ptr);
150 if (Settings.AllDirectionLines)
151 SET_FLAG (ALLDIRECTIONFLAG, ptr);
152 ptr->Clipping = 1; /* this is the most useful starting point for now */
153 if (Settings.RubberBandMode)
154 SET_FLAG (RUBBERBANDFLAG, ptr);
155 if (Settings.SwapStartDirection)
156 SET_FLAG (SWAPSTARTDIRFLAG, ptr);
157 if (Settings.UniqueNames)
158 SET_FLAG (UNIQUENAMEFLAG, ptr);
159 if (Settings.SnapPin)
160 SET_FLAG (SNAPPINFLAG, ptr);
161 if (Settings.ClearLine)
162 SET_FLAG (CLEARNEWFLAG, ptr);
163 if (Settings.FullPoly)
164 SET_FLAG (NEWFULLPOLYFLAG, ptr);
165 if (Settings.OrthogonalMoves)
166 SET_FLAG (ORTHOMOVEFLAG, ptr);
167 if (Settings.liveRouting)
168 SET_FLAG (LIVEROUTEFLAG, ptr);
169 if (Settings.ShowDRC)
170 SET_FLAG (SHOWDRCFLAG, ptr);
171 if (Settings.AutoDRC)
172 SET_FLAG (AUTODRCFLAG, ptr);
173 ptr->Grid = Settings.Grid;
174 ptr->LayerGroups = Settings.LayerGroups;
175 STYLE_LOOP (ptr);
177 *style = Settings.RouteStyle[n];
178 style->index = n;
180 END_LOOP;
181 hid_action ("RouteStylesChanged");
182 ptr->Zoom = Settings.Zoom;
183 ptr->MaxWidth = Settings.MaxWidth;
184 ptr->MaxHeight = Settings.MaxHeight;
185 ptr->ID = ID++;
186 ptr->ThermScale = 0.5;
188 ptr->Bloat = Settings.Bloat;
189 ptr->Shrink = Settings.Shrink;
190 ptr->minWid = Settings.minWid;
191 ptr->minSlk = Settings.minSlk;
192 ptr->minDrill = Settings.minDrill;
193 ptr->minRing = Settings.minRing;
195 for (i = 0; i < MAX_LAYER; i++)
196 ptr->Data->Layer[i].Name = MyStrdup (Settings.DefaultLayerName[i],
197 "CreateNewPCB()");
199 return (ptr);
203 CreateNewPCBPost (PCBTypePtr pcb, int use_defaults)
205 /* copy default settings */
206 pcb_colors_from_settings (pcb);
208 if (use_defaults)
210 if (ParseGroupString (Settings.Groups, &pcb->LayerGroups, DEF_LAYER))
211 return 1;
213 pcb->Data->Layer[max_layer + COMPONENT_LAYER].Name =
214 MyStrdup ("silk", "CreateNewPCB()");
215 pcb->Data->Layer[max_layer + SOLDER_LAYER].Name =
216 MyStrdup ("silk", "CreateNewPCB()");
218 return 0;
221 /* ---------------------------------------------------------------------------
222 * creates a new via
224 PinTypePtr
225 CreateNewVia (DataTypePtr Data,
226 LocationType X, LocationType Y,
227 BDimension Thickness, BDimension Clearance, BDimension Mask,
228 BDimension DrillingHole, char *Name, FlagType Flags)
230 PinTypePtr Via;
232 VIA_LOOP (Data);
234 if (SQUARE (via->X - X) + SQUARE (via->Y - Y) <=
235 SQUARE (via->Thickness / 2 + Thickness / 2))
237 Message ("Dropping via at (%d, %d) because it would overlap with the via"
238 "at (%d, %d)\n", X/100, Y/100, via->X/100, via->Y/100);
239 return (NULL); /* don't allow via stacking */
242 END_LOOP;
244 Via = GetViaMemory (Data);
246 if (!Via)
247 return (Via);
248 /* copy values */
249 Via->X = X;
250 Via->Y = Y;
251 Via->Thickness = Thickness;
252 Via->Clearance = Clearance;
253 Via->Mask = Mask;
254 Via->DrillingHole = vendorDrillMap (DrillingHole);
255 if (Via->DrillingHole != DrillingHole)
257 Message (_
258 ("Mapped via drill hole to %.2f mils from %.2f mils per vendor table\n"),
259 0.01 * Via->DrillingHole, 0.01 * DrillingHole);
262 Via->Name = MyStrdup (Name, "CreateNewVia()");
263 Via->Flags = Flags;
264 CLEAR_FLAG (WARNFLAG, Via);
265 SET_FLAG (VIAFLAG, Via);
266 Via->ID = ID++;
269 * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure
270 * hole)
272 if (!TEST_FLAG (HOLEFLAG, Via) &&
273 (Via->Thickness < Via->DrillingHole + MIN_PINORVIACOPPER))
275 Via->Thickness = Via->DrillingHole + MIN_PINORVIACOPPER;
276 Message (_("Increased via thickness to %.2f mils to allow enough copper"
277 " at (%.2f,%.2f).\n"),
278 0.01 * Via->Thickness, 0.01 * Via->X, 0.01 * Via->Y);
281 SetPinBoundingBox (Via);
282 if (!Data->via_tree)
283 Data->via_tree = r_create_tree (NULL, 0, 0);
284 r_insert_entry (Data->via_tree, (BoxTypePtr) Via, 0);
285 return (Via);
288 struct line_info
290 LocationType X1, X2, Y1, Y2;
291 BDimension Thickness;
292 FlagType Flags;
293 LineType test, *ans;
294 jmp_buf env;
297 static int
298 line_callback (const BoxType * b, void *cl)
300 LineTypePtr line = (LineTypePtr) b;
301 struct line_info *i = (struct line_info *) cl;
303 if (line->Point1.X == i->X1 &&
304 line->Point2.X == i->X2 &&
305 line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2)
307 i->ans = (LineTypePtr) (-1);
308 longjmp (i->env, 1);
310 /* check the other point order */
311 if (line->Point1.X == i->X1 &&
312 line->Point2.X == i->X2 &&
313 line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2)
315 i->ans = (LineTypePtr) (-1);
316 longjmp (i->env, 1);
318 if (line->Point2.X == i->X1 &&
319 line->Point1.X == i->X2 &&
320 line->Point2.Y == i->Y1 && line->Point1.Y == i->Y2)
322 i->ans = (LineTypePtr) - 1;
323 longjmp (i->env, 1);
325 /* remove unnecessary line points */
326 if (line->Thickness == i->Thickness
327 /* don't merge lines if the clear flags differ */
328 && TEST_FLAG (CLEARLINEFLAG, line) == TEST_FLAG (CLEARLINEFLAG, i))
330 if (line->Point1.X == i->X1 && line->Point1.Y == i->Y1)
332 i->test.Point1.X = line->Point2.X;
333 i->test.Point1.Y = line->Point2.Y;
334 i->test.Point2.X = i->X2;
335 i->test.Point2.Y = i->Y2;
336 if (IsPointOnLine ((float) i->X1, (float) i->Y1, 0.0, &i->test))
338 i->ans = line;
339 longjmp (i->env, 1);
342 else if (line->Point2.X == i->X1 && line->Point2.Y == i->Y1)
344 i->test.Point1.X = line->Point1.X;
345 i->test.Point1.Y = line->Point1.Y;
346 i->test.Point2.X = i->X2;
347 i->test.Point2.Y = i->Y2;
348 if (IsPointOnLine ((float) i->X1, (float) i->Y1, 0.0, &i->test))
350 i->ans = line;
351 longjmp (i->env, 1);
354 else if (line->Point1.X == i->X2 && line->Point1.Y == i->Y2)
356 i->test.Point1.X = line->Point2.X;
357 i->test.Point1.Y = line->Point2.Y;
358 i->test.Point2.X = i->X1;
359 i->test.Point2.Y = i->Y1;
360 if (IsPointOnLine ((float) i->X2, (float) i->Y2, 0.0, &i->test))
362 i->ans = line;
363 longjmp (i->env, 1);
366 else if (line->Point2.X == i->X2 && line->Point2.Y == i->Y2)
368 i->test.Point1.X = line->Point1.X;
369 i->test.Point1.Y = line->Point1.Y;
370 i->test.Point2.X = i->X1;
371 i->test.Point2.Y = i->Y1;
372 if (IsPointOnLine ((float) i->X2, (float) i->Y2, 0.0, &i->test))
374 i->ans = line;
375 longjmp (i->env, 1);
379 return 0;
383 /* ---------------------------------------------------------------------------
384 * creates a new line on a layer and checks for overlap and extension
386 LineTypePtr
387 CreateDrawnLineOnLayer (LayerTypePtr Layer,
388 LocationType X1, LocationType Y1,
389 LocationType X2, LocationType Y2,
390 BDimension Thickness, BDimension Clearance,
391 FlagType Flags)
393 struct line_info info;
394 BoxType search;
396 search.X1 = MIN (X1, X2);
397 search.X2 = MAX (X1, X2);
398 search.Y1 = MIN (Y1, Y2);
399 search.Y2 = MAX (Y1, Y2);
400 if (search.Y2 == search.Y1)
401 search.Y2++;
402 if (search.X2 == search.X1)
403 search.X2++;
404 info.X1 = X1;
405 info.X2 = X2;
406 info.Y1 = Y1;
407 info.Y2 = Y2;
408 info.Thickness = Thickness;
409 info.Flags = Flags;
410 info.test.Thickness = 0;
411 info.test.Flags = NoFlags ();
412 info.ans = NULL;
413 /* prevent stacking of duplicate lines
414 * and remove needless intermediate points
415 * verify that the layer is on the board first!
417 if (setjmp (info.env) == 0)
419 r_search (Layer->line_tree, &search, NULL, line_callback, &info);
420 return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
421 Thickness, Clearance, Flags);
424 if ((void *) info.ans == (void *) (-1))
425 return NULL; /* stacked line */
426 /* remove unnecessary points */
427 if (info.ans)
429 /* must do this BEFORE getting new line memory */
430 MoveObjectToRemoveUndoList (LINE_TYPE, Layer, info.ans, info.ans);
431 X1 = info.test.Point1.X;
432 X2 = info.test.Point2.X;
433 Y1 = info.test.Point1.Y;
434 Y2 = info.test.Point2.Y;
436 return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
437 Thickness, Clearance, Flags);
440 LineTypePtr
441 CreateNewLineOnLayer (LayerTypePtr Layer,
442 LocationType X1, LocationType Y1,
443 LocationType X2, LocationType Y2,
444 BDimension Thickness, BDimension Clearance,
445 FlagType Flags)
447 LineTypePtr Line;
449 Line = GetLineMemory (Layer);
450 if (!Line)
451 return (Line);
452 Line->ID = ID++;
453 Line->Flags = Flags;
454 CLEAR_FLAG (RATFLAG, Line);
455 Line->Thickness = Thickness;
456 Line->Clearance = Clearance;
457 Line->Point1.X = X1;
458 Line->Point1.Y = Y1;
459 Line->Point1.ID = ID++;
460 Line->Point2.X = X2;
461 Line->Point2.Y = Y2;
462 Line->Point2.ID = ID++;
463 SetLineBoundingBox (Line);
464 if (!Layer->line_tree)
465 Layer->line_tree = r_create_tree (NULL, 0, 0);
466 r_insert_entry (Layer->line_tree, (BoxTypePtr) Line, 0);
467 return (Line);
470 /* ---------------------------------------------------------------------------
471 * creates a new rat-line
473 RatTypePtr
474 CreateNewRat (DataTypePtr Data, LocationType X1, LocationType Y1,
475 LocationType X2, LocationType Y2, Cardinal group1,
476 Cardinal group2, BDimension Thickness, FlagType Flags)
478 RatTypePtr Line = GetRatMemory (Data);
480 if (!Line)
481 return (Line);
483 Line->ID = ID++;
484 Line->Flags = Flags;
485 SET_FLAG (RATFLAG, Line);
486 Line->Thickness = Thickness;
487 Line->Point1.X = X1;
488 Line->Point1.Y = Y1;
489 Line->Point1.ID = ID++;
490 Line->Point2.X = X2;
491 Line->Point2.Y = Y2;
492 Line->Point2.ID = ID++;
493 Line->group1 = group1;
494 Line->group2 = group2;
495 SetLineBoundingBox ((LineTypePtr) Line);
496 if (!Data->rat_tree)
497 Data->rat_tree = r_create_tree (NULL, 0, 0);
498 r_insert_entry (Data->rat_tree, &Line->BoundingBox, 0);
499 return (Line);
502 /* ---------------------------------------------------------------------------
503 * creates a new arc on a layer
505 ArcTypePtr
506 CreateNewArcOnLayer (LayerTypePtr Layer,
507 LocationType X1, LocationType Y1,
508 BDimension width,
509 BDimension height,
510 int sa,
511 int dir, BDimension Thickness,
512 BDimension Clearance, FlagType Flags)
514 ArcTypePtr Arc;
516 ARC_LOOP (Layer);
518 if (arc->X == X1 && arc->Y == Y1 && arc->Width == width &&
519 (arc->StartAngle + 360) % 360 == (sa + 360) % 360 &&
520 arc->Delta == dir)
521 return (NULL); /* prevent stacked arcs */
523 END_LOOP;
524 Arc = GetArcMemory (Layer);
525 if (!Arc)
526 return (Arc);
528 Arc->ID = ID++;
529 Arc->Flags = Flags;
530 Arc->Thickness = Thickness;
531 Arc->Clearance = Clearance;
532 Arc->X = X1;
533 Arc->Y = Y1;
534 Arc->Width = width;
535 Arc->Height = height;
536 Arc->StartAngle = sa;
537 Arc->Delta = dir;
538 SetArcBoundingBox (Arc);
539 if (!Layer->arc_tree)
540 Layer->arc_tree = r_create_tree (NULL, 0, 0);
541 r_insert_entry (Layer->arc_tree, (BoxTypePtr) Arc, 0);
542 return (Arc);
546 /* ---------------------------------------------------------------------------
547 * creates a new polygon from the old formats rectangle data
549 PolygonTypePtr
550 CreateNewPolygonFromRectangle (LayerTypePtr Layer,
551 LocationType X1, LocationType Y1,
552 LocationType X2, LocationType Y2,
553 FlagType Flags)
555 PolygonTypePtr polygon = CreateNewPolygon (Layer, Flags);
556 if (!polygon)
557 return (polygon);
559 CreateNewPointInPolygon (polygon, X1, Y1);
560 CreateNewPointInPolygon (polygon, X2, Y1);
561 CreateNewPointInPolygon (polygon, X2, Y2);
562 CreateNewPointInPolygon (polygon, X1, Y2);
563 SetPolygonBoundingBox (polygon);
564 if (!Layer->polygon_tree)
565 Layer->polygon_tree = r_create_tree (NULL, 0, 0);
566 r_insert_entry (Layer->polygon_tree, (BoxTypePtr) polygon, 0);
567 return (polygon);
570 /* ---------------------------------------------------------------------------
571 * creates a new text on a layer
573 TextTypePtr
574 CreateNewText (LayerTypePtr Layer, FontTypePtr PCBFont,
575 LocationType X, LocationType Y,
576 BYTE Direction, int Scale, char *TextString, FlagType Flags)
578 TextTypePtr text = GetTextMemory (Layer);
579 if (!text)
580 return (text);
582 /* copy values, width and height are set by drawing routine
583 * because at this point we don't know which symbols are available
585 text->X = X;
586 text->Y = Y;
587 text->Direction = Direction;
588 text->Flags = Flags;
589 text->Scale = Scale;
590 text->TextString = MyStrdup (TextString, "CreateNewText()");
592 /* calculate size of the bounding box */
593 SetTextBoundingBox (PCBFont, text);
594 text->ID = ID++;
595 if (!Layer->text_tree)
596 Layer->text_tree = r_create_tree (NULL, 0, 0);
597 r_insert_entry (Layer->text_tree, (BoxTypePtr) text, 0);
598 return (text);
601 /* ---------------------------------------------------------------------------
602 * creates a new polygon on a layer
604 PolygonTypePtr
605 CreateNewPolygon (LayerTypePtr Layer, FlagType Flags)
607 PolygonTypePtr polygon = GetPolygonMemory (Layer);
609 /* copy values */
610 polygon->Flags = Flags;
611 polygon->ID = ID++;
612 polygon->Clipped = NULL;
613 polygon->NoHoles = NULL;
614 polygon->NoHolesValid = 0;
615 return (polygon);
618 /* ---------------------------------------------------------------------------
619 * creates a new point in a polygon
621 PointTypePtr
622 CreateNewPointInPolygon (PolygonTypePtr Polygon, LocationType X,
623 LocationType Y)
625 PointTypePtr point = GetPointMemoryInPolygon (Polygon);
627 /* copy values */
628 point->X = X;
629 point->Y = Y;
630 point->ID = ID++;
631 return (point);
634 /* ---------------------------------------------------------------------------
635 * creates an new element
636 * memory is allocated if needed
638 ElementTypePtr
639 CreateNewElement (DataTypePtr Data, ElementTypePtr Element,
640 FontTypePtr PCBFont,
641 FlagType Flags,
642 char *Description, char *NameOnPCB, char *Value,
643 LocationType TextX, LocationType TextY, BYTE Direction,
644 int TextScale, FlagType TextFlags, Boolean uniqueName)
646 if (!Element)
647 Element = GetElementMemory (Data);
649 /* copy values and set additional information */
650 TextScale = MAX (MIN_TEXTSCALE, TextScale);
651 AddTextToElement (&DESCRIPTION_TEXT (Element), PCBFont, TextX, TextY,
652 Direction, Description, TextScale, TextFlags);
653 if (uniqueName)
654 NameOnPCB = UniqueElementName (Data, NameOnPCB);
655 AddTextToElement (&NAMEONPCB_TEXT (Element), PCBFont, TextX, TextY,
656 Direction, NameOnPCB, TextScale, TextFlags);
657 AddTextToElement (&VALUE_TEXT (Element), PCBFont, TextX, TextY,
658 Direction, Value, TextScale, TextFlags);
659 DESCRIPTION_TEXT (Element).Element = Element;
660 NAMEONPCB_TEXT (Element).Element = Element;
661 VALUE_TEXT (Element).Element = Element;
662 Element->Flags = Flags;
663 Element->ID = ID++;
664 return (Element);
667 /* ---------------------------------------------------------------------------
668 * creates a new arc in an element
670 ArcTypePtr
671 CreateNewArcInElement (ElementTypePtr Element,
672 LocationType X, LocationType Y,
673 BDimension Width, BDimension Height,
674 int Angle, int Delta, BDimension Thickness)
676 ArcTypePtr arc = Element->Arc;
678 /* realloc new memory if necessary and clear it */
679 if (Element->ArcN >= Element->ArcMax)
681 Element->ArcMax += STEP_ELEMENTARC;
682 arc = MyRealloc (arc, Element->ArcMax * sizeof (ArcType),
683 "CreateNewArcInElement()");
684 Element->Arc = arc;
685 memset (arc + Element->ArcN, 0, STEP_ELEMENTARC * sizeof (ArcType));
688 /* set Delta (0,360], StartAngle in [0,360) */
689 if ((Delta = Delta % 360) == 0)
690 Delta = 360;
691 if (Delta < 0)
693 Angle += Delta;
694 Delta = -Delta;
696 if ((Angle = Angle % 360) < 0)
697 Angle += 360;
699 /* copy values */
700 arc = arc + Element->ArcN++;
701 arc->X = X;
702 arc->Y = Y;
703 arc->Width = Width;
704 arc->Height = Height;
705 arc->StartAngle = Angle;
706 arc->Delta = Delta;
707 arc->Thickness = Thickness;
708 arc->ID = ID++;
709 return (arc);
712 /* ---------------------------------------------------------------------------
713 * creates a new line for an element
715 LineTypePtr
716 CreateNewLineInElement (ElementTypePtr Element,
717 LocationType X1, LocationType Y1,
718 LocationType X2, LocationType Y2,
719 BDimension Thickness)
721 LineTypePtr line = Element->Line;
723 if (Thickness == 0)
724 return (NULL);
725 /* realloc new memory if necessary and clear it */
726 if (Element->LineN >= Element->LineMax)
728 Element->LineMax += STEP_ELEMENTLINE;
729 line = MyRealloc (line, Element->LineMax * sizeof (LineType),
730 "CreateNewLineInElement()");
731 Element->Line = line;
732 memset (line + Element->LineN, 0, STEP_ELEMENTLINE * sizeof (LineType));
735 /* copy values */
736 line = line + Element->LineN++;
737 line->Point1.X = X1;
738 line->Point1.Y = Y1;
739 line->Point2.X = X2;
740 line->Point2.Y = Y2;
741 line->Thickness = Thickness;
742 line->Flags = NoFlags ();
743 line->ID = ID++;
744 return (line);
747 /* ---------------------------------------------------------------------------
748 * creates a new pin in an element
750 PinTypePtr
751 CreateNewPin (ElementTypePtr Element,
752 LocationType X, LocationType Y,
753 BDimension Thickness, BDimension Clearance, BDimension Mask,
754 BDimension DrillingHole, char *Name, char *Number,
755 FlagType Flags)
757 PinTypePtr pin = GetPinMemory (Element);
759 /* copy values */
760 pin->X = X;
761 pin->Y = Y;
762 pin->Thickness = Thickness;
763 pin->Clearance = Clearance;
764 pin->Mask = Mask;
765 pin->Name = MyStrdup (Name, "CreateNewPin()");
766 pin->Number = MyStrdup (Number, "CreateNewPin()");
767 pin->Flags = Flags;
768 CLEAR_FLAG (WARNFLAG, pin);
769 SET_FLAG (PINFLAG, pin);
770 pin->ID = ID++;
771 pin->Element = Element;
774 * If there is no vendor drill map installed, this will simply
775 * return DrillingHole.
777 pin->DrillingHole = vendorDrillMap (DrillingHole);
779 /* Unless we should not map drills on this element, map them! */
780 if (vendorIsElementMappable (Element))
782 if (pin->DrillingHole < MIN_PINORVIASIZE)
784 Message (_
785 ("Did not map pin #%s (%s) drill hole because %6.2f mil is below the minimum allowed size\n"),
786 UNKNOWN (Number), UNKNOWN (Name),
787 0.01 * pin->DrillingHole);
788 pin->DrillingHole = DrillingHole;
790 else if (pin->DrillingHole > MAX_PINORVIASIZE)
792 Message (_
793 ("Did not map pin #%s (%s) drill hole because %6.2f mil is above the maximum allowed size\n"),
794 UNKNOWN (Number), UNKNOWN (Name),
795 0.01 * pin->DrillingHole);
796 pin->DrillingHole = DrillingHole;
798 else if (!TEST_FLAG (HOLEFLAG, pin)
799 && (pin->DrillingHole > pin->Thickness - MIN_PINORVIACOPPER))
801 Message (_
802 ("Did not map pin #%s (%s) drill hole because %6.2f mil does not leave enough copper\n"),
803 UNKNOWN (Number), UNKNOWN (Name),
804 0.01 * pin->DrillingHole);
805 pin->DrillingHole = DrillingHole;
808 else
810 pin->DrillingHole = DrillingHole;
813 if (pin->DrillingHole != DrillingHole)
815 Message (_
816 ("Mapped pin drill hole to %.2f mils from %.2f mils per vendor table\n"),
817 0.01 * pin->DrillingHole, 0.01 * DrillingHole);
820 return (pin);
823 /* ---------------------------------------------------------------------------
824 * creates a new pad in an element
826 PadTypePtr
827 CreateNewPad (ElementTypePtr Element,
828 LocationType X1, LocationType Y1, LocationType X2,
829 LocationType Y2, BDimension Thickness, BDimension Clearance,
830 BDimension Mask, char *Name, char *Number, FlagType Flags)
832 PadTypePtr pad = GetPadMemory (Element);
834 /* copy values */
835 if (X1 > X2 || (X1 == X2 && Y1 > Y2))
837 pad->Point1.X = X2;
838 pad->Point1.Y = Y2;
839 pad->Point2.X = X1;
840 pad->Point2.Y = Y1;
842 else
844 pad->Point1.X = X1;
845 pad->Point1.Y = Y1;
846 pad->Point2.X = X2;
847 pad->Point2.Y = Y2;
849 pad->Thickness = Thickness;
850 pad->Clearance = Clearance;
851 pad->Mask = Mask;
852 pad->Name = MyStrdup (Name, "CreateNewPad()");
853 pad->Number = MyStrdup (Number, "CreateNewPad()");
854 pad->Flags = Flags;
855 CLEAR_FLAG (WARNFLAG, pad);
856 pad->ID = ID++;
857 pad->Element = Element;
858 return (pad);
861 /* ---------------------------------------------------------------------------
862 * creates a new textobject as part of an element
863 * copies the values to the appropriate text object
865 static void
866 AddTextToElement (TextTypePtr Text, FontTypePtr PCBFont,
867 LocationType X, LocationType Y,
868 BYTE Direction, char *TextString, int Scale, FlagType Flags)
870 MYFREE (Text->TextString);
871 Text->X = X;
872 Text->Y = Y;
873 Text->Direction = Direction;
874 Text->Flags = Flags;
875 Text->Scale = Scale;
876 Text->TextString = (TextString && *TextString) ?
877 MyStrdup (TextString, "AddTextToElement()") : NULL;
879 /* calculate size of the bounding box */
880 SetTextBoundingBox (PCBFont, Text);
881 Text->ID = ID++;
884 /* ---------------------------------------------------------------------------
885 * creates a new line in a symbol
887 LineTypePtr
888 CreateNewLineInSymbol (SymbolTypePtr Symbol,
889 LocationType X1, LocationType Y1,
890 LocationType X2, LocationType Y2, BDimension Thickness)
892 LineTypePtr line = Symbol->Line;
894 /* realloc new memory if necessary and clear it */
895 if (Symbol->LineN >= Symbol->LineMax)
897 Symbol->LineMax += STEP_SYMBOLLINE;
898 line = MyRealloc (line, Symbol->LineMax * sizeof (LineType),
899 "CreateNewLineInSymbol()");
900 Symbol->Line = line;
901 memset (line + Symbol->LineN, 0, STEP_SYMBOLLINE * sizeof (LineType));
904 /* copy values */
905 line = line + Symbol->LineN++;
906 line->Point1.X = X1;
907 line->Point1.Y = Y1;
908 line->Point2.X = X2;
909 line->Point2.Y = Y2;
910 line->Thickness = Thickness;
911 return (line);
914 /* ---------------------------------------------------------------------------
915 * parses a file with font information and installs it
916 * checks directories given as colon separated list by resource fontPath
917 * if the fonts filename doesn't contain a directory component
919 void
920 CreateDefaultFont (void)
922 if (ParseFont (&PCB->Font, Settings.FontFile))
923 Message (_("Can't find font-symbol-file '%s'\n"), Settings.FontFile);
926 /* ---------------------------------------------------------------------------
927 * adds a new line to the rubberband list of 'Crosshair.AttachedObject'
928 * if Layer == 0 it is a rat line
930 RubberbandTypePtr
931 CreateNewRubberbandEntry (LayerTypePtr Layer,
932 LineTypePtr Line, PointTypePtr MovedPoint)
934 RubberbandTypePtr ptr = GetRubberbandMemory ();
936 /* we toggle the RUBBERENDFLAG of the line to determine if */
937 /* both points are being moved. */
938 TOGGLE_FLAG (RUBBERENDFLAG, Line);
939 ptr->Layer = Layer;
940 ptr->Line = Line;
941 ptr->MovedPoint = MovedPoint;
942 return (ptr);
945 /* ---------------------------------------------------------------------------
946 * Add a new net to the netlist menu
948 LibraryMenuTypePtr
949 CreateNewNet (LibraryTypePtr lib, char *name, char *style)
951 LibraryMenuTypePtr menu;
952 char temp[64];
954 sprintf (temp, " %s", name);
955 menu = GetLibraryMenuMemory (lib);
956 menu->Name = MyStrdup (temp, "CreateNewNet()");
957 menu->flag = 1; /* net is enabled by default */
958 if (NSTRCMP ("(unknown)", style) == 0)
959 menu->Style = NULL;
960 else
961 menu->Style = MyStrdup (style, "CreateNewNet()");
962 return (menu);
965 /* ---------------------------------------------------------------------------
966 * Add a connection to the net
968 LibraryEntryTypePtr
969 CreateNewConnection (LibraryMenuTypePtr net, char *conn)
971 LibraryEntryTypePtr entry = GetLibraryEntryMemory (net);
973 entry->ListEntry = MyStrdup (conn, "CreateNewConnection()");
974 return (entry);
977 /* ---------------------------------------------------------------------------
978 * Add an attribute to a list.
980 AttributeTypePtr
981 CreateNewAttribute (AttributeListTypePtr list, char *name, char *value)
983 if (list->Number >= list->Max)
985 list->Max += 10;
986 list->List = MyRealloc (list->List,
987 list->Max * sizeof (AttributeType),
988 "CreateNewAttribute");
990 list->List[list->Number].name = MyStrdup (name, "CreateNewAttribute");
991 list->List[list->Number].value = MyStrdup (value, "CreateNewAttribute");
992 list->Number++;
993 return &list->List[list->Number - 1];