/* --------------------------------------------------------------------------- * 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); }
void doPerturb (PerturbationType * pt, bool undo) { LocationType bbcx, bbcy; /* compute center of element bounding box */ bbcx = (pt->element->VBox.X1 + pt->element->VBox.X2) / 2; bbcy = (pt->element->VBox.Y1 + pt->element->VBox.Y2) / 2; /* do exchange, shift or flip/rotate */ switch (pt->which) { case SHIFT: { LocationType DX = pt->DX, DY = pt->DY; if (undo) { DX = -DX; DY = -DY; } MoveElementLowLevel (PCB->Data, pt->element, DX, DY); return; } case ROTATE: { BYTE b = pt->rotate; if (undo) b = (4 - b) & 3; /* 0 - flip; 1-3, rotate. */ if (b) RotateElementLowLevel (PCB->Data, pt->element, bbcx, bbcy, b); else { LocationType y = pt->element->VBox.Y1; MirrorElementCoordinates (PCB->Data, pt->element, 0); /* mirroring moves the element. move it back. */ MoveElementLowLevel (PCB->Data, pt->element, 0, y - pt->element->VBox.Y1); } return; } case EXCHANGE: { /* first exchange positions */ LocationType x1 = pt->element->VBox.X1; LocationType y1 = pt->element->VBox.Y1; LocationType x2 = pt->other->BoundingBox.X1; LocationType y2 = pt->other->BoundingBox.Y1; MoveElementLowLevel (PCB->Data, pt->element, x2 - x1, y2 - y1); MoveElementLowLevel (PCB->Data, pt->other, x1 - x2, y1 - y2); /* then flip both elements if they are on opposite sides */ if (TEST_FLAG (ONSOLDERFLAG, pt->element) != TEST_FLAG (ONSOLDERFLAG, pt->other)) { PerturbationType mypt; mypt.element = pt->element; mypt.which = ROTATE; mypt.rotate = 0; /* flip */ doPerturb (&mypt, undo); mypt.element = pt->other; doPerturb (&mypt, undo); } /* done */ return; } default: assert (0); } }
/* --------------------------------------------------------------------------- * flip components/tracks from one side to the other */ static void SwapBuffer (BufferType *Buffer) { int j, k; Cardinal sgroup, cgroup; LayerType swap; ELEMENT_LOOP (Buffer->Data); { r_delete_element (Buffer->Data, element); MirrorElementCoordinates (Buffer->Data, element, 0); } END_LOOP; /* set buffer offset to 'mark' position */ Buffer->X = SWAP_X (Buffer->X); Buffer->Y = SWAP_Y (Buffer->Y); VIA_LOOP (Buffer->Data); { r_delete_entry (Buffer->Data->via_tree, (BoxType *)via); via->X = SWAP_X (via->X); via->Y = SWAP_Y (via->Y); SetPinBoundingBox (via); r_insert_entry (Buffer->Data->via_tree, (BoxType *)via, 0); } END_LOOP; ALLLINE_LOOP (Buffer->Data); { r_delete_entry (layer->line_tree, (BoxType *)line); line->Point1.X = SWAP_X (line->Point1.X); line->Point1.Y = SWAP_Y (line->Point1.Y); line->Point2.X = SWAP_X (line->Point2.X); line->Point2.Y = SWAP_Y (line->Point2.Y); SetLineBoundingBox (line); r_insert_entry (layer->line_tree, (BoxType *)line, 0); } ENDALL_LOOP; ALLARC_LOOP (Buffer->Data); { r_delete_entry (layer->arc_tree, (BoxType *)arc); arc->X = SWAP_X (arc->X); arc->Y = SWAP_Y (arc->Y); arc->StartAngle = SWAP_ANGLE (arc->StartAngle); arc->Delta = SWAP_DELTA (arc->Delta); SetArcBoundingBox (arc); r_insert_entry (layer->arc_tree, (BoxType *)arc, 0); } ENDALL_LOOP; ALLPOLYGON_LOOP (Buffer->Data); { r_delete_entry (layer->polygon_tree, (BoxType *)polygon); POLYGONPOINT_LOOP (polygon); { point->X = SWAP_X (point->X); point->Y = SWAP_Y (point->Y); } END_LOOP; SetPolygonBoundingBox (polygon); r_insert_entry (layer->polygon_tree, (BoxType *)polygon, 0); /* hmmm, how to handle clip */ } ENDALL_LOOP; ALLTEXT_LOOP (Buffer->Data); { r_delete_entry (layer->text_tree, (BoxType *)text); text->X = SWAP_X (text->X); text->Y = SWAP_Y (text->Y); TOGGLE_FLAG (ONSOLDERFLAG, text); SetTextBoundingBox (&PCB->Font, text); r_insert_entry (layer->text_tree, (BoxType *)text, 0); } ENDALL_LOOP; /* swap silkscreen layers */ swap = Buffer->Data->Layer[solder_silk_layer]; Buffer->Data->Layer[solder_silk_layer] = Buffer->Data->Layer[component_silk_layer]; Buffer->Data->Layer[component_silk_layer] = swap; /* swap layer groups when balanced */ sgroup = GetLayerGroupNumberByNumber (solder_silk_layer); cgroup = GetLayerGroupNumberByNumber (component_silk_layer); if (PCB->LayerGroups.Number[cgroup] == PCB->LayerGroups.Number[sgroup]) { for (j = k = 0; j < PCB->LayerGroups.Number[sgroup]; j++) { int t1, t2; Cardinal cnumber = PCB->LayerGroups.Entries[cgroup][k]; Cardinal snumber = PCB->LayerGroups.Entries[sgroup][j]; if (snumber >= max_copper_layer) continue; swap = Buffer->Data->Layer[snumber]; while (cnumber >= max_copper_layer) { k++; cnumber = PCB->LayerGroups.Entries[cgroup][k]; } Buffer->Data->Layer[snumber] = Buffer->Data->Layer[cnumber]; Buffer->Data->Layer[cnumber] = swap; k++; /* move the thermal flags with the layers */ ALLPIN_LOOP (Buffer->Data); { t1 = TEST_THERM (snumber, pin); t2 = TEST_THERM (cnumber, pin); ASSIGN_THERM (snumber, t2, pin); ASSIGN_THERM (cnumber, t1, pin); } ENDALL_LOOP; VIA_LOOP (Buffer->Data); { t1 = TEST_THERM (snumber, via); t2 = TEST_THERM (cnumber, via); ASSIGN_THERM (snumber, t2, via); ASSIGN_THERM (cnumber, t1, via); } END_LOOP; } } SetBufferBoundingBox (Buffer); SetCrosshairRangeToBuffer (); }