Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS drawImage fails with IndexSizeError: The index is not in allowed range #5951

Closed
Hoshinokoe opened this issue Dec 21, 2021 · 3 comments
Closed

Comments

@Hoshinokoe
Copy link

Version

  • Phaser Version: 3.55.2
  • Operating system: iOS (Desktop and mobile)
  • Browser: Safari, Chrome

Description

Following code fails only on iOS:

if (sprite.mask)
{
    sprite.mask.preRenderCanvas(this, sprite, camera);
}

//this line fails with parameters
//frameX = 0, frameY = 446, frameWidth = 219, frameHieght = 0, x = 0, y = 446, w = 219, h = 0      
ctx.drawImage(frame.source.image, frameX, frameY, frameWidth, frameHeight, x, y, frameWidth / res, frameHeight / res);

if (sprite.mask)
{
    sprite.mask.postRenderCanvas(this, sprite, camera);
}

Example Test Code

Example makes a printer (ejects paper) and fails on startup. Perfectly works on Windows (Chrome & Firefox).

var config = {
        type: Phaser.CANVAS,
        width: 480,
        height: 800,
        backgroundColor: '#cecece',
        physics: {
            default: 'arcade',
            arcade: {
                gravity: { y: 200 }
            }
        },
        scene: {
            preload: preload,
            create: create
        }
    };

    var game = new Phaser.Game(config);

    function preload ()
    {
        this.load.image('paper', 'https://gmteurope3.blob.core.windows.net/luckyshopperupload/55643243F3C039026025A983ACD9CFA7.png');
        this.load.image('button', 'https://gmteurope3.blob.core.windows.net/luckyshopperupload/F2F4FBA5857036A6E26DF0579E938AED.png');
    }

    function create ()
    {
        var noteBackgroundImage = this.make.image({ x: 0, y: 0, key: 'paper', add: false }).setOrigin(0);

        this.paperHeight = noteBackgroundImage.height;
        this.paperWidth = noteBackgroundImage.width;
        this.feedPosition = 0;
        this.printSpeedPixelsPerSec = 300;
        this.footerHeight = 94;
        this.headerHeight = 98;
        this.lineItemHeight = (this.paperHeight - this.footerHeight - this.headerHeight) / 9;
        this.lineItems = new Array();

        var button = this.add.image(30, 720, 'button').setOrigin(0);
        button.setInteractive();
        button.on('pointerdown', function () {
            this.feedPosition += this.lineItemHeight;
            var duration = this.lineItemHeight / this.printSpeedPixelsPerSec * 1000;

            var tweenCropRect = this.tweens.add({
                targets: this.cropRect,
                y: Math.max(this.paperHeight - this.feedPosition, 0),
                duration: duration,
                ease: Phaser.Math.Easing.Quadratic.Out,
                paused: true
            }).play();

            this.positionY += this.lineItemHeight;
            var tweenReceipt = this.tweens.add({
                targets: this.noteRenderTexture,
                y: this.positionY,
                duration: duration,
                ease: Phaser.Math.Easing.Quadratic.Out,
                paused: true
            }).play();
        }, this);
        
        this.positionY = 100 - noteBackgroundImage.height;

        this.cropRect = new Phaser.Geom.Rectangle(0, this.paperHeight, this.paperWidth, this.paperHeight);

        this.noteRenderTexture = this.make.renderTexture({ x: 100, y: 100 - noteBackgroundImage.height, width: noteBackgroundImage.width, height: noteBackgroundImage.height, add: true }).setOrigin(0);
        this.noteRenderTexture.draw(noteBackgroundImage, 0, 0);
        this.noteRenderTexture.setCrop(this.cropRect);
        this.noteRenderTexture.saveTexture();

        this.events.on('update', function () {
            this.noteRenderTexture.setCrop(this.cropRect);
        }, this);
    }

Additional Information

@photonstorm
Copy link
Collaborator

This error would happen if the values you've given (i.e. the tweened crop) are out of the range of the image being drawn, as it can't crop beyond the limits of the source texture, or into negative space.

I suspect it may also not be happy with non-integer crop values as well (which a tween would certainly generate).

@Hoshinokoe
Copy link
Author

Hoshinokoe commented Dec 21, 2021

@photonstorm

Simplified example to remove tweens:

    function create ()
    {
        var paper = this.make.image({ x: 0, y: 0, key: 'paper', add: false }).setOrigin(0);
        this.cropRect = new Phaser.Geom.Rectangle(0, paper.height, paper.width, paper.height);

        this.noteRenderTexture = this.make.renderTexture({
            x: 100, y: 100 - paper.height,
            width: paper.width,
            height: paper.height,
            add: true
        }).setOrigin(0);

        this.noteRenderTexture.draw(paper, 0, 0);
        this.noteRenderTexture.setCrop(this.cropRect);
        this.noteRenderTexture.saveTexture();
    }

All values are valid.

@photonstorm
Copy link
Collaborator

A width or height of zero is an invalid size for canvas drawImage. These are now checked for in code and it skips the drawImage if they are found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants