4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
28 /* functions used to rotate pins, elements ...
39 #include "crosshair.h"
47 #include "rubberband.h"
53 #ifdef HAVE_LIBDMALLOC
57 /* ---------------------------------------------------------------------------
58 * some local prototypes
60 static void *RotateText (LayerType
*, TextType
*);
61 static void *RotateArc (LayerType
*, ArcType
*);
62 static void *RotateElement (ElementType
*);
63 static void *RotateElementName (ElementType
*);
64 static void *RotateLinePoint (LayerType
*, LineType
*, PointType
*);
66 /* ----------------------------------------------------------------------
67 * some local identifiers
69 static Coord CenterX
, CenterY
; /* center of rotation */
70 static unsigned Number
; /* number of rotations */
71 static ObjectFunctionType RotateFunctions
= {
86 /* ---------------------------------------------------------------------------
87 * rotates a point in 90 degree steps
90 RotatePointLowLevel (PointType
*Point
, Coord X
, Coord Y
, unsigned Number
)
92 ROTATE (Point
->X
, Point
->Y
, X
, Y
, Number
);
95 /* ---------------------------------------------------------------------------
96 * rotates a line in 90 degree steps
99 RotateLineLowLevel (LineType
*Line
, Coord X
, Coord Y
, unsigned Number
)
101 ROTATE (Line
->Point1
.X
, Line
->Point1
.Y
, X
, Y
, Number
);
102 ROTATE (Line
->Point2
.X
, Line
->Point2
.Y
, X
, Y
, Number
);
103 /* keep horizontal, vertical Point2 > Point1 */
104 if (Line
->Point1
.X
== Line
->Point2
.X
)
106 if (Line
->Point1
.Y
> Line
->Point2
.Y
)
110 Line
->Point1
.Y
= Line
->Point2
.Y
;
114 else if (Line
->Point1
.Y
== Line
->Point2
.Y
)
116 if (Line
->Point1
.X
> Line
->Point2
.X
)
120 Line
->Point1
.X
= Line
->Point2
.X
;
124 /* instead of rotating the bounding box, the call updates both end points too */
125 SetLineBoundingBox (Line
);
128 /* ---------------------------------------------------------------------------
129 * rotates a text in 90 degree steps
130 * only the bounding box is rotated, text rotation itself
131 * is done by the drawing routines
134 RotateTextLowLevel (TextType
*Text
, Coord X
, Coord Y
, unsigned Number
)
138 number
= TEST_FLAG (ONSOLDERFLAG
, Text
) ? (4 - Number
) & 3 : Number
;
139 RotateBoxLowLevel (&Text
->BoundingBox
, X
, Y
, Number
);
140 ROTATE (Text
->X
, Text
->Y
, X
, Y
, Number
);
142 /* set new direction, 0..3,
143 * 0-> to the right, 1-> straight up,
144 * 2-> to the left, 3-> straight down
146 Text
->Direction
= ((Text
->Direction
+ number
) & 0x03);
149 /* ---------------------------------------------------------------------------
150 * rotates a polygon in 90 degree steps
153 RotatePolygonLowLevel (PolygonType
*Polygon
, Coord X
, Coord Y
, unsigned Number
)
155 POLYGONPOINT_LOOP (Polygon
);
157 ROTATE (point
->X
, point
->Y
, X
, Y
, Number
);
160 RotateBoxLowLevel (&Polygon
->BoundingBox
, X
, Y
, Number
);
163 /* ---------------------------------------------------------------------------
164 * rotates a text object and redraws it
167 RotateText (LayerType
*Layer
, TextType
*Text
)
169 EraseText (Layer
, Text
);
170 RestoreToPolygon (PCB
->Data
, TEXT_TYPE
, Layer
, Text
);
171 r_delete_entry (Layer
->text_tree
, (BoxType
*) Text
);
172 RotateTextLowLevel (Text
, CenterX
, CenterY
, Number
);
173 r_insert_entry (Layer
->text_tree
, (BoxType
*) Text
, 0);
174 ClearFromPolygon (PCB
->Data
, TEXT_TYPE
, Layer
, Text
);
175 DrawText (Layer
, Text
);
180 /* ---------------------------------------------------------------------------
184 RotateArcLowLevel (ArcType
*Arc
, Coord X
, Coord Y
, unsigned Number
)
188 /* add Number*90 degrees (i.e., Number quarter-turns) */
189 Arc
->StartAngle
= NormalizeAngle (Arc
->StartAngle
+ Number
* 90);
190 ROTATE (Arc
->X
, Arc
->Y
, X
, Y
, Number
);
192 /* now change width and height */
193 if (Number
== 1 || Number
== 3)
196 Arc
->Width
= Arc
->Height
;
199 RotateBoxLowLevel (&Arc
->BoundingBox
, X
, Y
, Number
);
200 ROTATE (Arc
->Point1
.X
, Arc
->Point1
.Y
, X
, Y
, Number
);
201 ROTATE (Arc
->Point2
.X
, Arc
->Point2
.Y
, X
, Y
, Number
);
204 /* ---------------------------------------------------------------------------
205 * rotate an element in 90 degree steps
208 RotateElementLowLevel (DataType
*Data
, ElementType
*Element
,
209 Coord X
, Coord Y
, unsigned Number
)
211 /* solder side objects need a different orientation */
213 /* the text subroutine decides by itself if the direction
216 ELEMENTTEXT_LOOP (Element
);
218 if (Data
&& Data
->name_tree
[n
])
219 r_delete_entry (Data
->name_tree
[n
], (BoxType
*) text
);
220 RotateTextLowLevel (text
, X
, Y
, Number
);
223 ELEMENTLINE_LOOP (Element
);
225 RotateLineLowLevel (line
, X
, Y
, Number
);
230 /* pre-delete the pins from the pin-tree before their coordinates change */
232 r_delete_entry (Data
->pin_tree
, (BoxType
*) pin
);
233 RestoreToPolygon (Data
, PIN_TYPE
, Element
, pin
);
234 ROTATE_PIN_LOWLEVEL (pin
, X
, Y
, Number
);
239 /* pre-delete the pads before their coordinates change */
241 r_delete_entry (Data
->pad_tree
, (BoxType
*) pad
);
242 RestoreToPolygon (Data
, PAD_TYPE
, Element
, pad
);
243 ROTATE_PAD_LOWLEVEL (pad
, X
, Y
, Number
);
248 RotateArcLowLevel (arc
, X
, Y
, Number
);
251 ROTATE (Element
->MarkX
, Element
->MarkY
, X
, Y
, Number
);
252 /* SetElementBoundingBox reenters the rtree data */
253 SetElementBoundingBox (Data
, Element
, &PCB
->Font
);
254 ClearFromPolygon (Data
, ELEMENT_TYPE
, Element
, Element
);
257 /* ---------------------------------------------------------------------------
258 * rotates a line's point
261 RotateLinePoint (LayerType
*Layer
, LineType
*Line
, PointType
*Point
)
266 RestoreToPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
267 r_delete_entry (Layer
->line_tree
, (BoxType
*) Line
);
270 r_delete_entry (PCB
->Data
->rat_tree
, (BoxType
*) Line
);
271 RotatePointLowLevel (Point
, CenterX
, CenterY
, Number
);
272 SetLineBoundingBox (Line
);
275 r_insert_entry (Layer
->line_tree
, (BoxType
*) Line
, 0);
276 ClearFromPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
277 DrawLine (Layer
, Line
);
281 r_insert_entry (PCB
->Data
->rat_tree
, (BoxType
*) Line
, 0);
282 DrawRat ((RatType
*) Line
);
288 /* ---------------------------------------------------------------------------
292 RotateArc (LayerType
*Layer
, ArcType
*Arc
)
295 r_delete_entry (Layer
->arc_tree
, (BoxType
*) Arc
);
296 RotateArcLowLevel (Arc
, CenterX
, CenterY
, Number
);
297 r_insert_entry (Layer
->arc_tree
, (BoxType
*) Arc
, 0);
298 DrawArc (Layer
, Arc
);
303 /* ---------------------------------------------------------------------------
307 RotateElement (ElementType
*Element
)
309 EraseElement (Element
);
310 RotateElementLowLevel (PCB
->Data
, Element
, CenterX
, CenterY
, Number
);
311 DrawElement (Element
);
316 /* ----------------------------------------------------------------------
317 * rotates the name of an element
320 RotateElementName (ElementType
*Element
)
322 EraseElementName (Element
);
323 ELEMENTTEXT_LOOP (Element
);
325 r_delete_entry (PCB
->Data
->name_tree
[n
], (BoxType
*) text
);
326 RotateTextLowLevel (text
, CenterX
, CenterY
, Number
);
327 r_insert_entry (PCB
->Data
->name_tree
[n
], (BoxType
*) text
, 0);
330 DrawElementName (Element
);
335 /* ---------------------------------------------------------------------------
336 * rotates a box in 90 degree steps
339 RotateBoxLowLevel (BoxType
*Box
, Coord X
, Coord Y
, unsigned Number
)
341 Coord x1
= Box
->X1
, y1
= Box
->Y1
, x2
= Box
->X2
, y2
= Box
->Y2
;
343 ROTATE (x1
, y1
, X
, Y
, Number
);
344 ROTATE (x2
, y2
, X
, Y
, Number
);
345 Box
->X1
= MIN (x1
, x2
);
346 Box
->Y1
= MIN (y1
, y2
);
347 Box
->X2
= MAX (x1
, x2
);
348 Box
->Y2
= MAX (y1
, y2
);
351 /* ----------------------------------------------------------------------
352 * rotates an objects at the cursor position as identified by its ID
353 * the center of rotation is determined by the current cursor location
356 RotateObject (int Type
, void *Ptr1
, void *Ptr2
, void *Ptr3
,
357 Coord X
, Coord Y
, unsigned Steps
)
361 bool changed
= false;
363 /* setup default global identifiers */
368 /* move all the rubberband lines... and reset the counter */
369 ptr
= Crosshair
.AttachedObject
.Rubberband
;
370 while (Crosshair
.AttachedObject
.RubberbandN
)
373 CLEAR_FLAG (RUBBERENDFLAG
, ptr
->Line
);
374 AddObjectToRotateUndoList (LINEPOINT_TYPE
, ptr
->Layer
, ptr
->Line
,
375 ptr
->MovedPoint
, CenterX
, CenterY
, Steps
);
376 EraseLine (ptr
->Line
);
379 RestoreToPolygon (PCB
->Data
, LINE_TYPE
, ptr
->Layer
, ptr
->Line
);
380 r_delete_entry (ptr
->Layer
->line_tree
, (BoxType
*) ptr
->Line
);
383 r_delete_entry (PCB
->Data
->rat_tree
, (BoxType
*) ptr
->Line
);
384 RotatePointLowLevel (ptr
->MovedPoint
, CenterX
, CenterY
, Steps
);
385 SetLineBoundingBox (ptr
->Line
);
388 r_insert_entry (ptr
->Layer
->line_tree
, (BoxType
*) ptr
->Line
, 0);
389 ClearFromPolygon (PCB
->Data
, LINE_TYPE
, ptr
->Layer
, ptr
->Line
);
390 DrawLine (ptr
->Layer
, ptr
->Line
);
394 r_insert_entry (PCB
->Data
->rat_tree
, (BoxType
*) ptr
->Line
, 0);
395 DrawRat ((RatType
*) ptr
->Line
);
397 Crosshair
.AttachedObject
.RubberbandN
--;
400 AddObjectToRotateUndoList (Type
, Ptr1
, Ptr2
, Ptr3
, CenterX
, CenterY
,
402 ptr2
= ObjectOperation (&RotateFunctions
, Type
, Ptr1
, Ptr2
, Ptr3
);
403 changed
|= (ptr2
!= NULL
);
407 IncrementUndoSerialNumber ();
413 RotateScreenObject (Coord X
, Coord Y
, unsigned Steps
)
416 void *ptr1
, *ptr2
, *ptr3
;
417 if ((type
= SearchScreen (X
, Y
, ROTATE_TYPES
, &ptr1
, &ptr2
,
420 if (TEST_FLAG (LOCKFLAG
, (ArcType
*) ptr2
))
422 Message (_("Sorry, the object is locked\n"));
425 Crosshair
.AttachedObject
.RubberbandN
= 0;
426 if (TEST_FLAG (RUBBERBANDFLAG
, PCB
))
427 LookupRubberbandLines (type
, ptr1
, ptr2
, ptr3
);
428 if (type
== ELEMENT_TYPE
)
429 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
430 RotateObject (type
, ptr1
, ptr2
, ptr3
, X
, Y
, Steps
);
431 SetChangedFlag (true);