Search code examples
iosswiftmatrixcore-graphicsmatrix-multiplication

Creating a Matrix Stack for iOS: Resetting Matrix to Identity


I'm working with Apple's Core Graphics framework and attempting to implement a push and pop matrix to isolate and encapsulate changes to the current transformation matrix (ctm) using a stack structure.

This would be external to Core Graphics' .saveGState() and .restoreGState() and the reason for this is that .saveGState() and .restoreGState() push and pop much more than just the ctm and I'd like to give my API/package users the option of separating style and matrix when pushing and popping.

The process I'd like to implement is:

  1. pushMatrix() - add ctm to stack.
  2. Do any scaling, translating, rotating, or application of a custom affine transform of the ctm.
  3. popMatrix() - change current ctm back to the last pushed state.

Here is the code I'm currently using (minus the stack code for brevity):

public func resetMatrixToIdentity() {
    let inverted = context?.ctm.inverted()
    context?.ctm.concatenating(inverted!)
}
    
open func pushMatrix() {
    let currentTransformation = (context?.ctm)!
    matrixStack.push(matrix: currentTransformation)
}
    
open func popMatrix() {
    resetMatrixToIdentity()
    context?.ctm.concatenating(matrixStack.pop()!)
}

The problem I'm having is that this code does not currently actually affect the CTM at all, so I'm wondering what I'm misunderstanding about the CTM in Core Graphics or matrix multiplication.

I am aware of this previous post and have attempted to apply the insights in my code, but it does not seem to work.


Solution

  • This was a really easy fix, so I'll answer my own question in case others make this mistake as well.

    The context's ctm property is get only. In order to set the ctm using concatenation I was trying:

    context?.ctm.concatenating(inverted!)
    

    This is incorrect. The function Core Graphics uses to concatenate is actually:

    context?.concatenate(inverted!)
    

    Once I replaced this everything worked as expected.