/* --------------------------------------------------------------------------- * moves a text object between layers; lowlevel routines */ static void * MoveTextToLayerLowLevel (LayerType *Source, TextType *text, LayerType *Destination) { RestoreToPolygon (PCB->Data, TEXT_TYPE, Source, text); r_delete_entry (Source->text_tree, (BoxType *)text); Source->Text = g_list_remove (Source->Text, text); Source->TextN --; Destination->Text = g_list_append (Destination->Text, text); Destination->TextN ++; if (GetLayerGroupNumberByNumber (solder_silk_layer) == GetLayerGroupNumberByPointer (Destination)) SET_FLAG (ONSOLDERFLAG, text); else CLEAR_FLAG (ONSOLDERFLAG, text); /* re-calculate the bounding box (it could be mirrored now) */ SetTextBoundingBox (&PCB->Font, text); if (!Destination->text_tree) Destination->text_tree = r_create_tree (NULL, 0, 0); r_insert_entry (Destination->text_tree, (BoxType *)text, 0); ClearFromPolygon (PCB->Data, TEXT_TYPE, Destination, text); return text; }
/*! * \brief Checks all visible lines which belong to the same group as the * passed arc. * * If one of the endpoints of the line lays inside the passed arc, * the scanned line is added to the 'rubberband' list */ static void CheckArcPointForRubberbandConnection (LayerType *Layer, ArcType *Arc, PointType *ArcPoint, bool Exact) { Cardinal group; struct rubber_info info; Coord t = Arc->Thickness / 2; /* lookup layergroup and check all visible lines in this group */ info.radius = Exact ? -1 : MAX(Arc->Thickness / 2, 1); info.box.X1 = ArcPoint->X - t; info.box.X2 = ArcPoint->X + t; info.box.Y1 = ArcPoint->Y - t; info.box.Y2 = ArcPoint->Y + t; info.line = NULL; info.X = ArcPoint->X; info.Y = ArcPoint->Y; group = GetLayerGroupNumberByPointer (Layer); GROUP_LOOP (PCB->Data, group); { /* check all visible lines of the group member */ if (layer->On) { info.layer = layer; r_search (layer->line_tree, &info.box, NULL, rubber_callback, &info); } } END_LOOP; }
static void CheckLinePointForRat (LayerType *Layer, PointType *Point) { struct rinfo info; info.group = GetLayerGroupNumberByPointer (Layer); info.point = Point; info.type = LINEPOINT_TYPE; r_search (PCB->Data->rat_tree, (BoxType *) Point, NULL, rat_callback, &info); }
/* --------------------------------------------------------------------------- * checks all visible lines which belong to the same group as the passed polygon. * If one of the endpoints of the line lays inside the passed polygon, * the scanned line is added to the 'rubberband' list. */ static void CheckPolygonForRubberbandConnection (LayerType *Layer, PolygonType *Polygon) { Cardinal group; /* lookup layergroup and check all visible lines in this group */ group = GetLayerGroupNumberByPointer (Layer); GROUP_LOOP (PCB->Data, group); { if (layer->On) { Coord thick; /* the following code just stupidly compares the endpoints * of the lines */ LINE_LOOP (layer); { if (TEST_FLAG (LOCKFLAG, line)) continue; if (TEST_FLAG (CLEARLINEFLAG, line)) continue; thick = (line->Thickness + 1) / 2; if (IsPointInPolygon (line->Point1.X, line->Point1.Y, thick, Polygon)) CreateNewRubberbandEntry (layer, line, &line->Point1); if (IsPointInPolygon (line->Point2.X, line->Point2.Y, thick, Polygon)) CreateNewRubberbandEntry (layer, line, &line->Point2); } END_LOOP; } } END_LOOP; }
static void * MoveLineToLayer (LayerType *Layer, LineType *Line) { struct via_info info; BoxType sb; LineTypePtr newone; void *ptr1, *ptr2, *ptr3; if (TEST_FLAG (LOCKFLAG, Line)) { Message (_("Sorry, the object is locked\n")); return NULL; } if (Dest == Layer && Layer->On) { DrawLine (Layer, Line); Draw (); } if (((long int) Dest == -1) || Dest == Layer) return (Line); AddObjectToMoveToLayerUndoList (LINE_TYPE, Layer, Line, Line); if (Layer->On) EraseLine (Line); RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line); newone = (LineTypePtr)MoveLineToLayerLowLevel (Layer, Line, Dest); Line = NULL; ClearFromPolygon (PCB->Data, LINE_TYPE, Dest, newone); if (Dest->On) DrawLine (Dest, newone); Draw (); if (!PCB->ViaOn || MoreToCome || GetLayerGroupNumberByPointer (Layer) == GetLayerGroupNumberByPointer (Dest) || TEST_SILK_LAYER(Layer) || TEST_SILK_LAYER(Dest)) return (newone); /* consider via at Point1 */ sb.X1 = newone->Point1.X - newone->Thickness / 2; sb.X2 = newone->Point1.X + newone->Thickness / 2; sb.Y1 = newone->Point1.Y - newone->Thickness / 2; sb.Y2 = newone->Point1.Y + newone->Thickness / 2; if ((SearchObjectByLocation (PIN_TYPES, &ptr1, &ptr2, &ptr3, newone->Point1.X, newone->Point1.Y, Settings.ViaThickness / 2) == NO_TYPE)) { info.X = newone->Point1.X; info.Y = newone->Point1.Y; if (setjmp (info.env) == 0) r_search (Layer->line_tree, &sb, NULL, moveline_callback, &info); } /* consider via at Point2 */ sb.X1 = newone->Point2.X - newone->Thickness / 2; sb.X2 = newone->Point2.X + newone->Thickness / 2; sb.Y1 = newone->Point2.Y - newone->Thickness / 2; sb.Y2 = newone->Point2.Y + newone->Thickness / 2; if ((SearchObjectByLocation (PIN_TYPES, &ptr1, &ptr2, &ptr3, newone->Point2.X, newone->Point2.Y, Settings.ViaThickness / 2) == NO_TYPE)) { info.X = newone->Point2.X; info.Y = newone->Point2.Y; if (setjmp (info.env) == 0) r_search (Layer->line_tree, &sb, NULL, moveline_callback, &info); } Draw (); return (newone); }
/*! * \brief Determine existing interconnections of the net and gather into * sub-nets. * * Initially the netlist has each connection in its own individual net * afterwards there can be many fewer nets with multiple connections * each. */ static bool GatherSubnets (NetListType *Netl, bool NoWarn, bool AndRats) { NetType *a, *b; ConnectionType *conn; Cardinal m, n; bool Warned = false; for (m = 0; Netl->NetN > 0 && m < Netl->NetN; m++) { a = &Netl->Net[m]; ClearFlagOnAllObjects (false, DRCFLAG); RatFindHook (a->Connection[0].type, a->Connection[0].ptr1, a->Connection[0].ptr2, a->Connection[0].ptr2, false, DRCFLAG, AndRats); /* now anybody connected to the first point has DRCFLAG set */ /* so move those to this subnet */ CLEAR_FLAG (DRCFLAG, (PinType *) a->Connection[0].ptr2); for (n = m + 1; n < Netl->NetN; n++) { b = &Netl->Net[n]; /* There can be only one connection in net b */ if (TEST_FLAG (DRCFLAG, (PinType *) b->Connection[0].ptr2)) { CLEAR_FLAG (DRCFLAG, (PinType *) b->Connection[0].ptr2); TransferNet (Netl, b, a); /* back up since new subnet is now at old index */ n--; } } /* now add other possible attachment points to the subnet */ /* e.g. line end-points and vias */ /* don't add non-manhattan lines, the auto-router can't route to them */ ALLLINE_LOOP (PCB->Data); { if (TEST_FLAG (DRCFLAG, line)) { conn = GetConnectionMemory (a); conn->X = line->Point1.X; conn->Y = line->Point1.Y; conn->type = LINE_TYPE; conn->ptr1 = layer; conn->ptr2 = line; conn->group = GetLayerGroupNumberByPointer (layer); conn->menu = NULL; /* agnostic view of where it belongs */ conn = GetConnectionMemory (a); conn->X = line->Point2.X; conn->Y = line->Point2.Y; conn->type = LINE_TYPE; conn->ptr1 = layer; conn->ptr2 = line; conn->group = GetLayerGroupNumberByPointer (layer); conn->menu = NULL; } } ENDALL_LOOP; /* add polygons so the auto-router can see them as targets */ ALLPOLYGON_LOOP (PCB->Data); { if (TEST_FLAG (DRCFLAG, polygon)) { conn = GetConnectionMemory (a); /* make point on a vertex */ conn->X = polygon->Clipped->contours->head.point[0]; conn->Y = polygon->Clipped->contours->head.point[1]; conn->type = POLYGON_TYPE; conn->ptr1 = layer; conn->ptr2 = polygon; conn->group = GetLayerGroupNumberByPointer (layer); conn->menu = NULL; /* agnostic view of where it belongs */ } } ENDALL_LOOP; VIA_LOOP (PCB->Data); { if (TEST_FLAG (DRCFLAG, via)) { conn = GetConnectionMemory (a); conn->X = via->X; conn->Y = via->Y; conn->type = VIA_TYPE; conn->ptr1 = via; conn->ptr2 = via; conn->group = bottom_group; } } END_LOOP; if (!NoWarn) Warned |= CheckShorts (a->Connection[0].menu); } ClearFlagOnAllObjects (false, DRCFLAG); return (Warned); }