Skip to content

Commit a047275

Browse files
committed
AffineTransform: Align with Darwin and misc fixes
- init(): Return a matrix with identity values. - NSAffineTransform: Fix constructor convenience init(transform: NSAffineTransform) -> convenience init(transform: AffineTransform) - Add NSAffineTransformStruct type and use for NSAffineTransform.transformStruct - NSAffineTransform: Store a private AffineTransform to use as backing. - Fixup tests.
1 parent a0f8df7 commit a047275

File tree

2 files changed

+107
-66
lines changed

2 files changed

+107
-66
lines changed

Foundation/AffineTransform.swift

Lines changed: 85 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,19 @@ public struct AffineTransform : ReferenceConvertible, Hashable, CustomStringConv
3232
public var m22: CGFloat
3333
public var tX: CGFloat
3434
public var tY: CGFloat
35-
35+
36+
// init() returns affine transformation matrix with identity values.
3637
public init() {
37-
self.init(m11: CGFloat(), m12: CGFloat(), m21: CGFloat(), m22: CGFloat(), tX: CGFloat(), tY: CGFloat())
38+
self.init(m11: 1.0, m12: 0.0,
39+
m21: 0.0, m22: 1.0,
40+
tX: 0.0, tY: 0.0)
3841
}
42+
3943
public init(m11: CGFloat, m12: CGFloat, m21: CGFloat, m22: CGFloat, tX: CGFloat, tY: CGFloat) {
4044
(self.m11, self.m12, self.m21, self.m22) = (m11, m12, m21, m22)
4145
(self.tX, self.tY) = (tX, tY)
4246
}
4347

44-
private init(reference: NSAffineTransform) {
45-
self = reference.transformStruct
46-
}
47-
48-
private var reference : NSAffineTransform {
49-
let ref = NSAffineTransform()
50-
ref.transformStruct = self
51-
return ref
52-
}
53-
5448
/**
5549
Creates an affine transformation matrix from translation values.
5650
The matrix takes the following form:
@@ -279,8 +273,57 @@ public struct AffineTransform : ReferenceConvertible, Hashable, CustomStringConv
279273
}
280274
}
281275

276+
public struct NSAffineTransformStruct {
277+
public var m11: CGFloat
278+
public var m12: CGFloat
279+
public var m21: CGFloat
280+
public var m22: CGFloat
281+
public var tX: CGFloat
282+
public var tY: CGFloat
283+
284+
// This is NOT an identity matrix
285+
public init() {
286+
m11 = 0.0
287+
m12 = 0.0
288+
m21 = 0.0
289+
m22 = 0.0
290+
tX = 0.0
291+
tY = 0.0
292+
}
293+
294+
public init(m11: CGFloat, m12: CGFloat, m21: CGFloat, m22: CGFloat, tX: CGFloat, tY: CGFloat) {
295+
self.m11 = m11
296+
self.m12 = m12
297+
self.m21 = m21
298+
self.m22 = m22
299+
self.tX = tX
300+
self.tY = tY
301+
}
302+
}
303+
282304
open class NSAffineTransform : NSObject, NSCopying, NSSecureCoding {
283-
305+
306+
private var affineTransform: AffineTransform
307+
308+
public var transformStruct: NSAffineTransformStruct {
309+
get {
310+
return NSAffineTransformStruct(m11: affineTransform.m11,
311+
m12: affineTransform.m12,
312+
m21: affineTransform.m21,
313+
m22: affineTransform.m22,
314+
tX: affineTransform.tX,
315+
tY: affineTransform.tY)
316+
}
317+
set {
318+
affineTransform.m11 = newValue.m11
319+
affineTransform.m12 = newValue.m12
320+
affineTransform.m21 = newValue.m21
321+
affineTransform.m22 = newValue.m22
322+
affineTransform.tX = newValue.tX
323+
affineTransform.tY = newValue.tY
324+
}
325+
}
326+
284327
open func encode(with aCoder: NSCoder) {
285328
guard aCoder.allowsKeyedCoding else {
286329
preconditionFailure("Unkeyed coding is unsupported.")
@@ -301,7 +344,7 @@ open class NSAffineTransform : NSObject, NSCopying, NSSecureCoding {
301344
}
302345

303346
open func copy(with zone: NSZone? = nil) -> Any {
304-
return NSAffineTransform(transform: self)
347+
return NSAffineTransform(transform: affineTransform)
305348
}
306349

307350
// Necessary because `NSObject.copy()` returns `self`.
@@ -328,53 +371,54 @@ open class NSAffineTransform : NSObject, NSCopying, NSSecureCoding {
328371
let tX = floatPointer[4]
329372
let tY = floatPointer[5]
330373

331-
self.transformStruct = AffineTransform(m11: CGFloat(m11), m12: CGFloat(m12),
332-
m21: CGFloat(m21), m22: CGFloat(m22),
333-
tX: CGFloat(tX), tY: CGFloat(tY))
374+
affineTransform = AffineTransform(m11: CGFloat(m11), m12: CGFloat(m12),
375+
m21: CGFloat(m21), m22: CGFloat(m22),
376+
tX: CGFloat(tX), tY: CGFloat(tY))
334377
}
335378

336379
open override func isEqual(_ object: Any?) -> Bool {
337380
guard let other = object as? NSAffineTransform else { return false }
338-
return other === self
339-
|| (other.transformStruct == self.transformStruct)
381+
return other === self || (other.affineTransform == self.affineTransform)
340382
}
341383

342384
open override var hashValue: Int {
343-
return transformStruct.hashValue
385+
return affineTransform.hashValue
344386
}
345387

346388
public static var supportsSecureCoding: Bool {
347389
return true
348390
}
349391

350392
// Initialization
351-
public convenience init(transform: NSAffineTransform) {
393+
public convenience init(transform: AffineTransform) {
352394
self.init()
353-
transformStruct = transform.transformStruct
395+
affineTransform = transform
354396
}
355-
397+
398+
// init() returns affine transformation matrix with identity values.
356399
public override init() {
357-
transformStruct = AffineTransform(
400+
affineTransform = AffineTransform(
358401
m11: CGFloat(1.0), m12: CGFloat(),
359402
m21: CGFloat(), m22: CGFloat(1.0),
360403
tX: CGFloat(), tY: CGFloat()
361404
)
362405
}
363-
406+
364407
// Translating
365408
open func translateX(by deltaX: CGFloat, yBy deltaY: CGFloat) {
366409
let translation = AffineTransform(translationByX: deltaX, byY: deltaY)
367-
transformStruct = translation.concatenated(transformStruct)
410+
affineTransform = translation.concatenated(affineTransform)
368411
}
369412

370413
// Rotating
371414
open func rotate(byDegrees angle: CGFloat) {
372415
let rotation = AffineTransform(rotationByDegrees: angle)
373-
transformStruct = rotation.concatenated(transformStruct)
416+
affineTransform = rotation.concatenated(affineTransform)
374417
}
418+
375419
open func rotate(byRadians angle: CGFloat) {
376420
let rotation = AffineTransform(rotationByRadians: angle)
377-
transformStruct = rotation.concatenated(transformStruct)
421+
affineTransform = rotation.concatenated(affineTransform)
378422
}
379423

380424
// Scaling
@@ -384,38 +428,36 @@ open class NSAffineTransform : NSObject, NSCopying, NSSecureCoding {
384428

385429
open func scaleX(by scaleX: CGFloat, yBy scaleY: CGFloat) {
386430
let scale = AffineTransform(scaleByX: scaleX, byY: scaleY)
387-
transformStruct = scale.concatenated(transformStruct)
431+
affineTransform = scale.concatenated(affineTransform)
388432
}
389433

390434
// Inverting
391435
open func invert() {
392-
if let inverse = transformStruct.inverted() {
393-
transformStruct = inverse
436+
if let inverse = affineTransform.inverted() {
437+
affineTransform = inverse
394438
}
395439
else {
396440
preconditionFailure("NSAffineTransform: Transform has no inverse")
397441
}
398442
}
399443

400444
// Transforming with transform
401-
open func append(_ transform: NSAffineTransform) {
402-
transformStruct = transformStruct.concatenated(transform.transformStruct)
445+
open func append(_ transform: AffineTransform) {
446+
affineTransform = affineTransform.concatenated(transform)
403447
}
404-
open func prepend(_ transform: NSAffineTransform) {
405-
transformStruct = transform.transformStruct.concatenated(transformStruct)
448+
449+
open func prepend(_ transform: AffineTransform) {
450+
affineTransform = transform.concatenated(affineTransform)
406451
}
407452

408453
// Transforming points and sizes
409454
open func transform(_ aPoint: NSPoint) -> NSPoint {
410-
return transformStruct.transform(aPoint)
455+
return affineTransform.transform(aPoint)
411456
}
412457

413458
open func transform(_ aSize: NSSize) -> NSSize {
414-
return transformStruct.transform(aSize)
459+
return affineTransform.transform(aSize)
415460
}
416-
417-
// Transform Struct
418-
open var transformStruct: AffineTransform
419461
}
420462

421463
extension AffineTransform : _ObjectTypeBridgeable {
@@ -429,9 +471,7 @@ extension AffineTransform : _ObjectTypeBridgeable {
429471

430472
@_semantics("convertToObjectiveC")
431473
public func _bridgeToObjectiveC() -> NSAffineTransform {
432-
let t = NSAffineTransform()
433-
t.transformStruct = self
434-
return t
474+
return NSAffineTransform(transform: self)
435475
}
436476

437477
public static func _forceBridgeFromObjectiveC(_ x: NSAffineTransform, result: inout AffineTransform?) {
@@ -441,7 +481,8 @@ extension AffineTransform : _ObjectTypeBridgeable {
441481
}
442482

443483
public static func _conditionallyBridgeFromObjectiveC(_ x: NSAffineTransform, result: inout AffineTransform?) -> Bool {
444-
result = x.transformStruct
484+
let ts = x.transformStruct
485+
result = AffineTransform(m11: ts.m11, m12: ts.m12, m21: ts.m21, m22: ts.m22, tX: ts.tX, tY: ts.tY)
445486
return true // Can't fail
446487
}
447488

TestFoundation/TestAffineTransform.swift

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -197,14 +197,14 @@ class TestAffineTransform : XCTestCase {
197197
func test_Inversion() {
198198
let point = NSPoint(x: CGFloat(10.0), y: CGFloat(10.0))
199199

200-
let translate = NSAffineTransform()
201-
translate.translateX(by: CGFloat(-30.0), yBy: CGFloat(40.0))
200+
var translate = AffineTransform()
201+
translate.translate(x: CGFloat(-30.0), y: CGFloat(40.0))
202202

203-
let rotate = NSAffineTransform()
203+
var rotate = AffineTransform()
204204
translate.rotate(byDegrees: CGFloat(30.0))
205205

206-
let scale = NSAffineTransform()
207-
scale.scale(by: CGFloat(2.0))
206+
var scale = AffineTransform()
207+
scale.scale(CGFloat(2.0))
208208

209209
let identityTransform = NSAffineTransform()
210210

@@ -270,15 +270,15 @@ class TestAffineTransform : XCTestCase {
270270
func test_AppendTransform() {
271271
let point = NSPoint(x: CGFloat(10.0), y: CGFloat(10.0))
272272

273-
let identityTransform = NSAffineTransform()
273+
var identityTransform = AffineTransform()
274274
identityTransform.append(identityTransform)
275-
checkPointTransformation(identityTransform, point: point, expectedPoint: point)
275+
checkPointTransformation(NSAffineTransform(transform: identityTransform), point: point, expectedPoint: point)
276276

277-
let translate = NSAffineTransform()
278-
translate.translateX(by: CGFloat(10.0), yBy: CGFloat())
277+
var translate = AffineTransform()
278+
translate.translate(x: CGFloat(10.0), y: CGFloat())
279279

280-
let scale = NSAffineTransform()
281-
scale.scale(by: CGFloat(2.0))
280+
var scale = AffineTransform()
281+
scale.scale(CGFloat(2.0))
282282

283283
let translateThenScale = NSAffineTransform(transform: translate)
284284
translateThenScale.append(scale)
@@ -288,15 +288,15 @@ class TestAffineTransform : XCTestCase {
288288
func test_PrependTransform() {
289289
let point = NSPoint(x: CGFloat(10.0), y: CGFloat(10.0))
290290

291-
let identityTransform = NSAffineTransform()
291+
var identityTransform = AffineTransform()
292292
identityTransform.prepend(identityTransform)
293-
checkPointTransformation(identityTransform, point: point, expectedPoint: point)
293+
checkPointTransformation(NSAffineTransform(transform: identityTransform), point: point, expectedPoint: point)
294294

295-
let translate = NSAffineTransform()
296-
translate.translateX(by: CGFloat(10.0), yBy: CGFloat())
295+
var translate = AffineTransform()
296+
translate.translate(x: CGFloat(10.0), y: CGFloat())
297297

298-
let scale = NSAffineTransform()
299-
scale.scale(by: CGFloat(2.0))
298+
var scale = AffineTransform()
299+
scale.scale(CGFloat(2.0))
300300

301301
let scaleThenTranslate = NSAffineTransform(transform: translate)
302302
scaleThenTranslate.prepend(scale)
@@ -313,13 +313,13 @@ class TestAffineTransform : XCTestCase {
313313
let rotate = NSAffineTransform()
314314
rotate.rotate(byDegrees: CGFloat(90.0))
315315

316-
let moveOrigin = NSAffineTransform()
317-
moveOrigin.translateX(by: -center.x, yBy: -center.y)
316+
var moveOrigin = AffineTransform()
317+
moveOrigin.translate(x: -center.x, y: -center.y)
318318

319-
let moveBack = NSAffineTransform(transform: moveOrigin)
319+
var moveBack = moveOrigin
320320
moveBack.invert()
321321

322-
let rotateAboutCenter = NSAffineTransform(transform: rotate)
322+
let rotateAboutCenter = rotate
323323
rotateAboutCenter.prepend(moveOrigin)
324324
rotateAboutCenter.append(moveBack)
325325

@@ -344,7 +344,7 @@ class TestAffineTransform : XCTestCase {
344344
]
345345
for val in values {
346346
let ref = NSAffineTransform()
347-
ref.transformStruct = val
347+
ref.transformStruct = NSAffineTransformStruct(m11: val.m11, m12: val.m12, m21: val.m21, m22: val.m22, tX: val.tX, tY: val.tY)
348348
XCTAssertEqual(ref.hashValue, val.hashValue)
349349
}
350350
}

0 commit comments

Comments
 (0)