gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash ChangeLog server/asobj/flash/display/Bitm...


From: Benjamin Wolsey
Subject: [Gnash-commit] gnash ChangeLog server/asobj/flash/display/Bitm...
Date: Fri, 20 Jun 2008 11:21:09 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Benjamin Wolsey <bwy>   08/06/20 11:21:09

Modified files:
        .              : ChangeLog 
        server/asobj/flash/display: BitmapData_as.cpp 
        testsuite/actionscript.all: BitmapData.as 

Log message:
                * testsuite/actionscript.all/BitmapData.as: more tests.
                * server/asobj/flash/display/BitmapData_as.cpp: implement
                  constructor, getPixel, getPixel32, height, width, 
transparency,
                  fillRect. 

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.6995&r2=1.6996
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/flash/display/BitmapData_as.cpp?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/BitmapData.as?cvsroot=gnash&r1=1.1&r2=1.2

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.6995
retrieving revision 1.6996
diff -u -b -r1.6995 -r1.6996
--- ChangeLog   20 Jun 2008 08:18:01 -0000      1.6995
+++ ChangeLog   20 Jun 2008 11:21:07 -0000      1.6996
@@ -1,5 +1,12 @@
 2008-06-20 Benjamin Wolsey <address@hidden>
 
+       * testsuite/actionscript.all/BitmapData.as: more tests.
+       * server/asobj/flash/display/BitmapData_as.cpp: implement
+         constructor, getPixel, getPixel32, height, width, transparency,
+         fillRect. 
+
+2008-06-20 Benjamin Wolsey <address@hidden>
+
        * server/asobj/SoundFfmpeg.h: AudioDecoder.h expects _leftOverData to
          be uint32_t, which isn't always the same as size_t.
        * libmedia/AudioDecoder.h: use legal header guards.

Index: server/asobj/flash/display/BitmapData_as.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/flash/display/BitmapData_as.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- server/asobj/flash/display/BitmapData_as.cpp        5 May 2008 18:53:31 
-0000       1.5
+++ server/asobj/flash/display/BitmapData_as.cpp        20 Jun 2008 11:21:08 
-0000      1.6
@@ -31,7 +31,10 @@
 #include "Object.h" // for AS inheritance
 #include "VM.h" // for addStatics
 
+#include <memory>
+#include <vector>
 #include <sstream>
+#include <algorithm>
 
 namespace gnash {
 
@@ -97,6 +100,7 @@
     o.init_property("rectangle", BitmapData_rectangle_getset, 
BitmapData_rectangle_getset);
     o.init_property("transparent", BitmapData_transparent_getset, 
BitmapData_transparent_getset);
     o.init_property("width", BitmapData_width_getset, BitmapData_width_getset);
+
 }
 
 static void
@@ -128,21 +132,145 @@
 class BitmapData_as: public as_object
 {
 
+    typedef std::vector<boost::uint32_t> BitmapArray;
+
 public:
 
-       BitmapData_as()
+    // The constructor sets the fill colour and the
+    // immutable size of the bitmap, as well as whether
+    // it can handle transparency or not.
+       BitmapData_as(size_t width, size_t height,
+                     bool transparent, boost::uint32_t fillColor)
                :
-               as_object(getBitmapDataInterface())
+               as_object(getBitmapDataInterface()),
+               _width(width),
+               _height(height),
+               _transparent(transparent),
+               _bitmapData(new BitmapArray(width * height, fillColor + (0xff 
<< 24)))
        {}
 
-       // override from as_object ?
-       //std::string get_text_value() const { return "BitmapData"; }
+    size_t getWidth() const { return _width; }
+    size_t getHeight() const { return _height; }
+    bool isTransparent() const { return _transparent; }
+    
+    // Returns an unsigned int representation of the pixel
+    // at (x, y) either with or without transparency.
+    boost::int32_t getPixel(int x, int y, bool transparency) const;
+    
+    // Fill the bitmap with a colour starting at x, y
+    void fillRect(int x, int y, int w, int h, boost::uint32_t color);
+
+private:
+
+    // The width of the image, max 2880. This is immutable.
+    const size_t _width;
+    
+    // The height of the image, max 2880. This is immutable.
+    const size_t _height;
+    
+    // Whether the image is transparent. This is immutable.
+    const bool _transparent;
+
+    // A static array of 32-bit values holding the actual bitmap data.
+    // The maximum size is 2880 x 2880 * 4 bytes = 33177600 bytes, so
+    // this must be heap allocated.
+    std::auto_ptr<BitmapArray> _bitmapData;
 
-       // override from as_object ?
-       //double get_numeric_value() const { return 0; }
 };
 
 
+// 
+boost::int32_t
+BitmapData_as::getPixel(int x, int y, bool transparency) const
+{
+
+    // A value of 0, 0 is inside the bitmap.
+    if (x < 0 || y < 0) return 0;
+    
+    // A value of _width, _height is outside the bitmap.
+    if (static_cast<size_t>(x) >= _width || static_cast<size_t>(y) >= _height) 
return 0;
+
+    const size_t pixelIndex = y * _width + x;
+
+    assert ( pixelIndex < _bitmapData->size());
+    
+    const boost::uint32_t pixel = (*_bitmapData)[pixelIndex];
+    
+    if (transparency)
+    {
+        return static_cast<boost::int32_t>(pixel);
+    }
+    
+    // Without transparency
+    return static_cast<boost::int32_t>(pixel & 0x00ffffff);
+
+}
+
+void
+BitmapData_as::fillRect(int x, int y, int w, int h, boost::uint32_t color)
+{
+    if (w < 0 || h < 0) return;
+
+    // Nothing to do if x or y are outside the image (negative height
+    // or width are not allowed). The cast to int is fine as neither
+    // dimension can be more than 2880 pixels.
+    if (x >= static_cast<int>(_width) || y >= static_cast<int>(_height)) 
return;
+
+    // If x or y is less than 0, make a rectangle of the
+    // intersection with the bitmap.    
+    if (x < 0)
+    {
+        w += x;
+        x = 0;
+    }
+
+    if (y < 0)
+    {
+        h += y;
+        y = 0;
+    }
+
+    // Make sure that the rectangle has some area in the 
+    // bitmap and that its bottom corner is within the
+    // the bitmap.    
+    if (w <= 0 || h <= 0) return;
+    w = std::min<size_t>(_width - x, w);
+    h = std::min<size_t>(_height - y, h);
+    
+    BitmapArray::iterator it = _bitmapData->begin() + y * _width;
+    
+    // This cannot be past .end() because h + y is no larger than the
+    // height of the image.
+    const BitmapArray::iterator e = it + _width * h;
+    
+    // Make colour non-transparent if the image doesn't support it.
+    if (!_transparent) color |= 0xff000000;
+    
+    while (it != e)
+    {
+
+        // Fill from x for the width of the rectangle.
+        std::fill_n(it + x, w, color);
+
+        // Move to the next line
+        std::advance(it, _width);
+
+    }
+
+}
+
+as_function* getFlashDisplayBitmapDataConstructor()
+{
+    static builtin_function* cl = NULL;
+    if ( ! cl )
+    {
+        cl=new builtin_function(&BitmapData_ctor, getBitmapDataInterface());
+        VM::get().addStatic(cl);
+        attachBitmapDataStaticProperties(*cl);
+    }
+    return cl;
+}
+
 static as_value
 BitmapData_applyFilter(const fn_call& fn)
 {
@@ -191,6 +319,9 @@
 static as_value
 BitmapData_dispose(const fn_call& fn)
 {
+
+    // Should free the memory storing the bitmap.
+    // What is the size afterwards? Can it be reused?
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
        UNUSED(ptr);
        LOG_ONCE( log_unimpl (__FUNCTION__) );
@@ -210,11 +341,42 @@
 BitmapData_fillRect(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
-       UNUSED(ptr);
-       LOG_ONCE( log_unimpl (__FUNCTION__) );
+
+    if (fn.nargs < 2) return as_value();
+    
+    const as_value& arg = fn.arg(0);
+    
+    if ( ! arg.is_object() )
+    {
+        /// Isn't an object...
+        IF_VERBOSE_ASCODING_ERRORS(
+            std::ostringstream ss;
+            fn.dump_args(ss);
+            log_aserror("Matrix.deltaTransformPoint(%s): needs an object", 
ss.str());
+        );
+        return as_value();
+    }
+
+    // This can be any object with the right properties.   
+    as_object* obj = arg.to_object().get();
+    assert(obj);
+    
+    as_value x, y, w, h;
+    
+    obj->get_member(NSV::PROP_X, &x);
+    obj->get_member(NSV::PROP_Y, &y);
+    obj->get_member(NSV::PROP_WIDTH, &w);
+    obj->get_member(NSV::PROP_HEIGHT, &h);    
+
+    boost::uint32_t color = fn.arg(1).to_int();
+       
+    ptr->fillRect(x.to_int(), y.to_int(), w.to_int(), h.to_int(), color);
+    
        return as_value();
 }
 
+
+// Fills the bitmap with a colour starting at point x, y.
 static as_value
 BitmapData_floodFill(const fn_call& fn)
 {
@@ -246,18 +408,35 @@
 BitmapData_getPixel(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
-       UNUSED(ptr);
-       LOG_ONCE( log_unimpl (__FUNCTION__) );
+
+    if (fn.nargs < 2)
+    {
        return as_value();
+    }
+    
+    // TODO: what happens when the pixel is outside the image?
+    
+    int x = fn.arg(0).to_int();
+    int y = fn.arg(1).to_int();
+    
+    return ptr->getPixel(x, y, false);
 }
 
 static as_value
 BitmapData_getPixel32(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
-       UNUSED(ptr);
-       LOG_ONCE( log_unimpl (__FUNCTION__) );
+    if (fn.nargs < 2)
+    {
        return as_value();
+    }
+    
+    // TODO: what happens when the pixel is outside the image?
+    
+    int x = fn.arg(0).to_int();
+    int y = fn.arg(1).to_int();
+    
+    return ptr->getPixel(x, y, true);
 }
 
 static as_value
@@ -354,9 +533,12 @@
 BitmapData_height_getset(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
-       UNUSED(ptr);
-       LOG_ONCE( log_unimpl (__FUNCTION__) );
-       return as_value();
+
+    // Read-only
+    if (fn.nargs) return as_value();
+    
+    // Returns the immutable height of the bitmap.
+       return as_value(ptr->getHeight());
 }
 
 static as_value
@@ -372,18 +554,24 @@
 BitmapData_transparent_getset(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
-       UNUSED(ptr);
-       LOG_ONCE( log_unimpl (__FUNCTION__) );
-       return as_value();
+
+    // Read-only
+    if (fn.nargs) return as_value();
+    
+    // Returns the immutable height of the bitmap.
+       return as_value(ptr->isTransparent());
 }
 
 static as_value
 BitmapData_width_getset(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
-       UNUSED(ptr);
-       LOG_ONCE( log_unimpl (__FUNCTION__) );
-       return as_value();
+
+    // Read-only
+    if (fn.nargs) return as_value();
+    
+    // Returns the immutable height of the bitmap.
+       return as_value(ptr->getWidth());
 }
 
 
@@ -397,32 +585,61 @@
 }
 
 
+static as_value
+get_flash_display_bitmap_data_constructor(const fn_call& /*fn*/)
+{
+    log_debug("Loading flash.display.BitmapData class");
+    return getFlashDisplayBitmapDataConstructor();
+}
+
 as_value
 BitmapData_ctor(const fn_call& fn)
 {
-       boost::intrusive_ptr<as_object> obj = new BitmapData_as;
 
-       if ( fn.nargs )
+       if ( fn.nargs < 2)
        {
-               std::stringstream ss;
-               fn.dump_args(ss);
-               LOG_ONCE( log_unimpl("BitmapData(%s): %s", ss.str(), 
_("arguments discarded")) );
+           // TODO: should fail if not enough arguments are passed.
+               boost::intrusive_ptr<as_object> obj = new as_object;
+        return as_value(obj.get());
        }
 
+    size_t width, height;
+    bool transparent = true;
+    boost::uint32_t fillColor = 0xffffff;
+
+    switch (fn.nargs)
+    {
+        default:
+            // log AS coding error
+        case 4:
+            fillColor = fn.arg(3).to_int();
+        case 3:
+            transparent = fn.arg(2).to_bool();
+        case 2:
+            // Is to_int correct?
+            height = fn.arg(1).to_int();
+            width = fn.arg(0).to_int();
+            break;
+    }
+    
+    // Should fail to construct the object.
+    if (width > 2880) width = 2880;
+    if (height > 2880) height = 2880;
+
+    boost::intrusive_ptr<BitmapData_as> obj =
+                new BitmapData_as(width, height, transparent, fillColor);
+
        return as_value(obj.get()); // will keep alive
 }
 
 // extern 
 void BitmapData_class_init(as_object& where)
 {
-       // This is going to be the BitmapData "class"/"function"
-       // in the 'where' package
-       boost::intrusive_ptr<builtin_function> cl;
-       cl=new builtin_function(&BitmapData_ctor, getBitmapDataInterface());
-       attachBitmapDataStaticProperties(*cl);
 
+    string_table& st = where.getVM().getStringTable();
        // Register _global.BitmapData
-       where.init_member("BitmapData", cl.get());
+       where.init_destructive_property(st.find("BitmapData"),
+                       get_flash_display_bitmap_data_constructor);
 }
 
 } // end of gnash namespace

Index: testsuite/actionscript.all/BitmapData.as
===================================================================
RCS file: /sources/gnash/gnash/testsuite/actionscript.all/BitmapData.as,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- testsuite/actionscript.all/BitmapData.as    19 Jun 2008 17:40:15 -0000      
1.1
+++ testsuite/actionscript.all/BitmapData.as    20 Jun 2008 11:21:09 -0000      
1.2
@@ -20,7 +20,7 @@
 // compile this test case with Ming makeswf, and then
 // execute it like this gnash -1 -r 0 -v out.swf
 
-rcsid="$Id: BitmapData.as,v 1.1 2008/06/19 17:40:15 bwy Exp $";
+rcsid="$Id: BitmapData.as,v 1.2 2008/06/20 11:21:09 bwy Exp $";
 
 
 #include "check.as"
@@ -80,26 +80,113 @@
 check(!bmp.hasOwnProperty("width"));
 check(!bmp.hasOwnProperty("rectangle"));
 check(!bmp.hasOwnProperty("transparent"));
-xcheck_equals(bmp.height, 10);
-xcheck_equals(bmp.width, 10);
-xcheck_equals(bmp.transparent, true);
+check_equals(bmp.height, 10);
+check_equals(bmp.width, 10);
+check_equals(bmp.transparent, true);
 xcheck_equals(bmp.rectangle.toString(), "(x=0, y=0, w=10, h=10)");
-xcheck_equals(bmp.getPixel(1, 1), 16777215);
-xcheck_equals(bmp.getPixel(9, 9), 16777215);
-xcheck_equals(bmp.getPixel32(1, 1), -1);
+check_equals(bmp.getPixel(1, 1), 16777215);
+check_equals(bmp.getPixel(9, 9), 16777215);
+check_equals(bmp.getPixel32(1, 1), -1);
+
+bmp = new Bitmap(10, 10, true);
+check_equals(bmp.getPixel32(1, 1), -1);
+bmp = new Bitmap(10, 10, false);
+check_equals(bmp.getPixel32(1, 1), -1);
+
 
 bmp = new Bitmap(20, 30, false, 0xeeddee);
-xcheck_equals(bmp.height, 30);
-xcheck_equals(bmp.width, 20);
-xcheck_equals(bmp.transparent, false);
+check_equals(bmp.height, 30);
+check_equals(bmp.width, 20);
+check_equals(bmp.transparent, false);
 xcheck_equals(bmp.rectangle.toString(), "(x=0, y=0, w=20, h=30)");
-xcheck_equals(bmp.getPixel(1, 1), 0xeeddee);
-xcheck_equals(bmp.getPixel32(1, 1), -1122834);
+check_equals(bmp.getPixel(1, 1), 0xeeddee);
+check_equals(bmp.getPixel32(1, 1), -1122834);
+
+// limits
+
+check_equals(bmp.getPixel(50, 1), 0);
+check_equals(bmp.getPixel(0, 0), 15654382);
+check_equals(bmp.getPixel(-2, -5), 0);
+
+// 0,0 is inside, 20, 30 outside a 20x30 bitmap.
+check_equals(bmp.getPixel(20, 30), 0);
+
+bmp = new Bitmap(10000, 0);
+xcheck_equals(bmp, undefined);
+bmp = new Bitmap(0, 10000);
+xcheck_equals(bmp, undefined);
+
+bmp = new Bitmap(2881, 0);
+xcheck_equals(bmp, undefined);
+bmp = new Bitmap(0, 2881);
+xcheck_equals(bmp, undefined);
+
+
+// floodFill
+bmp = new Bitmap(20, 20, false);
+bmp.floodFill(10, 10, 0x0000ff00);
+
+xcheck_equals(bmp.getPixel(10, 10), 0x0000ff00);
+bmp.floodFill(5, 5, 0x000000ff);
+xcheck_equals(bmp.getPixel(10, 0), 0x000000ff);
+
+mc = this.createEmptyMovieClip("mc", this.getNextHighestDepth());
+mc.attachBitmap(bmp, this.getNextHighestDepth());
+
+Rectangle = flash.geom.Rectangle;
+
+bmp = new Bitmap(20, 20, false);
+r = new Rectangle(2, 2, 5, 5);
+bmp.fillRect(r, 0xff1100);
+check_equals(bmp.getPixel(1, 1), 0xffffff);
+check_equals(bmp.getPixel(2, 2), 0xff1100);
+check_equals(bmp.getPixel(2, 5), 0xff1100);
+check_equals(bmp.getPixel(5, 2), 0xff1100);
+check_equals(bmp.getPixel(2, 6), 0xff1100);
+check_equals(bmp.getPixel(6, 6), 0xff1100);
+check_equals(bmp.getPixel(6, 7), 0xffffff);
+check_equals(bmp.getPixel(7, 6), 0xffffff);
+
+r = new Rectangle(-2, -2, 8, 8);
+bmp.fillRect(r, 0x00ff00);
+check_equals(bmp.getPixel(1, 1), 0x00ff00);
+
+// Fails.
+r = new Rectangle(18, 18, -4, -4);
+bmp.fillRect(r, 0x0000ff);
+check_equals(bmp.getPixel(7, 6), 0xffffff);
+
+r = new Rectangle(18, 18, 200, 200);
+bmp.fillRect(r, 0x0000ff);
+check_equals(bmp.getPixel(19,19), 0x0000ff);
+
+// Doesn't have to be a rectangle
+g = {x: 15, y: 15, width: 2, height: 2};
+bmp.fillRect(g, 0xff00ff);
+check_equals(bmp.getPixel(16, 16), 0xff00ff);
+
+// Transparency (this bitmap is not transparent).
+g = {x: 18, y: 2, width: 7, height: 7};
+bmp.fillRect(g, 0xddff00ff);
+check_equals(bmp.getPixel32(18, 2), -65281);
+
+mc.attachBitmap(bmp, this.getNextHighestDepth());
+
+// Transparency (transparent bitmap). Fill just obliterates
+// what was there, even if it's transparent.
+bmp = new Bitmap(20, 20, true);
+r = new Rectangle(1, 1, 10, 10);
+bmp.fillRect(r, 0xff00ff00);
+r = new Rectangle(2, 2, 9, 9);
+bmp.fillRect(r, 0x99ff1100);
+check_equals(bmp.getPixel32(3, 3), -1711337216);
+
+mc.attachBitmap(bmp, this.getNextHighestDepth());
 
 //-------------------------------------------------------------
 // END OF TEST
 //-------------------------------------------------------------
 
-totals(51);
+totals(77);
 
 #endif // OUTPUT_VERSION >= 8




reply via email to

[Prev in Thread] Current Thread [Next in Thread]