shanethehat
shanethehat

Reputation: 15570

BitmapData.draw clipRect not working as expected

I have a component that contains 4 layers: (in ascending depth order) bgImage:Sprite, dropZone:Sprite, dropMask:Sprite and line:Sprite. The bgImage is at 0,0, and the other objects are placed at various positive coordinates. dropMask is masking dropZone.

At the point of bitmap capture I want to only draw from the dropZone and dropMask layers, so I'm trying this:

removeChild(bgImage);
removeChild(line);
var bmd:BitmapData = new BitmapData(dropMask.width,dropMask.height,true,0);
bmd.draw(this,null,null,null,dropMask.getBounds(this));

Despite the dropMask being located at 50,60 the capture always starts from 0,0. I've also tried getting the boundary rectangle and forcing the x,y, but it makes no difference. What am I doing wrong here, and should I just forget clipRect and use a matrix instead?

Upvotes: 3

Views: 5447

Answers (2)

Michael Antipin
Michael Antipin

Reputation: 3532

A common routine for that:

var rect:Rectangle = dropMask.getRect(dropMask.parent);
var matrix:Matrix = new Matrix();
matrix.translate(-rect.x, -rect.y);
var bmp:BitmapData = new BitmapData(rect.width, rect.height, false, 0xFFFF0000);
bmp.draw(dropMask.parent, matrix);

Solution steps:

  1. get a rectangle in coordinate space of what you are going to draw.
  2. get identity matrix, and translate it by -rectangle.x, -rectangle.y
  3. use this matrix in draw() call.

In step 1 you may even encounter something like that:

import flash.display.Sprite;

var test:Sprite = new Sprite();
test.graphics.beginFill(0, 1);
test.graphics.drawCircle(125, 234, 100);
test.graphics.endFill();

// we are going to draw test, so we get a rectangle 
// in its own coordinate space to deal with registration point offset
var rect:Rectangle = test.getRect(test);
var matrix:Matrix = new Matrix();
matrix.translate(-rect.x, -rect.y);
var bmp:BitmapData = new BitmapData(rect.width, rect.height, false, 0xFFFF0000);
bmp.draw(test, matrix);

// see if we are done
addChild(new Bitmap(bmp));

When I code something that uses a lot of drawing clips, I create a matrix and reuse it each time, doing matrix.identity(); to reset transforms. No need to create new matrix for each drawing.

EDIT And no, clipRect doesn't help here. You use it only when you want to draw somthing partially, not the whole clip.

Upvotes: 7

shanethehat
shanethehat

Reputation: 15570

Nevermind, I've misunderstood the purpose of clipRect. http://pixelwelders.com/blog/actionscript-3/2008/as3-bitmapdata-foibles/. Using a matrix for this is easy and solves the problem.

var mat:Matrix = new Matrix(1,0,0,1,-offsetX,-offsetY);
bmd.draw(this,mat);

Upvotes: 0

Related Questions