static void draw_element_package (ElementType *element) { /* set color and draw lines, arcs, text and pins */ if (doing_pinout || doing_assy) gui->graphics->set_color (Output.fgGC, PCB->ElementColor); else if (TEST_FLAG (SELECTEDFLAG, element)) gui->graphics->set_color (Output.fgGC, PCB->ElementSelectedColor); else if (FRONT (element)) gui->graphics->set_color (Output.fgGC, PCB->ElementColor); else gui->graphics->set_color (Output.fgGC, PCB->InvisibleObjectsColor); /* draw lines, arcs, text and pins */ ELEMENTLINE_LOOP (element); { gui->graphics->draw_pcb_line (Output.fgGC, line); } END_LOOP; ARC_LOOP (element); { gui->graphics->draw_pcb_arc (Output.fgGC, arc); } END_LOOP; }
void FreeRotateElementLowLevel (DataType *Data, ElementType *Element, Coord X, Coord Y, double cosa, double sina, Angle angle) { /* solder side objects need a different orientation */ /* the text subroutine decides by itself if the direction * is to be corrected */ #if 0 ELEMENTTEXT_LOOP (Element); { if (Data && Data->name_tree[n]) r_delete_entry (Data->name_tree[n], (BoxType *)text); RotateTextLowLevel (text, X, Y, Number); } END_LOOP; #endif ELEMENTLINE_LOOP (Element); { free_rotate (&line->Point1.X, &line->Point1.Y, X, Y, cosa, sina); free_rotate (&line->Point2.X, &line->Point2.Y, X, Y, cosa, sina); SetLineBoundingBox (line); } END_LOOP; PIN_LOOP (Element); { /* pre-delete the pins from the pin-tree before their coordinates change */ if (Data) r_delete_entry (Data->pin_tree, (BoxType *)pin); RestoreToPolygon (Data, PIN_TYPE, Element, pin); free_rotate (&pin->X, &pin->Y, X, Y, cosa, sina); SetPinBoundingBox (pin); } END_LOOP; PAD_LOOP (Element); { /* pre-delete the pads before their coordinates change */ if (Data) r_delete_entry (Data->pad_tree, (BoxType *)pad); RestoreToPolygon (Data, PAD_TYPE, Element, pad); free_rotate (&pad->Point1.X, &pad->Point1.Y, X, Y, cosa, sina); free_rotate (&pad->Point2.X, &pad->Point2.Y, X, Y, cosa, sina); SetLineBoundingBox ((LineType *) pad); } END_LOOP; ARC_LOOP (Element); { free_rotate (&arc->X, &arc->Y, X, Y, cosa, sina); arc->StartAngle = NormalizeAngle (arc->StartAngle + angle); } END_LOOP; free_rotate (&Element->MarkX, &Element->MarkY, X, Y, cosa, sina); SetElementBoundingBox (Data, Element, &PCB->Font); ClearFromPolygon (Data, ELEMENT_TYPE, Element, Element); }
/* --------------------------------------------------------------------------- * mirrors the coordinates of an element * an additional offset is passed */ void MirrorElementCoordinates (DataTypePtr Data, ElementTypePtr Element, Coord yoff) { r_delete_element (Data, Element); ELEMENTLINE_LOOP (Element); { line->Point1.X = SWAP_X (line->Point1.X); line->Point1.Y = SWAP_Y (line->Point1.Y) + yoff; line->Point2.X = SWAP_X (line->Point2.X); line->Point2.Y = SWAP_Y (line->Point2.Y) + yoff; } END_LOOP; PIN_LOOP (Element); { RestoreToPolygon (Data, PIN_TYPE, Element, pin); pin->X = SWAP_X (pin->X); pin->Y = SWAP_Y (pin->Y) + yoff; } END_LOOP; PAD_LOOP (Element); { RestoreToPolygon (Data, PAD_TYPE, Element, pad); pad->Point1.X = SWAP_X (pad->Point1.X); pad->Point1.Y = SWAP_Y (pad->Point1.Y) + yoff; pad->Point2.X = SWAP_X (pad->Point2.X); pad->Point2.Y = SWAP_Y (pad->Point2.Y) + yoff; TOGGLE_FLAG (ONSOLDERFLAG, pad); } END_LOOP; ARC_LOOP (Element); { arc->X = SWAP_X (arc->X); arc->Y = SWAP_Y (arc->Y) + yoff; arc->StartAngle = SWAP_ANGLE (arc->StartAngle); arc->Delta = SWAP_DELTA (arc->Delta); } END_LOOP; ELEMENTTEXT_LOOP (Element); { text->X = SWAP_X (text->X); text->Y = SWAP_Y (text->Y) + yoff; TOGGLE_FLAG (ONSOLDERFLAG, text); } END_LOOP; Element->MarkX = SWAP_X (Element->MarkX); Element->MarkY = SWAP_Y (Element->MarkY) + yoff; /* now toggle the solder-side flag */ TOGGLE_FLAG (ONSOLDERFLAG, Element); /* this inserts all of the rtree data too */ SetElementBoundingBox (Data, Element, &PCB->Font); ClearFromPolygon (Data, ELEMENT_TYPE, Element, Element); }
/* --------------------------------------------------------------------------- * draws the package of an element */ void DrawElementPackage (ElementType *Element) { ELEMENTLINE_LOOP (Element); { DrawLine (NULL, line); } END_LOOP; ARC_LOOP (Element); { DrawArc (NULL, arc); } END_LOOP; }
/* --------------------------------------------------------------------------- * erases an element */ void EraseElement (ElementType *Element) { ELEMENTLINE_LOOP (Element); { EraseLine (line); } END_LOOP; ARC_LOOP (Element); { EraseArc (arc); } END_LOOP; EraseElementName (Element); EraseElementPinsAndPads (Element); }
/*! * \brief Creates a new arc on a layer. */ ArcType * CreateNewArcOnLayer (LayerType *Layer, Coord X1, Coord Y1, Coord width, Coord height, Angle sa, Angle dir, Coord Thickness, Coord Clearance, FlagType Flags) { ArcType *Arc; ARC_LOOP (Layer); { if (arc->X == X1 && arc->Y == Y1 && arc->Width == width && NormalizeAngle (arc->StartAngle) == NormalizeAngle (sa) && arc->Delta == dir) return (NULL); /* prevent stacked arcs */ } END_LOOP; Arc = GetArcMemory (Layer); if (!Arc) return (Arc); Arc->ID = ID++; Arc->Flags = Flags; Arc->Thickness = Thickness; Arc->Clearance = Clearance; Arc->X = X1; Arc->Y = Y1; Arc->Width = width; Arc->Height = height; Arc->StartAngle = sa; Arc->Delta = dir; SetArcBoundingBox (Arc); if (!Layer->arc_tree) Layer->arc_tree = r_create_tree (NULL, 0, 0); r_insert_entry (Layer->arc_tree, (BoxType *) Arc, 0); return (Arc); }
/* --------------------------------------------------------------------------- * creates a new arc on a layer */ ArcTypePtr CreateNewArcOnLayer (LayerTypePtr Layer, LocationType X1, LocationType Y1, BDimension width, BDimension height, int sa, int dir, BDimension Thickness, BDimension Clearance, FlagType Flags) { ArcTypePtr Arc; ARC_LOOP (Layer); { if (arc->X == X1 && arc->Y == Y1 && arc->Width == width && (arc->StartAngle + 360) % 360 == (sa + 360) % 360 && arc->Delta == dir) return (NULL); /* prevent stacked arcs */ } END_LOOP; Arc = GetArcMemory (Layer); if (!Arc) return (Arc); Arc->ID = ID++; Arc->Flags = Flags; Arc->Thickness = Thickness; Arc->Clearance = Clearance; Arc->X = X1; Arc->Y = Y1; Arc->Width = width; Arc->Height = height; Arc->StartAngle = sa; Arc->Delta = dir; SetArcBoundingBox (Arc); if (!Layer->arc_tree) Layer->arc_tree = r_create_tree (NULL, 0, 0); r_insert_entry (Layer->arc_tree, (BoxTypePtr) Arc, 0); return (Arc); }
/* --------------------------------------------------------------------------- * get next slot for an arc, allocates memory if necessary */ ArcTypePtr GetArcMemory (LayerTypePtr Layer) { ArcTypePtr arc = Layer->Arc; /* realloc new memory if necessary and clear it */ if (Layer->ArcN >= Layer->ArcMax) { Layer->ArcMax += STEP_ARC; if (Layer->arc_tree) r_destroy_tree (&Layer->arc_tree); arc = (ArcTypePtr)realloc (arc, Layer->ArcMax * sizeof (ArcType)); Layer->Arc = arc; memset (arc + Layer->ArcN, 0, STEP_ARC * sizeof (ArcType)); Layer->arc_tree = r_create_tree (NULL, 0, 0); ARC_LOOP (Layer); { r_insert_entry (Layer->arc_tree, (BoxTypePtr) arc, 0); } END_LOOP; } return (arc + Layer->ArcN++); }
/* --------------------------------------------------------------------------- * searches for a object by it's unique ID. It doesn't matter if * the object is visible or not. The search is performed on a PCB, a * buffer or on the remove list. * The calling routine passes two pointers to allocated memory for storing * the results. * A type value is returned too which is NO_TYPE if no objects has been found. */ int SearchObjectByID (DataTypePtr Base, void **Result1, void **Result2, void **Result3, int ID, int type) { if (type == LINE_TYPE || type == LINEPOINT_TYPE) { ALLLINE_LOOP (Base); { if (line->ID == ID) { *Result1 = (void *) layer; *Result2 = *Result3 = (void *) line; return (LINE_TYPE); } if (line->Point1.ID == ID) { *Result1 = (void *) layer; *Result2 = (void *) line; *Result3 = (void *) &line->Point1; return (LINEPOINT_TYPE); } if (line->Point2.ID == ID) { *Result1 = (void *) layer; *Result2 = (void *) line; *Result3 = (void *) &line->Point2; return (LINEPOINT_TYPE); } } ENDALL_LOOP; } if (type == ARC_TYPE) { ALLARC_LOOP (Base); { if (arc->ID == ID) { *Result1 = (void *) layer; *Result2 = *Result3 = (void *) arc; return (ARC_TYPE); } } ENDALL_LOOP; } if (type == TEXT_TYPE) { ALLTEXT_LOOP (Base); { if (text->ID == ID) { *Result1 = (void *) layer; *Result2 = *Result3 = (void *) text; return (TEXT_TYPE); } } ENDALL_LOOP; } if (type == POLYGON_TYPE || type == POLYGONPOINT_TYPE) { ALLPOLYGON_LOOP (Base); { if (polygon->ID == ID) { *Result1 = (void *) layer; *Result2 = *Result3 = (void *) polygon; return (POLYGON_TYPE); } if (type == POLYGONPOINT_TYPE) POLYGONPOINT_LOOP (polygon); { if (point->ID == ID) { *Result1 = (void *) layer; *Result2 = (void *) polygon; *Result3 = (void *) point; return (POLYGONPOINT_TYPE); } } END_LOOP; } ENDALL_LOOP; } if (type == VIA_TYPE) { VIA_LOOP (Base); { if (via->ID == ID) { *Result1 = *Result2 = *Result3 = (void *) via; return (VIA_TYPE); } } END_LOOP; } if (type == RATLINE_TYPE || type == LINEPOINT_TYPE) { RAT_LOOP (Base); { if (line->ID == ID) { *Result1 = *Result2 = *Result3 = (void *) line; return (RATLINE_TYPE); } if (line->Point1.ID == ID) { *Result1 = (void *) NULL; *Result2 = (void *) line; *Result3 = (void *) &line->Point1; return (LINEPOINT_TYPE); } if (line->Point2.ID == ID) { *Result1 = (void *) NULL; *Result2 = (void *) line; *Result3 = (void *) &line->Point2; return (LINEPOINT_TYPE); } } END_LOOP; } if (type == ELEMENT_TYPE || type == PAD_TYPE || type == PIN_TYPE || type == ELEMENTLINE_TYPE || type == ELEMENTNAME_TYPE || type == ELEMENTARC_TYPE) /* check pins and elementnames too */ ELEMENT_LOOP (Base); { if (element->ID == ID) { *Result1 = *Result2 = *Result3 = (void *) element; return (ELEMENT_TYPE); } if (type == ELEMENTLINE_TYPE) ELEMENTLINE_LOOP (element); { if (line->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) line; return (ELEMENTLINE_TYPE); } } END_LOOP; if (type == ELEMENTARC_TYPE) ARC_LOOP (element); { if (arc->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) arc; return (ELEMENTARC_TYPE); } } END_LOOP; if (type == ELEMENTNAME_TYPE) ELEMENTTEXT_LOOP (element); { if (text->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) text; return (ELEMENTNAME_TYPE); } } END_LOOP; if (type == PIN_TYPE) PIN_LOOP (element); { if (pin->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) pin; return (PIN_TYPE); } } END_LOOP; if (type == PAD_TYPE) PAD_LOOP (element); { if (pad->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) pad; return (PAD_TYPE); } } END_LOOP; } END_LOOP; Message ("hace: Internal error, search for ID %d failed\n", ID); return (NO_TYPE); }
/* --------------------------------------------------------------------------- * moves a element by +-X and +-Y */ void MoveElementLowLevel (DataTypePtr Data, ElementTypePtr Element, Coord DX, Coord DY) { if (Data) r_delete_entry (Data->element_tree, (BoxType *)Element); ELEMENTLINE_LOOP (Element); { MOVE_LINE_LOWLEVEL (line, DX, DY); } END_LOOP; PIN_LOOP (Element); { if (Data) { r_delete_entry (Data->pin_tree, (BoxType *)pin); RestoreToPolygon (Data, PIN_TYPE, Element, pin); } MOVE_PIN_LOWLEVEL (pin, DX, DY); if (Data) { r_insert_entry (Data->pin_tree, (BoxType *)pin, 0); ClearFromPolygon (Data, PIN_TYPE, Element, pin); } } END_LOOP; PAD_LOOP (Element); { if (Data) { r_delete_entry (Data->pad_tree, (BoxType *)pad); RestoreToPolygon (Data, PAD_TYPE, Element, pad); } MOVE_PAD_LOWLEVEL (pad, DX, DY); if (Data) { r_insert_entry (Data->pad_tree, (BoxType *)pad, 0); ClearFromPolygon (Data, PAD_TYPE, Element, pad); } } END_LOOP; ARC_LOOP (Element); { MOVE_ARC_LOWLEVEL (arc, DX, DY); } END_LOOP; ELEMENTTEXT_LOOP (Element); { if (Data && Data->name_tree[n]) r_delete_entry (PCB->Data->name_tree[n], (BoxType *)text); MOVE_TEXT_LOWLEVEL (text, DX, DY); if (Data && Data->name_tree[n]) r_insert_entry (PCB->Data->name_tree[n], (BoxType *)text, 0); } END_LOOP; MOVE_BOX_LOWLEVEL (&Element->BoundingBox, DX, DY); MOVE_BOX_LOWLEVEL (&Element->VBox, DX, DY); MOVE (Element->MarkX, Element->MarkY, DX, DY); if (Data) r_insert_entry (Data->element_tree, (BoxType *)Element, 0); }
/* --------------------------------------------------------------------------- * draws the elements of a loaded circuit which is to be merged in */ static void XORDrawElement (ElementTypePtr Element, LocationType DX, LocationType DY) { /* if no silkscreen, draw the bounding box */ if (Element->ArcN == 0 && Element->LineN == 0) { gui->draw_line (Crosshair.GC, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y1, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y2); gui->draw_line (Crosshair.GC, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y2, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y2); gui->draw_line (Crosshair.GC, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y2, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y1); gui->draw_line (Crosshair.GC, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y1, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y1); } else { ELEMENTLINE_LOOP (Element); { gui->draw_line (Crosshair.GC, DX + line->Point1.X, DY + line->Point1.Y, DX + line->Point2.X, DY + line->Point2.Y); } END_LOOP; /* arc coordinates and angles have to be converted to X11 notation */ ARC_LOOP (Element); { gui->draw_arc (Crosshair.GC, DX + arc->X, DY + arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); } END_LOOP; } /* pin coordinates and angles have to be converted to X11 notation */ PIN_LOOP (Element); { gui->draw_arc (Crosshair.GC, DX + pin->X, DY + pin->Y, pin->Thickness / 2, pin->Thickness / 2, 0, 360); } END_LOOP; /* pads */ PAD_LOOP (Element); { if ((TEST_FLAG (ONSOLDERFLAG, pad) != 0) == Settings.ShowSolderSide || PCB->InvisibleObjectsOn) { if (pad->Point1.X == pad->Point2.X || pad->Point1.Y == pad->Point2.Y) { int minx, miny, maxx, maxy; minx = DX + MIN (pad->Point1.X, pad->Point2.X) - pad->Thickness/2; maxx = DX + MAX (pad->Point1.X, pad->Point2.X) + pad->Thickness/2; miny = DY + MIN (pad->Point1.Y, pad->Point2.Y) - pad->Thickness/2; maxy = DY + MAX (pad->Point1.Y, pad->Point2.Y) + pad->Thickness/2; gui->draw_line (Crosshair.GC, minx, miny, maxx, miny); gui->draw_line (Crosshair.GC, minx, miny, minx, maxy); gui->draw_line (Crosshair.GC, maxx, miny, maxx, maxy); gui->draw_line (Crosshair.GC, minx, maxy, maxx, maxy); } else { /* FIXME: draw outlines, not centerlines. */ gui->draw_line (Crosshair.GC, DX + pad->Point1.X, DY + pad->Point1.Y, DX + pad->Point2.X, DY + pad->Point2.Y); } } } END_LOOP; /* mark */ gui->draw_line (Crosshair.GC, Element->MarkX + DX - EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY - EMARK_SIZE); gui->draw_line (Crosshair.GC, Element->MarkX + DX + EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY - EMARK_SIZE); gui->draw_line (Crosshair.GC, Element->MarkX + DX - EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY + EMARK_SIZE); gui->draw_line (Crosshair.GC, Element->MarkX + DX + EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY + EMARK_SIZE); }
/* --------------------------------------------------------------------------- * draws all visible and attached objects of the pastebuffer */ static void XORDrawBuffer (BufferTypePtr Buffer) { Cardinal i; LocationType x, y; /* set offset */ x = Crosshair.X - Buffer->X; y = Crosshair.Y - Buffer->Y; /* draw all visible layers */ for (i = 0; i < max_copper_layer + 2; i++) if (PCB->Data->Layer[i].On) { LayerTypePtr layer = &Buffer->Data->Layer[i]; LINE_LOOP (layer); { /* XORDrawAttachedLine(x +line->Point1.X, y +line->Point1.Y, x +line->Point2.X, y +line->Point2.Y, line->Thickness); */ gui->draw_line (Crosshair.GC, x + line->Point1.X, y + line->Point1.Y, x + line->Point2.X, y + line->Point2.Y); } END_LOOP; ARC_LOOP (layer); { gui->draw_arc (Crosshair.GC, x + arc->X, y + arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); } END_LOOP; TEXT_LOOP (layer); { BoxTypePtr box = &text->BoundingBox; gui->draw_rect (Crosshair.GC, x + box->X1, y + box->Y1, x + box->X2, y + box->Y2); } END_LOOP; /* the tmp polygon has n+1 points because the first * and the last one are set to the same coordinates */ POLYGON_LOOP (layer); { XORPolygon (polygon, x, y); } END_LOOP; } /* draw elements if visible */ if (PCB->PinOn && PCB->ElementOn) ELEMENT_LOOP (Buffer->Data); { if (FRONT (element) || PCB->InvisibleObjectsOn) XORDrawElement (element, x, y); } END_LOOP; /* and the vias, move offset by thickness/2 */ if (PCB->ViaOn) VIA_LOOP (Buffer->Data); { gui->draw_arc (Crosshair.GC, x + via->X, y + via->Y, via->Thickness / 2, via->Thickness / 2, 0, 360); } END_LOOP; }
/* --------------------------------------------------------------------------- * pastes the contents of the buffer to the layout. Only visible objects * are handled by the routine. */ bool CopyPastebufferToLayout (Coord X, Coord Y) { Cardinal i; bool changed = false; #ifdef DEBUG printf("Entering CopyPastebufferToLayout.....\n"); #endif /* set movement vector */ DeltaX = X - PASTEBUFFER->X, DeltaY = Y - PASTEBUFFER->Y; /* paste all layers */ for (i = 0; i < max_copper_layer + 2; i++) { LayerType *sourcelayer = &PASTEBUFFER->Data->Layer[i]; LayerType *destlayer = LAYER_PTR (i); if (destlayer->On) { changed = changed || (sourcelayer->LineN != 0) || (sourcelayer->ArcN != 0) || (sourcelayer->PolygonN != 0) || (sourcelayer->TextN != 0); LINE_LOOP (sourcelayer); { CopyLine (destlayer, line); } END_LOOP; ARC_LOOP (sourcelayer); { CopyArc (destlayer, arc); } END_LOOP; TEXT_LOOP (sourcelayer); { CopyText (destlayer, text); } END_LOOP; POLYGON_LOOP (sourcelayer); { CopyPolygon (destlayer, polygon); } END_LOOP; } } /* paste elements */ if (PCB->PinOn && PCB->ElementOn) { ELEMENT_LOOP (PASTEBUFFER->Data); { #ifdef DEBUG printf("In CopyPastebufferToLayout, pasting element %s\n", element->Name[1].TextString); #endif if (FRONT (element) || PCB->InvisibleObjectsOn) { CopyElement (element); changed = true; } } END_LOOP; } /* finally the vias */ if (PCB->ViaOn) { changed |= (PASTEBUFFER->Data->ViaN != 0); VIA_LOOP (PASTEBUFFER->Data); { CopyVia (via); } END_LOOP; } if (changed) { Draw (); IncrementUndoSerialNumber (); } #ifdef DEBUG printf(" .... Leaving CopyPastebufferToLayout.\n"); #endif return (changed); }
/* ---------------------------------------------------------------------- * selects/unselects all visible objects within the passed box * Flag determines if the block is to be selected or unselected * returns true if the state of any object has changed */ bool SelectBlock (BoxTypePtr Box, bool Flag) { bool changed = false; if (PCB->RatOn || !Flag) RAT_LOOP (PCB->Data); { if (LINE_IN_BOX ((LineTypePtr) line, Box) && !TEST_FLAG (LOCKFLAG, line) && TEST_FLAG (SELECTEDFLAG, line) != Flag) { AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line); ASSIGN_FLAG (SELECTEDFLAG, Flag, line); if (PCB->RatOn) DrawRat (line, 0); changed = true; } } END_LOOP; /* check layers */ LAYER_LOOP(PCB->Data, max_copper_layer + 2); { if (layer == & PCB->Data->SILKLAYER) { if (! (PCB->ElementOn || !Flag)) continue; } else if (layer == & PCB->Data->BACKSILKLAYER) { if (! (PCB->InvisibleObjectsOn || !Flag)) continue; } else if (! (layer->On || !Flag)) continue; LINE_LOOP (layer); { if (LINE_IN_BOX (line, Box) && !TEST_FLAG (LOCKFLAG, line) && TEST_FLAG (SELECTEDFLAG, line) != Flag) { AddObjectToFlagUndoList (LINE_TYPE, layer, line, line); ASSIGN_FLAG (SELECTEDFLAG, Flag, line); if (layer->On) DrawLine (layer, line, 0); changed = true; } } END_LOOP; ARC_LOOP (layer); { if (ARC_IN_BOX (arc, Box) && !TEST_FLAG (LOCKFLAG, arc) && TEST_FLAG (SELECTEDFLAG, arc) != Flag) { AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc); ASSIGN_FLAG (SELECTEDFLAG, Flag, arc); if (layer->On) DrawArc (layer, arc, 0); changed = true; } } END_LOOP; TEXT_LOOP (layer); { if (!Flag || TEXT_IS_VISIBLE(PCB, layer, text)) { if (TEXT_IN_BOX (text, Box) && !TEST_FLAG (LOCKFLAG, text) && TEST_FLAG (SELECTEDFLAG, text) != Flag) { AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text); ASSIGN_FLAG (SELECTEDFLAG, Flag, text); if (TEXT_IS_VISIBLE(PCB, layer, text)) DrawText (layer, text, 0); changed = true; } } } END_LOOP; POLYGON_LOOP (layer); { if (POLYGON_IN_BOX (polygon, Box) && !TEST_FLAG (LOCKFLAG, polygon) && TEST_FLAG (SELECTEDFLAG, polygon) != Flag) { AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon); ASSIGN_FLAG (SELECTEDFLAG, Flag, polygon); if (layer->On) DrawPolygon (layer, polygon, 0); changed = true; } } END_LOOP; } END_LOOP; /* elements */ ELEMENT_LOOP (PCB->Data); { { bool gotElement = false; if ((PCB->ElementOn || !Flag) && !TEST_FLAG (LOCKFLAG, element) && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT || PCB->InvisibleObjectsOn)) { if (BOX_IN_BOX (&ELEMENT_TEXT (PCB, element).BoundingBox, Box) && !TEST_FLAG (LOCKFLAG, &ELEMENT_TEXT (PCB, element)) && TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)) != Flag) { /* select all names of element */ ELEMENTTEXT_LOOP (element); { AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text); ASSIGN_FLAG (SELECTEDFLAG, Flag, text); } END_LOOP; if (PCB->ElementOn) DrawElementName (element, 0); changed = true; } if ((PCB->PinOn || !Flag) && ELEMENT_IN_BOX (element, Box)) if (TEST_FLAG (SELECTEDFLAG, element) != Flag) { AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element); ASSIGN_FLAG (SELECTEDFLAG, Flag, element); PIN_LOOP (element); { if (TEST_FLAG (SELECTEDFLAG, pin) != Flag) { AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin); ASSIGN_FLAG (SELECTEDFLAG, Flag, pin); if (PCB->PinOn) DrawPin (pin, 0); changed = true; } } END_LOOP; PAD_LOOP (element); { if (TEST_FLAG (SELECTEDFLAG, pad) != Flag) { AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad); ASSIGN_FLAG (SELECTEDFLAG, Flag, pad); if (PCB->PinOn) DrawPad (pad, 0); changed = true; } } END_LOOP; if (PCB->PinOn) DrawElement (element, 0); changed = true; gotElement = true; } } if ((PCB->PinOn || !Flag) && !TEST_FLAG (LOCKFLAG, element) && !gotElement) { PIN_LOOP (element); { if ((VIA_OR_PIN_IN_BOX (pin, Box) && TEST_FLAG (SELECTEDFLAG, pin) != Flag)) { AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin); ASSIGN_FLAG (SELECTEDFLAG, Flag, pin); if (PCB->PinOn) DrawPin (pin, 0); changed = true; } } END_LOOP; PAD_LOOP (element); { if (PAD_IN_BOX (pad, Box) && TEST_FLAG (SELECTEDFLAG, pad) != Flag) { AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad); ASSIGN_FLAG (SELECTEDFLAG, Flag, pad); if (PCB->PinOn) DrawPad (pad, 0); changed = true; } } END_LOOP; } } } END_LOOP; /* end with vias */ if (PCB->ViaOn || !Flag) VIA_LOOP (PCB->Data); { if (VIA_OR_PIN_IN_BOX (via, Box) && !TEST_FLAG (LOCKFLAG, via) && TEST_FLAG (SELECTEDFLAG, via) != Flag) { AddObjectToFlagUndoList (VIA_TYPE, via, via, via); ASSIGN_FLAG (SELECTEDFLAG, Flag, via); if (PCB->ViaOn) DrawVia (via, 0); changed = true; } } END_LOOP; if (changed) { Draw (); IncrementUndoSerialNumber (); } return (changed); }
/* --------------------------------------------------------------------------- * copies data from one element to another and creates the destination * if necessary */ ElementType * CopyElementLowLevel (DataType *Data, ElementType *Src, bool uniqueName, Coord dx, Coord dy, int mask_flags) { int i; ElementType *Dest; /* both coordinates and flags are the same */ Dest = CreateNewElement (Data, &PCB->Font, MaskFlags (Src->Flags, mask_flags), DESCRIPTION_NAME (Src), NAMEONPCB_NAME (Src), VALUE_NAME (Src), DESCRIPTION_TEXT (Src).X + dx, DESCRIPTION_TEXT (Src).Y + dy, DESCRIPTION_TEXT (Src).Direction, DESCRIPTION_TEXT (Src).Scale, MaskFlags (DESCRIPTION_TEXT (Src).Flags, mask_flags), uniqueName); /* abort on error */ if (!Dest) return (Dest); ELEMENTLINE_LOOP (Src); { CreateNewLineInElement (Dest, line->Point1.X + dx, line->Point1.Y + dy, line->Point2.X + dx, line->Point2.Y + dy, line->Thickness); } END_LOOP; PIN_LOOP (Src); { CreateNewPin (Dest, pin->X + dx, pin->Y + dy, pin->Thickness, pin->Clearance, pin->Mask, pin->DrillingHole, pin->Name, pin->Number, MaskFlags (pin->Flags, mask_flags)); } END_LOOP; PAD_LOOP (Src); { CreateNewPad (Dest, pad->Point1.X + dx, pad->Point1.Y + dy, pad->Point2.X + dx, pad->Point2.Y + dy, pad->Thickness, pad->Clearance, pad->Mask, pad->Name, pad->Number, MaskFlags (pad->Flags, mask_flags)); } END_LOOP; ARC_LOOP (Src); { CreateNewArcInElement (Dest, arc->X + dx, arc->Y + dy, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness); } END_LOOP; for (i=0; i<Src->Attributes.Number; i++) CreateNewAttribute (& Dest->Attributes, Src->Attributes.List[i].name, Src->Attributes.List[i].value); Dest->MarkX = Src->MarkX + dx; Dest->MarkY = Src->MarkY + dy; SetElementBoundingBox (Data, Dest, &PCB->Font); return (Dest); }
/*--------------------------------------------------------------------------- * * break buffer element into pieces */ bool SmashBufferElement (BufferType *Buffer) { ElementType *element; Cardinal group; LayerType *clayer, *slayer; if (Buffer->Data->ElementN != 1) { Message (_("Error! Buffer doesn't contain a single element\n")); return (false); } /* * At this point the buffer should contain just a single element. * Now we detach the single element from the buffer and then clear the * buffer, ready to receive the smashed elements. As a result of detaching * it the single element is orphaned from the buffer and thus will not be * free()'d by FreeDataMemory (called via ClearBuffer). This leaves it * around for us to smash bits off it. It then becomes our responsibility, * however, to free the single element when we're finished with it. */ element = Buffer->Data->Element->data; Buffer->Data->Element = NULL; Buffer->Data->ElementN = 0; ClearBuffer (Buffer); ELEMENTLINE_LOOP (element); { CreateNewLineOnLayer (&Buffer->Data->SILKLAYER, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness, 0, NoFlags ()); if (line) line->Number = STRDUP (NAMEONPCB_NAME (element)); } END_LOOP; ARC_LOOP (element); { CreateNewArcOnLayer (&Buffer->Data->SILKLAYER, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness, 0, NoFlags ()); } END_LOOP; PIN_LOOP (element); { FlagType f = NoFlags (); AddFlags (f, VIAFLAG); if (TEST_FLAG (HOLEFLAG, pin)) AddFlags (f, HOLEFLAG); CreateNewVia (Buffer->Data, pin->X, pin->Y, pin->Thickness, pin->Clearance, pin->Mask, pin->DrillingHole, pin->Number, f); } END_LOOP; group = GetLayerGroupNumberByNumber (SWAP_IDENT ? solder_silk_layer : component_silk_layer); clayer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]]; group = GetLayerGroupNumberByNumber (SWAP_IDENT ? component_silk_layer : solder_silk_layer); slayer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]]; PAD_LOOP (element); { LineType *line; line = CreateNewLineOnLayer (TEST_FLAG (ONSOLDERFLAG, pad) ? slayer : clayer, pad->Point1.X, pad->Point1.Y, pad->Point2.X, pad->Point2.Y, pad->Thickness, pad->Clearance, NoFlags ()); if (line) line->Number = STRDUP (pad->Number); } END_LOOP; FreeElementMemory (element); g_slice_free (ElementType, element); return (true); }
/*--------------------------------------------------------------------------- * * convert buffer contents into an element */ bool ConvertBufferToElement (BufferType *Buffer) { ElementType *Element; Cardinal group; Cardinal pin_n = 1; bool hasParts = false, crooked = false; int onsolder; bool warned = false; if (Buffer->Data->pcb == 0) Buffer->Data->pcb = PCB; Element = CreateNewElement (PCB->Data, &PCB->Font, NoFlags (), NULL, NULL, NULL, PASTEBUFFER->X, PASTEBUFFER->Y, 0, 100, MakeFlags (SWAP_IDENT ? ONSOLDERFLAG : NOFLAG), false); if (!Element) return (false); VIA_LOOP (Buffer->Data); { char num[8]; if (via->Mask < via->Thickness) via->Mask = via->Thickness + 2 * MASKFRAME; if (via->Name) CreateNewPin (Element, via->X, via->Y, via->Thickness, via->Clearance, via->Mask, via->DrillingHole, NULL, via->Name, MaskFlags (via->Flags, VIAFLAG | NOCOPY_FLAGS | SELECTEDFLAG | WARNFLAG)); else { sprintf (num, "%d", pin_n++); CreateNewPin (Element, via->X, via->Y, via->Thickness, via->Clearance, via->Mask, via->DrillingHole, NULL, num, MaskFlags (via->Flags, VIAFLAG | NOCOPY_FLAGS | SELECTEDFLAG | WARNFLAG)); } hasParts = true; } END_LOOP; for (onsolder = 0; onsolder < 2; onsolder ++) { int silk_layer; int onsolderflag; if ((!onsolder) == (!SWAP_IDENT)) { silk_layer = component_silk_layer; onsolderflag = NOFLAG; } else { silk_layer = solder_silk_layer; onsolderflag = ONSOLDERFLAG; } #define MAYBE_WARN() \ if (onsolder && !hasParts && !warned) \ { \ warned = true; \ Message \ (_("Warning: All of the pads are on the opposite\n" \ "side from the component - that's probably not what\n" \ "you wanted\n")); \ } \ /* get the component-side SM pads */ group = GetLayerGroupNumberByNumber (silk_layer); GROUP_LOOP (Buffer->Data, group); { char num[8]; LINE_LOOP (layer); { sprintf (num, "%d", pin_n++); CreateNewPad (Element, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness, line->Clearance, line->Thickness + line->Clearance, NULL, line->Number ? line->Number : num, MakeFlags (onsolderflag)); MAYBE_WARN(); hasParts = true; } END_LOOP; POLYGON_LOOP (layer); { Coord x1, y1, x2, y2, w, h, t; if (! polygon_is_rectangle (polygon)) { crooked = true; continue; } w = polygon->Points[2].X - polygon->Points[0].X; h = polygon->Points[1].Y - polygon->Points[0].Y; t = (w < h) ? w : h; x1 = polygon->Points[0].X + t/2; y1 = polygon->Points[0].Y + t/2; x2 = x1 + (w-t); y2 = y1 + (h-t); sprintf (num, "%d", pin_n++); CreateNewPad (Element, x1, y1, x2, y2, t, 2 * Settings.Keepaway, t + Settings.Keepaway, NULL, num, MakeFlags (SQUAREFLAG | onsolderflag)); MAYBE_WARN(); hasParts = true; } END_LOOP; } END_LOOP; } /* now add the silkscreen. NOTE: elements must have pads or pins too */ LINE_LOOP (&Buffer->Data->SILKLAYER); { if (line->Number && !NAMEONPCB_NAME (Element)) NAMEONPCB_NAME (Element) = strdup (line->Number); CreateNewLineInElement (Element, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness); hasParts = true; } END_LOOP; ARC_LOOP (&Buffer->Data->SILKLAYER); { CreateNewArcInElement (Element, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness); hasParts = true; } END_LOOP; if (!hasParts) { DestroyObject (PCB->Data, ELEMENT_TYPE, Element, Element, Element); Message (_("There was nothing to convert!\n" "Elements must have some silk, pads or pins.\n")); return (false); } if (crooked) Message (_("There were polygons that can't be made into pins!\n" "So they were not included in the element\n")); Element->MarkX = Buffer->X; Element->MarkY = Buffer->Y; if (SWAP_IDENT) SET_FLAG (ONSOLDERFLAG, Element); SetElementBoundingBox (PCB->Data, Element, &PCB->Font); ClearBuffer (Buffer); MoveObjectToBuffer (Buffer->Data, PCB->Data, ELEMENT_TYPE, Element, Element, Element); SetBufferBoundingBox (Buffer); return (true); }
/* --------------------------------------------------------------------------- * draws the elements of a loaded circuit which is to be merged in */ static void XORDrawElement (ElementTypePtr Element, Coord DX, Coord DY) { /* if no silkscreen, draw the bounding box */ if (Element->ArcN == 0 && Element->LineN == 0) { gui->draw_line (Crosshair.GC, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y1, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y2); gui->draw_line (Crosshair.GC, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y2, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y2); gui->draw_line (Crosshair.GC, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y2, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y1); gui->draw_line (Crosshair.GC, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y1, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y1); } else { ELEMENTLINE_LOOP (Element); { gui->draw_line (Crosshair.GC, DX + line->Point1.X, DY + line->Point1.Y, DX + line->Point2.X, DY + line->Point2.Y); } END_LOOP; /* arc coordinates and angles have to be converted to X11 notation */ ARC_LOOP (Element); { gui->draw_arc (Crosshair.GC, DX + arc->X, DY + arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); } END_LOOP; } /* pin coordinates and angles have to be converted to X11 notation */ PIN_LOOP (Element); { thindraw_moved_pv (pin, DX, DY); } END_LOOP; /* pads */ PAD_LOOP (Element); { if (PCB->InvisibleObjectsOn || (TEST_FLAG (ONSOLDERFLAG, pad) != 0) == Settings.ShowSolderSide) { /* Make a copy of the pad structure, moved to the correct position */ PadType moved_pad = *pad; moved_pad.Point1.X += DX; moved_pad.Point1.Y += DY; moved_pad.Point2.X += DX; moved_pad.Point2.Y += DY; gui->thindraw_pcb_pad (Crosshair.GC, &moved_pad, false, false); } } END_LOOP; /* mark */ gui->draw_line (Crosshair.GC, Element->MarkX + DX - EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY - EMARK_SIZE); gui->draw_line (Crosshair.GC, Element->MarkX + DX + EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY - EMARK_SIZE); gui->draw_line (Crosshair.GC, Element->MarkX + DX - EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY + EMARK_SIZE); gui->draw_line (Crosshair.GC, Element->MarkX + DX + EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY + EMARK_SIZE); }
static void pinout_set_data (GhidPinoutPreview * pinout, ElementType * element) { gint tx, ty, x_min = 0, y_min = 0; if (element == NULL) { FreeElementMemory (&pinout->element); pinout->w_pixels = 0; pinout->h_pixels = 0; return; } /* * copy element data * enable output of pin and padnames * move element to a 5% offset from zero position * set all package lines/arcs to zero width */ CopyElementLowLevel (NULL, &pinout->element, element, FALSE, 0, 0); PIN_LOOP (&pinout->element); { tx = abs (pinout->element.Pin[0].X - pin->X); ty = abs (pinout->element.Pin[0].Y - pin->Y); if (x_min == 0 || (tx != 0 && tx < x_min)) x_min = tx; if (y_min == 0 || (ty != 0 && ty < y_min)) y_min = ty; SET_FLAG (DISPLAYNAMEFLAG, pin); } END_LOOP; PAD_LOOP (&pinout->element); { tx = abs (pinout->element.Pad[0].Point1.X - pad->Point1.X); ty = abs (pinout->element.Pad[0].Point1.Y - pad->Point1.Y); if (x_min == 0 || (tx != 0 && tx < x_min)) x_min = tx; if (y_min == 0 || (ty != 0 && ty < y_min)) y_min = ty; SET_FLAG (DISPLAYNAMEFLAG, pad); } END_LOOP; MoveElementLowLevel (NULL, &pinout->element, Settings.PinoutOffsetX - pinout->element.BoundingBox.X1, Settings.PinoutOffsetY - pinout->element.BoundingBox.Y1); if (!pinout_zoom_fit (pinout, 2)) pinout_zoom_fit (pinout, 3); ELEMENTLINE_LOOP (&pinout->element); { line->Thickness = 0; } END_LOOP; ARC_LOOP (&pinout->element); { /* * for whatever reason setting a thickness of 0 causes the arcs to * not display so pick 1 which does display but is still quite * thin. */ arc->Thickness = 1; } END_LOOP; }