Search code examples
actionscript-3haxeopenfl

Drawing sprite onto bitmapData without padding


I have a sprite which is a primitive rectangle rotated by 45 degrees. I'd like to create a Bitmap using BitmapData which will copy it exactly. I thought that BitmapData#draw will operate only on my sprite, so I tried naive approach:

var a = new Sprite();
a.graphics.beginFill(0xFF0000);
a.graphics.drawRect(0, 0, 200, 100);
a.graphics.endFill();
a.x = 100;
a.y = 100;
a.rotation = 45;

addChild(a);

var bitmapData = new openfl.display.BitmapData(1500, 1500, false, 0x00000000);
bitmapData.draw(a);

var bitmap = new openfl.display.Bitmap(bitmapData);
bitmap.x = 500;
bitmap.y = 100;
addChild(bitmap);

However the result surprised me: Weird padding

It seems it preserves transformation matrix (which in fact makes sense, otherwise rotation would be lost). So I tried more robust approach:

var bitmapData = new openfl.display.BitmapData(1500, 1500, false, 0x00000000);

var rect = a.getBounds(a.parent);
var matrix = a.transform.concatenatedMatrix;
matrix.translate(-rect.left, -rect.top);
bitmapData.draw(a, matrix);

Desired result is

And still, same result as in the image provided. I've tried clipRect param, but even more weirdly, no matter how big the rectangle is, object is not copied at all (only black space remains). I forgot about x and y, clip is not an issue

var bitmapData = new openfl.display.BitmapData(1500, 1500, false, 0x00000000);
var clip = new openfl.geom.Rectangle(1500, 1500);
bitmapData.draw(a, clip);

Am I misusing BitmapData#draw? Any help appreciated

(It must be BitmapData, as I have to use it in pixel-perfect collision testing using BitmapData#hitTest)

OpenFL 4.0.0
Tested with Cpp, Neko and HTML5

Thank you.


Solution

  • With Flash, the proper result should be a solid rectangle at the top left of the bitmap area, like this:

    var sp:Sprite = new Sprite();
            sp.graphics.beginFill(0xff0000, 1);
            sp.graphics.drawRect(0, 0, 100, 50);
            sp.graphics.endFill();
            sp.x = 100;
            sp.y = 100;
            sp.rotation = 45;
            addChild(sp);
            var bd:BitmapData = new BitmapData(400, 400, false, 0);
            bd.draw(sp);
            var bm:Bitmap = new Bitmap(bd);
            bm.x = 200;
            bm.y = 0;
            addChild(bm);
    

    Result:

    drawn bitmap

    So really, check the OpenFL behavior, if it's default to use the transformation matrix of passed target, then OK, but for Flash the default behavior is to only use the passed matrix if there is one.

    EDIT: Tested with your code too:

    var rect = sp.getBounds(sp.parent);
    var matrix = sp.transform.concatenatedMatrix;
    matrix.translate(-rect.left, -rect.top);
    bd.draw(sp, matrix);
    

    The result matches your desired result. So yes, this should be an OpenFL bug.