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); }
static void replace_one_footprint_aux(ElementTypePtr old_element, PadOrPinType* old1_pp, PadOrPinType* old2_pp, ElementTypePtr copy_element, PadOrPinType* copy1_pp, PadOrPinType* copy2_pp) { Boolean two_points = (old2_pp && copy2_pp); Boolean reflect = IS_REFLECTED(copy_element, old_element); debug_log("Reflect?: %s\n", (reflect ? "yes" : "no")); if (reflect) { /* Change side of board */ ChangeElementSide(copy_element, 0); } CheapPointType copy1_pt = pad_or_pin_center(copy1_pp); CheapPointType old1_pt = pad_or_pin_center(old1_pp); BYTE rot_steps = 0; if (two_points) { /* Calculate nearest rotation steps */ CheapPointType copy2_pt = pad_or_pin_center(copy2_pp); CheapPointType old2_pt = pad_or_pin_center(old2_pp); rot_steps = calculate_rotation_steps(copy1_pt, copy2_pt, old1_pt, old2_pt); } if (rot_steps) { /* Rotate copy */ RotateElementLowLevel(PCB->Data, copy_element, 0, 0, rot_steps); /* Recalculate since copy_element has changed. */ copy1_pt = pad_or_pin_center(copy1_pp); } /* Calculate translation */ LocationType dx = old1_pt.X - copy1_pt.X; LocationType dy = old1_pt.Y - copy1_pt.Y; /* Move element */ MoveElementLowLevel(PCB->Data, copy_element, dx, dy); /* Transfer pad/pin text and names. */ transfer_text(old_element, copy_element); transfer_names(old_element, copy_element); transfer_flags(old_element, copy_element); SetElementBoundingBox(PCB->Data, copy_element, &PCB->Font); AddObjectToCreateUndoList(ELEMENT_TYPE, copy_element, copy_element, copy_element); /* Remove old element. */ MoveObjectToRemoveUndoList(ELEMENT_TYPE, old_element, old_element, old_element); }
/* --------------------------------------------------------------------------- * loads element data from file/library into buffer * parse the file with disabled 'PCB mode' (see parser) * returns false on error * if successful, update some other stuff and reposition the pastebuffer */ bool LoadElementToBuffer (BufferType *Buffer, char *Name, bool FromFile) { ElementType *element; ClearBuffer (Buffer); if (FromFile) { if (!ParseElementFile (Buffer->Data, Name)) { if (Settings.ShowSolderSide) SwapBuffer (Buffer); SetBufferBoundingBox (Buffer); if (Buffer->Data->ElementN) { element = Buffer->Data->Element->data; Buffer->X = element->MarkX; Buffer->Y = element->MarkY; } else { Buffer->X = 0; Buffer->Y = 0; } return (true); } } else { if (!ParseLibraryEntry (Buffer->Data, Name) && Buffer->Data->ElementN != 0) { element = Buffer->Data->Element->data; /* always add elements using top-side coordinates */ if (Settings.ShowSolderSide) MirrorElementCoordinates (Buffer->Data, element, 0); SetElementBoundingBox (Buffer->Data, element, &PCB->Font); /* set buffer offset to 'mark' position */ Buffer->X = element->MarkX; Buffer->Y = element->MarkY; SetBufferBoundingBox (Buffer); return (true); } } /* release memory which might have been acquired */ ClearBuffer (Buffer); return (false); }
/* --------------------------------------------------------------------------- * moves a element to buffer without allocating memory for pins/names */ static void * MoveElementToBuffer (ElementType *element) { /* * Delete the element from the source (remove it from trees, * restore to polygons) */ r_delete_element (Source, element); Source->Element = g_list_remove (Source->Element, element); Source->ElementN --; Dest->Element = g_list_append (Dest->Element, element); Dest->ElementN ++; PIN_LOOP (element); { RestoreToPolygon(Source, PIN_TYPE, element, pin); CLEAR_FLAG (WARNFLAG | NOCOPY_FLAGS, pin); } END_LOOP; PAD_LOOP (element); { RestoreToPolygon(Source, PAD_TYPE, element, pad); CLEAR_FLAG (WARNFLAG | NOCOPY_FLAGS, pad); } END_LOOP; SetElementBoundingBox (Dest, element, &PCB->Font); /* * Now clear the from the polygons in the destination */ PIN_LOOP (element); { ClearFromPolygon (Dest, PIN_TYPE, element, pin); } END_LOOP; PAD_LOOP (element); { ClearFromPolygon (Dest, PAD_TYPE, element, pad); } END_LOOP; return element; }
void *ChangePadClearSize( ElementTypePtr Element, PadTypePtr Pad ) { int eax; int ebx; int esi; BDimension value = Absolute; value = ( Pad->Clearance + Delta < ( PCB->Bloat + 1 ) * 2 ? Pad->Clearance + Delta : ( PCB->Bloat + 1 ) * 2 ) <= 0x989680 ? 0x989680 : Pad->Clearance + Delta < ( PCB->Bloat + 1 ) * 2 ? Pad->Clearance + Delta : ( PCB->Bloat + 1 ) * 2; if ( value + -100 <= 0x98961c && Pad->Clearance != value ) { AddObjectToClearSizeUndoList( 512, (void*)Element, (void*)Pad, (void*)Pad ); RestoreToPolygon( &PCB->Data, 512, (void*)Element, (void*)Pad ); ErasePad( Pad ); r_delete_entry( &PCB->Data->pad_tree, (int)( &Pad->BoundingBox ) ); Pad->Clearance = value; SetElementBoundingBox( &PCB->Data, Element, &PCB->Font ); ClearFromPolygon( &PCB->Data, 512, (void*)Element, (void*)Pad ); DrawPad( Pad, 0 ); return (void*)Pad; } }
void *ChangePinClearSize( ElementTypePtr Element, PinTypePtr Pin ) { int eax; int ebx; int esi; BDimension value = Absolute; value = ( Pin->Clearance + Delta < ( PCB->Bloat + 1 ) * 2 ? Pin->Clearance + Delta : ( PCB->Bloat + 1 ) * 2 ) <= 0x989680 ? 0x989680 : Pin->Clearance + Delta < ( PCB->Bloat + 1 ) * 2 ? Pin->Clearance + Delta : ( PCB->Bloat + 1 ) * 2; if ( Pin->Clearance != ( ( Pin->Clearance + Delta < ( PCB->Bloat + 1 ) * 2 ? Pin->Clearance + Delta : ( PCB->Bloat + 1 ) * 2 ) <= 0x989680 ? 10000000 : Pin->Clearance + Delta < ( PCB->Bloat + 1 ) * 2 ? Pin->Clearance + Delta : ( PCB->Bloat + 1 ) * 2 ) ) { RestoreToPolygon( &PCB->Data, 256, (void*)Element, (void*)Pin ); AddObjectToClearSizeUndoList( 256, (void*)Element, (void*)Pin, (void*)Pin ); ErasePin( Pin ); r_delete_entry( &PCB->Data->pin_tree, (int)( &Pin->BoundingBox ) ); Pin->Clearance = value; SetElementBoundingBox( &PCB->Data, Element, &PCB->Font ); ClearFromPolygon( &PCB->Data, 256, (void*)Element, (void*)Pin ); DrawPin( Pin, 0 ); return (void*)Pin; } }
void *ChangePadSize( ElementTypePtr Element, PadTypePtr Pad ) { int eax; int ebx; int esi; int edi; BDimension value = Absolute; if ( value + -100 <= 0x98961c && Pad->Thickness != value ) { AddObjectToSizeUndoList( 512, (void*)Element, (void*)Pad, (void*)Pad ); AddObjectToMaskSizeUndoList( 512, (void*)Element, (void*)Pad, (void*)Pad ); RestoreToPolygon( &PCB->Data, 512, (void*)Element, (void*)Pad ); ErasePad( Pad ); r_delete_entry( &PCB->Data->pad_tree, (int)( &Pad->BoundingBox ) ); Pad->Thickness = value; Pad->Mask = ( Pad->Mask + value ) - Pad->Thickness; SetElementBoundingBox( &PCB->Data, Element, &PCB->Font ); ClearFromPolygon( &PCB->Data, 512, (void*)Element, (void*)Pad ); DrawPad( Pad, 0 ); return (void*)Pad; } }
void *ChangePinSize( ElementTypePtr Element, PinTypePtr Pin ) { int eax; int ebx; int esi; int edi; BDimension value = Absolute; if ( value <= 0x989680 && !( ( Pin->Flags.f & 8 ) & 255 ) && value > 1999 && Pin->DrillingHole + 399 < value && Pin->Thickness != value ) { AddObjectToSizeUndoList( 256, (void*)Element, (void*)Pin, (void*)Pin ); AddObjectToMaskSizeUndoList( 256, (void*)Element, (void*)Pin, (void*)Pin ); ErasePin( Pin ); r_delete_entry( &PCB->Data->pin_tree, (int)( &Pin->BoundingBox ) ); RestoreToPolygon( &PCB->Data, 256, (void*)Element, (void*)Pin ); Pin->Thickness = value; Pin->Mask = ( Pin->Mask + value ) - Pin->Thickness; SetElementBoundingBox( &PCB->Data, Element, &PCB->Font ); ClearFromPolygon( &PCB->Data, 256, (void*)Element, (void*)Pin ); DrawPin( Pin, 0 ); return (void*)Pin; } }
/* --------------------------------------------------------------------------- * 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); }
/*--------------------------------------------------------------------------- * * 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); }