gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r10449: Implement MovieClip.attachBi


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10449: Implement MovieClip.attachBitmap().
Date: Wed, 17 Dec 2008 10:47:14 +0100
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10449
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Wed 2008-12-17 10:47:14 +0100
message:
  Implement MovieClip.attachBitmap().
  
  As only BitmapData.fillRect() is implemented, this isn't very exciting. The
  most common use - BitmapData.draw() - needs renderer support.
  
  Change some of the render_handler interface (render.h interface is unchanged),
  and reduce memcpy in agg.
added:
  libcore/Bitmap.cpp
  libcore/Bitmap.h
modified:
  backend/render_handler.h
  backend/render_handler_agg.cpp
  backend/render_handler_agg_bitmap.h
  backend/render_handler_agg_style.h
  backend/render_handler_cairo.cpp
  backend/render_handler_ogl.cpp
  libcore/BitmapMovieInstance.cpp
  libcore/BitmapMovieInstance.h
  libcore/Makefile.am
  libcore/MovieClip.cpp
  libcore/MovieClip.h
  libcore/asobj/flash/display/BitmapData_as.cpp
  libcore/asobj/flash/display/BitmapData_as.h
  libcore/character.h
  libcore/parser/BitmapMovieDefinition.cpp
  libcore/parser/BitmapMovieDefinition.h
  libcore/render.cpp
    ------------------------------------------------------------
    revno: 10444.1.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2008-12-16 19:44:10 +0100
    message:
      Rough and unoptimized implementation of MovieClip.attachBitmap().
    added:
      libcore/Bitmap.cpp
      libcore/Bitmap.h
    modified:
      libcore/Makefile.am
      libcore/MovieClip.cpp
      libcore/MovieClip.h
      libcore/asobj/flash/display/BitmapData_as.cpp
      libcore/asobj/flash/display/BitmapData_as.h
    ------------------------------------------------------------
    revno: 10444.1.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2008-12-16 20:29:41 +0100
    message:
      Fix segfault, various other improvements. misc-ming.all/BitmapDataTest.swf
      passes visually now.
    modified:
      libcore/Bitmap.cpp
      libcore/Bitmap.h
      libcore/asobj/flash/display/BitmapData_as.cpp
      libcore/asobj/flash/display/BitmapData_as.h
    ------------------------------------------------------------
    revno: 10444.1.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2008-12-16 21:10:27 +0100
    message:
      Add debugging to MovieClip.attachBitmap.
    modified:
      libcore/MovieClip.cpp
    ------------------------------------------------------------
    revno: 10444.1.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2008-12-16 22:05:21 +0100
    message:
      Cleaning up.
    modified:
      libcore/asobj/flash/display/BitmapData_as.cpp
    ------------------------------------------------------------
    revno: 10444.1.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 08:25:22 +0100
    message:
      Separate drawing and finalizing. Cache width and height as they are
      constant and used frequently.
    modified:
      libcore/Bitmap.cpp
      libcore/Bitmap.h
    ------------------------------------------------------------
    revno: 10444.1.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 08:27:15 +0100
    message:
      Use typeName for nicer display. Drop comment about inheritance.
    modified:
      libcore/character.h
    ------------------------------------------------------------
    revno: 10444.1.7
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 08:27:54 +0100
    message:
      Convert GnashImage to BitmapInfo straight away, as there isn't any
      advantage to delaying it. Drop _image member.
    modified:
      libcore/parser/BitmapMovieDefinition.cpp
      libcore/parser/BitmapMovieDefinition.h
    ------------------------------------------------------------
    revno: 10444.1.8
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 08:29:09 +0100
    message:
      Add virtual method for rendering MovieClip to a bitmap. Not implemented.
    modified:
      libcore/MovieClip.cpp
      libcore/MovieClip.h
    ------------------------------------------------------------
    revno: 10444.1.9
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 08:29:36 +0100
    message:
      Override virtual method for rendering to an image. Not implemented.
    modified:
      libcore/BitmapMovieInstance.cpp
      libcore/BitmapMovieInstance.h
    ------------------------------------------------------------
    revno: 10444.1.10
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 08:30:02 +0100
    message:
      Use the unimplemented method for drawing MovieClips onto a Bitmap. It
      just needs the data and more testing now.
    modified:
      libcore/asobj/flash/display/BitmapData_as.cpp
      libcore/asobj/flash/display/BitmapData_as.h
    ------------------------------------------------------------
    revno: 10444.1.11
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 08:54:39 +0100
    message:
      Drop templated agg_bitmap_info. Drop separate create_bitmap_info for
      rgb and rgba, as it's not hard to work it out.
      
      Don't abort() after return, as I don't think returns in C++ are generally
      thought to need a fallback.
      
      Don't copy the image data when we can take ownership of it.
    modified:
      backend/render_handler.h
      backend/render_handler_agg.cpp
      backend/render_handler_agg_bitmap.h
      backend/render_handler_agg_style.h
      libcore/render.cpp
    ------------------------------------------------------------
    revno: 10444.1.12
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 09:11:05 +0100
    message:
      Modify create_bitmap_* functions in ogl and cairo to match agg.
    modified:
      backend/render_handler_cairo.cpp
      backend/render_handler_ogl.cpp
    ------------------------------------------------------------
    revno: 10444.1.13
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 09:19:34 +0100
    message:
      Fix ogl properly.
    modified:
      backend/render_handler_ogl.cpp
    ------------------------------------------------------------
    revno: 10444.1.14
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 10:10:25 +0100
    message:
      Don't unregister Bitmap, as it causes memory errors. Use the
      stagePlacementCallback to register the bitmap, as it's not guaranteed that
      the Bitmap character will be placed, and that would be a waste.
    modified:
      libcore/Bitmap.cpp
      libcore/Bitmap.h
      libcore/asobj/flash/display/BitmapData_as.cpp
      libcore/asobj/flash/display/BitmapData_as.h
    ------------------------------------------------------------
    revno: 10444.1.15
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Wed 2008-12-17 10:14:56 +0100
    message:
      Add copyright information.
    modified:
      libcore/Bitmap.cpp
      libcore/Bitmap.h
=== modified file 'backend/render_handler.h'
--- a/backend/render_handler.h  2008-12-16 15:15:55 +0000
+++ b/backend/render_handler.h  2008-12-17 07:54:39 +0000
@@ -218,22 +218,11 @@
  
   virtual ~render_handler() {}
 
-  // Your handler should return these with a ref-count of 0.  (@@ is that the 
right policy?)
-
   /// \brief
   /// Given an image, returns a pointer to a bitmap_info class
   /// that can later be passed to fill_styleX_bitmap(), to set a
   /// bitmap fill style.
-  virtual BitmapInfo*  create_bitmap_info_rgb(ImageRGB* im) = 0;
-
-  /// \brief
-  /// Given an image, returns a pointer to a bitmap_info class
-  /// that can later be passed to fill_style_bitmap(), to set a
-  /// bitmap fill style.
-  //
-  /// This version takes an image with an alpha channel.
-  ///
-  virtual BitmapInfo*  create_bitmap_info_rgba(ImageRGBA* im) = 0;
+  virtual BitmapInfo* createBitmapInfo(std::auto_ptr<GnashImage> im) = 0;
 
   /// Draws a video frame. 
   //

=== modified file 'backend/render_handler_agg.cpp'
--- a/backend/render_handler_agg.cpp    2008-12-16 15:15:55 +0000
+++ b/backend/render_handler_agg.cpp    2008-12-17 07:54:39 +0000
@@ -392,39 +392,12 @@
   };
 
 
-  gnash::BitmapInfo* create_bitmap_info_rgb(ImageRGB* im)
+  gnash::BitmapInfo* createBitmapInfo(std::auto_ptr<GnashImage> im)
   // Given an image, returns a pointer to a bitmap_info class
   // that can later be passed to fill_styleX_bitmap(), to set a
   // bitmap fill style.
   {    
-    return new agg_bitmap_info<agg::pixfmt_rgb24_pre> (im->width(), 
im->height(),
-      im->pitch(), im->data(), 24);
-    abort(); 
-  }
-
-
-  gnash::BitmapInfo* create_bitmap_info_rgba(ImageRGBA* im)
-  // Given an image, returns a pointer to a BitmapInfo class
-  // that can later be passed to fill_style_bitmap(), to set a
-  // bitmap fill style.
-  //
-  // This version takes an image with an alpha channel.
-  {
-    return new agg_bitmap_info<agg::pixfmt_rgba32_pre> (im->width(), 
im->height(),
-      im->pitch(), im->data(), 32); 
-  }
-
-
-  gnash::BitmapInfo* create_bitmap_info_empty()
-  // Create a placeholder bitmap_info.  Used when
-  // DO_NOT_LOAD_BITMAPS is set; then later on the host program
-  // can use movie_definition::get_bitmap_info_count() and
-  // movie_definition::get_bitmap_info() to stuff precomputed
-  // textures into these bitmap infos.
-  {
-    // bitmaps currently not supported! - return dummy for fontlib
-    unsigned char dummy=0;
-    return new agg_bitmap_info<agg::pixfmt_rgb24_pre> (0, 0, 0, &dummy, 24);
+    return new agg_bitmap_info(im);
   }
 
   void drawVideoFrame(GnashImage* frame, const SWFMatrix* source_mat, 
@@ -1340,7 +1313,7 @@
           m.concatenate(cm);
           m.concatenate(inv_stage_matrix);
 
-          sh.add_bitmap(dynamic_cast<agg_bitmap_info_base*> 
+          sh.add_bitmap(dynamic_cast<agg_bitmap_info*> 
             (fill_styles[fno].get_bitmap_info()), m, cx, 
             (fill_type==SWF::FILL_TILED_BITMAP) || 
(fill_type==SWF::FILL_TILED_BITMAP_HARD),
             smooth && m_enable_antialias);

=== modified file 'backend/render_handler_agg_bitmap.h'
--- a/backend/render_handler_agg_bitmap.h       2008-12-16 15:15:55 +0000
+++ b/backend/render_handler_agg_bitmap.h       2008-12-17 07:54:39 +0000
@@ -20,55 +20,34 @@
 
 // This include file used only to make render_handler_agg more readable.
 
-
 namespace gnash {
 
-/// Bitmap class used internally by the AGG renderer. There's no reason to
-/// use it outside. It does not much except providing all necessary 
information. 
-class agg_bitmap_info_base : public BitmapInfo
-{
-public:
-
-  int get_width() const { return m_width; }  
-  int get_height() const { return m_height;  }  
-  int get_bpp() const { return m_bpp; }  
-  int get_rowlen() const { return m_rowlen; }  
-  boost::uint8_t* get_data() const { return m_data; }
-
-protected:
-  boost::uint8_t* m_data;
-  int m_width;
-  int m_height;
-  int m_bpp;
-  int m_rowlen;  
-};
-
-
 /// The class itself uses a template. Currently this is unnecessary and it may
 /// be removed but an older implementation required this method and it may be
 /// necessary again when the last missing parts of the renderer will be
-/// implemented. 
-template <class PixelFormat>
-class agg_bitmap_info : public agg_bitmap_info_base 
+/// implemented. And when might that be? I don't think I'll wait.
+class agg_bitmap_info : public BitmapInfo
 {
 public:
 
-  agg_bitmap_info(int width, int height, int rowlen, boost::uint8_t* data, int 
bpp) 
+  agg_bitmap_info(std::auto_ptr<GnashImage> im)
+      :
+      _image(im),
+      _bpp(_image->type() == GNASH_IMAGE_RGB ? 24 : 32)
   {
-    //printf("creating bitmap %dx%d pixels with %d bytes rowsize\n", 
width,height,rowlen);
-
-    m_bpp = bpp;    
-    m_width = width;
-    m_height = height;
-    m_rowlen = rowlen;
-
-    m_data = new boost::uint8_t[height*rowlen];
-    memcpy(m_data, data, height*rowlen);   
   }
+ 
+  int get_width() const { return _image->width(); }  
+  int get_height() const { return _image->height();  }  
+  int get_bpp() const { return _bpp; }  
+  int get_rowlen() const { return _image->pitch(); }  
+  boost::uint8_t* get_data() const { return _image->data(); }
   
-  ~agg_bitmap_info() {
-    delete [] m_data;
-  }
+private:
+
+  std::auto_ptr<GnashImage> _image;
+
+  int _bpp;
     
 };
 

=== modified file 'backend/render_handler_agg_style.h'
--- a/backend/render_handler_agg_style.h        2008-12-16 09:58:40 +0000
+++ b/backend/render_handler_agg_style.h        2008-12-17 07:54:39 +0000
@@ -324,7 +324,7 @@
     }
     
     /// Adds a new bitmap fill style
-    void add_bitmap(agg_bitmap_info_base* bi, gnash::SWFMatrix mat, 
gnash::cxform cx, 
+    void add_bitmap(agg_bitmap_info* bi, gnash::SWFMatrix mat, gnash::cxform 
cx, 
       bool repeat, bool smooth) {
 
       if (bi==NULL) {
@@ -396,7 +396,7 @@
     // === RGB24 ===
     
 
-    void add_bitmap_repeat_nn_rgb24(agg_bitmap_info_base* bi, gnash::SWFMatrix 
mat, gnash::cxform cx) {
+    void add_bitmap_repeat_nn_rgb24(agg_bitmap_info* bi, gnash::SWFMatrix mat, 
gnash::cxform cx) {
 
       // tiled, nearest neighbor method (faster)   
 
@@ -419,7 +419,7 @@
         
     
     
-    void add_bitmap_clip_nn_rgb24(agg_bitmap_info_base* bi, gnash::SWFMatrix 
mat, gnash::cxform cx) {
+    void add_bitmap_clip_nn_rgb24(agg_bitmap_info* bi, gnash::SWFMatrix mat, 
gnash::cxform cx) {
 
       // clipped, nearest neighbor method (faster)   
 
@@ -440,7 +440,7 @@
     
     
     
-    void add_bitmap_repeat_aa_rgb24(agg_bitmap_info_base* bi, gnash::SWFMatrix 
mat, gnash::cxform cx) {  
+    void add_bitmap_repeat_aa_rgb24(agg_bitmap_info* bi, gnash::SWFMatrix mat, 
gnash::cxform cx) {  
 
       // tiled, bilinear method (better quality)   
 
@@ -461,7 +461,7 @@
     }
         
     
-    void add_bitmap_clip_aa_rgb24(agg_bitmap_info_base* bi, gnash::SWFMatrix 
mat, gnash::cxform cx) {
+    void add_bitmap_clip_aa_rgb24(agg_bitmap_info* bi, gnash::SWFMatrix mat, 
gnash::cxform cx) {
 
       // clipped, bilinear method (better quality)   
 
@@ -484,7 +484,7 @@
     
     // === RGBA32 ===    
 
-    void add_bitmap_repeat_nn_rgba32(agg_bitmap_info_base* bi, 
gnash::SWFMatrix mat, gnash::cxform cx) {
+    void add_bitmap_repeat_nn_rgba32(agg_bitmap_info* bi, gnash::SWFMatrix 
mat, gnash::cxform cx) {
     
       // tiled, nearest neighbor method (faster)   
 
@@ -507,7 +507,7 @@
         
     
     
-    void add_bitmap_clip_nn_rgba32(agg_bitmap_info_base* bi, gnash::SWFMatrix 
mat, gnash::cxform cx) {
+    void add_bitmap_clip_nn_rgba32(agg_bitmap_info* bi, gnash::SWFMatrix mat, 
gnash::cxform cx) {
 
       // clipped, nearest neighbor method (faster)   
 
@@ -528,7 +528,7 @@
     
     
     
-    void add_bitmap_repeat_aa_rgba32(agg_bitmap_info_base* bi, 
gnash::SWFMatrix mat, gnash::cxform cx) {  
+    void add_bitmap_repeat_aa_rgba32(agg_bitmap_info* bi, gnash::SWFMatrix 
mat, gnash::cxform cx) {  
 
       // tiled, bilinear method (better quality)   
 
@@ -549,7 +549,7 @@
     }
         
     
-    void add_bitmap_clip_aa_rgba32(agg_bitmap_info_base* bi, gnash::SWFMatrix 
mat, gnash::cxform cx) {
+    void add_bitmap_clip_aa_rgba32(agg_bitmap_info* bi, gnash::SWFMatrix mat, 
gnash::cxform cx) {
 
       // clipped, bilinear method (better quality)   
 

=== modified file 'backend/render_handler_cairo.cpp'
--- a/backend/render_handler_cairo.cpp  2008-12-16 15:15:55 +0000
+++ b/backend/render_handler_cairo.cpp  2008-12-17 08:11:05 +0000
@@ -47,7 +47,7 @@
 
 // Converts from RGB image to 32-bit pixels in CAIRO_FORMAT_RGB24 format
 static void
-rgb_to_cairo_rgb24(boost::uint8_t* dst, const ImageRGB* im)
+rgb_to_cairo_rgb24(boost::uint8_t* dst, const GnashImage* im)
 {
   boost::uint32_t* dst32 = reinterpret_cast<boost::uint32_t*>(dst);
   for (size_t y = 0;  y < im->height();  y++)
@@ -62,7 +62,7 @@
 
 // Converts from RGBA image to 32-bit pixels in CAIRO_FORMAT_ARGB32 format
 static void
-rgba_to_cairo_argb(boost::uint8_t* dst, const ImageRGBA* im)
+rgba_to_cairo_argb(boost::uint8_t* dst, const GnashImage* im)
 {
   boost::uint32_t* dst32 = reinterpret_cast<boost::uint32_t*>(dst);
   for (size_t y = 0;  y < im->height();  y++)
@@ -419,26 +419,34 @@
   {
   }
 
-  virtual BitmapInfo*  create_bitmap_info_rgb(ImageRGB* im) 
+  virtual BitmapInfo* createBitmapInfo(std::auto_ptr<GnashImage> im) 
   {
+
     int buf_size = im->width() * im->height() * 4;
     boost::uint8_t* buffer = new boost::uint8_t[buf_size];
-    
-    rgb_to_cairo_rgb24(buffer, im);
-    
-    return new bitmap_info_cairo(buffer, im->width(), im->height(), 4,
+
+    switch (im->type())
+    {
+    
+        case GNASH_IMAGE_RGB:
+        {
+            rgb_to_cairo_rgb24(buffer, im.get());
+    
+            return new bitmap_info_cairo(buffer, im->width(), im->height(), 4,
                                  CAIRO_FORMAT_RGB24);
-  }
-
-  virtual BitmapInfo*  create_bitmap_info_rgba(ImageRGBA* im)
-  {        
-    int buf_size = im->width() * im->height() * 4;
-    boost::uint8_t* buffer = new boost::uint8_t[buf_size];
-    
-    rgba_to_cairo_argb(buffer, im);
-    
-    return new bitmap_info_cairo(buffer, im->width(), im->height(), 4,
+        }
+        
+        case GNASH_IMAGE_RGBA:
+        {
+            rgba_to_cairo_argb(buffer, im.get());
+    
+            return new bitmap_info_cairo(buffer, im->width(), im->height(), 4,
                                  CAIRO_FORMAT_ARGB32);
+        }
+
+        default:
+            std::abort();
+    }
   }
 
   virtual void drawVideoFrame(GnashImage* baseframe, const SWFMatrix* m, const 
rect* bounds)

=== modified file 'backend/render_handler_ogl.cpp'
--- a/backend/render_handler_ogl.cpp    2008-12-16 15:15:55 +0000
+++ b/backend/render_handler_ogl.cpp    2008-12-17 08:19:34 +0000
@@ -641,14 +641,17 @@
 #endif
   }    
 
-  virtual BitmapInfo*  create_bitmap_info_rgb(ImageRGB* im)
-  {
-    return new bitmap_info_ogl(im, GL_RGB, ogl_accessible());
-  }
-
-  virtual BitmapInfo*  create_bitmap_info_rgba(ImageRGBA* im)
-  {
-    return new bitmap_info_ogl(im, GL_RGBA, ogl_accessible());
+  virtual BitmapInfo* createBitmapInfo(std::auto_ptr<GnashImage> im)
+  {
+      switch (im->type())
+      {
+          case GNASH_IMAGE_RGB:
+              return new bitmap_info_ogl(im.get(), GL_RGB, ogl_accessible());
+          case GNASH_IMAGE_RGBA:
+                return new bitmap_info_ogl(im.get(), GL_RGBA, 
ogl_accessible());
+          default:
+                std::abort();
+      }
   }
 
   // Since we store drawing operations in display lists, we take special care

=== added file 'libcore/Bitmap.cpp'
--- a/libcore/Bitmap.cpp        1970-01-01 00:00:00 +0000
+++ b/libcore/Bitmap.cpp        2008-12-17 09:14:56 +0000
@@ -0,0 +1,168 @@
+// 
+//   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+#include "Bitmap.h"
+#include "flash/display/BitmapData_as.h"
+#include "GnashImage.h"
+#include "DynamicShape.h"
+#include "rect.h"
+
+namespace gnash {
+
+Bitmap::Bitmap(boost::intrusive_ptr<BitmapData_as> bd, character* parent,
+        int id)
+    :
+    character(parent, id),
+    _bitmapData(bd),
+    _bitmapInfo(0),
+    _shapeDef(new DynamicShape),
+    _width(_bitmapData->getWidth()),
+    _height(_bitmapData->getHeight())
+{
+    _shapeDef->set_bound(rect(0, 0, _width * 20, _height * 20));
+}
+
+
+Bitmap::~Bitmap()
+{
+}
+
+
+void
+Bitmap::stagePlacementCallback(as_object* initObj)
+{
+    assert(!initObj);
+
+    _bitmapData->registerBitmap(this);
+    update();
+}
+
+
+void
+Bitmap::display()
+{
+    assert(_shapeDef);
+
+    _shapeDef->display(this);
+
+    clear_invalidated();
+}
+
+void
+Bitmap::add_invalidated_bounds(InvalidatedRanges& ranges, bool force)
+{
+    if (!force && !m_invalidated) return;
+
+    ranges.add(m_old_invalidated_ranges);
+
+    rect bounds;
+    bounds.expand_to_transformed_rect(getWorldMatrix(), getBounds()); 
+    ranges.add(bounds.getRange());
+
+    log_debug("ranges now: %s", ranges);
+
+}
+
+rect
+Bitmap::getBounds() const
+{
+    return _shapeDef->get_bound();
+}
+
+void
+Bitmap::drawBitmap()
+{
+
+    const BitmapData_as::BitmapArray& data = _bitmapData->getBitmapData();
+
+    std::auto_ptr<GnashImage> im(new ImageRGBA(_width, _height)); 
+
+    for (size_t i = 0; i < _height; ++i) {
+
+        boost::uint8_t* row = im->scanline(i);
+
+        for (size_t j = 0; j < _width; ++j) {
+            const BitmapData_as::BitmapArray::value_type pixel =
+                data[i * _width + j];
+            row[j * 4] = (pixel & 0x00ff0000) >> 16;
+            row[j * 4 + 1] = (pixel & 0x0000ff00) >> 8;
+            row[j * 4 + 2] = (pixel & 0x000000ff);
+            row[j * 4 + 3] = (pixel & 0xff000000) >> 24;
+        }
+    }
+
+    _bitmapInfo = render::createBitmapInfo(im);
+
+}
+
+
+void
+Bitmap::finalize()
+{
+
+    if (!_bitmapData) return;
+
+    const BitmapData_as::BitmapArray& data = _bitmapData->getBitmapData();
+
+    /// In this case, dispose() was called. It seems like a good idea to
+    /// set _bitmapData to 0 to avoid any further interaction.
+    if (data.empty()) {
+        _bitmapData = 0;
+        _shapeDef->set_bound(rect());
+        return;
+    }
+
+    drawBitmap();
+
+    // Width and height are a maximum of 2880, so there is no risk of 
+    // overflow 
+    const int w = _width * 20;
+    const int h = _height * 20;
+
+    if (!_shapeDef) {
+    }
+
+    SWFMatrix mat;
+    mat.set_scale(1.0 / 20, 1.0 / 20);
+    fill_style fill(_bitmapInfo.get(), mat);
+    const size_t fillLeft = _shapeDef->add_fill_style(fill);
+
+
+    path bmpath(w, h, fillLeft, 0, 0, false);
+    bmpath.drawLineTo(w, 0);
+    bmpath.drawLineTo(0, 0);
+    bmpath.drawLineTo(0, h);
+    bmpath.drawLineTo(w, h);
+
+    _shapeDef->add_path(bmpath);
+
+    _shapeDef->finalize();
+
+}
+
+void
+Bitmap::update()
+{
+
+    set_invalidated();
+
+    finalize();
+
+}
+
+}

=== added file 'libcore/Bitmap.h'
--- a/libcore/Bitmap.h  1970-01-01 00:00:00 +0000
+++ b/libcore/Bitmap.h  2008-12-17 09:14:56 +0000
@@ -0,0 +1,98 @@
+// 
+//   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+#ifndef GNASH_BITMAP_H
+#define GNASH_BITMAP_H
+
+#include "character.h" 
+#include "BitmapInfo.h"
+#include "flash/display/BitmapData_as.h"
+#include "render.h"
+
+#include "DynamicShape.h"
+
+
+namespace gnash {
+
+
+/// A Dynamic Bitmap DisplayObject. This is not AS-referencable, but can be
+/// removed and placed using depths like normal characters (DisplayObjects).
+class Bitmap : public character
+{
+public:
+
+       Bitmap(boost::intrusive_ptr<BitmapData_as> bd, character* parent, int 
id);
+
+    ~Bitmap();
+
+    void update();
+
+    virtual void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
+
+    virtual void display();
+
+    virtual rect getBounds() const;
+
+    virtual void stagePlacementCallback(as_object* initObj = 0);
+
+protected:
+
+    void markReachableObjects() const {
+        if (_bitmapData) _bitmapData->setReachable();
+        if (_bitmapInfo) _bitmapInfo->setReachable();
+        if (_shapeDef) _shapeDef->setReachable();
+    }
+
+private:
+
+    /// This must convert the BitmapData to a BitmapInfo.
+    //
+    /// The result must be stored in _bitmapInfo.
+    void drawBitmap();
+
+    /// Call this before rendering to make sure the BitmapInfo is updated.
+    void finalize();
+
+    boost::intrusive_ptr<BitmapData_as> _bitmapData;
+
+    /// The current bitmap information is stored here.
+    boost::intrusive_ptr<BitmapInfo> _bitmapInfo;
+
+    /// FIXME: using shape_character_def is unpleasant.
+    boost::intrusive_ptr<DynamicShape> _shapeDef;
+
+    /// This is cached to save querying the BitmapData often
+    size_t _width;
+
+    /// This is cached to save querying the BitmapData often
+    size_t _height;
+
+};
+
+}      // end namespace gnash
+
+
+#endif // GNASH_DYNAMIC_SHAPE_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:

=== modified file 'libcore/BitmapMovieInstance.cpp'
--- a/libcore/BitmapMovieInstance.cpp   2008-05-21 15:08:22 +0000
+++ b/libcore/BitmapMovieInstance.cpp   2008-12-17 07:29:36 +0000
@@ -23,20 +23,29 @@
 
 namespace gnash {
 
-BitmapMovieInstance::BitmapMovieInstance(BitmapMovieDefinition* def, 
character* parent)
+BitmapMovieInstance::BitmapMovieInstance(BitmapMovieDefinition* def,
+        character* parent)
        :
        movie_instance(def, parent)
 {  
        // We need to assign a character id to the instance, or an assertion
        // will fail in character.cpp (parent==NULL || id != -1)
+
        character_def* chdef = def->get_character_def(1); 
        assert(chdef);
-       boost::intrusive_ptr<character> ch = 
chdef->create_character_instance(this, 1);
+       boost::intrusive_ptr<character> ch = 
+        chdef->create_character_instance(this, 1);
        
        const int depth = 1 + character::staticDepthOffset;
        place_character(ch.get(), depth);
 }
 
+std::auto_ptr<GnashImage>
+BitmapMovieInstance::drawToBitmap(const SWFMatrix& mat, const cxform& cx,
+        character::BlendMode bm, const rect& clipRect, bool smooth)
+{
+    return std::auto_ptr<GnashImage>();
+}
 
 } // namespace gnash
 

=== modified file 'libcore/BitmapMovieInstance.h'
--- a/libcore/BitmapMovieInstance.h     2008-03-27 10:50:12 +0000
+++ b/libcore/BitmapMovieInstance.h     2008-12-17 07:29:36 +0000
@@ -25,6 +25,7 @@
 namespace gnash
 {
        class BitmapMovieDefinition;
+    class GnashImage;
 }
 
 namespace gnash
@@ -41,6 +42,16 @@
 
        virtual ~BitmapMovieInstance() {}
 
+    /// Render this MovieClip to a GnashImage using the passed transform
+    //
+    /// @return     The GnashImage with the MovieClip drawn onto it.
+    virtual std::auto_ptr<GnashImage> drawToBitmap(
+            const SWFMatrix& mat = SWFMatrix(), 
+            const cxform& cx = cxform(),
+            character::BlendMode bm = character::BLENDMODE_NORMAL,
+            const rect& clipRect = rect(),
+            bool smooth = false);
+
        /// Do nothing on restart. Especially don't trash the DisplayList 
        //
        /// TODO: this is needed due to the implementation detail of 

=== modified file 'libcore/Makefile.am'
--- a/libcore/Makefile.am       2008-12-16 15:15:55 +0000
+++ b/libcore/Makefile.am       2008-12-16 18:44:10 +0000
@@ -64,6 +64,7 @@
        CharacterProxy.cpp \
        cxform.cpp \
        DynamicShape.cpp        \
+       Bitmap.cpp \
        TextField.cpp \
         BlurFilter.cpp \
         GlowFilter.cpp \
@@ -137,6 +138,7 @@
        as_prop_flags.h \
        as_value.h \
        asClass.h \
+       Bitmap.h \
        BitmapInfo.h \
        BitmapMovieInstance.h \
        builtin_function.h \

=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp     2008-12-13 08:33:04 +0000
+++ b/libcore/MovieClip.cpp     2008-12-17 07:29:09 +0000
@@ -27,7 +27,8 @@
 #include "movie_definition.h"
 #include "as_value.h"
 #include "as_function.h"
-#include "TextField.h" // for registered variables
+#include "Bitmap.h"
+#include "TextField.h"
 #include "ControlTag.h"
 #include "fn_call.h"
 #include "Key_as.h"
@@ -53,9 +54,11 @@
 #include "styles.h" // for cap_style_e and join_style_e enums
 #include "PlaceObject2Tag.h" 
 #include "NetStream_as.h"
+#include "flash/display/BitmapData_as.h"
 #include "flash/geom/Matrix_as.h"
 #include "ExportableResource.h"
 
+
 #ifdef USE_SWFTREE
 # include "tree.hh"
 #endif
@@ -492,7 +495,8 @@
 //
 /// The frame_spec could be an integer or a string.
 ///
-void MovieClip::call_frame_actions(const as_value& frame_spec)
+void
+MovieClip::call_frame_actions(const as_value& frame_spec)
 {
     size_t frame_number;
     if ( ! get_frame_number(frame_spec, frame_number) )
@@ -534,7 +538,8 @@
 
 }
 
-character* MovieClip::add_empty_movieclip(const char* name, int depth)
+character*
+MovieClip::add_empty_movieclip(const char* name, int depth)
 {
     // empty_movieclip_def will be deleted during deleting movieclip
     sprite_definition* empty_sprite_def =
@@ -624,7 +629,6 @@
     return newmovieclip; 
 }
 
-/* public */
 void
 MovieClip::queueAction(const action_buffer& action)
 {
@@ -632,7 +636,6 @@
     root.pushAction(action, boost::intrusive_ptr<MovieClip>(this));
 }
 
-/* private */
 void
 MovieClip::queueActions(ActionList& actions)
 {
@@ -1282,6 +1285,22 @@
     return true; 
 }
 
+std::auto_ptr<GnashImage>
+MovieClip::drawToBitmap(const SWFMatrix& mat, const cxform& cx,
+        character::BlendMode bm, const rect& clipRect, bool smooth)
+{
+    return std::auto_ptr<GnashImage>();
+}
+
+void
+MovieClip::attachBitmap(boost::intrusive_ptr<BitmapData_as> bd, int depth)
+{
+    character* ch = new Bitmap(bd, this, 0);
+
+    attachCharacter(*ch, depth, 0);
+
+}
+
 character*
 MovieClip::add_display_object(const SWF::PlaceObject2Tag* tag,
         DisplayList& dlist)
@@ -5101,10 +5120,34 @@
 as_value
 movieclip_attachBitmap(const fn_call& fn)
 {
-    boost::intrusive_ptr<MovieClip> ptr = 
-        ensureType<MovieClip>(fn.this_ptr);
-    UNUSED(ptr);
-    LOG_ONCE( log_unimpl (__FUNCTION__) );
+
+    GNASH_REPORT_FUNCTION;
+
+    boost::intrusive_ptr<MovieClip> ptr = ensureType<MovieClip>(fn.this_ptr);
+
+    if (fn.nargs < 2) {
+        IF_VERBOSE_ASCODING_ERRORS(
+            log_debug("MovieClip.attachBitmap: expected 2 args, got %d",
+                fn.nargs);
+        );
+        return as_value();
+    }
+
+    as_object* obj = fn.arg(0).to_object().get();
+    boost::intrusive_ptr<BitmapData_as> bd = dynamic_cast<BitmapData_as*>(obj);
+
+    if (!bd) {
+        IF_VERBOSE_ASCODING_ERRORS(
+            log_debug("MovieClip.attachBitmap: first argument should be a "
+                "BitmapData", fn.arg(1));
+        );
+        return as_value();
+    }
+
+    int depth = fn.arg(1).to_int();
+
+    ptr->attachBitmap(bd, depth);
+
     return as_value();
 }
 

=== modified file 'libcore/MovieClip.h'
--- a/libcore/MovieClip.h       2008-12-05 08:57:08 +0000
+++ b/libcore/MovieClip.h       2008-12-17 07:29:09 +0000
@@ -51,6 +51,8 @@
     class LoadVariablesThread;
     class gradient_record;
     class TextField;
+    class BitmapData_as;
+    class BitmapInfo;
     namespace SWF {
         class PlaceObject2Tag;
     }
@@ -229,8 +231,7 @@
 
     //float get_timer() const;
 
-    void    restart();
-
+    void restart();
 
     bool has_looped() const
     {
@@ -247,10 +248,12 @@
     /// Return the topmost entity that the given point
     /// covers that can receive mouse events.  NULL if
     /// none.  Coords are in parent's frame.
-    virtual character* get_topmost_mouse_entity(boost::int32_t x, 
boost::int32_t y);
+    virtual character* get_topmost_mouse_entity(boost::int32_t x,
+            boost::int32_t y);
 
     // see dox in character.h
-    const character* findDropTarget(boost::int32_t x, boost::int32_t y, 
character* dragging) const;
+    const character* findDropTarget(boost::int32_t x, boost::int32_t y,
+            character* dragging) const;
 
     void setDropTarget(const std::string& tgt)
     {
@@ -267,16 +270,16 @@
         return true; // sprites can be referenced 
     }
 
-    virtual void    advance();
+    virtual void advance();
 
-    void    advance_sprite();
+    void advance_sprite();
 
     /// Set the sprite state at the specified frame number.
     //
     /// 0-based frame numbers!! 
     ///(in contrast to ActionScript and Flash MX)
     ///
-    void    goto_frame(size_t target_frame_number);
+    void goto_frame(size_t target_frame_number);
 
     /// Parse frame spec and return a 0-based frame number.
     //
@@ -317,7 +320,7 @@
     //
     /// This should only be used by the Color AS class
     ///
-    cxform  get_user_cxform() const
+    cxform get_user_cxform() const
     {
         return _userCxform;
     }
@@ -388,7 +391,7 @@
 
     /// Proxy of DisplayList::remove_character()
     ///
-    /// @param ch
+    /// @
     /// new character to be used for replacing.
     ///
     /// @param depth
@@ -677,6 +680,19 @@
     ///
     void removeMovieClip();
 
+    /// Create a Bitmap DisplayObject at the specified depth.
+    void attachBitmap(boost::intrusive_ptr<BitmapData_as> bd, int depth);
+
+    /// Render this MovieClip to a GnashImage using the passed transform
+    //
+    /// @return     The GnashImage with the MovieClip drawn onto it.
+    virtual std::auto_ptr<GnashImage> drawToBitmap(
+            const SWFMatrix& mat = SWFMatrix(), 
+            const cxform& cx = cxform(),
+            character::BlendMode bm = character::BLENDMODE_NORMAL,
+            const rect& clipRect = rect(),
+            bool smooth = false);
+
     /// @name Drawing API
     /// @{ 
     

=== modified file 'libcore/asobj/flash/display/BitmapData_as.cpp'
--- a/libcore/asobj/flash/display/BitmapData_as.cpp     2008-11-15 19:49:41 
+0000
+++ b/libcore/asobj/flash/display/BitmapData_as.cpp     2008-12-17 09:10:25 
+0000
@@ -22,6 +22,8 @@
 #endif
 
 #include "BitmapData_as.h"
+#include "GnashImage.h"
+#include "Bitmap.h"
 #include "flash/geom/Rectangle_as.h" // for BitmapData.rectangle
 #include "as_object.h" // for inheritance
 #include "log.h"
@@ -32,102 +34,53 @@
 #include "Object.h" // for AS inheritance
 #include "VM.h" // for addStatics
 
+#include "BitmapMovieInstance.h"
+
 #include <vector>
 #include <sstream>
 #include <algorithm>
 
 namespace gnash {
 
-static as_value BitmapData_applyFilter(const fn_call& fn);
-static as_value BitmapData_clone(const fn_call& fn);
-static as_value BitmapData_colorTransform(const fn_call& fn);
-static as_value BitmapData_copyChannel(const fn_call& fn);
-static as_value BitmapData_copyPixels(const fn_call& fn);
-static as_value BitmapData_dispose(const fn_call& fn);
-static as_value BitmapData_draw(const fn_call& fn);
-static as_value BitmapData_fillRect(const fn_call& fn);
-static as_value BitmapData_floodFill(const fn_call& fn);
-static as_value BitmapData_generateFilterRect(const fn_call& fn);
-static as_value BitmapData_getColorBoundsRect(const fn_call& fn);
-static as_value BitmapData_getPixel(const fn_call& fn);
-static as_value BitmapData_getPixel32(const fn_call& fn);
-static as_value BitmapData_hitTest(const fn_call& fn);
-static as_value BitmapData_merge(const fn_call& fn);
-static as_value BitmapData_noise(const fn_call& fn);
-static as_value BitmapData_paletteMap(const fn_call& fn);
-static as_value BitmapData_perlinNoise(const fn_call& fn);
-static as_value BitmapData_pixelDissolve(const fn_call& fn);
-static as_value BitmapData_scroll(const fn_call& fn);
-static as_value BitmapData_setPixel(const fn_call& fn);
-static as_value BitmapData_setPixel32(const fn_call& fn);
-static as_value BitmapData_threshold(const fn_call& fn);
-static as_value BitmapData_height_getset(const fn_call& fn);
-static as_value BitmapData_rectangle_getset(const fn_call& fn);
-static as_value BitmapData_transparent_getset(const fn_call& fn);
-static as_value BitmapData_width_getset(const fn_call& fn);
-
-static as_value BitmapData_loadBitmap(const fn_call& fn);
-
-as_value BitmapData_ctor(const fn_call& fn);
-
-static void
-attachBitmapDataInterface(as_object& o)
-{
-    o.init_member("applyFilter", new builtin_function(BitmapData_applyFilter));
-    o.init_member("clone", new builtin_function(BitmapData_clone));
-    o.init_member("colorTransform", new 
builtin_function(BitmapData_colorTransform));
-    o.init_member("copyChannel", new builtin_function(BitmapData_copyChannel));
-    o.init_member("copyPixels", new builtin_function(BitmapData_copyPixels));
-    o.init_member("dispose", new builtin_function(BitmapData_dispose));
-    o.init_member("draw", new builtin_function(BitmapData_draw));
-    o.init_member("fillRect", new builtin_function(BitmapData_fillRect));
-    o.init_member("floodFill", new builtin_function(BitmapData_floodFill));
-    o.init_member("generateFilterRect", new 
builtin_function(BitmapData_generateFilterRect));
-    o.init_member("getColorBoundsRect", new 
builtin_function(BitmapData_getColorBoundsRect));
-    o.init_member("getPixel", new builtin_function(BitmapData_getPixel));
-    o.init_member("getPixel32", new builtin_function(BitmapData_getPixel32));
-    o.init_member("hitTest", new builtin_function(BitmapData_hitTest));
-    o.init_member("merge", new builtin_function(BitmapData_merge));
-    o.init_member("noise", new builtin_function(BitmapData_noise));
-    o.init_member("paletteMap", new builtin_function(BitmapData_paletteMap));
-    o.init_member("perlinNoise", new builtin_function(BitmapData_perlinNoise));
-    o.init_member("pixelDissolve", new 
builtin_function(BitmapData_pixelDissolve));
-    o.init_member("scroll", new builtin_function(BitmapData_scroll));
-    o.init_member("setPixel", new builtin_function(BitmapData_setPixel));
-    o.init_member("setPixel32", new builtin_function(BitmapData_setPixel32));
-    o.init_member("threshold", new builtin_function(BitmapData_threshold));
-    o.init_property("height", BitmapData_height_getset, 
BitmapData_height_getset);
-    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
-attachBitmapDataStaticProperties(as_object& o)
-{
-   
-    o.init_member("loadBitmap", new builtin_function(BitmapData_loadBitmap));
-}
-
-static as_object*
-getBitmapDataInterface()
-{
-       static boost::intrusive_ptr<as_object> o;
-
-       if ( ! o )
-       {
-               // TODO: check if this class should inherit from Object
-               //       or from a different class
-               o = new as_object(getObjectInterface());
-               VM::get().addStatic(o.get());
-
-               attachBitmapDataInterface(*o);
-
-       }
-
-       return o.get();
-}
+namespace {
+
+    as_value BitmapData_applyFilter(const fn_call& fn);
+    as_value BitmapData_clone(const fn_call& fn);
+    as_value BitmapData_colorTransform(const fn_call& fn);
+    as_value BitmapData_copyChannel(const fn_call& fn);
+    as_value BitmapData_copyPixels(const fn_call& fn);
+    as_value BitmapData_dispose(const fn_call& fn);
+    as_value BitmapData_draw(const fn_call& fn);
+    as_value BitmapData_fillRect(const fn_call& fn);
+    as_value BitmapData_floodFill(const fn_call& fn);
+    as_value BitmapData_generateFilterRect(const fn_call& fn);
+    as_value BitmapData_getColorBoundsRect(const fn_call& fn);
+    as_value BitmapData_getPixel(const fn_call& fn);
+    as_value BitmapData_getPixel32(const fn_call& fn);
+    as_value BitmapData_hitTest(const fn_call& fn);
+    as_value BitmapData_merge(const fn_call& fn);
+    as_value BitmapData_noise(const fn_call& fn);
+    as_value BitmapData_paletteMap(const fn_call& fn);
+    as_value BitmapData_perlinNoise(const fn_call& fn);
+    as_value BitmapData_pixelDissolve(const fn_call& fn);
+    as_value BitmapData_scroll(const fn_call& fn);
+    as_value BitmapData_setPixel(const fn_call& fn);
+    as_value BitmapData_setPixel32(const fn_call& fn);
+    as_value BitmapData_threshold(const fn_call& fn);
+    as_value BitmapData_height(const fn_call& fn);
+    as_value BitmapData_rectangle(const fn_call& fn);
+    as_value BitmapData_transparent(const fn_call& fn);
+    as_value BitmapData_width(const fn_call& fn);
+    as_value BitmapData_loadBitmap(const fn_call& fn);
+    as_value BitmapData_ctor(const fn_call& fn);
+
+    void attachBitmapDataInterface(as_object& o);
+    void attachBitmapDataStaticProperties(as_object& o);
+    as_object* getBitmapDataInterface();
+    as_value get_flash_display_bitmap_data_constructor(const fn_call& fn);
+
+}
+
 
 BitmapData_as::BitmapData_as(size_t width, size_t height,
                      bool transparent, boost::uint32_t fillColor)
@@ -140,8 +93,34 @@
 {
 }
 
-
-// 
+void
+BitmapData_as::markReachableResources() const
+{
+    std::for_each(_attachedBitmaps.begin(), _attachedBitmaps.end(),
+            std::mem_fun(&character::setReachable));
+}
+
+void
+BitmapData_as::update(const boost::uint8_t* data)
+{
+    for (size_t i = 0; i < _width * _height; ++i) {
+        boost::uint32_t pixel = (*(data++) << 16);
+        pixel |= (*(data++) << 8);
+        pixel |= (*(data++));
+        pixel |= (0xff << 24);
+        _bitmapData[i] = pixel;
+    }
+}
+   
+
+void
+BitmapData_as::updateAttachedBitmaps()
+{
+    log_debug("Updating %d attached bitmaps", _attachedBitmaps.size());
+    std::for_each(_attachedBitmaps.begin(), _attachedBitmaps.end(),
+            std::mem_fun(&Bitmap::update));
+}
+
 boost::int32_t
 BitmapData_as::getPixel(int x, int y, bool transparency) const
 {
@@ -150,7 +129,9 @@
     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;
+    if (static_cast<size_t>(x) >= _width || static_cast<size_t>(y) >= _height) 
{
+        return 0;
+    }
 
     const size_t pixelIndex = y * _width + x;
 
@@ -171,6 +152,9 @@
 void
 BitmapData_as::fillRect(int x, int y, int w, int h, boost::uint32_t color)
 {
+
+    GNASH_REPORT_FUNCTION;
+
     // The bitmap has been "disposed".
     if (_bitmapData.empty()) return;
     assert (_bitmapData.size() == _width * _height);
@@ -200,6 +184,7 @@
     // 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);
     
@@ -223,15 +208,19 @@
 
     }
 
+    updateAttachedBitmaps();
+
 }
 
 void
 BitmapData_as::dispose()
 {
     _bitmapData.clear();
+    updateAttachedBitmaps();
 }
 
-as_function* getFlashDisplayBitmapDataConstructor()
+as_function*
+getFlashDisplayBitmapDataConstructor()
 {
     static builtin_function* cl = NULL;
     if ( ! cl )
@@ -243,7 +232,21 @@
     return cl;
 }
 
-static as_value
+
+// extern 
+void BitmapData_class_init(as_object& where)
+{
+
+    string_table& st = where.getVM().getStringTable();
+       // Register _global.BitmapData
+       where.init_destructive_property(st.find("BitmapData"),
+                       get_flash_display_bitmap_data_constructor);
+}
+
+
+namespace {
+
+as_value
 BitmapData_applyFilter(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -252,7 +255,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_clone(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -261,7 +264,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_colorTransform(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -270,7 +273,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_copyChannel(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -279,7 +282,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_copyPixels(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -288,7 +291,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_dispose(const fn_call& fn)
 {
     // Should free the memory storing the bitmap.
@@ -298,16 +301,50 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_draw(const fn_call& fn)
 {
-       boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
-       UNUSED(ptr);
-       LOG_ONCE( log_unimpl (__FUNCTION__) );
+       boost::intrusive_ptr<BitmapData_as> ptr =
+        ensureType<BitmapData_as>(fn.this_ptr);
+
+    std::ostringstream os;
+    fn.dump_args(os);
+    log_unimpl("BitmapData.draw(%s) called", os.str());
+
+    if (!fn.nargs) {
+        //log error
+        return as_value();
+    }
+
+    MovieClip* mc = fn.arg(0).to_sprite();
+
+    if (!mc) {
+        // log error
+        return as_value();
+    }
+
+    /// TODO: pass the other arguments for transform.
+    std::auto_ptr<GnashImage> im = mc->drawToBitmap();
+
+    if (!im.get()) { 
+        // log error
+        return as_value();
+    }
+
+    const size_t width = im->width();
+    const size_t height = im->height();
+
+    if (width > 2880 || height > 2880) {
+        log_error("Height (%d) or width (%d) exceed 2880", height, width);
+        return as_value();
+    }
+
+    ptr->update(im->data());
+
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_fillRect(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -347,7 +384,7 @@
 
 
 // Fills the bitmap with a colour starting at point x, y.
-static as_value
+as_value
 BitmapData_floodFill(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -356,7 +393,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_generateFilterRect(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -365,7 +402,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_getColorBoundsRect(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -374,10 +411,11 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_getPixel(const fn_call& fn)
 {
-       boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
+       boost::intrusive_ptr<BitmapData_as> ptr =
+        ensureType<BitmapData_as>(fn.this_ptr);
 
     if (fn.nargs < 2)
     {
@@ -392,10 +430,12 @@
     return ptr->getPixel(x, y, false);
 }
 
-static as_value
+as_value
 BitmapData_getPixel32(const fn_call& fn)
 {
-       boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
+       boost::intrusive_ptr<BitmapData_as> ptr =
+        ensureType<BitmapData_as>(fn.this_ptr);
+
     if (fn.nargs < 2)
     {
         return as_value();
@@ -409,7 +449,8 @@
     return ptr->getPixel(x, y, true);
 }
 
-static as_value
+
+as_value
 BitmapData_hitTest(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -418,7 +459,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_merge(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -427,7 +468,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_noise(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -436,7 +477,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_paletteMap(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -445,7 +486,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_perlinNoise(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -454,7 +495,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_pixelDissolve(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -463,7 +504,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_scroll(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -472,7 +513,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_setPixel(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -481,7 +522,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_setPixel32(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -490,7 +531,7 @@
        return as_value();
 }
 
-static as_value
+as_value
 BitmapData_threshold(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -499,8 +540,8 @@
        return as_value();
 }
 
-static as_value
-BitmapData_height_getset(const fn_call& fn)
+as_value
+BitmapData_height(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
 
@@ -512,12 +553,13 @@
        return as_value(ptr->getHeight());
 }
 
-static as_value
-BitmapData_rectangle_getset(const fn_call& fn)
+as_value
+BitmapData_rectangle(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
 
-    // Returns the immutable rectangle of the bitmap or -1 if dispose() has 
been called.
+    // Returns the immutable rectangle of the bitmap or -1 if dispose()
+    // has been called.
     if (ptr->getBitmapData().empty()) return -1;
 
        boost::intrusive_ptr<as_object> obj = init_Rectangle_instance();
@@ -530,8 +572,8 @@
        return as_value(obj.get()); // will keep alive
 }
 
-static as_value
-BitmapData_transparent_getset(const fn_call& fn)
+as_value
+BitmapData_transparent(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
 
@@ -543,21 +585,22 @@
        return as_value(ptr->isTransparent());
 }
 
-static as_value
-BitmapData_width_getset(const fn_call& fn)
+as_value
+BitmapData_width(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
 
     // Read-only
     if (fn.nargs) return as_value();
     
-    // Returns the immutable width of the bitmap or -1 if dispose() has been 
called.
+    // Returns the immutable width of the bitmap or -1 if dispose() has
+    // been called.
     if (ptr->getBitmapData().empty()) return -1;
        return as_value(ptr->getWidth());
 }
 
 
-static as_value
+as_value
 BitmapData_loadBitmap(const fn_call& fn)
 {
        boost::intrusive_ptr<BitmapData_as> ptr = 
ensureType<BitmapData_as>(fn.this_ptr);
@@ -567,7 +610,7 @@
 }
 
 
-static as_value
+as_value
 get_flash_display_bitmap_data_constructor(const fn_call& /*fn*/)
 {
     log_debug("Loading flash.display.BitmapData class");
@@ -613,14 +656,64 @@
        return as_value(obj.get()); // will keep alive
 }
 
-// extern 
-void BitmapData_class_init(as_object& where)
-{
-
-    string_table& st = where.getVM().getStringTable();
-       // Register _global.BitmapData
-       where.init_destructive_property(st.find("BitmapData"),
-                       get_flash_display_bitmap_data_constructor);
-}
-
+void
+attachBitmapDataInterface(as_object& o)
+{
+    o.init_member("applyFilter", new builtin_function(BitmapData_applyFilter));
+    o.init_member("clone", new builtin_function(BitmapData_clone));
+    o.init_member("colorTransform", new 
builtin_function(BitmapData_colorTransform));
+    o.init_member("copyChannel", new builtin_function(BitmapData_copyChannel));
+    o.init_member("copyPixels", new builtin_function(BitmapData_copyPixels));
+    o.init_member("dispose", new builtin_function(BitmapData_dispose));
+    o.init_member("draw", new builtin_function(BitmapData_draw));
+    o.init_member("fillRect", new builtin_function(BitmapData_fillRect));
+    o.init_member("floodFill", new builtin_function(BitmapData_floodFill));
+    o.init_member("generateFilterRect", new 
builtin_function(BitmapData_generateFilterRect));
+    o.init_member("getColorBoundsRect", new 
builtin_function(BitmapData_getColorBoundsRect));
+    o.init_member("getPixel", new builtin_function(BitmapData_getPixel));
+    o.init_member("getPixel32", new builtin_function(BitmapData_getPixel32));
+    o.init_member("hitTest", new builtin_function(BitmapData_hitTest));
+    o.init_member("merge", new builtin_function(BitmapData_merge));
+    o.init_member("noise", new builtin_function(BitmapData_noise));
+    o.init_member("paletteMap", new builtin_function(BitmapData_paletteMap));
+    o.init_member("perlinNoise", new builtin_function(BitmapData_perlinNoise));
+    o.init_member("pixelDissolve", new 
builtin_function(BitmapData_pixelDissolve));
+    o.init_member("scroll", new builtin_function(BitmapData_scroll));
+    o.init_member("setPixel", new builtin_function(BitmapData_setPixel));
+    o.init_member("setPixel32", new builtin_function(BitmapData_setPixel32));
+    o.init_member("threshold", new builtin_function(BitmapData_threshold));
+    o.init_property("height", BitmapData_height, BitmapData_height);
+    o.init_property("rectangle", BitmapData_rectangle, BitmapData_rectangle);
+    o.init_property("transparent", BitmapData_transparent, 
BitmapData_transparent);
+    o.init_property("width", BitmapData_width, BitmapData_width);
+
+}
+
+void
+attachBitmapDataStaticProperties(as_object& o)
+{
+   
+    o.init_member("loadBitmap", new builtin_function(BitmapData_loadBitmap));
+}
+
+as_object*
+getBitmapDataInterface()
+{
+       static boost::intrusive_ptr<as_object> o;
+
+       if ( ! o )
+       {
+               // TODO: check if this class should inherit from Object
+               //       or from a different class
+               o = new as_object(getObjectInterface());
+               VM::get().addStatic(o.get());
+
+               attachBitmapDataInterface(*o);
+
+       }
+
+       return o.get();
+}
+
+} // anonymous namespace
 } // end of gnash namespace

=== modified file 'libcore/asobj/flash/display/BitmapData_as.h'
--- a/libcore/asobj/flash/display/BitmapData_as.h       2008-10-01 12:15:30 
+0000
+++ b/libcore/asobj/flash/display/BitmapData_as.h       2008-12-17 09:10:25 
+0000
@@ -31,14 +31,16 @@
 
 class as_function;
 class as_object;
+class Bitmap;
+
 
 class BitmapData_as: public as_object
 {
 
+public:
+
     typedef std::vector<boost::uint32_t> BitmapArray;
 
-public:
-
     // The constructor sets the fill colour and the
     // immutable size of the bitmap, as well as whether
     // it can handle transparency or not.
@@ -57,15 +59,27 @@
     // 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;
-    
+
+    void update(const boost::uint8_t* data);
+
     // Fill the bitmap with a colour starting at x, y
     void fillRect(int x, int y, int w, int h, boost::uint32_t color);
     
     // Free the bitmap data (clear the array)
     void dispose();
 
+    void registerBitmap(Bitmap* bitmap) {
+        _attachedBitmaps.push_back(bitmap);
+    }
+
+protected:
+
+    void markReachableResources() const;
+
 private:
 
+    void updateAttachedBitmaps();
+
     // The width of the image, max 2880. This is immutable.
     const size_t _width;
     
@@ -78,7 +92,9 @@
     // A static array of 32-bit values holding the actual bitmap data.
     // The maximum size is 2880 x 2880 * 4 bytes = 33177600 bytes.
     BitmapArray _bitmapData;
-    
+
+    std::list<Bitmap*> _attachedBitmaps;
+
 };
 
 
@@ -89,5 +105,4 @@
 
 } // end of gnash namespace
 
-// __GNASH_ASOBJ_BITMAPDATA_H__
 #endif

=== modified file 'libcore/character.h'
--- a/libcore/character.h       2008-12-11 16:56:44 +0000
+++ b/libcore/character.h       2008-12-17 07:27:15 +0000
@@ -39,7 +39,6 @@
 #include <map>
 #include <string>
 #include <cassert>
-#include <typeinfo>
 
 //#define DEBUG_SET_INVALIDATED 1
 
@@ -57,8 +56,6 @@
 /// Character is a live, stateful instance of a character_def.
 //
 /// It represents a single active element in a movie.
-/// Inheritance from movie is an horrible truth!
-///
 class character : public as_object
 {
 
@@ -440,7 +437,7 @@
     virtual rect getBounds() const
     {
         log_error("FIXME: character %s did not override the getBounds() 
method",
-                typeid(*this).name());
+                typeName(*this));
         return rect();
     }
 

=== modified file 'libcore/parser/BitmapMovieDefinition.cpp'
--- a/libcore/parser/BitmapMovieDefinition.cpp  2008-12-16 15:15:55 +0000
+++ b/libcore/parser/BitmapMovieDefinition.cpp  2008-12-17 07:27:54 +0000
@@ -34,14 +34,9 @@
 {
        if ( _shapedef ) return _shapedef.get();
 
-    _bitmap = gnash::render::createBitmapInfo(_image);
-
     // It's possible for this to fail.
     if (!_bitmap.get()) return 0;
 
-    // Ownership transferred.
-    assert (!_image.get());
-
        // Create the shape definition
        _shapedef = new DynamicShape();
 
@@ -90,8 +85,8 @@
        _framecount(1),
        _framerate(12),
        _url(url),
-       _image(image),
-       _bytesTotal(_image->size())
+       _bytesTotal(image->size()),
+       _bitmap(render::createBitmapInfo(image))
 {
        // Do not create shape_character_def now (why?)
 }

=== modified file 'libcore/parser/BitmapMovieDefinition.h'
--- a/libcore/parser/BitmapMovieDefinition.h    2008-12-16 15:15:55 +0000
+++ b/libcore/parser/BitmapMovieDefinition.h    2008-12-17 07:27:54 +0000
@@ -40,38 +40,6 @@
 ///
 class BitmapMovieDefinition : public movie_definition
 {
-       int _version;
-       rect _framesize;
-       size_t _framecount;
-       float _framerate;
-       std::string _url;
-
-       std::auto_ptr<GnashImage> _image;
-
-       boost::intrusive_ptr<BitmapInfo> _bitmap;
-
-       boost::intrusive_ptr<DynamicShape> _shapedef;
-
-       /// Get the shape character definition for this bitmap movie
-       //
-       /// It will create the definition the first time it's called
-       ///
-       shape_character_def* getShapeDef();
-
-       size_t _bytesTotal;
-
-protected:
-
-#ifdef GNASH_USE_GC
-       /// Mark reachable resources of a BitmapMovieDefinition
-       //
-       /// Reachable resources are:
-       ///     - dynamic shape (_shapedef)
-       ///     - bitmap (_bitmap)
-       ///
-       void markReachableResources() const;
-#endif // GNASH_USE_GC
-
 public:
 
 
@@ -157,6 +125,43 @@
        {
                return 1;
        }
+
+    BitmapInfo* getBitmap() const {
+        return _bitmap.get();
+    }
+
+protected:
+
+#ifdef GNASH_USE_GC
+       /// Mark reachable resources of a BitmapMovieDefinition
+       //
+       /// Reachable resources are:
+       ///     - dynamic shape (_shapedef)
+       ///     - bitmap (_bitmap)
+       ///
+       void markReachableResources() const;
+#endif // GNASH_USE_GC
+
+private:
+
+       int _version;
+       rect _framesize;
+       size_t _framecount;
+       float _framerate;
+       std::string _url;
+
+       size_t _bytesTotal;
+
+    boost::intrusive_ptr<BitmapInfo> _bitmap;
+
+       boost::intrusive_ptr<DynamicShape> _shapedef;
+
+       /// Get the shape character definition for this bitmap movie
+       //
+       /// It will create the definition the first time it's called
+       ///
+       shape_character_def* getShapeDef();
+
 };
 
 } // namespace gnash

=== modified file 'libcore/render.cpp'
--- a/libcore/render.cpp        2008-12-16 15:15:55 +0000
+++ b/libcore/render.cpp        2008-12-17 07:54:39 +0000
@@ -78,19 +78,9 @@
                 return NULL;
 
             case GNASH_IMAGE_RGB:
-            {
-                std::auto_ptr<ImageRGB> imageRGB(
-                            dynamic_cast<ImageRGB*>(im.release()));
-                assert(imageRGB.get());
-                return  
s_render_handler->create_bitmap_info_rgb(imageRGB.get());
-            }
-
             case GNASH_IMAGE_RGBA:
             {
-                std::auto_ptr<ImageRGBA> imageRGBA(
-                            dynamic_cast<ImageRGBA*>(im.release()));
-                assert(imageRGBA.get());
-                return 
s_render_handler->create_bitmap_info_rgba(imageRGBA.get());
+                return s_render_handler->createBitmapInfo(im);
             }
         }
 


reply via email to

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