BitmapData.rect创建一个新的矩形?

时间:2011-07-15 04:29:17

标签: flash flex actionscript-3 adobe blit

我今天正在研究一些blitting代码,在分析后发现我创建了1000个新的矩形。我感到震惊,因为我只有1或2个不同的新Rectangle()调用,或者我正在使用BitmapData的.rect属性。

我开始评论大量的代码,直到我在sprite类中留下这段代码: canvas.bitmapData.copyPixels(_bitmapData, _bitmapData.rect, destination, null, null, true);

我在创建对象时缓存了_bitmapData.rect的结果,并且我的数千个新的矩形调用突然从探查器中消失了。

为什么BitmapData.rect会创建一个新的矩形?有没有办法检查核心库或其他东西并确认这是真的?这似乎令人费解。

4 个答案:

答案 0 :(得分:1)

Bethanny Anne说:

  

为什么BitmapData.rect会创建一个新的矩形?有没有办法检查核心库或其他东西并确认这是真的?这似乎令人费解。

想象一下以下假设情况:BitmapData.rect总是返回相同的Rectangle实例:

public function BitmapDataRectTest()
{
    var bmp:BitmapData = new BitmapData(100, 100, true, 0);

    var rect1:Rectangle = bmp.rect;
    rect1.width = 200;

    var rect2:Rectangle = bmp.rect;
    trace(rect2.width); // 200 <--- this would be wrong, 
                        //          the BitmapData is still only 100 pixels wide.
}

BitmapData.rect每次都会返回一个新实例,以避免出现这种情况,并确保在返回的Rectangle实例中获取正确的数据。

最后注意事项:这涉及'按值传递'(基本类型)和'传递引用'(复杂类型)变量。有关详情,请查看有关stackoverflow的Google或其他帖子:Pass by reference or pass by value?

答案 1 :(得分:0)

是的,BitmapData.rect显然是一个在访问时创建新矩形的getter。

您可以通过比较参考或检查内存地址来证明:

示例:

package
{
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.geom.Rectangle;

    public class BitmapDataRectTest extends Sprite
    {
        public function BitmapDataRectTest()
        {
            var bmp:BitmapData = new BitmapData(100, 100, true, 0);
            trace(bmp.rect == bmp.rect); // false
            var rect1:Rectangle = bmp.rect;
            var rect2:Rectangle = bmp.rect;

            trace("Place breakpoint here and look at rect1 and rect2 memory addresses");
            // rect1 address on my pc: @6900f71
            // rect2 address on my pc: @6900f41
        }
    }
}

编辑本机类中的类似行为:

  • DisplayObject.transform:在每次访问时返回新的Transform实例
  • Transform.colorTransform:在每次访问时返回新的ColorTransform实例
  • DisplayObject.filters:在每次访问时返回新的Array实例
  • ...当您获得内部对象的副本时,您可以找到很多其他案例。

在所有这些案例中,课程保护自己免受破坏。只需这样考虑:当一个类使用聚合时,它不能按原样公开它的聚合实例,因为否则有必要在内部对象发生时通知主类的更改。这是更新和验证每个聚合实例的每个字段中的更改的大量逻辑。

答案 2 :(得分:0)

有趣的观察。

您可以使用===运算符检查任何Object的两个实例是否相同。

BitmapData内部可能使用不同的数据结构来维持其可视状态。必须将rect属性实现为getter函数。但是,人们会期望因为BitmapData的维度是不可变的,所以Rectangle对象永远不需要重新创建,甚至根本不需要重新计算。

修改 rect上的BitmapData属性为只读(无设置器),但Rectangle上的属性不是。创建Rectangle的新实例可确保外部对象无法进行突变。

答案 3 :(得分:0)

是的,这听起来很令人沮丧,但如果你看一下BitmapData类的源代码,你会发现这个:

public class BitmapData extends Object implements IBitmapDrawable {
...
    public function get rect() : Rectangle {
        return new Rectangle(0, 0, this.width, this.height);
    }
...
}

所以答案是肯定的,每次通过访问器函数检索时,AVM都会在堆中创建新的Rectangle实例。