Issue with clip frame on canvas

I created a system to generate generic pieces for my jigsaw puzzle. I simply have to change the image of the puzzle itself and determine the amount of columns and rows and I can have a brand new puzzle, which is perfect.

However, I’m facing some issues regarding the frame added to the canvas. According to the piece, it can have 3 types of sides : Flat, Hole and Neck. The logic works fine but I can’t seem to figure out why the frame is not correctly drawn when the side is a neck.

When there’s suppose to have a neck (a section of the mask which is suppose to go further than the simple square shape), the side is simply flat. I think that the issue is caused by that line in my code below:

canvas.add(`${x}x${y}`, 0, x * pieceWidth, y * pieceHeight, pieceWidth, pieceHeight)

Since the frame can be bigger than the base shape (pieceWidth and pieceHeight), the neck is not drawn. However, When I add more space like the code below, I have some irregular mask shapes.

canvas.add(`${x}x${y}`, 0, x * pieceWidth, y * pieceHeight, pieceWidth + pieceWidth /3, pieceHeight pieceHeight /3)

Here’s my full code below:

const cols = 5 // Value can be changed to have an easier or harder puzzle
const rows = 5 // Value can be changed to have an easier or harder puzzle
const pieceWidth = this.puzzleWidth / cols
const pieceHeight = this.puzzleHeight / rows

// Create canvas texture
const canvas = this.scene.textures.createCanvas(
  'puzzlePiece',
  this.puzzleWidth,
  this.puzzleHeight
) as Phaser.Textures.CanvasTexture

// Get canvas context
const ctx = canvas.context

let index = 0

// Create mask for alll pieces
for (let x = 0; x < cols; x++) {
  for (let y = 0; y < rows; y++) {
    index++

    // Set base offset
    const xOffset = x * pieceWidth
    const yOffset = y * pieceHeight

    ctx.save()

    // Start creating the mask
    ctx.moveTo(xOffset, yOffset)
    ctx.beginPath()

   // Draw the mask according to the previous pieces generated
   // Skip this part because it is to long to showcase
   // [...]

    // Close mask path
    ctx.closePath()

    // Apply mask
    ctx.clip()

    // Draw image on texture
    const puzzleImg = this.scene.textures.get(this.puzzle.getId()).getSourceImage() as HTMLImageElement
    ctx.drawImage(puzzleImg, 0, 0)

    ctx.restore()

    // Add the texture frame
    canvas.add(`${x}x${y}`, 0, x * pieceWidth, y * pieceHeight, pieceWidth, pieceHeight)
 
    // Create piece which is a custom class which inherit the Phaser.GameObjects.Image class
    // The image use the texture created above and the frame as the section of the texture from above.
    // [...]
  }
}

canvas.refresh()

Do you have any idea why this is happening? Thanks