Skip to content

Commit 59a8aad

Browse files
author
Dominique d'Argent
committed
Implement NSAffineTransform methods
1 parent 34d8865 commit 59a8aad

File tree

1 file changed

+168
-30
lines changed

1 file changed

+168
-30
lines changed

Foundation/NSAffineTransform.swift

Lines changed: 168 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
88
//
99

10+
#if os(OSX) || os(iOS)
11+
import Darwin
12+
#elseif os(Linux)
13+
import Glibc
14+
#endif
1015

1116
public struct NSAffineTransformStruct {
1217
public var m11: CGFloat
@@ -52,57 +57,190 @@ public class NSAffineTransform : NSObject, NSCopying, NSSecureCoding {
5257
}
5358

5459
public override init() {
55-
transformStruct = NSAffineTransformStruct(m11: CGFloat(1.0), m12: CGFloat(), m21: CGFloat(), m22: CGFloat(1.0), tX: CGFloat(), tY: CGFloat())
60+
transformStruct = NSAffineTransformStruct(
61+
m11: CGFloat(1.0), m12: CGFloat(),
62+
m21: CGFloat(), m22: CGFloat(1.0),
63+
tX: CGFloat(), tY: CGFloat()
64+
)
5665
}
5766

5867
// Translating
59-
public func translateXBy(deltaX: CGFloat, yBy deltaY: CGFloat) { NSUnimplemented() }
68+
public func translateXBy(deltaX: CGFloat, yBy deltaY: CGFloat) {
69+
let translation = NSAffineTransformStruct.translation(tX: deltaX, tY: deltaY)
70+
71+
transformStruct = transformStruct.concat(translation)
72+
}
6073

6174
// Rotating
62-
public func rotateByDegrees(angle: CGFloat) { NSUnimplemented() }
63-
public func rotateByRadians(angle: CGFloat) { NSUnimplemented() }
75+
public func rotateByDegrees(angle: CGFloat) {
76+
let rotation = NSAffineTransformStruct.rotation(degrees: angle)
77+
78+
transformStruct = transformStruct.concat(rotation)
79+
}
80+
public func rotateByRadians(angle: CGFloat) {
81+
let rotation = NSAffineTransformStruct.rotation(radians: angle)
82+
83+
transformStruct = transformStruct.concat(rotation)
84+
}
6485

6586
// Scaling
66-
public func scaleBy(scale: CGFloat) { NSUnimplemented() }
67-
public func scaleXBy(scaleX: CGFloat, yBy scaleY: CGFloat) { NSUnimplemented() }
87+
public func scaleBy(scale: CGFloat) {
88+
let scale = NSAffineTransformStruct.scale(sX: scale, sY: scale)
89+
90+
transformStruct = transformStruct.concat(scale)
91+
}
92+
public func scaleXBy(scaleX: CGFloat, yBy scaleY: CGFloat) {
93+
let scale = NSAffineTransformStruct.scale(sX: scaleX, sY: scaleY)
94+
95+
transformStruct = transformStruct.concat(scale)
96+
}
6897

6998
// Inverting
7099
public func invert() { NSUnimplemented() }
71100

72101
// Transforming with transform
73-
public func appendTransform(transform: NSAffineTransform) { NSUnimplemented() }
74-
public func prependTransform(transform: NSAffineTransform) { NSUnimplemented() }
102+
public func appendTransform(transform: NSAffineTransform) {
103+
transformStruct = transformStruct.concat(transform.transformStruct)
104+
}
105+
public func prependTransform(transform: NSAffineTransform) {
106+
transformStruct = transform.transformStruct.concat(transformStruct)
107+
}
75108

76109
// Transforming points and sizes
77110
public func transformPoint(aPoint: NSPoint) -> NSPoint {
78-
let (t, p) = (transformStruct, aPoint)
111+
return transformStruct.applied(toPoint: aPoint)
112+
}
113+
114+
public func transformSize(aSize: NSSize) -> NSSize {
115+
return transformStruct.applied(toSize: aSize)
116+
}
117+
118+
// Transform Struct
119+
public var transformStruct: NSAffineTransformStruct
120+
}
121+
122+
123+
private extension NSAffineTransformStruct {
124+
/**
125+
Creates an affine transformation matrix from translation values.
126+
The matrix takes the following form:
127+
128+
[ 1 0 tX ]
129+
[ 0 1 tY ]
130+
[ 0 0 1 ]
131+
*/
132+
static func translation(tX tX: CGFloat, tY: CGFloat) -> NSAffineTransformStruct {
133+
return NSAffineTransformStruct(
134+
m11: CGFloat(1.0), m12: CGFloat(),
135+
m21: CGFloat(), m22: CGFloat(1.0),
136+
tX: tX, tY: tY
137+
)
138+
}
139+
140+
/**
141+
Creates an affine transformation matrix from scaling values.
142+
The matrix takes the following form:
143+
144+
[ sX 0 0 ]
145+
[ 0 sY 0 ]
146+
[ 0 0 1 ]
147+
*/
148+
static func scale(sX sX: CGFloat, sY: CGFloat) -> NSAffineTransformStruct {
149+
return NSAffineTransformStruct(
150+
m11: sX, m12: CGFloat(),
151+
m21: CGFloat(), m22: sY,
152+
tX: CGFloat(), tY: CGFloat()
153+
)
154+
}
155+
156+
/**
157+
Creates an affine transformation matrix from rotation value (angle in radians).
158+
The matrix takes the following form:
159+
160+
[ cos α -sin α 0 ]
161+
[ sin α cos α 0 ]
162+
[ 0 0 1 ]
163+
*/
164+
static func rotation(radians angle: CGFloat) -> NSAffineTransformStruct {
165+
let α = Double(angle)
79166

80-
/**
81-
[ x' ] [ x ] [ m11 m12 tX ] [ x ] [ m11*x + m12*y + tX ]
82-
[ y' ] = T [ y ] = [ m21 m22 tY ] [ y ] = [ m21*x + m22*y + tY ]
83-
[ 1 ] [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
84-
*/
85-
let x = (t.m11 * p.x) + (t.m12 * p.y) + t.tX
86-
let y = (t.m21 * p.x) + (t.m22 * p.y) + t.tY
167+
return NSAffineTransformStruct(
168+
m11: CGFloat(cos(α)), m12: CGFloat(-sin(α)),
169+
m21: CGFloat(sin(α)), m22: CGFloat(cos(α)),
170+
tX: CGFloat(), tY: CGFloat()
171+
)
172+
}
173+
174+
/**
175+
Creates an affine transformation matrix from a rotation value (angle in degrees).
176+
The matrix takes the following form:
177+
178+
[ cos α -sin α 0 ]
179+
[ sin α cos α 0 ]
180+
[ 0 0 1 ]
181+
*/
182+
static func rotation(degrees angle: CGFloat) -> NSAffineTransformStruct {
183+
let α = Double(angle) * M_PI / 180.0
87184

88-
return NSPoint(x: x, y: y)
185+
return rotation(radians: CGFloat(α))
89186
}
187+
188+
/**
189+
Creates an affine transformation matrix by combining the receiver with `transformStruct`.
190+
That is, it computes `T * M` and returns the result, where `T` is the receiver's and `M` is
191+
the `transformStruct`'s affine transformation matrix.
192+
The resulting matrix takes the following form:
193+
194+
[ m11_T m12_T tX_T ] [ m11_M m12_M tX_M ]
195+
T * M = [ m21_T m22_T tY_T ] [ m21_M m22_M tY_M ]
196+
[ 0 0 1 ] [ 0 0 1 ]
197+
198+
[ (m11_T*m11_M + m12_T*m21_M) (m11_T*m12_M + m12_T*m22_M) (m11_T*tX_M + m12_T*tY_M + tX_T) ]
199+
= [ (m21_T*m11_M + m22_T*m21_M) (m21_T*m12_M + m22_T*m22_M) (m21_T*tX_M + m22_T*tY_M + tY_T) ]
200+
[ 0 0 1 ]
201+
*/
202+
func concat(transformStruct: NSAffineTransformStruct) -> NSAffineTransformStruct {
203+
let (t, m) = (self, transformStruct)
90204

91-
public func transformSize(aSize: NSSize) -> NSSize {
92-
let (t, s) = (transformStruct, aSize)
205+
return NSAffineTransformStruct(
206+
m11: (t.m11 * m.m11) + (t.m12 * m.m21), m12: (t.m11 * m.m12) + (t.m12 * m.m22),
207+
m21: (t.m21 * m.m11) + (t.m22 * m.m21), m22: (t.m21 * m.m12) + (t.m22 * m.m22),
208+
tX: (t.m11 * m.tX) + (t.m12 * m.tY) + t.tX,
209+
tY: (t.m21 * m.tX) + (t.m22 * m.tY) + t.tY
210+
)
211+
}
212+
213+
/**
214+
Applies the affine transformation to `toPoint` and returns the result.
215+
The resulting point takes the following form:
216+
217+
[ x' ] [ x ] [ m11 m12 tX ] [ x ] [ m11*x + m12*y + tX ]
218+
[ y' ] = T [ y ] = [ m21 m22 tY ] [ y ] = [ m21*x + m22*y + tY ]
219+
[ 1 ] [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
220+
*/
221+
func applied(toPoint p: NSPoint) -> NSPoint {
222+
let x = (m11 * p.x) + (m12 * p.y) + tX
223+
let y = (m21 * p.x) + (m22 * p.y) + tY
93224

94-
/**
95-
[ w' ] [ w ] [ m11 m12 tX ] [ w ] [ m11*w + m12*h ]
96-
[ h' ] = T [ h ] = [ m21 m22 tY ] [ h ] = [ m21*w + m22*h ]
97-
[ 0 ] [ 0 ] [ 0 0 1 ] [ 1 ] [ 0 ]
98-
NOTE: Translation has no effect on sizes.
99-
*/
100-
let w = (t.m11 * s.width) + (t.m12 * s.height)
101-
let h = (t.m21 * s.width) + (t.m22 * s.height)
225+
return NSPoint(x: x, y: y)
226+
}
227+
228+
/**
229+
Applies the affine transformation to `toSize` and returns the result.
230+
The resulting size takes the following form:
231+
232+
[ w' ] [ w ] [ m11 m12 tX ] [ w ] [ m11*w + m12*h ]
233+
[ h' ] = T [ h ] = [ m21 m22 tY ] [ h ] = [ m21*w + m22*h ]
234+
[ 0 ] [ 0 ] [ 0 0 1 ] [ 1 ] [ 0 ]
235+
236+
Note: Translation has no effect on the size.
237+
*/
238+
func applied(toSize s: NSSize) -> NSSize {
239+
let w = (m11 * s.width) + (m12 * s.height)
240+
let h = (m21 * s.width) + (m22 * s.height)
102241

103242
return NSSize(width: w, height: h)
104243
}
105-
106-
// Transform Struct
107-
public var transformStruct: NSAffineTransformStruct
108244
}
245+
246+

0 commit comments

Comments
 (0)