gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r10236: Further reduce the libcore/p


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10236: Further reduce the libcore/parser directory.
Date: Fri, 07 Nov 2008 10:10:54 +0100
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10236
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Fri 2008-11-07 10:10:54 +0100
message:
  Further reduce the libcore/parser directory.
added:
  libcore/swf/VideoFrameTag.cpp
  libcore/swf/VideoFrameTag.h
renamed:
  libcore/parser/video_stream_def.cpp => libcore/swf/DefineVideoStreamTag.cpp
  libcore/parser/video_stream_def.h => libcore/swf/DefineVideoStreamTag.h
  libcore/video_stream_instance.cpp => libcore/Video.cpp
  libcore/video_stream_instance.h => libcore/Video.h
modified:
  libcore/Makefile.am
  libcore/asobj/ClassHierarchy.cpp
  libcore/asobj/Global.cpp
  libcore/asobj/NetStream_as.h
  libcore/impl.cpp
  libcore/parser/Makefile.am
  libcore/parser/morph2_character_def.cpp
  libcore/parser/morph2_character_def.h
  libcore/parser/shape_character_def.cpp
  libcore/parser/shape_character_def.h
  libcore/swf/tag_loaders.cpp
  libcore/swf/DefineVideoStreamTag.cpp
  libcore/swf/DefineVideoStreamTag.h
  libcore/Video.cpp
  libcore/Video.h
    ------------------------------------------------------------
    revno: 10229.1.11
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Thu 2008-11-06 22:10:36 +0100
    message:
      Clean up shape_character_def so it's almost readable. Drop the debugging
      stuff, which almost certainly doesn't work any more.
    modified:
      libcore/parser/shape_character_def.cpp
    ------------------------------------------------------------
    revno: 10229.1.12
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Thu 2008-11-06 23:57:43 +0100
    message:
      Split video stream parsing into DefineVideoStreamTag and VideoFrameTag. 
Push the
      data in the frame tags to the DefineVideoStreamTag on parsing.
      
      Drop things from shape_character_def that aren't immediately useful. They 
      can easily be retrieved if necessary.
    added:
      libcore/swf/VideoFrameTag.cpp
      libcore/swf/VideoFrameTag.h
    renamed:
      libcore/parser/video_stream_def.cpp => 
libcore/swf/DefineVideoStreamTag.cpp
      libcore/parser/video_stream_def.h => libcore/swf/DefineVideoStreamTag.h
    modified:
      libcore/Makefile.am
      libcore/impl.cpp
      libcore/parser/Makefile.am
      libcore/parser/shape_character_def.cpp
      libcore/parser/shape_character_def.h
      libcore/swf/tag_loaders.cpp
      libcore/video_stream_instance.cpp
      libcore/video_stream_instance.h
      libcore/swf/DefineVideoStreamTag.cpp
      libcore/swf/DefineVideoStreamTag.h
    ------------------------------------------------------------
    revno: 10229.1.13
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Fri 2008-11-07 00:06:02 +0100
    message:
      Rename video_stream_instance to Video.
    renamed:
      libcore/video_stream_instance.cpp => libcore/Video.cpp
      libcore/video_stream_instance.h => libcore/Video.h
    modified:
      libcore/Makefile.am
      libcore/asobj/ClassHierarchy.cpp
      libcore/asobj/Global.cpp
      libcore/asobj/NetStream_as.h
      libcore/swf/DefineVideoStreamTag.cpp
      libcore/Video.cpp
      libcore/Video.h
    ------------------------------------------------------------
    revno: 10229.1.14
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Fri 2008-11-07 00:21:13 +0100
    message:
      Use std::fill_n instead of memset.
    modified:
      libcore/swf/VideoFrameTag.cpp
    ------------------------------------------------------------
    revno: 10229.1.15
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Fri 2008-11-07 09:37:30 +0100
    message:
      Separate shape and morph parsing / definition classes properly.
    modified:
      libcore/parser/morph2_character_def.cpp
      libcore/parser/morph2_character_def.h
      libcore/parser/shape_character_def.h
=== modified file 'libcore/Makefile.am'
--- a/libcore/Makefile.am       2008-11-06 11:56:50 +0000
+++ b/libcore/Makefile.am       2008-11-06 23:06:02 +0000
@@ -82,6 +82,8 @@
        rect.cpp \
        MovieClip.cpp \
        swf/TagLoadersTable.cpp \
+       swf/DefineVideoStreamTag.cpp \
+       swf/VideoFrameTag.cpp \
        swf/tag_loaders.cpp \
        swf/DefineFontAlignZonesTag.cpp \
        swf/DefineEditTextTag.cpp \
@@ -91,7 +93,7 @@
        swf/StartSoundTag.cpp \
        swf/StreamSoundBlockTag.cpp \
        swf_function.cpp \
-       video_stream_instance.cpp \
+       Video.cpp \
        StreamProvider.cpp \
        array.cpp \
        Button.cpp \
@@ -175,6 +177,8 @@
        swf.h \
        swf/TagLoadersTable.h \
        swf/tag_loaders.h \
+       swf/VideoFrameTag.h \
+       swf/DefineVideoStreamTag.h \
        swf/ControlTag.h \
        swf/DefineFontAlignZonesTag.h \
        swf/CSMTextSettingsTag.h \
@@ -194,7 +198,7 @@
        text.h \
        timers.h \
        RGBA.h  \
-       video_stream_instance.h \
+       Video.h \
        $(NULL)
 
 libgnashcore_la_LIBADD = \

=== renamed file 'libcore/video_stream_instance.cpp' => 'libcore/Video.cpp'
--- a/libcore/video_stream_instance.cpp 2008-10-27 16:05:13 +0000
+++ b/libcore/Video.cpp 2008-11-06 23:06:02 +0000
@@ -1,4 +1,4 @@
-// video_stream_instance.cpp:  Draw individual video frames, for Gnash.
+// Video.cpp:  Draw individual video frames, for Gnash.
 // 
 //   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 // 
@@ -19,8 +19,8 @@
 
 
 #include "MovieClip.h"
-#include "video_stream_instance.h"
-#include "video_stream_def.h"
+#include "Video.h"
+#include "DefineVideoStreamTag.h"
 #include "fn_call.h"
 #include "as_value.h"
 #include "NetStream_as.h"
@@ -114,7 +114,7 @@
 static as_value
 video_attach(const fn_call& fn)
 {
-       boost::intrusive_ptr<video_stream_instance> video = 
ensureType<video_stream_instance>(fn.this_ptr);
+       boost::intrusive_ptr<Video> video = ensureType<Video>(fn.this_ptr);
 
        if (fn.nargs < 1)
        {
@@ -153,14 +153,14 @@
 
        // I'm not sure We can rely on the def and parent values being accepted 
 as NULL
        // Not till we add some testing...
-       boost::intrusive_ptr<character> obj = new video_stream_instance(NULL, 
NULL, -1);
+       boost::intrusive_ptr<character> obj = new Video(NULL, NULL, -1);
        obj->setDynamic();
        return as_value(obj.get()); // will keep alive
 }
 
 /*private*/
 void
-video_stream_instance::initializeDecoder()
+Video::initializeDecoder()
 {
 
        media::MediaHandler* mh = media::MediaHandler::get();
@@ -188,7 +188,7 @@
        }
 }
 
-video_stream_instance::video_stream_instance(video_stream_definition* def,
+Video::Video(SWF::DefineVideoStreamTag* def,
                character* parent, int id)
        :
        character(parent, id),
@@ -199,7 +199,7 @@
        _lastDecodedVideoFrameNum(-1),
        _lastDecodedVideoFrame()
 {
-       //log_debug("video_stream_instance %p ctor", (void*)this);
+       //log_debug("Video %p ctor", (void*)this);
 
        if ( m_def )
        {
@@ -211,12 +211,12 @@
        set_prototype(getVideoInterface(*this));
 }
 
-video_stream_instance::~video_stream_instance()
+Video::~Video()
 {
 }
 
 void
-video_stream_instance::display()
+Video::display()
 {
        // if m_def is NULL we've been constructed by 'new Video', in this
        // case I think display() would never be invoked on us...
@@ -235,7 +235,7 @@
 }
 
 GnashImage*
-video_stream_instance::getVideoFrame()
+Video::getVideoFrame()
 {
 
 
@@ -323,7 +323,7 @@
 }
 
 void
-video_stream_instance::stagePlacementCallback()
+Video::stagePlacementCallback()
 {
     saveOriginalTarget(); // for softref
 
@@ -333,7 +333,7 @@
 
 
 void
-video_stream_instance::advance()
+Video::advance()
 {
        if (_ns) {
                //_ns->advance();
@@ -342,7 +342,7 @@
 }
 
 void
-video_stream_instance::add_invalidated_bounds(InvalidatedRanges& ranges, 
+Video::add_invalidated_bounds(InvalidatedRanges& ranges, 
        bool force)
 {      
        if (!force && !m_invalidated) return; // no need to redraw
@@ -362,7 +362,7 @@
 }
 
 void
-video_stream_instance::setStream(boost::intrusive_ptr<NetStream_as> ns)
+Video::setStream(boost::intrusive_ptr<NetStream_as> ns)
 {
        _ns = ns;
        _ns->setInvalidatedVideo(this);
@@ -389,7 +389,7 @@
 }
 
 rect
-video_stream_instance::getBounds() const
+Video::getBounds() const
 {
        if (_embeddedStream) return m_def->get_bound();
 
@@ -400,7 +400,7 @@
 
 #ifdef GNASH_USE_GC
 void
-video_stream_instance::markReachableResources() const
+Video::markReachableResources() const
 {
        if ( _ns ) _ns->setReachable();
 

=== renamed file 'libcore/video_stream_instance.h' => 'libcore/Video.h'
--- a/libcore/video_stream_instance.h   2008-10-27 16:05:13 +0000
+++ b/libcore/Video.h   2008-11-06 23:06:02 +0000
@@ -21,12 +21,17 @@
 #define GNASH_VIDEO_STREAM_INSTANCE_H
 
 #include "character.h" // for inheritance
-#include "video_stream_def.h"
-#include "snappingrange.h"
 
 // Forward declarations
 namespace gnash {
        class NetStream_as;
+    class GnashImage;
+    namespace SWF {
+        class DefineVideoStreamTag;
+    }
+    namespace media {
+        class VideoDecoder;
+    }
 }
 
 namespace gnash {
@@ -37,17 +42,17 @@
 /// embedded into the SWF itself or loaded from the
 /// network using an associated NetStream object.
 ///
-class video_stream_instance : public character
+class Video : public character
 {
 
 public:
 
-       boost::intrusive_ptr<video_stream_definition>   m_def;
+       boost::intrusive_ptr<SWF::DefineVideoStreamTag> m_def;
        
-       video_stream_instance(video_stream_definition* def,
-                       character* parent, int id);
+       Video(SWF::DefineVideoStreamTag* def, character* parent,
+            int id);
 
-       ~video_stream_instance();
+       ~Video();
 
        virtual bool pointInShape(boost::int32_t x, boost::int32_t y) const
        {

=== modified file 'libcore/asobj/ClassHierarchy.cpp'
--- a/libcore/asobj/ClassHierarchy.cpp  2008-11-05 10:02:06 +0000
+++ b/libcore/asobj/ClassHierarchy.cpp  2008-11-06 23:06:02 +0000
@@ -52,7 +52,7 @@
 #include "System_as.h"
 #include "TextSnapshot_as.h"
 #include "TextFormat.h"
-#include "video_stream_instance.h"
+#include "Video.h"
 #include "extension.h"
 #include "VM.h"
 #include "timers.h"

=== modified file 'libcore/asobj/Global.cpp'
--- a/libcore/asobj/Global.cpp  2008-11-05 10:02:06 +0000
+++ b/libcore/asobj/Global.cpp  2008-11-06 23:06:02 +0000
@@ -58,7 +58,7 @@
 #include "System_as.h"
 #include "TextFormat.h"
 #include "TextSnapshot_as.h"
-#include "video_stream_instance.h"
+#include "Video.h"
 #include "extension.h"
 #include "VM.h"
 #include "timers.h"

=== modified file 'libcore/asobj/NetStream_as.h'
--- a/libcore/asobj/NetStream_as.h      2008-11-04 01:14:26 +0000
+++ b/libcore/asobj/NetStream_as.h      2008-11-06 23:06:02 +0000
@@ -29,7 +29,6 @@
 
 #include "smart_ptr.h" // GNASH_USE_GC
 #include "impl.h"
-#include "video_stream_instance.h"
 #include "NetConnection.h"
 #include "MediaParser.h"
 #include "as_function.h" // for visibility of destructor by intrusive_ptr

=== modified file 'libcore/impl.cpp'
--- a/libcore/impl.cpp  2008-11-06 11:56:50 +0000
+++ b/libcore/impl.cpp  2008-11-06 22:57:43 +0000
@@ -47,6 +47,8 @@
 #include "SetBackgroundColorTag.h"
 #include "StartSoundTag.h"
 #include "StreamSoundBlockTag.h"
+#include "DefineVideoStreamTag.h"
+#include "VideoFrameTag.h"
 #include "swf/tag_loaders.h" // for all tag loaders..
 #include "RunInfo.h"
 #ifdef GNASH_USE_GC
@@ -166,8 +168,10 @@
 
     register_tag_loader(SWF::INITACTION, DoInitActionTag::doInitActionLoader); 
 // 59  
 
-    register_tag_loader(SWF::DEFINEVIDEOSTREAM, define_video_loader); // 60
-    register_tag_loader(SWF::VIDEOFRAME, video_loader); // 61
+    // 60
+    register_tag_loader(SWF::DEFINEVIDEOSTREAM, DefineVideoStreamTag::loader);
+    // 61
+    register_tag_loader(SWF::VIDEOFRAME, VideoFrameTag::loader);
 
     // 62, DEFINEFONTINFO2 is done above.
     // We're not an authoring tool.

=== modified file 'libcore/parser/Makefile.am'
--- a/libcore/parser/Makefile.am        2008-11-06 11:56:50 +0000
+++ b/libcore/parser/Makefile.am        2008-11-06 22:57:43 +0000
@@ -57,8 +57,7 @@
         morph2_character_def.cpp \
        shape_character_def.cpp \
        sound_definition.cpp \
-       sprite_definition.cpp \
-       video_stream_def.cpp
+       sprite_definition.cpp
 
 noinst_HEADERS = \
        abc_block.h \
@@ -74,8 +73,7 @@
        Namespace.h \
        shape_character_def.h \
        sound_definition.h \
-       sprite_definition.h \
-       video_stream_def.h
+       sprite_definition.h
 
 libgnashparser_la_LIBADD = \
        $(top_builddir)/libamf/libgnashamf.la \

=== modified file 'libcore/parser/morph2_character_def.cpp'
--- a/libcore/parser/morph2_character_def.cpp   2008-10-30 13:15:12 +0000
+++ b/libcore/parser/morph2_character_def.cpp   2008-11-07 08:37:30 +0000
@@ -97,200 +97,212 @@
 
 };
 
-       morph2_character_def::morph2_character_def():
-               m_last_ratio(-1.0f)
-       {   /* Markus: No delete??? */
-               m_shape1 = new shape_character_def();
-               m_shape2 = new shape_character_def();
-       }
-
-
-       morph2_character_def::~morph2_character_def()
-       {
-       }
-
-       void    morph2_character_def::display(character* inst)
-       {
+morph2_character_def::morph2_character_def():
+    m_last_ratio(-1.0f)
+{   /* Markus: No delete??? */
+    m_shape1 = new shape_character_def();
+    m_shape2 = new shape_character_def();
+}
+
+
+morph2_character_def::~morph2_character_def()
+{
+}
+
+void   morph2_character_def::display(character* inst)
+{
 //             GNASH_REPORT_FUNCTION;
 
-               unsigned int i = 0;
-               float ratio = inst->get_ratio() / 65535.0;
-               // bounds
-               rect    new_bound;
-               new_bound.set_lerp(m_shape1->get_bound(), 
m_shape2->get_bound(), ratio);
-               set_bound(new_bound);
-
-               // fill styles
-               for (; i < m_fill_styles.size(); i++)
-               {
-                       fill_style& fs = m_fill_styles[i];
-
-                       const fill_style& fs1 = m_shape1->get_fill_styles()[i];
-                       const fill_style& fs2 = m_shape2->get_fill_styles()[i];
-
-                       fs.set_lerp(fs1, fs2, ratio);
-               }
-
-               // line styles
-               for (i=0; i < m_line_styles.size(); i++)
-               {
-                       line_style& ls = m_line_styles[i];
-
-                       const line_style& ls1 = m_shape1->get_line_styles()[i];
-                       const line_style& ls2 = m_shape2->get_line_styles()[i];
-
-                       ls.set_lerp(ls1, ls2, ratio);
-               }
-
-               // This is used for cases in which number
-               // of paths in start shape and end shape are not
-               // the same.
-               path empty_path;
-               edge empty_edge;
-
-               // shape
-               unsigned int k=0, n=0;
-               const std::vector<path>& paths1 = m_shape1->get_paths();
-               const std::vector<path>& paths2 = m_shape2->get_paths();
-               for (i=0; i < m_paths.size(); i++)
-               {
-                       path& p = m_paths[i];
-                       const path& p1 = i < paths1.size() ? paths1[i] : 
empty_path;
-                       const path& p2 = n < paths2.size() ? paths2[n] : 
empty_path;
-
-                       float new_ax = utility::flerp(p1.ap.x, p2.ap.x, ratio);
-                       float new_ay = utility::flerp(p1.ap.y, p2.ap.y, ratio);
-
-                       p.reset ( new_ax, new_ay, p1.getLeftFill(), 
p2.getRightFill(), p1.getLineStyle() );
-
-                       //  edges;
-                       size_t len = p1.size();
-                       p.m_edges.resize(len);
-
-                       for (size_t j=0; j < p.size(); j++)
-                       {
-                               edge& e = p[j];
-                               const edge& e1 = j < p1.size() ? p1[j] : 
empty_edge;
-                               const edge& e2 = k < p2.size() ? p2[k] : 
empty_edge;
-
-                               e.cp.x = 
static_cast<int>(utility::flerp(e1.cp.x, e2.cp.x, ratio));
-                               e.cp.y = 
static_cast<int>(utility::flerp(e1.cp.y, e2.cp.y, ratio));
-                               e.ap.x = 
static_cast<int>(utility::flerp(e1.ap.x, e2.ap.x, ratio));
-                               e.ap.y = 
static_cast<int>(utility::flerp(e1.ap.y, e2.ap.y, ratio));
-                               k++;
-                               if (p2.size() <= k)
-                               {
-                                       k=0; n++;
-                               }
-                       }
-               }
+    unsigned int i = 0;
+    float ratio = inst->get_ratio() / 65535.0;
+    // bounds
+    rect       new_bound;
+    new_bound.set_lerp(m_shape1->get_bound(), m_shape2->get_bound(), ratio);
+    set_bound(new_bound);
+
+    // fill styles
+    for (; i < m_fill_styles.size(); i++)
+    {
+        fill_style& fs = m_fill_styles[i];
+
+        const fill_style& fs1 = m_shape1->get_fill_styles()[i];
+        const fill_style& fs2 = m_shape2->get_fill_styles()[i];
+
+        fs.set_lerp(fs1, fs2, ratio);
+    }
+
+    // line styles
+    for (i=0; i < m_line_styles.size(); i++)
+    {
+        line_style& ls = m_line_styles[i];
+
+        const line_style& ls1 = m_shape1->get_line_styles()[i];
+        const line_style& ls2 = m_shape2->get_line_styles()[i];
+
+        ls.set_lerp(ls1, ls2, ratio);
+    }
+
+    // This is used for cases in which number
+    // of paths in start shape and end shape are not
+    // the same.
+    path empty_path;
+    edge empty_edge;
+
+    // shape
+    unsigned int k=0, n=0;
+    const std::vector<path>& paths1 = m_shape1->get_paths();
+    const std::vector<path>& paths2 = m_shape2->get_paths();
+    for (i=0; i < m_paths.size(); i++)
+    {
+        path& p = m_paths[i];
+        const path& p1 = i < paths1.size() ? paths1[i] : empty_path;
+        const path& p2 = n < paths2.size() ? paths2[n] : empty_path;
+
+        float new_ax = utility::flerp(p1.ap.x, p2.ap.x, ratio);
+        float new_ay = utility::flerp(p1.ap.y, p2.ap.y, ratio);
+
+        p.reset(new_ax, new_ay, p1.getLeftFill(),
+                p2.getRightFill(), p1.getLineStyle());
+
+        //  edges;
+        size_t len = p1.size();
+        p.m_edges.resize(len);
+
+        for (size_t j=0; j < p.size(); j++)
+        {
+            edge& e = p[j];
+            const edge& e1 = j < p1.size() ? p1[j] : empty_edge;
+            const edge& e2 = k < p2.size() ? p2[k] : empty_edge;
+
+            e.cp.x = static_cast<int>(utility::flerp(e1.cp.x, e2.cp.x, ratio));
+            e.cp.y = static_cast<int>(utility::flerp(e1.cp.y, e2.cp.y, ratio));
+            e.ap.x = static_cast<int>(utility::flerp(e1.ap.x, e2.ap.x, ratio));
+            e.ap.y = static_cast<int>(utility::flerp(e1.ap.y, e2.ap.y, ratio));
+            k++;
+            if (p2.size() <= k)
+            {
+                k=0; n++;
+            }
+        }
+    }
 
 //  display
 
-    {
-    gnash::render::draw_shape_character(this, inst);
-    }
-
-       }
-
-
-       void    morph2_character_def::read(SWFStream& in, int tag_type, 
movie_definition& md)
-       {
-               assert(tag_type == SWF::DEFINEMORPHSHAPE
-                       || tag_type == SWF::DEFINEMORPHSHAPE2
-                       || tag_type == SWF::DEFINEMORPHSHAPE2_);
-
-               rect    bound1, bound2;
-               bound1.read(in);
-               bound2.read(in);
-
-       if (tag_type == SWF::DEFINEMORPHSHAPE2 || tag_type == 
SWF::DEFINEMORPHSHAPE2_)
-       {
-               // TODO: Use these values.
-               rect inner_bound1, inner_bound2;
-               inner_bound1.read(in);
-               inner_bound2.read(in);
-               // This should be used -- first 6 bits reserved, then 
'non-scaling' stroke,
-               // then 'scaling' stroke -- these can be used to optimize 
morphing.
-               
-               in.ensureBytes(1);
-               static_cast<void>(in.read_u8());
-       }
-
-               in.ensureBytes(4);
-               offset = in.read_u32();
-
-               // Next line will throw ParserException on malformed SWF
-               fill_style_count = in.read_variable_count();
-               int i;
-               fill_style fs1, fs2;
-               for (i = 0; i < fill_style_count; ++i)
-               {
-                       fs1.read(in, tag_type, md, &fs2);
-                       m_shape1->m_fill_styles.push_back(fs1);
-                       m_shape2->m_fill_styles.push_back(fs2);
-               }
-
-               line_style_count = in.read_variable_count();
-               line_style ls1, ls2;
-               for (i = 0; i < line_style_count; ++i)
-               {
-                       ls1.read_morph(in, tag_type, md, &ls2);
-                       m_shape1->m_line_styles.push_back(ls1);
-                       m_shape2->m_line_styles.push_back(ls2);
-               }
-
-               m_shape1->read(in, tag_type, false, md);
-               in.align();
-               m_shape2->read(in, tag_type, false, md);
-
-               // Set bounds as read in *this* tags rather then
-               // the one computed from shape_character_def parser
-               // (does it make sense ?)
-               m_shape1->set_bound(bound1);
-               m_shape2->set_bound(bound2);
-
-               assert(m_shape1->m_fill_styles.size() == 
m_shape2->m_fill_styles.size());
-               assert(m_shape1->m_line_styles.size() == 
m_shape2->m_line_styles.size());
-
-               // setup array size
-               m_fill_styles.resize(m_shape1->m_fill_styles.size());
-               unsigned int k;
-               for (k = 0; k < m_fill_styles.size(); k++)
-               {
-                       fill_style& fs = m_fill_styles[k];
-                       fill_style& fs1 = m_shape1->m_fill_styles[k];
-                       fs.m_gradients.resize(fs1.m_gradients.size());
-               }
-
-               m_line_styles.resize(m_shape1->m_line_styles.size());
-               m_paths.resize(m_shape1->m_paths.size());
-
-               unsigned edges_count1 = 
PathList::computeNumberOfEdges(m_shape1->m_paths);
-               unsigned edges_count2 = 
PathList::computeNumberOfEdges(m_shape2->m_paths);
-
-               IF_VERBOSE_PARSE(
-                 log_parse("morph: "
-                         "startShape(paths:%d, edges:%u), "
-                         "endShape(paths:%d, edges:%u)",
-                         m_shape1->m_paths.size(), edges_count1,
-                         m_shape2->m_paths.size(), edges_count2);
-               );
-
-               IF_VERBOSE_MALFORMED_SWF(
-               // It is perfectly legal to have a different number of patsh,
-               // edges count should be the same instead
-               if ( edges_count1 != edges_count2 )
-               {
-                       log_swferror(_("Different number of edges "
-                               "in start (%u) and end (%u) shapes "
-                               "of a morph"),
-                               edges_count1, edges_count1);
-               }
-
-               );
-
-       }
+{
+gnash::render::draw_shape_character(this, inst);
+}
+
+}
+
+
+void morph2_character_def::read(SWFStream& in, int tag_type,
+        movie_definition& md)
+{
+    assert(tag_type == SWF::DEFINEMORPHSHAPE
+        || tag_type == SWF::DEFINEMORPHSHAPE2
+        || tag_type == SWF::DEFINEMORPHSHAPE2_);
+
+    rect bound1, bound2;
+    bound1.read(in);
+    bound2.read(in);
+
+    if (tag_type == SWF::DEFINEMORPHSHAPE2 ||
+            tag_type == SWF::DEFINEMORPHSHAPE2_)
+    {
+        // TODO: Use these values.
+        rect inner_bound1, inner_bound2;
+        inner_bound1.read(in);
+        inner_bound2.read(in);
+        // This should be used -- first 6 bits reserved, then
+        // 'non-scaling' stroke, then 'scaling' stroke -- these can be
+        // used to optimize morphing.
+        
+        in.ensureBytes(1);
+        static_cast<void>(in.read_u8());
+    }
+
+    in.ensureBytes(4);
+    offset = in.read_u32();
+
+    // Next line will throw ParserException on malformed SWF
+    fill_style_count = in.read_variable_count();
+    int i;
+    fill_style fs1, fs2;
+    for (i = 0; i < fill_style_count; ++i)
+    {
+        fs1.read(in, tag_type, md, &fs2);
+        m_shape1->addFillStyle(fs1);
+        m_shape2->addFillStyle(fs2);
+    }
+
+    line_style_count = in.read_variable_count();
+    line_style ls1, ls2;
+    for (i = 0; i < line_style_count; ++i)
+    {
+        ls1.read_morph(in, tag_type, md, &ls2);
+        m_shape1->addLineStyle(ls1);
+        m_shape2->addLineStyle(ls2);
+    }
+
+    m_shape1->read(in, tag_type, false, md);
+    in.align();
+    m_shape2->read(in, tag_type, false, md);
+
+    // Set bounds as read in *this* tags rather then
+    // the one computed from shape_character_def parser
+    // (does it make sense ?)
+    m_shape1->set_bound(bound1);
+    m_shape2->set_bound(bound2);
+
+    const shape_character_def::FillStyleVect& s1Fills = 
+        m_shape1->get_fill_styles();
+
+    const shape_character_def::LineStyleVect& s1Lines = 
+        m_shape1->get_line_styles();
+
+    assert(s1Fills.size() == m_shape2->get_fill_styles().size());
+    assert(s1Lines.size() == m_shape2->get_line_styles().size());
+
+    // setup array size
+    m_fill_styles.resize(s1Fills.size());
+    unsigned int k;
+    for (k = 0; k < m_fill_styles.size(); k++)
+    {
+        fill_style& fs = m_fill_styles[k];
+        const fill_style& fs1 = s1Fills[k];
+        fs.m_gradients.resize(fs1.m_gradients.size());
+    }
+
+    m_line_styles.resize(s1Lines.size());
+    m_paths.resize(m_shape1->get_paths().size());
+
+    unsigned edges_count1 = PathList::computeNumberOfEdges(
+            m_shape1->get_paths());
+    unsigned edges_count2 = PathList::computeNumberOfEdges(
+            m_shape2->get_paths());
+
+    IF_VERBOSE_PARSE(
+      log_parse("morph: "
+          "startShape(paths:%d, edges:%u), "
+          "endShape(paths:%d, edges:%u)",
+          m_shape1->get_paths().size(), edges_count1,
+          m_shape2->get_paths().size(), edges_count2);
+    );
+
+    IF_VERBOSE_MALFORMED_SWF(
+        // It is perfectly legal to have a different number of paths,
+        // edges count should be the same instead
+        if ( edges_count1 != edges_count2 )
+        {
+            log_swferror(_("Different number of edges "
+                "in start (%u) and end (%u) shapes "
+                "of a morph"),
+                edges_count1, edges_count1);
+        }
+
+    );
+
+}
 }
 
 // Local Variables:

=== modified file 'libcore/parser/morph2_character_def.h'
--- a/libcore/parser/morph2_character_def.h     2008-10-30 13:15:12 +0000
+++ b/libcore/parser/morph2_character_def.h     2008-11-07 08:37:30 +0000
@@ -49,8 +49,8 @@
     /// invalidated area when rendering morphs
     virtual const rect&        get_bound() const 
     { 
-        m_bound.expand_to_rect(m_shape1->m_bound);
-        m_bound.expand_to_rect(m_shape2->m_bound);
+        m_bound.expand_to_rect(m_shape1->get_bound());
+        m_bound.expand_to_rect(m_shape2->get_bound());
         return m_bound;
     }
 

=== modified file 'libcore/parser/shape_character_def.cpp'
--- a/libcore/parser/shape_character_def.cpp    2008-10-30 13:15:12 +0000
+++ b/libcore/parser/shape_character_def.cpp    2008-11-06 22:57:43 +0000
@@ -38,12 +38,6 @@
 // and compare them with the bounds encoded in the SWF
 //#define GNASH_DEBUG_SHAPE_BOUNDS 1
 
-//#define DEBUG_DISPLAY_SHAPE_PATHS    // won't probably work anymore (Udo)
-#ifdef DEBUG_DISPLAY_SHAPE_PATHS
-// For debugging only!
-bool  gnash_debug_show_paths = false;
-#endif                                            // DEBUG_DISPLAY_SHAPE_PATHS
-
 namespace gnash
 {
 
@@ -78,10 +72,10 @@
     }
 }
 
+// Read line styles and push them onto the back of the given array.
 static void
 read_line_styles(std::vector<line_style>& styles, SWFStream& in, int tag_type,
                  movie_definition& md)
-// Read line styles and push them onto the back of the given array.
 {
     in.ensureBytes(1);
     int line_style_count = in.read_u8();
@@ -174,7 +168,8 @@
     int num_line_bits = (num_bits & 0x0F);
     
     IF_VERBOSE_PARSE(
-        log_parse(_("  shape_character_def read: nfillbits = %d, nlinebits = 
%d"), num_fill_bits, num_line_bits);
+        log_parse(_("  shape_character_def read: nfillbits = %d, "
+                "nlinebits = %d"), num_fill_bits, num_line_bits);
     );
     
     if ( !num_fill_bits && !num_line_bits )
@@ -193,9 +188,11 @@
         /// Pretty ugly... till next bug report.
         ///
         ///
-        if (tag_type == SWF::DEFINEFONT || tag_type == SWF::DEFINEFONT2 || 
tag_type == SWF::DEFINEFONT3)
+        if (tag_type == SWF::DEFINEFONT || tag_type == SWF::DEFINEFONT2 || 
+                tag_type == SWF::DEFINEFONT3)
         {
-            log_debug("Skipping glyph read, being fill and line bits zero. SWF 
tag is %d.", tag_type);
+            log_debug("Skipping glyph read, being fill and line bits zero. "
+                    "SWF tag is %d.", tag_type);
             return;
         }
     }
@@ -255,11 +252,11 @@
                 current_path.ap.x = x;
                 current_path.ap.y = y;
     
-    #if SHAPE_LOG
+#if SHAPE_LOG
                 IF_VERBOSE_PARSE(
                     log_parse(_("  shape_character read: moveto %d %d"), x, y);
                 );
-    #endif
+#endif
             }
             if ((flags & flagFillStyle0Change) && num_fill_bits > 0)
             {
@@ -278,12 +275,14 @@
                     style += fill_base;
                 }
     
-                if ( tag_type == SWF::DEFINEFONT || tag_type == 
SWF::DEFINEFONT2 )
+                if (tag_type == SWF::DEFINEFONT || tag_type == 
SWF::DEFINEFONT2)
                 {
                     if ( style > 1 )          // 0:hide 1:renderer
                     {
                         IF_VERBOSE_MALFORMED_SWF(
-                             log_swferror(_("Invalid fill style %d in 
fillStyle0Change record for font tag (0 or 1 valid). Set to 0."), style);
+                             log_swferror(_("Invalid fill style %d in "
+                                     "fillStyle0Change record for font tag "
+                                     "(0 or 1 valid). Set to 0."), style);
                         );
                         style = 0;
                     }
@@ -294,18 +293,21 @@
                     if ( style > m_fill_styles.size() )
                     {
                         IF_VERBOSE_MALFORMED_SWF(
-                             log_swferror(_("Invalid fill style %d in 
fillStyle0Change record - %d defined. Set to 0."), style, m_fill_styles.size());
-                         );
+                             log_swferror(_("Invalid fill style %d in "
+                                     "fillStyle0Change record - %d defined. "
+                                     "Set to 0."), style, 
m_fill_styles.size());
+                        );
                         style = 0;
                     }
                 }
     
                 current_path.setLeftFill(style);
-    #if SHAPE_LOG
+#if SHAPE_LOG
                 IF_VERBOSE_PARSE(
-                     log_parse(_("  shape_character read: fill0 (left) = %d"), 
current_path.getLeftFill());
+                     log_parse(_("  shape_character read: fill0 (left) = %d"),
+                         current_path.getLeftFill());
                 );
-    #endif
+#endif
             }
             if ((flags & flagFillStyle1Change) && num_fill_bits > 0)
             {
@@ -324,12 +326,14 @@
                     style += fill_base;
                 }
     
-                if ( tag_type == SWF::DEFINEFONT || tag_type == 
SWF::DEFINEFONT2 )
+                if (tag_type == SWF::DEFINEFONT || tag_type == 
SWF::DEFINEFONT2)
                 {
                     if ( style > 1 )          // 0:hide 1:renderer
                     {
                         IF_VERBOSE_MALFORMED_SWF(
-                             log_swferror(_("Invalid fill style %d in 
fillStyle1Change record for font tag (0 or 1 valid). Set to 0."), style);
+                             log_swferror(_("Invalid fill style %d in "
+                                     "fillStyle1Change record for font tag "
+                                     "(0 or 1 valid). Set to 0."), style);
                         );
                         style = 0;
                     }
@@ -340,17 +344,20 @@
                     if ( style > m_fill_styles.size() )
                     {
                         IF_VERBOSE_MALFORMED_SWF(
-                            log_swferror(_("Invalid fill style %d in 
fillStyle1Change record - %d defined. Set to 0."), style, m_fill_styles.size());
+                            log_swferror(_("Invalid fill style %d in "
+                                    "fillStyle1Change record - %d defined. "
+                                    "Set to 0."), style, m_fill_styles.size());
                         );
                         style = 0;
                     }
                 }
                 current_path.setRightFill(style);
-    #if SHAPE_LOG
+#if SHAPE_LOG
                 IF_VERBOSE_PARSE (
-                    log_parse(_("  shape_character read: fill1 (right) = %d"), 
current_path.getRightFill());
+                    log_parse(_("  shape_character read: fill1 (right) = %d"),
+                        current_path.getRightFill());
                 );
-    #endif
+#endif
             }
             if ((flags & flagLineStyleChange) && num_line_bits > 0)
             {
@@ -368,12 +375,14 @@
                 {
                     style += line_base;
                 }
-                if ( tag_type == SWF::DEFINEFONT || tag_type == 
SWF::DEFINEFONT2 )
+                if (tag_type == SWF::DEFINEFONT || tag_type == 
SWF::DEFINEFONT2)
                 {
                     if ( style > 1 )          // 0:hide 1:renderer
                     {
                         IF_VERBOSE_MALFORMED_SWF(
-                            log_swferror(_("Invalid line style %d in 
lineStyleChange record for font tag (0 or 1 valid). Set to 0."), style);
+                            log_swferror(_("Invalid line style %d in "
+                                    "lineStyleChange record for font tag "
+                                    "(0 or 1 valid). Set to 0."), style);
                         );
                         style = 0;
                     }
@@ -384,24 +393,28 @@
                     if ( style > m_line_styles.size() )
                     {
                         IF_VERBOSE_MALFORMED_SWF(
-                            log_swferror(_("Invalid fill style %d in 
lineStyleChange record - %d defined. Set to 0."), style, m_line_styles.size());
+                            log_swferror(_("Invalid fill style %d in "
+                                    "lineStyleChange record - %d defined. "
+                                    "Set to 0."), style, m_line_styles.size());
                         );
                         style = 0;
                     }
                 }
                 current_path.setLineStyle(style);
-    #if SHAPE_LOG
-                IF_VERBOSE_PARSE (
-                    log_parse(_("  shape_character_read: line = %d"), 
current_path.getLineStyle());
+#if SHAPE_LOG
+                IF_VERBOSE_PARSE(
+                    log_parse(_("  shape_character_read: line = %d"), 
+                        current_path.getLineStyle());
                 )
-    #endif
+#endif
             }
             if (flags & flagHasNewStyles)
             {
                 if (!with_style)
                 {
                     IF_VERBOSE_MALFORMED_SWF(
-                         log_swferror("Unexpected HasNewStyle flag in tag %d 
shape record", tag_type);
+                         log_swferror("Unexpected HasNewStyle flag in tag "
+                             "%d shape record", tag_type);
                     );
                     continue;
                 }
@@ -448,11 +461,12 @@
                 int ax = cx + in.read_sint(num_bits);
                 int ay = cy + in.read_sint(num_bits);
     
-    #if SHAPE_LOG
+#if SHAPE_LOG
                 IF_VERBOSE_PARSE (
-                    log_parse(_("  shape_character read: curved edge   = %d %d 
- %d %d - %d %d"), x, y, cx, cy, ax, ay);
+                    log_parse(_("  shape_character read: curved edge   = "
+                            "%d %d - %d %d - %d %d"), x, y, cx, cy, ax, ay);
                 );
-    #endif
+#endif
                 current_path.m_edges.push_back(edge(cx, cy, ax, ay));
                 x = ax;
                 y = ay;
@@ -489,12 +503,14 @@
                     }
                 }
     
-    #if SHAPE_LOG
+#if SHAPE_LOG
                 IF_VERBOSE_PARSE (
-                     log_parse(_("  shape_character_read: straight edge = %d 
%d - %d %d"), x, y, x + dx, y + dy);
+                     log_parse(_("  shape_character_read: straight edge = "
+                             "%d %d - %d %d"), x, y, x + dx, y + dy);
                 );
-    #endif
-                current_path.m_edges.push_back(edge(x + dx, y + dy, x + dx, y 
+ dy));
+#endif
+                current_path.m_edges.push_back(edge(x + dx, y + dy,
+                            x + dx, y + dy));
                 x += dx;
                 y += dy;
             }
@@ -507,527 +523,367 @@
         //       the bounds as edges are parsed.
         compute_bound(&m_bound, m.get_version());
     }
-    #ifdef GNASH_DEBUG_SHAPE_BOUNDS
+#ifdef GNASH_DEBUG_SHAPE_BOUNDS
     else
     {
         rect computedBounds;
         compute_bound(&computedBounds, m->get_version());
         if ( computedBounds != m_bounds )
         {
-            log_debug("Shape character read for tag %d contained embedded 
bounds %s, while we computed bounds %s",
-                      tag_type, m_bound.toString().c_str(), 
computedBounds.toString().c_str());
+            log_debug("Shape character read for tag %d contained embedded "
+                    "bounds %s, while we computed bounds %s",
+                    tag_type, m_bound, computedBounds);
         }
     }
-    #endif                                    // GNASH_DEBUG_SHAPE_BOUNDS
+#endif
 }
 
-    void  shape_character_def::display(character* inst)
+void  shape_character_def::display(character* inst)
+{
     // Draw the shape using our own inherent styles.
-    {
-        gnash::render::draw_shape_character(this, inst);
-    }
-
-#ifdef DEBUG_DISPLAY_SHAPE_PATHS
-
-#include "ogl.h"
-
-    static void point_normalize(point* p)
-    {
-        float mag2 = p->x * p->x + p->y * p->y;
-        if (mag2 < 1e-9f)
-        {
-            p->x = 1;
-            p->y = 0;
-        }
-
-        float inv_mag = 1.0f / sqrtf(mag2);
-        p->x *= inv_mag;
-        p->y *= inv_mag;
-    }
-
-    static void show_fill_number(const point& p, int fill_number)
-    {
-        // We're inside a glBegin(GL_LINES)
-
-        // Eh, let's do it in binary, least sig four bits...
-        float x = p.x;
-        float y = p.y;
-
-        int mask = 8;
-        while (mask)
-        {
-            if (mask & fill_number)
-            {
-                // Vert line --> 1.
-                glVertex2f(x, y - 40.0f);
-                glVertex2f(x, y + 40.0f);
-            }
-            else
-            {
-                // Rectangle --> 0.
-                glVertex2f(x - 10.0f, y - 40.0f);
-                glVertex2f(x + 10.0f, y - 40.0f);
-
-                glVertex2f(x + 10.0f, y - 40.0f);
-                glVertex2f(x + 10.0f, y + 40.0f);
-
-                glVertex2f(x - 10.0f, y + 40.0f);
-                glVertex2f(x + 10.0f, y + 40.0f);
-
-                glVertex2f(x - 10.0f, y - 40.0f);
-                glVertex2f(x - 10.0f, y + 40.0f);
-            }
-            x += 40.0f;
-            mask >>= 1;
-        }
-    }
-
-    static void debug_display_shape_paths(
-        const SWFMatrix& mat,
-        float /* object_space_max_error */,
-        const std::vector<path>& paths,
-        const std::vector<fill_style>& /* fill_styles */,
-        const std::vector<line_style>& /* line_styles */)
-    {
-        for (unsigned int i = 0; i < paths.size(); i++)
-        {
-            const path& p = paths[i];
-
-            if (p.getLeftFill() == 0 && p.getRightFill() == 0)
-            {
-                continue;
-            }
-
-            gnash::render::setMatrix(mat);
-
-            // Color the line according to which side has
-            // fills.
-            if (p.getLeftFill() == 0) glColor4f(1, 0, 0, 0.5);
-            else if (p.getRightFill() == 0) glColor4f(0, 1, 0, 0.5);
-            else glColor4f(0, 0, 1, 0.5);
-
-            // Offset according to which loop we are.
-            float offset_x = (i & 1) * 80.0f;
-            float offset_y = ((i & 2) >> 1) * 80.0f;
-            glMatrixMode(GL_MODELVIEW);
-            glPushMatrix();
-            glTranslatef(offset_x, offset_y, 0.f);
-
-            point pt;
-
-            glBegin(GL_LINE_STRIP);
-
-            mat.transform(&pt, point(p.ap.x, p.ap.y));
-            glVertex2f(pt.x, pt.y);
-
-            for (unsigned int j = 0; j < p.m_edges.size(); j++)
-            {
-                mat.transform(&pt, point(p.m_edges[j].cp.x, 
p.m_edges[j].cp.y));
-                glVertex2f(pt.x, pt.y);
-                mat.transform(&pt, point(p.m_edges[j].ap.x, 
p.m_edges[j].ap.y));
-                glVertex2f(pt.x, pt.y);
-            }
-
-            glEnd();
-
-            // Draw arrowheads.
-            point dir, right, p0, p1;
-            glBegin(GL_LINES);
-            {
-                for (unsigned int j = 0; j < p.m_edges.size(); j++)
-                {
-                    mat.transform(&p0, point(p.m_edges[j].cp.x, 
p.m_edges[j].cp.y));
-                    mat.transform(&p1, point(p.m_edges[j].ap.x, 
p.m_edges[j].ap.y));
-                    dir = point(p1.x - p0.x, p1.y - p0.y);
-                    point_normalize(&dir);
-                    right = point(-dir.y, dir.x); // perpendicular
-
-                    const float ARROW_MAG = 60.f; // TWIPS?
-                    if (p.getLeftFill() != 0)
-                    {
-                        glColor4f(0, 1, 0, 0.5);
-                        glVertex2f(p0.x,
-                            p0.y);
-                        glVertex2f(p0.x - dir.x * ARROW_MAG - right.x * 
ARROW_MAG,
-                            p0.y - dir.y * ARROW_MAG - right.y * ARROW_MAG);
-
-                        show_fill_number(point(p0.x - right.x * ARROW_MAG * 4,
-                            p0.y - right.y * ARROW_MAG * 4),
-                            p.getLeftFill());
-                    }
-                    if (p.getRightFill() != 0)
-                    {
-                        glColor4f(1, 0, 0, 0.5);
-                        glVertex2f(p0.x,
-                            p0.y);
-                        glVertex2f(p0.x - dir.x * ARROW_MAG + right.x * 
ARROW_MAG,
-                            p0.y - dir.y * ARROW_MAG + right.y * ARROW_MAG);
-
-                        show_fill_number(point(p0.x + right.x * ARROW_MAG * 4,
-                            p0.y + right.y * ARROW_MAG * 4),
-                            p.getRightFill());
-                    }
-                }
-            }
-            glEnd();
-
-            glPopMatrix();
-        }
-    }
-#endif  // DEBUG_DISPLAY_SHAPE_PATHS
-
-    void  shape_character_def::display(
-        const SWFMatrix& mat,
-        const cxform& cx,
-        const std::vector<fill_style>& fill_styles,
-        const std::vector<line_style>& line_styles) const
-    {
-        shape_character_def* this_non_const = 
const_cast<shape_character_def*>(this);
-
-        render_handler* renderer = get_render_handler();
-
-        renderer->draw_shape_character(this_non_const, mat, cx, fill_styles,
-                                       line_styles);
-    }
-
-    // TODO: this should be moved to libgeometry or something
-    int curve_x_crossings(float x0, float y0, float x1, float y1,
-        float cx, float cy, float y, float &cross1, float &cross2)
-    // Finds the quadratic bezier curve crossings with the line Y.
-    // The function can have zero, one or two solutions (cross1, cross2). The
-    // return value of the function is the number of solutions.
-    // x0, y0 = start point of the curve
-    // x1, y1 = end point of the curve (anchor, aka ax|ay)
-    // cx, cy = control point of the curve
-    // If there are two crossings, cross1 is the nearest to x0|y0 on the curve.
-    {
-        int count=0;
-
-        // check if any crossings possible
-        if ( ((y0 < y) && (y1 < y) && (cy < y))
-            || ((y0 > y) && (y1 > y) && (cy > y)) )
-        {
-            // all above or below -- no possibility of crossing
-            return 0;
-        }
-
-        // Quadratic bezier is:
-        //
-        // p = (1-t)^2 * a0 + 2t(1-t) * c + t^2 * a1
-        //
-        // We need to solve for x at y.
-
-        // Use the quadratic formula.
-
-        // Numerical Recipes suggests this variation:
-        // q = -0.5 [b +sgn(b) sqrt(b^2 - 4ac)]
-        // x1 = q/a;  x2 = c/q;
-
-        float A = y1 + y0 - 2 * cy;
-        float B = 2 * (cy - y0);
-        float C = y0 - y;
-
-        float rad = B * B - 4 * A * C;
-
-        if (rad < 0)
-        {
-            return 0;
+    gnash::render::draw_shape_character(this, inst);
+}
+
+void  shape_character_def::display(const SWFMatrix& mat, const cxform& cx,
+    const std::vector<fill_style>& fill_styles,
+    const std::vector<line_style>& line_styles) const
+{
+    shape_character_def* this_non_const =
+        const_cast<shape_character_def*>(this);
+
+    render_handler* renderer = get_render_handler();
+
+    renderer->draw_shape_character(this_non_const, mat, cx, fill_styles,
+                                   line_styles);
+}
+
+// TODO: this should be moved to libgeometry or something
+// Finds the quadratic bezier curve crossings with the line Y.
+// The function can have zero, one or two solutions (cross1, cross2). The
+// return value of the function is the number of solutions.
+// x0, y0 = start point of the curve
+// x1, y1 = end point of the curve (anchor, aka ax|ay)
+// cx, cy = control point of the curve
+// If there are two crossings, cross1 is the nearest to x0|y0 on the curve.
+int curve_x_crossings(float x0, float y0, float x1, float y1,
+    float cx, float cy, float y, float &cross1, float &cross2)
+{
+    int count=0;
+
+    // check if any crossings possible
+    if ( ((y0 < y) && (y1 < y) && (cy < y))
+        || ((y0 > y) && (y1 > y) && (cy > y)) )
+    {
+        // all above or below -- no possibility of crossing
+        return 0;
+    }
+
+    // Quadratic bezier is:
+    //
+    // p = (1-t)^2 * a0 + 2t(1-t) * c + t^2 * a1
+    //
+    // We need to solve for x at y.
+
+    // Use the quadratic formula.
+
+    // Numerical Recipes suggests this variation:
+    // q = -0.5 [b +sgn(b) sqrt(b^2 - 4ac)]
+    // x1 = q/a;  x2 = c/q;
+
+    float A = y1 + y0 - 2 * cy;
+    float B = 2 * (cy - y0);
+    float C = y0 - y;
+
+    float rad = B * B - 4 * A * C;
+
+    if (rad < 0)
+    {
+        return 0;
+    }
+    else
+    {
+        float q;
+        float sqrt_rad = sqrtf(rad);
+        if (B < 0)
+        {
+            q = -0.5f * (B - sqrt_rad);
         }
         else
         {
-            float q;
-            float sqrt_rad = sqrtf(rad);
-            if (B < 0)
-            {
-                q = -0.5f * (B - sqrt_rad);
-            }
-            else
-            {
-                q = -0.5f * (B + sqrt_rad);
-            }
-
-            // The old-school way.
-            // float t0 = (-B + sqrt_rad) / (2 * A);
-            // float t1 = (-B - sqrt_rad) / (2 * A);
-
-            if (q != 0)
-            {
-                float t1 = C / q;
-                if (t1 >= 0 && t1 < 1)
-                {
-                    float x_at_t1 =
-                        x0 + 2 * (cx - x0) * t1 + (x1 + x0 - 2 * cx) * t1 * t1;
-
-                    count++;
-                    assert(count==1);
-                    cross1 = x_at_t1;             // order is important!
-                }
-            }
-
-            if (A != 0)
-            {
-                float t0 = q / A;
-                if (t0 >= 0 && t0 < 1)
-                {
-                    float x_at_t0 =
-                        x0 + 2 * (cx - x0) * t0 + (x1 + x0 - 2 * cx) * t0 * t0;
-
-                    count++;
-                    if (count==2)
-                        cross2 = x_at_t0;         // order is important!
-                    else
-                        cross1 = x_at_t0;
-                }
-            }
-
-        }
-
-        return count;
-    }
-
-    bool  shape_character_def::point_test_local(boost::int32_t x, 
boost::int32_t y, SWFMatrix& wm)
-    {
-        /*
-        Principle:
-        For the fill of the shape, we project a ray from the test point to the 
left
-        side of the shape counting all crossings. When a line or curve segment 
is
-        crossed we add 1 if the left fill style is set. Regardless of the left 
fill
-        style we subtract 1 from the counter then the right fill style is set.
-        This is true when the line goes in downward direction. If it goes 
upward,
-        the fill styles are reversed.
-
-        The final counter value reveals if the point is inside the shape (and 
depends
-        on filling rule, see below).
-        This method should not depend on subshapes and work for some malformed
-        shapes situations:
-        - wrong fill side (eg. left side set for a clockwise drawen rectangle)
-        - intersecting paths
-        */
-        point pt(x, y);
-
-        bool even_odd = true;  // later we will need non-zero for glyphs... 
(TODO)
-
-        // FIXME: if the shape contains non-scaled strokes
-        //        we can't rely on boundary itself for a quick
-        //        way out. Bounds supposedly already include
-        //        thickness, so we might keep a flag telling us
-        //        whether *non_scaled* strokes are present
-        //        and if not still use the boundary check.
-        // NOTE: just skipping this test breaks a corner-case
-        //       in DrawingApiTest (kind of a fill-leakage making
-        //       the collision detection find you inside a self-crossing
-        //       shape).
-        //
-        if (m_bound.point_test(x, y) == false)
-        {
-            return false;
-        }
-
-        unsigned npaths = m_paths.size();
-        int counter = 0;
-
-        // browse all paths
-        for (unsigned pno=0; pno<npaths; pno++)
-        {
-            const path& pth = m_paths[pno];
-            unsigned nedges = pth.m_edges.size();
-
-            float  next_pen_x = pth.ap.x;
-            float  next_pen_y = pth.ap.y;
-            float  pen_x, pen_y;
-
-            if (pth.m_new_shape)
-            {
-                if ( ( even_odd && (counter % 2) != 0) ||
-                     (!even_odd && (counter != 0)) )
-                {
-                    // the point is inside the previous subshape, so exit now
-                    return true;
-                }
-
-                counter=0;
-            }
-            if (pth.empty())
-                continue;
-
-            // If the path has a line style, check for strokes there
-            if (pth.m_line != 0 )
-            {
-                assert(m_line_styles.size() >= pth.m_line);
-                line_style& ls = m_line_styles[pth.m_line-1];
-                double thickness = ls.getThickness();
-                if (! thickness )
-                {
-                    thickness = 20; // at least ONE PIXEL thick.
-                }
-                else if ( (!ls.scaleThicknessVertically()) && 
(!ls.scaleThicknessHorizontally()) )
-                {
-                    // TODO: pass the SWFMatrix to withinSquareDistance 
instead ?
-                    double xScale = wm.get_x_scale();
-                    double yScale = wm.get_y_scale();
-                       //log_debug("thickness:%d, xScale:%g, yScale:%g", 
thickness, xScale, yScale);
-                    thickness *= std::max(xScale, yScale);
-                       //log_debug("after scaling, thickness:%d", thickness);
-                }
-                else if ( ls.scaleThicknessVertically() != 
ls.scaleThicknessHorizontally() )
-                {
-                    LOG_ONCE( log_unimpl("Collision detection for 
unidirectionally scaled strokes") );
-                }
-
-                double dist = thickness / 2.0;
-                double sqdist = dist * dist;
-                if (pth.withinSquareDistance(pt, sqdist))
-                    return true;
-            }
-
-            // browse all edges of the path
-            for (unsigned eno=0; eno<nedges; eno++)
-            {
-                const edge& edg = pth.m_edges[eno];
-                pen_x = next_pen_x;
-                pen_y = next_pen_y;
-                next_pen_x = edg.ap.x;
-                next_pen_y = edg.ap.y;
-
-                float cross1, cross2;
-                int dir1, dir2 = 0; // +1 = downward, -1 = upward
-                int crosscount = 0;
-
-                if (edg.is_straight())
-                {
-                    // ignore horizontal lines
-                    if (edg.ap.y == pen_y)  // TODO: better check for small 
difference?
-                    {
-                        continue;
-                    }
-                    // does this line cross the Y coordinate?
-                    if ( ((pen_y <= y) && (edg.ap.y >= y))
-                        || ((pen_y >= y) && (edg.ap.y <= y)) )
-                    {
-
-                        // calculate X crossing
-                        cross1 = pen_x + (edg.ap.x - pen_x) *
-                            (y - pen_y) / (edg.ap.y - pen_y);
-
-                        if (pen_y > edg.ap.y)
-                            dir1 = -1;  // upward
-                        else
-                            dir1 = +1;  // downward
-
-                        crosscount = 1;
-                    }
-                    else
-                    {
-                        // no crossing found
-                        crosscount = 0;
-                    }
-                }
-                else
-                {
-                    // ==> curve case
-                    crosscount = curve_x_crossings(pen_x, pen_y, edg.ap.x, 
edg.ap.y,
-                        edg.cp.x, edg.cp.y, y, cross1, cross2);
-                    dir1 = pen_y > y ? -1 : +1;
-                    dir2 = dir1 * (-1); // second crossing always in opposite 
dir.
-                } // curve
-
-                // ==> we have now:
-                //  - one (cross1) or two (cross1, cross2) ray crossings (X 
coordinate)
-                //  - dir1/dir2 tells the direction of the crossing
-                //    (+1 = downward, -1 = upward)
-                //  - crosscount tells the number of crossings
-
-                // need at least one crossing
-                if (crosscount == 0)
+            q = -0.5f * (B + sqrt_rad);
+        }
+
+        // The old-school way.
+        // float t0 = (-B + sqrt_rad) / (2 * A);
+        // float t1 = (-B - sqrt_rad) / (2 * A);
+
+        if (q != 0)
+        {
+            float t1 = C / q;
+            if (t1 >= 0 && t1 < 1)
+            {
+                float x_at_t1 =
+                    x0 + 2 * (cx - x0) * t1 + (x1 + x0 - 2 * cx) * t1 * t1;
+
+                count++;
+                assert(count==1);
+                cross1 = x_at_t1;             // order is important!
+            }
+        }
+
+        if (A != 0)
+        {
+            float t0 = q / A;
+            if (t0 >= 0 && t0 < 1)
+            {
+                float x_at_t0 =
+                    x0 + 2 * (cx - x0) * t0 + (x1 + x0 - 2 * cx) * t0 * t0;
+
+                count++;
+                // order is important!
+                if (count == 2) cross2 = x_at_t0;
+                else cross1 = x_at_t0;
+            }
+        }
+
+    }
+
+    return count;
+}
+
+bool  shape_character_def::point_test_local(boost::int32_t x,
+        boost::int32_t y, SWFMatrix& wm)
+{
+    /*
+    Principle:
+    For the fill of the shape, we project a ray from the test point to the left
+    side of the shape counting all crossings. When a line or curve segment is
+    crossed we add 1 if the left fill style is set. Regardless of the left fill
+    style we subtract 1 from the counter then the right fill style is set.
+    This is true when the line goes in downward direction. If it goes upward,
+    the fill styles are reversed.
+
+    The final counter value reveals if the point is inside the shape (and
+    depends on filling rule, see below).
+    This method should not depend on subshapes and work for some malformed
+    shapes situations:
+    - wrong fill side (eg. left side set for a clockwise drawen rectangle)
+    - intersecting paths
+    */
+    point pt(x, y);
+
+    // later we will need non-zero for glyphs... (TODO)
+    bool even_odd = true;  
+
+    // FIXME: if the shape contains non-scaled strokes
+    //        we can't rely on boundary itself for a quick
+    //        way out. Bounds supposedly already include
+    //        thickness, so we might keep a flag telling us
+    //        whether *non_scaled* strokes are present
+    //        and if not still use the boundary check.
+    // NOTE: just skipping this test breaks a corner-case
+    //       in DrawingApiTest (kind of a fill-leakage making
+    //       the collision detection find you inside a self-crossing
+    //       shape).
+    //
+    if (m_bound.point_test(x, y) == false)
+    {
+        return false;
+    }
+
+    unsigned npaths = m_paths.size();
+    int counter = 0;
+
+    // browse all paths
+    for (unsigned pno=0; pno<npaths; pno++)
+    {
+        const path& pth = m_paths[pno];
+        unsigned nedges = pth.m_edges.size();
+
+        float next_pen_x = pth.ap.x;
+        float next_pen_y = pth.ap.y;
+        float pen_x, pen_y;
+
+        if (pth.m_new_shape)
+        {
+            if ( ( even_odd && (counter % 2) != 0) ||
+                 (!even_odd && (counter != 0)) )
+            {
+                // the point is inside the previous subshape, so exit now
+                return true;
+            }
+
+            counter=0;
+        }
+        if (pth.empty()) continue;
+
+        // If the path has a line style, check for strokes there
+        if (pth.m_line != 0 )
+        {
+            assert(m_line_styles.size() >= pth.m_line);
+            line_style& ls = m_line_styles[pth.m_line-1];
+            double thickness = ls.getThickness();
+            if (! thickness )
+            {
+                thickness = 20; // at least ONE PIXEL thick.
+            }
+            else if ((!ls.scaleThicknessVertically()) &&
+                    (!ls.scaleThicknessHorizontally()) )
+            {
+                // TODO: pass the SWFMatrix to withinSquareDistance instead ?
+                double xScale = wm.get_x_scale();
+                double yScale = wm.get_y_scale();
+        //log_debug("thickness:%d, xScale:%g, yScale:%g", thickness, xScale, 
yScale);
+                thickness *= std::max(xScale, yScale);
+        //log_debug("after scaling, thickness:%d", thickness);
+            }
+            else if (ls.scaleThicknessVertically() != 
+                    ls.scaleThicknessHorizontally())
+            {
+                LOG_ONCE( log_unimpl("Collision detection for "
+                            "unidirectionally scaled strokes") );
+            }
+
+            double dist = thickness / 2.0;
+            double sqdist = dist * dist;
+            if (pth.withinSquareDistance(pt, sqdist))
+                return true;
+        }
+
+        // browse all edges of the path
+        for (unsigned eno=0; eno<nedges; eno++)
+        {
+            const edge& edg = pth.m_edges[eno];
+            pen_x = next_pen_x;
+            pen_y = next_pen_y;
+            next_pen_x = edg.ap.x;
+            next_pen_y = edg.ap.y;
+
+            float cross1, cross2;
+            int dir1, dir2 = 0; // +1 = downward, -1 = upward
+            int crosscount = 0;
+
+            if (edg.is_straight())
+            {
+                // ignore horizontal lines
+                // TODO: better check for small difference?
+                if (edg.ap.y == pen_y)  
                 {
                     continue;
                 }
-
-                bool touched=false;
-
-                // check first crossing
-                if (cross1 <= x)
-                {
-                    if (pth.m_fill0 > 0) counter += dir1;
-                    if (pth.m_fill1 > 0) counter -= dir1;
-
-                    touched = true;
-                }
-
-                // check optional second crossing (only possible with curves)
-                if ( (crosscount > 1) && (cross2 <= x) )
-                {
-                    if (pth.m_fill0 > 0) counter += dir2;
-                    if (pth.m_fill1 > 0) counter -= dir2;
-
-                    touched = true;
-                }
-
-            }// for edge
-        } // for path
-
-        return ( (even_odd && (counter % 2) != 0) ||
-                 (!even_odd && (counter != 0)) );
-    }
-
-    // Find the bounds of this shape, and store them in the given rectangle.
-    void  shape_character_def::compute_bound(rect* r, int swfVersion) const
+                // does this line cross the Y coordinate?
+                if ( ((pen_y <= y) && (edg.ap.y >= y))
+                    || ((pen_y >= y) && (edg.ap.y <= y)) )
+                {
+
+                    // calculate X crossing
+                    cross1 = pen_x + (edg.ap.x - pen_x) *
+                        (y - pen_y) / (edg.ap.y - pen_y);
+
+                    if (pen_y > edg.ap.y)
+                        dir1 = -1;  // upward
+                    else
+                        dir1 = +1;  // downward
+
+                    crosscount = 1;
+                }
+                else
+                {
+                    // no crossing found
+                    crosscount = 0;
+                }
+            }
+            else
+            {
+                // ==> curve case
+                crosscount = curve_x_crossings(pen_x, pen_y, edg.ap.x, 
edg.ap.y,
+                    edg.cp.x, edg.cp.y, y, cross1, cross2);
+                dir1 = pen_y > y ? -1 : +1;
+                dir2 = dir1 * (-1); // second crossing always in opposite dir.
+            } // curve
+
+            // ==> we have now:
+            //  - one (cross1) or two (cross1, cross2) ray crossings (X
+            //    coordinate)
+            //  - dir1/dir2 tells the direction of the crossing
+            //    (+1 = downward, -1 = upward)
+            //  - crosscount tells the number of crossings
+
+            // need at least one crossing
+            if (crosscount == 0)
+            {
+                continue;
+            }
+
+            bool touched = false;
+
+            // check first crossing
+            if (cross1 <= x)
+            {
+                if (pth.m_fill0 > 0) counter += dir1;
+                if (pth.m_fill1 > 0) counter -= dir1;
+
+                touched = true;
+            }
+
+            // check optional second crossing (only possible with curves)
+            if ( (crosscount > 1) && (cross2 <= x) )
+            {
+                if (pth.m_fill0 > 0) counter += dir2;
+                if (pth.m_fill1 > 0) counter -= dir2;
+
+                touched = true;
+            }
+
+        }// for edge
+    } // for path
+
+    return ( (even_odd && (counter % 2) != 0) ||
+             (!even_odd && (counter != 0)) );
+}
+
+// Find the bounds of this shape, and store them in the given rectangle.
+void
+shape_character_def::compute_bound(rect* r, int swfVersion) const
+{
+    r->set_null();
+
+    for (unsigned int i = 0; i < m_paths.size(); i++)
     {
-        r->set_null();
+        const path& p = m_paths[i];
 
-        for (unsigned int i = 0; i < m_paths.size(); i++)
+        unsigned thickness = 0;
+        if ( p.m_line )
         {
-            const path& p = m_paths[i];
-
-            unsigned thickness = 0;
-            if ( p.m_line )
-            {
-                // For glyph shapes m_line is allowed to be 1
-                // while no defined line styles are allowed.
-                if ( m_line_styles.empty() )
-                {
-                    // This is either a Glyph, for which m_line==1 is valid
-                    // or a bug in the parser, which we have no way to
-                    // check at this time
-                    assert(p.m_line == 1);
-                }
-                else
-                {
-                    thickness = m_line_styles[p.m_line-1].getThickness();
-                }
-            }
-            p.expandBounds(*r, thickness, swfVersion);
+            // For glyph shapes m_line is allowed to be 1
+            // while no defined line styles are allowed.
+            if ( m_line_styles.empty() )
+            {
+                // This is either a Glyph, for which m_line==1 is valid
+                // or a bug in the parser, which we have no way to
+                // check at this time
+                assert(p.m_line == 1);
+            }
+            else
+            {
+                thickness = m_line_styles[p.m_line-1].getThickness();
+            }
         }
+        p.expandBounds(*r, thickness, swfVersion);
     }
+}
 
 #ifdef GNASH_USE_GC
-    void  shape_character_def::markReachableResources() const
-    {
-        assert(isReachable());
-        for (FillStyleVect::const_iterator i=m_fill_styles.begin(), 
e=m_fill_styles.end();
-            i != e; ++i)
-        {
-            i->markReachableResources();
-        }
-    }
-#endif                                        // GNASH_USE_GC
-
-    size_t  shape_character_def::numPaths() const
-    {
-        return m_paths.size();
-    }
-
-    size_t  shape_character_def::numEdges() const
-    {
-        typedef std::vector<path> PathList;
-
-        size_t count = 0;
-        for  (PathList::const_iterator i=m_paths.begin(), ie=m_paths.end(); 
i!=ie; ++i)
-        {
-            count += i->size();
-        }
-        return count;
-    }
+void  shape_character_def::markReachableResources() const
+{
+    assert(isReachable());
+    for (FillStyleVect::const_iterator i=m_fill_styles.begin(),
+            e=m_fill_styles.end(); i != e; ++i)
+    {
+        i->markReachableResources();
+    }
+}
+#endif
 
 } // end namespace gnash
 

=== modified file 'libcore/parser/shape_character_def.h'
--- a/libcore/parser/shape_character_def.h      2008-10-30 13:15:12 +0000
+++ b/libcore/parser/shape_character_def.h      2008-11-07 08:37:30 +0000
@@ -49,7 +49,8 @@
     /// Incoming coords are local coords (twips).
     /// The SWFMatrix will be used for lines with non-scalable strokes.
     ///
-    virtual bool point_test_local(boost::int32_t x, boost::int32_t y, 
SWFMatrix& wm);
+    virtual bool point_test_local(boost::int32_t x, boost::int32_t y,
+            SWFMatrix& wm);
 
     /// \brief
     /// Read a shape definition as included in DEFINEFONT*,
@@ -73,12 +74,10 @@
     ///        The movie definition corresponding to the SWF we/re parsing.
     ///        This is used to resolve bitmap characters for fill styles, never
     ///        used if with_style is false.
-    ///
-    void read(SWFStream& in, int tag_type, bool with_style, movie_definition& 
m);
+    void read(SWFStream& in, int tag_type, bool with_style,
+            movie_definition& m);
 
-    void       display(
-        const SWFMatrix& mat,
-        const cxform& cx,
+    void display(const SWFMatrix& mat, const cxform& cx,
         const std::vector<fill_style>& fill_styles,
         const std::vector<line_style>& line_styles) const;
 
@@ -86,7 +85,7 @@
     const rect&        get_bound() const { return m_bound; }
 
     /// Compute bounds by looking at the component paths
-    void       compute_bound(rect* r, int swfVersion) const;
+    void compute_bound(rect* r, int swfVersion) const;
 
     const FillStyleVect& get_fill_styles() const { return m_fill_styles; }
     const LineStyleVect& get_line_styles() const { return m_line_styles; }
@@ -94,15 +93,20 @@
     const std::vector<path>& get_paths() const { return m_paths; }
 
     // morph uses this
-    void       set_bound(const rect& r) { m_bound = r; /* should do some 
verifying */ }
-
-    size_t numEdges() const;
-
-    size_t numPaths() const;
+    // Should this be verified?
+    void set_bound(const rect& r) { m_bound = r; }
+
+    // Morph uses this.
+    void addFillStyle(const fill_style& fs) {
+        m_fill_styles.push_back(fs);
+    }
+
+    void addLineStyle(const line_style& fs) {
+        m_line_styles.push_back(fs);
+    }
 
 protected:
 
-    friend class morph2_character_def;
 #ifdef GNASH_USE_GC
     /// Mark reachable resources (for the GC)
     //

=== renamed file 'libcore/parser/video_stream_def.cpp' => 
'libcore/swf/DefineVideoStreamTag.cpp'
--- a/libcore/parser/video_stream_def.cpp       2008-09-06 07:35:31 +0000
+++ b/libcore/swf/DefineVideoStreamTag.cpp      2008-11-06 23:06:02 +0000
@@ -17,29 +17,26 @@
 
 // 
 
-#include "video_stream_def.h"
-#include "video_stream_instance.h"
-#include "render.h"
-#include "BitsReader.h"
-//#include "MediaHandler.h"
+#include "DefineVideoStreamTag.h"
+#include "Video.h"
 #include "MediaParser.h" // for VideoInfo
 #include "VideoDecoder.h"
 #include "SWFStream.h" // for read()
-
-#include <boost/bind.hpp>
-
+#include "movie_definition.h"
 
 namespace gnash {
+namespace SWF {
 
-video_stream_definition::video_stream_definition(boost::uint16_t char_id)
+DefineVideoStreamTag::DefineVideoStreamTag(SWFStream& in, boost::uint16_t 
char_id)
        :
        m_char_id(char_id),
        _width(0),
        _height(0)
 {
+    read(in);
 }
 
-video_stream_definition::~video_stream_definition()
+DefineVideoStreamTag::~DefineVideoStreamTag()
 {
        std::for_each(_video_frames.begin(), _video_frames.end(),
                      boost::checked_deleter<media::EncodedVideoFrame>());
@@ -47,11 +44,24 @@
 
 
 void
-video_stream_definition::readDefineVideoStream(SWFStream& in, SWF::tag_type 
tag, movie_definition& /*m*/)
-{
-       // Character ID has been read already, and was loaded in the constructor
-
-       assert(tag == SWF::DEFINEVIDEOSTREAM);
+DefineVideoStreamTag::loader(SWFStream& in, SWF::tag_type tag,
+        movie_definition& m, const RunInfo& /*r*/)
+{
+    assert(tag == SWF::DEFINEVIDEOSTREAM); // 60
+    
+    in.ensureBytes(2);
+    boost::uint16_t id = in.read_u16();
+
+    std::auto_ptr<DefineVideoStreamTag> vs(new DefineVideoStreamTag(in, id));
+
+    m.add_character(id, vs.release());
+
+}
+
+void
+DefineVideoStreamTag::read(SWFStream& in)
+{
+
        assert(!_videoInfo.get()); // allowed to be called only once
 
        //m_start_frame = m->get_loading_frame();
@@ -83,50 +93,23 @@
                return;
        }
 
-       _videoInfo.reset( new media::VideoInfo(m_codec_id, _width, _height, 0 
/*framerate*/, 0 /*duration*/, media::FLASH /*typei*/) );
+       _videoInfo.reset(new media::VideoInfo(m_codec_id, _width, _height,
+                0 /*framerate*/, 0 /*duration*/, media::FLASH /*typei*/));
 }
 
 void
-video_stream_definition::readDefineVideoFrame(SWFStream& in, SWF::tag_type 
tag, movie_definition& /*m*/)
+DefineVideoStreamTag::addVideoFrameTag(
+        std::auto_ptr<media::EncodedVideoFrame> frame)
 {
-       // Character ID has been read already, and was loaded in the constructor
-
-       assert(tag == SWF::VIDEOFRAME);
-
-       // TODO: skip if there's no MediaHandler registered ?
-
-       in.ensureBytes(2);
-       unsigned int frameNum = in.read_u16(); 
-
-       const unsigned int dataLength = in.get_tag_end_position() - in.tell();
-       
-       boost::uint8_t* buffer = new uint8_t[dataLength + 8]; // FIXME: catch 
bad_alloc
-
-       const size_t bytesRead = in.read(reinterpret_cast<char*>(buffer), 
dataLength);
-
-    if (bytesRead < dataLength)
-    {
-        throw ParserException(_("Could not read enough bytes when parsing "
-                                "VideoFrame tag. Perhaps we reached the "
-                                "end of the stream!"));
-    }  
-       
-       memset(buffer + bytesRead, 0, 8);
-
-       using namespace media;
-
-       EncodedVideoFrame* frame = new EncodedVideoFrame(buffer, dataLength, 
frameNum);
-
        boost::mutex::scoped_lock lock(_video_mutex);
 
-       _video_frames.push_back(frame);
+    _video_frames.push_back(frame.release());
 }
 
-
 character*
-video_stream_definition::create_character_instance(character* parent, int id)
+DefineVideoStreamTag::create_character_instance(character* parent, int id)
 {
-       character* ch = new video_stream_instance(this, parent, id);
+       character* ch = new Video(this, parent, id);
        return ch;
 }
 
@@ -137,13 +120,14 @@
 }
 
 void
-video_stream_definition::getEncodedFrameSlice(boost::uint32_t from, 
boost::uint32_t to, EmbedFrameVec& ret)
+DefineVideoStreamTag::getEncodedFrameSlice(boost::uint32_t from,
+        boost::uint32_t to, EmbeddedFrames& ret)
 {
        assert(from<=to);
 
        boost::mutex::scoped_lock lock(_video_mutex);
 
-       EmbedFrameVec::iterator it=_video_frames.begin(), 
itEnd=_video_frames.end();
+       EmbeddedFrames::iterator it=_video_frames.begin(), 
itEnd=_video_frames.end();
        for (; it!=itEnd; ++it)
        {
                media::EncodedVideoFrame* frame = *it;
@@ -165,6 +149,6 @@
 
 }
 
-
+} // namespace SWF
 } // namespace gnash
 

=== renamed file 'libcore/parser/video_stream_def.h' => 
'libcore/swf/DefineVideoStreamTag.h'
--- a/libcore/parser/video_stream_def.h 2008-10-27 16:05:13 +0000
+++ b/libcore/swf/DefineVideoStreamTag.h        2008-11-06 22:57:43 +0000
@@ -17,40 +17,38 @@
 
 // 
 
-#ifndef GNASH_VIDEO_STREAM_DEF_H
-#define GNASH_VIDEO_STREAM_DEF_H
+#ifndef GNASH_SWF_DEFINEVIDEOSTREAMTAG_H
+#define GNASH_SWF_DEFINEVIDEOSTREAMTAG_H
 
 #ifdef HAVE_CONFIG_H
 #include "gnashconfig.h"
 #endif
 
 #include "character_def.h"
-#include "movie_definition.h"
 #include "swf.h"
 #include "rect.h" // for composition
-#include "ControlTag.h"
-#include "VideoDecoder.h"
 #include "MediaParser.h" // for videoFrameType and videoCodecType enums
 
-#include "GnashImage.h"
-
 #include <boost/shared_array.hpp>
-#include <boost/shared_ptr.hpp>
 #include <boost/thread/mutex.hpp>
 
 #include <memory> // for auto_ptr
 
-namespace gnash {
-
 // Forward declarations
-class SWFStream;
+namespace gnash {
+    class movie_definition;
+    class SWFStream;
+    class RunInfo;
+}
 
+namespace gnash {
 
 /// Class used to store data for the undecoded embedded video frames.
 /// Contains the data, the data size and the type of the frame
 class VideoData {
 public:
-       VideoData(boost::shared_array<boost::uint8_t> data, boost::uint32_t 
size, media::videoFrameType ft)
+       VideoData(boost::shared_array<boost::uint8_t> data, boost::uint32_t 
size,
+            media::videoFrameType ft)
                :
                videoData(data),
                dataSize(size),
@@ -67,20 +65,21 @@
        media::videoFrameType frameType;
 };
 
-class video_stream_definition : public character_def
+namespace SWF {
+
+class DefineVideoStreamTag : public character_def
 {
 public:
 
        /// Construct a video stream definition with given ID
        //
-       /// NOTE: for dynamically created definitions (ActionScript Video class 
instances)
-       ///       you can use an id of -1. See character_def constructor, as 
that's the
-       ///       one which will eventually get passed the id.
-       ///
-       video_stream_definition(boost::uint16_t char_id);
-
-       ~video_stream_definition();
-
+       /// NOTE: for dynamically created definitions (ActionScript Video class
+    ///       instances) you can use an id of -1. See character_def
+    ///       constructor, as that's the one which will eventually get passed
+    ///       the id.
+       DefineVideoStreamTag(SWFStream& in, boost::uint16_t id);
+
+       ~DefineVideoStreamTag();
 
        character* create_character_instance(character* parent, int id);
 
@@ -91,17 +90,19 @@
        /// This function is allowed to be called only *once* for each
        /// instance of this class.
        ///
-       void readDefineVideoStream(SWFStream& in, SWF::tag_type tag, 
movie_definition& m);
+       static void loader(SWFStream& in, SWF::tag_type tag, movie_definition& 
m,
+            const RunInfo& r);
+
 
        /// Read tag SWF::VIDEOFRAME
        //
-       /// The character_id (used to find this instance in the character's 
dictionary)
-       /// is assumed to have been already read.
+       /// The character_id (used to find this instance in the character's
+    /// dictionary) is assumed to have been already read.
        ///
        /// This function is allowed to be called zero or more times, as long
        /// as readDefineVideoStream was read before.
-       ///
-       void readDefineVideoFrame(SWFStream& in, SWF::tag_type tag, 
movie_definition& m);
+       void readDefineVideoFrame(SWFStream& in, SWF::tag_type tag,
+            movie_definition& m);
 
        /// Return local video bounds in twips
        const rect&     get_bound() const
@@ -135,9 +136,13 @@
        void getEncodedFrameSlice(boost::uint32_t from, boost::uint32_t to,
                std::vector<media::EncodedVideoFrame*>& ret);
 
+    
+    void addVideoFrameTag(std::auto_ptr<media::EncodedVideoFrame> frame);
 
 private:
 
+       void read(SWFStream& in);
+
        /// Id of this character definition, set by constructor.
        ///
        /// The id is currently set to -1 when the definition is actually
@@ -175,17 +180,17 @@
        /// Bounds of the video, as read from the DEFINEVIDEOSTREAM tag.
        rect m_bound;
 
-       /// The undecoded video frames and its size, using the swf-frame number 
as key
+       /// The undecoded video frames and its size, using the swf-frame number
+    /// as key
        //
        /// Elements of this vector are owned by this instance, and will be 
deleted 
        /// at instance destruction time.
        ///
-       typedef std::vector<media::EncodedVideoFrame*> EmbedFrameVec;
+       typedef std::vector<media::EncodedVideoFrame*> EmbeddedFrames;
        
        boost::mutex _video_mutex;
        
-
-       EmbedFrameVec _video_frames;
+       EmbeddedFrames _video_frames;
 
        /// Width of the video
        boost::uint32_t _width;
@@ -195,13 +200,14 @@
 
        /// Info about embedded video
        //
-       /// TODO: drop _width/_height/m_codec_id leaving all in this member 
instead ?
-       ///
+       /// TODO: drop _width/_height/m_codec_id leaving all in this member
+    /// instead ?
        std::auto_ptr<media::VideoInfo> _videoInfo;
 
 };
 
-}      // end namespace gnash
+} // namespace SWF
+} // namespace gnash
 
 
 #endif // GNASH_VIDEO_STREAM_DEF_H

=== added file 'libcore/swf/VideoFrameTag.cpp'
--- a/libcore/swf/VideoFrameTag.cpp     1970-01-01 00:00:00 +0000
+++ b/libcore/swf/VideoFrameTag.cpp     2008-11-06 23:21:13 +0000
@@ -0,0 +1,93 @@
+// 
+//   Copyright (C) 2005, 2006, 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 "DefineVideoStreamTag.h"
+#include "VideoFrameTag.h"
+#include "VideoDecoder.h"
+#include "SWFStream.h" // for read()
+#include "movie_definition.h"
+#include "utility.h"
+
+#include <algorithm>
+
+namespace gnash {
+namespace SWF {
+
+
+void
+VideoFrameTag::loader(SWFStream& in, SWF::tag_type tag, movie_definition& m,
+        const RunInfo& /*r*/)
+{
+    assert(tag == SWF::VIDEOFRAME);
+
+    in.ensureBytes(2);
+    boost::uint16_t character_id = in.read_u16();
+    character_def* chdef = m.get_character_def(character_id);
+
+    if (!chdef)
+    {
+        IF_VERBOSE_MALFORMED_SWF(
+            log_swferror(_("VideoFrame tag refers to unknown video "
+                    "stream id %d"), character_id);
+        );
+        return;
+    }
+
+    DefineVideoStreamTag* vs = dynamic_cast<DefineVideoStreamTag*> (chdef);
+    if (!vs)
+    {
+        IF_VERBOSE_MALFORMED_SWF(
+        log_swferror(_("VideoFrame tag refers to a non-video character "
+                "%d (%s)"), character_id, typeName(*chdef));
+        );
+        return;
+    }
+
+       // TODO: skip if there's no MediaHandler registered ?
+
+       in.ensureBytes(2);
+       unsigned int frameNum = in.read_u16(); 
+
+       const unsigned int dataLength = in.get_tag_end_position() - in.tell();
+       
+    // FIXME: catch bad_alloc
+       boost::uint8_t* buffer = new uint8_t[dataLength + 8]; 
+
+       const size_t bytesRead = in.read(reinterpret_cast<char*>(buffer),
+            dataLength);
+
+    if (bytesRead < dataLength)
+    {
+        throw ParserException(_("Could not read enough bytes when parsing "
+                                "VideoFrame tag. Perhaps we reached the "
+                                "end of the stream!"));
+    }  
+       
+    std::fill_n(buffer + bytesRead, 8, 0);
+
+       using namespace media;
+
+    std::auto_ptr<EncodedVideoFrame> frame(
+            new EncodedVideoFrame(buffer, dataLength, frameNum));
+
+       vs->addVideoFrameTag(frame);
+}
+
+} // namespace SWF
+} // namespace gnash
+

=== added file 'libcore/swf/VideoFrameTag.h'
--- a/libcore/swf/VideoFrameTag.h       1970-01-01 00:00:00 +0000
+++ b/libcore/swf/VideoFrameTag.h       2008-11-06 22:57:43 +0000
@@ -0,0 +1,64 @@
+// 
+//   Copyright (C) 2005, 2006, 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_SWF_VIDEOFRAMETAG_H
+#define GNASH_SWF_VIDEOFRAMETAG_H
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include "character_def.h"
+#include "movie_definition.h"
+#include "swf.h"
+#include "rect.h" // for composition
+#include "ControlTag.h"
+#include "VideoDecoder.h"
+
+#include <memory> // for auto_ptr
+
+namespace gnash {
+    // Forward declarations
+    class SWFStream;
+}
+
+namespace gnash {
+namespace SWF {
+
+class VideoFrameTag 
+{
+public:
+
+       /// Read tag SWF::VIDEOFRAME
+       //
+       /// The character_id (used to find this instance in the character's
+    /// dictionary) is assumed to have been already read.
+       ///
+       /// This function is allowed to be called zero or more times, as long
+       /// as a DefineVideoStreamTag was read before.
+       static void loader(SWFStream& in, SWF::tag_type tag, movie_definition& 
m,
+            const RunInfo& r);
+
+};
+
+} // namespace SWF
+} // namespace gnash
+
+
+#endif // GNASH_VIDEO_STREAM_DEF_H

=== modified file 'libcore/swf/tag_loaders.cpp'
--- a/libcore/swf/tag_loaders.cpp       2008-11-06 11:56:50 +0000
+++ b/libcore/swf/tag_loaders.cpp       2008-11-06 22:57:43 +0000
@@ -52,7 +52,7 @@
 #include "text_character_def.h"
 #include "URL.h"
 #include "GnashException.h"
-#include "video_stream_def.h"
+#include "swf/DefineVideoStreamTag.h"
 #include "sound_definition.h"
 #include "abc_block.h"
 #include "SoundInfo.h"
@@ -1442,54 +1442,6 @@
     m.set_loading_sound_stream_id(handler_id);
 }
 
-void
-define_video_loader(SWFStream& in, tag_type tag, movie_definition& m,
-               const RunInfo& /*r*/)
-{
-    assert(tag == SWF::DEFINEVIDEOSTREAM); // 60
-    
-    in.ensureBytes(2);
-    boost::uint16_t character_id = in.read_u16();
-
-    std::auto_ptr<video_stream_definition> chdef (
-            new video_stream_definition(character_id));
-
-    chdef->readDefineVideoStream(in, tag, m);
-
-    m.add_character(character_id, chdef.release());
-
-}
-
-void
-video_loader(SWFStream& in, tag_type tag, movie_definition& m,
-               const RunInfo& /*r*/)
-{
-    assert(tag == SWF::VIDEOFRAME); // 61
-
-    in.ensureBytes(2);
-    boost::uint16_t character_id = in.read_u16();
-    character_def* chdef = m.get_character_def(character_id);
-
-    if (!chdef)
-    {
-        IF_VERBOSE_MALFORMED_SWF(
-        log_swferror(_("VideoFrame tag refers to unknown video stream id %d"), 
character_id);
-        );
-        return;
-    }
-
-    // TODO: add a character_def::cast_to_video_def ?
-    video_stream_definition* vdef = dynamic_cast<video_stream_definition*> 
(chdef);
-    if ( ! vdef )
-    {
-        IF_VERBOSE_MALFORMED_SWF(
-        log_swferror(_("VideoFrame tag refers to a non-video character %d 
(%s)"), character_id, typeName(*chdef));
-        );
-        return;
-    }
-
-    vdef->readDefineVideoFrame(in, tag, m);
-}
 
 void
 file_attributes_loader(SWFStream& in, tag_type tag, movie_definition& /*m*/,


reply via email to

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