+1  A: 

Using the display objects getBounds function can be a reliable solution to translate the coordinates while drawing :

private function drawOntoGraphics(source : IBitmapDrawable, target : Graphics, position : Point = null) : void
{
        position = position == null ? new Point() : position;

        var bounds : Rectangle = DisplayObject(source).getBounds(DisplayObject(source));
        var bitmapData : BitmapData = new BitmapData(bounds.width, bounds.height, true, 0x00000000);

        bitmapData.draw(source, new Matrix(1, 0, 0, 1, -bounds.x, -bounds.y), null, null, null, true);
        target.beginBitmapFill(bitmapData, new Matrix(1, 0, 0, 1, bounds.x + position.x, bounds.y + position.y));
        target.drawRect(bounds.x + position.x, bounds.y + position.y, bounds.width, bounds.height);
}

In addition to your comments... Below the same method using a BitmapData instead of the Graphics object as canvas:

private function drawOntoBitmapData(source : IBitmapDrawable, target : BitmapData, position : Point = null) : void
{
    position = position == null ? new Point() : position;
    var bounds : Rectangle = DisplayObject(source).getBounds(DisplayObject(source));
    var bitmapData : BitmapData = new BitmapData(bounds.width, bounds.height, true, 0x00000000);
    bitmapData.draw(source, new Matrix(1, 0, 0, 1, -bounds.x, -bounds.y), null, null, null, true);
    target.draw(bitmapData, new Matrix(1, 0, 0, 1, bounds.x + position.x, bounds.y + position.y));
}
Theo.T
beginBitmapFill() using a Matrix doesn't actually change where on the target Graphics surface the bitmap is drawn - it just shifts the bitmap brush around itself. What I want is to draw a rectangle anywhere on the target Graphics surface, using the bitmap as a brush. Am I making any sense?
bzlm
What I mean is that I want the rectangle containing the bitmap to be drawn at an arbitrary position on the target surface. I'm not sure what the "position" parameter in your drawOntoGraphics() does, other than rotate (along x and y) the source bitmap within its own container.
bzlm
Sorry, I forgot to add the position to the drawRect() - last line. It seems to work fine now.
Theo.T
Aha. I see now that the trick is to match the beginBitmapFill() transform Matrix coordinates with the drawRect() coordinates exactly. Your function meets my particular need perfectly. Thanks! (Honestly though, beginBitmapFill() and drawRect() feels like an awkward solution somehow...)
bzlm
Yes, well this was a direct answer to you question trying not to sidetrack you on other solutions. Alas if you add a lot of fills you may get glitches. I would reuse the function but instead of drawing on a Graphics object i would do on a Bitmap "canvas". Good luck ; )
Theo.T
Thanks. The reason I'm drawing on a Graphics is that I draw with lines using lineTo() etc. If I drew on a Bitmap I would have to render everything as BitmapData all the time.
bzlm
If you are only using one canvas it wouldn't make much difference in terms of performance using a bitmapData (as target). But maybe you want to still be able to draw vector shapes on the canvas ... I added an example above, give it a try.
Theo.T
I just realized this solution doesn't apply rotation or scaling applied to the DisplayObject being drawn. I've edited my question to include this since it would be nice to support it, and my experiments with matrix scaling/rotation haven't turned out very well.
bzlm
Mmm, it would just save a few lines of code if you just placed the rotated and scaled object into a holder that you draw ...
Theo.T
Hmm, how would I do that "placing"?
bzlm
objectToBeDrawn.addChild(scaledAndRotatedObject);
Theo.T
Aha! Of course. Thanks, I'll try that.
bzlm
I have a working implementation now. Thanks for your patience!
bzlm
+2  A: 

The way i see it you have several ways to approach this:

  • Use the graphics property of a "canvas" Shape
    Pros: Nice and simple
    Cons: Very limited, especially if you need to remove things, since you would have to redraw the whole canvas.

  • Use a Bitmap and the .draw() method
    Pros: Also nice and simple, and you can do duplication of things more easily.
    Cons: Basically has the same problems as the prior approach, deleting anything would need a complete redraw. Also it won't be scalable since it's a bitmap.

  • Use a Sprite and add primitives as children
    Pros: Very flexible.
    Cons: This allows you to move, scale and delete objects individually. However, it will be slightly more complicated than the previous two options.

Using the last approach (which I would recommend if you're going to do anything more than something very small with this) your problem can be solved by using Bitmaps that you add to your "drawing", these support transparency (like you've found out) and are a bit more straightforward than using bitmapFill (which is a bit tricky to get right).

I have an example of using a bitmap to clone and draw other DisplayObjects on my blog. It's not exactly what you want but the code might be of some use, atleast the matrix part for the draw method.

grapefrukt
I subscribe to your blog and like it very much, so I'd actually already read that article. I'm opting for the first solution because the scenario here is really "bitmap brush" - I have lineTo()s that I want to intermix with the bitmap, and no deleting is really necessary. Thanks for the other tips!
bzlm
I've edited the question to include support rotation and scaling of the DisplayObject being drawn.
bzlm
A: 

bzlm - you could always make the starting X position a constant, and combine drawRect with a Matrix translate.

var xPos:Number = 750;
var matrix:Matrix = new Matrix();
matrix.translate(xPos,0);
mySprite.graphics.beginBitmapFill(myBitmap,matrix);
mySprite.graphics.drawRect(xPos,yPos,imgWidth,imgHeight);