Search code examples
iosswiftcore-graphicsfoundation

CGAffineTransform to scale width and height only


How to scale a CGontext without affecting its origin i.e only the width and height should get scaled? If I use scale like the below one directly it scales the origin also.

context.scaledBy(x: 2.0, y: 2.0)

Is there a way to construct an AffineTransform that manipulates the width and height, leaving the origin untouched?

I want an AffineTransform that can be used to both CGContext and CGRect.

For example a CGRect rect = {x, y, w, h}

var t = CGAffineTransform.identity
t = t.scaledBy(x: sx, y: sy)
let tRect = rect.applying(t)

tRect will be {x * sx, y * sy, w * sx, h * sy}

But I want {x, y, w * sx, h * sy}. Though it can be achieved by calculation, I need CGAffineTransform to do this.


Solution

  • You need to translate the origin, then scale, then undo the translation:

    import Foundation
    import CoreGraphics
    
    let rect = CGRect(x: 1, y: 2, width: 3, height: 4) // Whatever
    
    // Translation to move rect's origin to <0,0>
    let t0 = CGAffineTransform(translationX: -rect.origin.x, y: -rect.origin.y)
    // Scale - <0,0> will not move, width & height will
    let ts = CGAffineTransform(scaleX: 2, y: 3) // Whatever
    // Translation to restore origin
    let t1 = CGAffineTransform(translationX: rect.origin.x, y: rect.origin.y)
    
    //Compound transform:
    let t = t0.concatenating(ts).concatenating(t1)
    
    // Test it:
    let tRect = rect.applying(t) // 1, 2, 6, 12 as required