gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r12240: Change the way exports and i


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r12240: Change the way exports and initactions are handled.
Date: Fri, 11 Jun 2010 14:42:20 +0200
User-agent: Bazaar (2.0.3)

------------------------------------------------------------
revno: 12240 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Fri 2010-06-11 14:42:20 +0200
message:
  Change the way exports and initactions are handled.
  
  This involves:
  
  1. Creating a runtime "dictionary" of parsed characters to track definitions
     an initialization.
  2. Executing ExportAssets, ImportAssets, and DefinitionTags to allow
     runtime tracking.
  3. Dropping the ExportableResource class, so not relying on RTTI for
     exports.
  4. Waiting for parsing to advance only in import, not in export as well.
  5. Only executing initactions and performing attachMovie for known characters
     (fixes swfdec/ExportAssets-swf and misc-ming.all/InitActions2.swf).
  
  This allows better separation of immutable definitions from AS runtime 
objects.
  
  Left for later commits are:
  
  1. Renaming of ControlTag and DefinitionTag to something less similar to
     the SWF spec concepts (which are different).
  2. Possible optimizations by using ownership rather than refcounting for
     ControlTags.
  3. Moving Export and Import parsing to their own files.
  
  Make the naptime for imports shorter, which speeds up the actionscript.all
  testsuite by a factor of 3.
removed:
  libcore/ExportableResource.h
added:
  libcore/swf/DefinitionTag.cpp
modified:
  libcore/Font.h
  libcore/Makefile.am
  libcore/Movie.h
  libcore/MovieClip.cpp
  libcore/SWFMovie.cpp
  libcore/SWFMovie.h
  libcore/asobj/Object.cpp
  libcore/asobj/flash/display/MovieClip_as.cpp
  libcore/asobj/flash/media/Sound_as.cpp
  libcore/parser/SWFMovieDefinition.cpp
  libcore/parser/SWFMovieDefinition.h
  libcore/parser/movie_definition.h
  libcore/parser/sound_definition.h
  libcore/parser/sprite_definition.cpp
  libcore/parser/sprite_definition.h
  libcore/swf/ControlTag.h
  libcore/swf/DefineButtonTag.cpp
  libcore/swf/DefineButtonTag.h
  libcore/swf/DefineEditTextTag.cpp
  libcore/swf/DefineEditTextTag.h
  libcore/swf/DefineMorphShapeTag.cpp
  libcore/swf/DefineMorphShapeTag.h
  libcore/swf/DefineShapeTag.cpp
  libcore/swf/DefineShapeTag.h
  libcore/swf/DefineTextTag.cpp
  libcore/swf/DefineTextTag.h
  libcore/swf/DefineVideoStreamTag.cpp
  libcore/swf/DefineVideoStreamTag.h
  libcore/swf/DefinitionTag.h
  libcore/swf/DoInitActionTag.h
  libcore/swf/tag_loaders.cpp
  testsuite/misc-ming.all/InitActionTest2.c
  testsuite/swfdec/PASSING
=== removed file 'libcore/ExportableResource.h'
--- a/libcore/ExportableResource.h      2010-05-20 10:57:04 +0000
+++ b/libcore/ExportableResource.h      1970-01-01 00:00:00 +0000
@@ -1,40 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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_RESOURCE_H
-#define GNASH_RESOURCE_H
-
-#include "ref_counted.h" // for inheritance
-
-namespace gnash {
-
-/// A class for SWF resources that may be exported
-//
-/// They are: DefinitionTag, sound_sample, and font.
-/// These may be held in the export map of a SWFMovieDefinition.
-class ExportableResource : public ref_counted
-{
-protected:
-    ExportableResource() {}
-       virtual ~ExportableResource() {}
-};
-
-
-} // namespace gnash
-
-#endif // GNASH_RESOURCE_H

=== modified file 'libcore/Font.h'
--- a/libcore/Font.h    2010-05-20 10:57:04 +0000
+++ b/libcore/Font.h    2010-06-11 09:32:36 +0000
@@ -24,8 +24,6 @@
 #ifndef GNASH_FONT_H
 #define GNASH_FONT_H
 
-#include "ExportableResource.h" 
-
 #include <string>
 #include <boost/scoped_ptr.hpp>
 #include <boost/shared_ptr.hpp>
@@ -34,6 +32,8 @@
 #include <vector>
 #include <map>
 
+#include "ref_counted.h"
+
 namespace gnash {
     class FreetypeGlyphsProvider;
     namespace SWF {
@@ -85,7 +85,9 @@
 /// font simultaneously means that callers must themselves ensure they
 /// specify which font they require. Failure to do this consistently may mean
 /// callers end up with the wrong information about a font.
-class Font : public ExportableResource
+//
+/// TODO: check whether it really needs to be ref_counted.
+class Font : public ref_counted
 {
 public:
 

=== modified file 'libcore/Makefile.am'
--- a/libcore/Makefile.am       2010-05-29 16:06:49 +0000
+++ b/libcore/Makefile.am       2010-06-11 09:32:36 +0000
@@ -102,6 +102,7 @@
        swf/DefineButtonTag.cpp \
        swf/DefineFontTag.cpp \
        swf/VideoFrameTag.cpp \
+       swf/DefinitionTag.cpp \
        swf/ShapeRecord.cpp \
        swf/SoundInfoRecord.cpp \
        swf/TextRecord.cpp \
@@ -271,7 +272,6 @@
        MovieFactory.h \
        fill_style.h \
        LineStyle.h \
-       ExportableResource.h \
        BitmapInfo.h \
        RGBA.h  \
        Geometry.h      \

=== modified file 'libcore/Movie.h'
--- a/libcore/Movie.h   2010-03-12 15:42:07 +0000
+++ b/libcore/Movie.h   2010-06-11 10:02:03 +0000
@@ -69,13 +69,39 @@
         return true;
     }
 
+    /// Get the URL the Movie was loaded from.
     virtual const std::string& url() const = 0;
 
+    /// Get the version of the Movie
+    //
+    /// @return     Either the version of the Movie or -1 if the Movie is of
+    ///             a type that has no version.
     virtual int version() const = 0;
 
-       /// Set a DisplayObject in the dictionary as initialized, returning
-       /// true if not already initialized.
-       virtual bool setCharacterInitialized(int /*cid*/) {
+    /// Get an exported character definition by its symbol name.
+    //
+    /// The character is only available after the ExportAssets tag has been
+    /// executed.
+    //
+    /// @param symbol   The exported symbol of the character to retrieve.
+    /// @return         The DefinitionTag of the requested character or 0
+    ///                 if the character has not yet been exported.
+    virtual SWF::DefinitionTag* exportedCharacter(const std::string& /*s*/) {
+        return 0;
+    }
+
+    /// Add a character to the list of known characters
+    //
+    /// This makes the character known to ActionScript for initialization.
+    /// Exported characters must both be in the definition's list of exports
+    /// and added with this function before they are available.
+    virtual void addCharacter(boost::uint16_t /*id*/) {}
+
+    /// Attempt to mark a character as initialized.
+    //
+    /// The default is to return false. Only a SWFMovie can have a list of
+    /// characters.
+       virtual bool initializeCharacter(boost::uint16_t /*id*/) {
         return false;
     }
 

=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp     2010-06-09 14:39:48 +0000
+++ b/libcore/MovieClip.cpp     2010-06-11 12:21:46 +0000
@@ -54,7 +54,6 @@
 #include "LineStyle.h" // for CapStyle and JoinStyle enums
 #include "PlaceObject2Tag.h" 
 #include "flash/geom/Matrix_as.h"
-#include "ExportableResource.h"
 #include "GnashNumeric.h"
 #include "InteractiveObject.h"
 #include "DisplayObjectContainer.h"
@@ -861,7 +860,9 @@
 void
 MovieClip::execute_init_action_buffer(const action_buffer& a, int cid)
 {
-    if ( _swf->setCharacterInitialized(cid) )
+    assert(cid >= 0);
+
+    if ( _swf->initializeCharacter(cid) )
     {
 #ifdef GNASH_DEBUG
         log_debug(_("Queuing init actions in frame %d of movieclip %s"),
@@ -1213,11 +1214,13 @@
     assert(_def);
     assert(tag != NULL);
 
-    SWF::DefinitionTag* cdef = _def->getDefinitionTag(tag->getID());
+    const boost::uint16_t id = tag->getID();
+
+    SWF::DefinitionTag* cdef = _def->getDefinitionTag(id);
     if (cdef == NULL)
     {
         log_error(_("movieclip::replace_display_object(): "
-            "unknown cid = %d"), tag->getID());
+            "unknown cid = %d"), id);
         return;
     }
     assert(cdef);

=== modified file 'libcore/SWFMovie.cpp'
--- a/libcore/SWFMovie.cpp      2010-06-06 10:17:39 +0000
+++ b/libcore/SWFMovie.cpp      2010-06-11 10:18:17 +0000
@@ -23,10 +23,11 @@
 
 #include <vector>
 #include <string>
-#include <cmath>
 
 #include <functional> // for mem_fun, bind1st
 #include <algorithm> // for for_each, std::min
+#include <utility>
+#include <map>
 
 namespace gnash {
 
@@ -80,5 +81,43 @@
 
     MovieClip::advance(); 
 }
+    
+SWF::DefinitionTag*
+SWFMovie::exportedCharacter(const std::string& symbol)
+{
+    log_debug("Looking for export %s", symbol);
+    const boost::uint16_t id = _def->exportID(symbol);
+    if (!id) return 0;
+    log_debug("Corresponds to character %s", id);
+    Characters::iterator it = _characters.find(id);
+    if (it == _characters.end()) return 0;
+    log_debug("Found character");
+    return _def->getDefinitionTag(id);
+}
+
+void
+SWFMovie::addCharacter(boost::uint16_t id)
+{
+    // If a character is already known, we don't want to mark it uninitialized
+    // again.
+    _characters.insert(std::make_pair(id, false));
+}
+
+bool
+SWFMovie::initializeCharacter(boost::uint16_t cid)
+{
+    Characters::iterator it = _characters.find(cid);
+    if (it == _characters.end()) {
+        IF_VERBOSE_MALFORMED_SWF(
+            log_swferror("Attempt to perform initialized for a character %s "
+                "that does not exist (either not exported or not defined)",
+                cid);
+        );
+        return false;
+    }
+    if (it->second) return false;
+    it->second = true;
+    return true;
+}
 
 } // namespace gnash

=== modified file 'libcore/SWFMovie.h'
--- a/libcore/SWFMovie.h        2010-06-06 10:17:39 +0000
+++ b/libcore/SWFMovie.h        2010-06-11 10:07:21 +0000
@@ -27,7 +27,7 @@
 
 #include <boost/intrusive_ptr.hpp>
 #include <string>
-#include <set>
+#include <map>
 
 // Forward declarations
 namespace gnash {
@@ -38,9 +38,20 @@
 {
 
 /// Stateful Movie object (a special kind of sprite)
+//
+/// The tasks of the Movie include:
+//
+/// 1. Keep a 'dictionary' of parsed characters.
+///     This is a container of characters defined in previous frames. It
+///     acts like a genuine runtime dictionary of characters, although Gnash
+///     actually stores the definitions in the SWFMovieDefinition as it is
+///     parsed.
 class SWFMovie : public Movie
 {
 
+    /// A container to track known characters and whether they are initialized.
+    typedef std::map<boost::uint16_t, bool> Characters;
+
 public:
 
        SWFMovie(as_object* object, const SWFMovieDefinition* def,
@@ -74,20 +85,51 @@
        /// It's intended to be called by movie_root::setLevel().
     void construct(as_object* init = 0);
 
+    /// Get the URL of the SWFMovie's definition.
     const std::string& url() const {
         return _def->get_url();
     }
 
+    /// Get the version of the SWFMovie.
+    //
+    /// @return     the version of the SWFMovie.
     int version() const {
         return _def->get_version();
     }
-
-       /// Set a DisplayObject in the dictionary as initialized, returning
-       /// true if not already initialized.
-       bool setCharacterInitialized(int cid)
-       {
-               return _initializedCharacters.insert(cid).second;
-       }
+    
+    /// Get an exported character definition by its symbol name.
+    //
+    /// The character is only available after the ExportAssets tag has been
+    /// executed.
+    //
+    /// @param symbol   The exported symbol of the character to retrieve.
+    /// @return         The DefinitionTag of the requested character or 0
+    ///                 if the character has not yet been exported.
+    virtual SWF::DefinitionTag* exportedCharacter(const std::string& symbol);
+
+    /// Add a character to the list of known characters
+    //
+    /// This makes the character known to ActionScript for initialization.
+    /// Exported characters must both be in the definition's list of exports
+    /// and added with this function before they are available.
+    //
+    /// If a duplicated character is added, it will not be marked
+    /// uninitialized, as SWF::DoInitAction tags are only executed once
+    /// for each id.
+    void addCharacter(boost::uint16_t id);
+
+    /// Attempt to mark a character as initialized.
+    //
+    /// A character can be initialized once, but only after it is known to this
+    /// Movie.
+    //
+    /// @param id   The id of the character to initialize.
+    /// @return     false if the character cannot be initialized. This can mean
+    ///             1. The character is not yet present (either not exported
+    ///                or has not yet been placed on stage).
+    ///             2. The character has already been initialized.
+    ///             true if the character was marked initialized.
+       bool initializeCharacter(boost::uint16_t id);
 
     const movie_definition* definition() const {
         return _def.get();
@@ -95,12 +137,8 @@
 
 private:
 
-       /// A map to track execution of init actions
-       //
-       /// Elements of this set are ids of DisplayObjects
-       /// in our definition's CharacterDictionary.
-       ///
-       std::set<int> _initializedCharacters;
+    /// Tracks known characters and whether they have been initialized.
+       Characters _characters;
 
     /// This should only be a top-level movie, not a sprite_definition.
        const boost::intrusive_ptr<const SWFMovieDefinition> _def;

=== modified file 'libcore/asobj/Object.cpp'
--- a/libcore/asobj/Object.cpp  2010-03-22 23:46:33 +0000
+++ b/libcore/asobj/Object.cpp  2010-06-09 11:13:16 +0000
@@ -305,8 +305,11 @@
     assert(relRoot);
     const movie_definition* def = relRoot->definition();
     
-    ExportableResource* exp_res = def->get_exported_resource(symbolid).get();
-    if (!exp_res) {
+    // We only care about definitions, not other exportable resources.
+    const boost::uint16_t id = def->exportID(symbolid);
+    SWF::DefinitionTag* d = def->getDefinitionTag(id);
+
+    if (!d) {
         IF_VERBOSE_ASCODING_ERRORS(
             log_aserror(_("Object.registerClass(%s, %s): "
                 "can't find exported symbol"),
@@ -317,17 +320,14 @@
 
     // Check that the exported resource is a sprite_definition
     // (we're looking for a MovieClip symbol)
-
-    sprite_definition* exp_clipdef(
-            dynamic_cast<sprite_definition*>(exp_res));
-
+    sprite_definition* exp_clipdef(dynamic_cast<sprite_definition*>(d));
 
     if (!exp_clipdef) {
         IF_VERBOSE_ASCODING_ERRORS(
         log_aserror(_("Object.registerClass(%s, %s): "
             "exported symbol is not a MovieClip symbol "
             "(sprite_definition), but a %s"),
-            symbolid, typeName(theclass), typeName(exp_res));
+            symbolid, typeName(theclass), typeName(d));
         );
         return as_value(false);
     }

=== modified file 'libcore/asobj/flash/display/MovieClip_as.cpp'
--- a/libcore/asobj/flash/display/MovieClip_as.cpp      2010-06-05 09:00:48 
+0000
+++ b/libcore/asobj/flash/display/MovieClip_as.cpp      2010-06-10 13:43:34 
+0000
@@ -463,28 +463,14 @@
     // Get exported resource 
     const std::string& id_name = fn.arg(0).to_string();
 
-    boost::intrusive_ptr<ExportableResource> exported =
-        movieclip->get_root()->definition()->get_exported_resource(id_name);
-
-    if (!exported)
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("attachMovie: '%s': no such exported resource - "
-            "returning undefined"), id_name);
-        );
-        return as_value(); 
-    }
-    
-    SWF::DefinitionTag* exported_movie =
-        dynamic_cast<SWF::DefinitionTag*>(exported.get());
+    SWF::DefinitionTag* exported_movie = 
+        movieclip->get_root()->exportedCharacter(id_name);
 
     if (!exported_movie)
     {
         IF_VERBOSE_ASCODING_ERRORS(
         log_aserror(_("attachMovie: exported resource '%s' "
-            "is not a DisplayObject definition (%s) -- "
-            "returning undefined"), id_name,
-            typeid(*(exported.get())).name());
+            "is not a DisplayObject definition. Returning undefined"), 
id_name);
         );
         return as_value();
     }

=== modified file 'libcore/asobj/flash/media/Sound_as.cpp'
--- a/libcore/asobj/flash/media/Sound_as.cpp    2010-05-21 06:02:23 +0000
+++ b/libcore/asobj/flash/media/Sound_as.cpp    2010-06-11 09:32:36 +0000
@@ -35,7 +35,6 @@
 #include "smart_ptr.h" // for boost intrusive_ptr
 #include "VM.h"
 #include "namedStrings.h"
-#include "ExportableResource.h"
 #include "StreamProvider.h"
 
 #include <string>
@@ -803,25 +802,25 @@
         // check the import.
         const movie_definition* def = fn.callerDef;
         assert(def);
-        boost::intrusive_ptr<ExportableResource> res = 
-            def->get_exported_resource(name);
 
-        if (!res) {
+        const boost::uint16_t id = def->exportID(name);
+        if (!id) {
             IF_VERBOSE_MALFORMED_SWF(
-                log_swferror(_("import error: resource '%s' is not exported"),
+                log_swferror(_("No such export '%s'"),
                     name);
                 );
             return as_value();
         }
 
-        sound_sample* ss = dynamic_cast<sound_sample*>(res.get());
-
-        if (ss != NULL) {
-            si = ss->m_sound_handler_id;
-        } else {
-            log_error(_("sound sample is NULL (doesn't cast to 
sound_sample)"));
+        sound_sample* ss = def->get_sound_sample(id);
+        if (!ss) {
+            IF_VERBOSE_MALFORMED_SWF(
+                log_swferror(_("Export '%s'is not a sound"), name);
+                );
             return as_value();
         }
+
+        si = ss->m_sound_handler_id;
     }
     
     so->stop(si);
@@ -856,25 +855,26 @@
     // (see 'winter bell' from orisinal morning sunshine for a testcase)
     const movie_definition* def = fn.callerDef;
     assert(def);
-    boost::intrusive_ptr<ExportableResource> res = 
-        def->get_exported_resource(name);
-    if (!res) {
+
+
+    const boost::uint16_t id = def->exportID(name);
+    if (!id) {
         IF_VERBOSE_MALFORMED_SWF(
-            log_swferror(_("import error: resource '%s' is not exported"),
+            log_swferror(_("No such export '%s'"),
                 name);
-        );
-        return as_value();
-    }
-
-    int si = 0;
-    sound_sample* ss = dynamic_cast<sound_sample*>(res.get());
-
-    if (ss) {
-        si = ss->m_sound_handler_id;
-    } else {
-        log_error(_("sound sample is NULL (doesn't cast to sound_sample)"));
-        return as_value();
-    }
+            );
+        return as_value();
+    }
+
+    sound_sample* ss = def->get_sound_sample(id);
+    if (!ss) {
+        IF_VERBOSE_MALFORMED_SWF(
+            log_swferror(_("Export '%s'is not a sound"), name);
+            );
+        return as_value();
+    }
+
+    const int si = ss->m_sound_handler_id;
 
     // sanity check
     assert(si >= 0);

=== modified file 'libcore/parser/SWFMovieDefinition.cpp'
--- a/libcore/parser/SWFMovieDefinition.cpp     2010-06-09 14:39:48 +0000
+++ b/libcore/parser/SWFMovieDefinition.cpp     2010-06-11 12:21:46 +0000
@@ -38,7 +38,6 @@
 #include "GnashException.h" // for parser exception
 #include "ControlTag.h"
 #include "sound_definition.h" // for sound_sample
-#include "ExportableResource.h"
 #include "GnashAlgorithm.h"
 #include "SWFParser.h"
 #include "Global_as.h"
@@ -169,18 +168,8 @@
 
 SWFMovieDefinition::~SWFMovieDefinition()
 {
-
     // Request cancelation of the loading thread
     _loadingCanceled = true;
-
-    // Release frame tags
-    for (PlayListMap::iterator i = m_playlist.begin(),
-            e = m_playlist.end(); i != e; ++i)
-    {
-        PlayList& pl = i->second;
-        deleteChecked(pl.begin(), pl.end());
-    }
-
 }
 
 void
@@ -189,6 +178,7 @@
     assert(c);
     boost::mutex::scoped_lock lock(_dictionaryMutex);
     _dictionary.addDisplayObject(id, c);
+    addControlTag(c);
 }
 
 SWF::DefinitionTag*
@@ -587,144 +577,16 @@
 }
 
 void
-SWFMovieDefinition::exportResource(const std::string& symbol, int id)
+SWFMovieDefinition::registerExport(const std::string& symbol,
+        boost::uint16_t id)
 {
-    // _exportedResources access should be protected by a mutex
+    assert(id);
+
     boost::mutex::scoped_lock lock(_exportedResourcesMutex);
-
-    ExportableResource* f;
-    if ((f = get_font(id)) || (f = getDefinitionTag(id)) ||
-            (f = get_sound_sample(id))) {
-
-        // SWFs sometimes export the same thing more than once!
-        _exportedResources[symbol] = f;
-    }
-    else {
-        IF_VERBOSE_MALFORMED_SWF(
-            log_swferror(_("don't know how to export resource '%s' "
-                        "with id %d (can't find that id)"), symbol, id);
-        );
-        return;
-    }
-}
-
-
-boost::intrusive_ptr<ExportableResource>
-SWFMovieDefinition::get_exported_resource(const std::string& symbol) const
-{
-#ifdef DEBUG_EXPORTS
-    log_debug("get_exported_resource(%s) called, loading frame:%u",
-            symbol, m_frame_count);
-#endif
-
-    // Don't call get_exported_resource() from this movie loader
-    assert( ! _loader.isSelfThread() );
-
-    // Keep trying until either we found the export or
-    // the stream is over, or there is NO frames progress
-    // after def_timeout microseconds.
-    //
-    // Note that the NO frame progress might be due
-    // to a circular import chain:
-    //
-    //     A imports B imports A
-    //
-
-    // Sleep 1/2 of a second between checks
-    // NOTE: make sure the nap is enough time for
-    //       thread execution switch !!
-    const unsigned long naptime=500000;
-
-    // Timeout after two seconds of NO frames progress
-    const unsigned long timeout_ms=2000000;
-    const unsigned long def_timeout=timeout_ms/naptime; 
-
-    unsigned long timeout=def_timeout;
-    size_t loading_frame = (size_t)-1; // used to keep track of advancements
-
-    for(;;)
-    {
-
-        // we query the loaded frame count before looking
-        // up the exported resources map because while
-        // we query the loader keeps parsing more frames.
-        // and we don't want to giveup w/out having queried
-        // up to the last frame.
-        size_t new_loading_frame = get_loading_frame();
-
-        // _exportedResources access is thread-safe
-        {
-            boost::mutex::scoped_lock lock(_exportedResourcesMutex);
-            ExportMap::const_iterator it = _exportedResources.find(symbol);
-            if ( it != _exportedResources.end() )
-            {
-#ifdef DEBUG_EXPORTS
-                log_debug(" resource found, loading frame:%u", 
new_loading_frame);
-#endif
-                return it->second;
-            }
-        }
-
-        // We checked last (or past-last) advertised frame. 
-        // TODO: this check should really be for a parser
-        //       process being active or not, as SWF
-        //       might advertise less frames then actually
-        //       found in it...
-        //
-        if (new_loading_frame >= m_frame_count) {
-            // Update of loading_frame is
-            // really just for the latter debugging output
-            loading_frame = new_loading_frame;
-            break;
-        }
-
-        // There's more frames to parse, go ahead
-        // TODO: this is still based on *advertised*
-        //       number of frames, if SWF advertises
-        //       more then actually found we'd be
-        //       keep trying till timeout, see the
-        //       other TODO above.
-
-        // We made frame progress since last iteration
-        // so sleep some and try again
-        if (new_loading_frame != loading_frame) {
-#ifdef DEBUG_EXPORTS
-            log_debug(_("looking for exported resource: frame load "
-                        "advancement (from %d to %d)"),
-                loading_frame, new_loading_frame);
-#endif
-            loading_frame = new_loading_frame;
-            timeout = def_timeout+1;
-        }
-        else if (!--timeout) {
-            // no progress since last run, and 
-            // timeout reached: give up
-            break;
-        }
-
-        // take a breath to give other threads more time to advance
-        gnashSleep(naptime);
-
-    }
-
-    // timed out
-    if (!timeout) {
-        log_error("Timeout (%d milliseconds) seeking export symbol %s in "
-                "movie %s. Frames loaded %d/%d", timeout_ms / 1000, symbol,
-                _url, loading_frame, m_frame_count);
-    }
-    else {
-        // eof
-        assert(loading_frame >= m_frame_count);
-        log_error("No export symbol %s found in movie %s. "
-            "Frames loaded %d/%d",
-            symbol, _url, loading_frame, m_frame_count);
-        //abort();
-    }
-
-    return boost::intrusive_ptr<ExportableResource>(0); // 0
-
-}
+    log_debug("%s registering export %s, %s", get_url(), symbol, id);
+    _exportTable[symbol] = id;
+}
+
 
 void
 SWFMovieDefinition::add_frame_name(const std::string& n)
@@ -746,53 +608,139 @@
     return true;
 }
 
+
+boost::uint16_t
+SWFMovieDefinition::exportID(const std::string& symbol) const
+{
+    boost::mutex::scoped_lock lock(_exportedResourcesMutex);
+    Exports::const_iterator it = _exportTable.find(symbol);
+    return (it == _exportTable.end()) ? 0 : it->second;
+}
+
+
 void
 SWFMovieDefinition::importResources(
-        boost::intrusive_ptr<movie_definition> source, Imports& imports)
+        boost::intrusive_ptr<movie_definition> source, const Imports& imports)
 {
     size_t importedSyms = 0;
 
     // Mutex scope.
-    {
-        boost::mutex::scoped_lock lock(_exportedResourcesMutex);
-
-        for (Imports::iterator i = imports.begin(), e = imports.end(); i != e;
-                ++i) {
-
-            const int id = i->first;
-            const std::string& symbolName = i->second;
-
-            boost::intrusive_ptr<ExportableResource> res =
-                source->get_exported_resource(symbolName);
-
-            if (!res) {
-                log_error(_("import error: could not find resource '%s' in "
-                            "movie '%s'"), symbolName, source->get_url());
-                continue;
-            }
-
-#ifdef DEBUG_EXPORTS
-            log_debug("Exporting symbol %s imported from source %s",
+
+    for (Imports::const_iterator i = imports.begin(), e = imports.end(); i != 
e;
+            ++i) {
+    
+        size_t new_loading_frame = source->get_loading_frame();
+        
+        // 0.1 seconds.
+        const size_t naptime = 100000;
+
+        // Timeout after two seconds of NO frames progress
+        const size_t timeout_ms = 2000000;
+        const size_t def_timeout = timeout_ms / naptime; 
+
+        size_t timeout = def_timeout;
+        size_t loading_frame = (size_t)-1; // used to keep track of 
advancements
+
+        const int id = i->first;
+        const std::string& symbolName = i->second;
+
+        log_debug("%s importing %s from %s", get_url(), symbolName,
+                source->get_url());
+
+        boost::uint16_t targetID;
+
+        while(!(targetID = source->exportID(symbolName))) {
+            
+            // We checked last (or past-last) advertised frame. 
+            // TODO: this check should really be for a parser
+            //       process being active or not, as SWF
+            //       might advertise less frames then actually
+            //       found in it...
+            //
+            if (new_loading_frame >= source->get_frame_count()) {
+                // Update of loading_frame is
+                // really just for the latter debugging output
+                loading_frame = new_loading_frame;
+                break;
+            }
+
+            // There's more frames to parse, go ahead
+            // TODO: this is still based on *advertised*
+            //       number of frames, if SWF advertises
+            //       more then actually found we'd be
+            //       keep trying till timeout, see the
+            //       other TODO above.
+
+            // We made frame progress since last iteration
+            // so sleep some and try again
+            if (new_loading_frame != loading_frame) {
+#ifdef DEBUG_EXPORTS
+                log_debug(_("looking for exported resource: frame load "
+                            "advancement (from %d to %d)"),
+                    loading_frame, new_loading_frame);
+#endif
+                loading_frame = new_loading_frame;
+                timeout = def_timeout+1;
+            }
+            else if (!--timeout) {
+                // no progress since last run, and 
+                // timeout reached: give up
+                break;
+            }
+
+            // take a breath to give other threads more time to advance
+            gnashSleep(naptime);
+
+        }
+
+        // timed out
+        if (!timeout) {
+            log_error("Timeout (%d milliseconds) seeking export "
+                "symbol %s in movie %s. Frames loaded %d/%d",
+                timeout_ms / 1000, symbolName,
+                source->get_url(), loading_frame, source->get_frame_count());
+            continue;
+        }
+        else {
+            // eof
+            //assert(loading_frame >= m_frame_count);
+            log_error("No export symbol %s found in movie %s. "
+                "Frames loaded %d/%d",
+                symbolName, source->get_url(), loading_frame,
+                source->get_frame_count());
+        }
+
+        // TODO: can this be anything else?
+        boost::intrusive_ptr<SWF::DefinitionTag> res =
+            source->getDefinitionTag(targetID);
+
+        if (!res) {
+            log_error(_("import error: could not find resource '%s' in "
+                        "movie '%s'"), symbolName, source->get_url());
+            continue;
+        }
+
+#ifdef DEBUG_EXPORTS
+        log_debug("Exporting symbol %s imported from source %s",
+            symbolName, source->get_url());
+#endif
+        registerExport(symbolName, id);
+
+        if (Font* f = dynamic_cast<Font*>(res.get())) {
+            // Add this shared font to the currently-loading movie.
+            add_font(id, f);
+            ++importedSyms;
+        }
+        else if (SWF::DefinitionTag* ch =
+                dynamic_cast<SWF::DefinitionTag*>(res.get())) {
+            // Add this DisplayObject to the loading movie.
+            addDisplayObject(id, ch);
+            ++importedSyms;
+        }
+        else {
+            log_error(_("importResources error: unsupported import of '%s' "
+                "from movie '%s' has unknown type"),
                 symbolName, source->get_url());
-#endif
-            _exportedResources[symbolName] = res.get();
-
-            if (Font* f = dynamic_cast<Font*>(res.get())) {
-                // Add this shared font to the currently-loading movie.
-                add_font(id, f);
-                ++importedSyms;
-            }
-            else if (SWF::DefinitionTag* ch =
-                    dynamic_cast<SWF::DefinitionTag*>(res.get())) {
-                // Add this DisplayObject to the loading movie.
-                addDisplayObject(id, ch);
-                ++importedSyms;
-            }
-            else {
-                log_error(_("importResources error: unsupported import of '%s' 
"
-                    "from movie '%s' has unknown type"),
-                    symbolName, source->get_url());
-            }
         }
     }
 

=== modified file 'libcore/parser/SWFMovieDefinition.h'
--- a/libcore/parser/SWFMovieDefinition.h       2010-06-09 14:39:48 +0000
+++ b/libcore/parser/SWFMovieDefinition.h       2010-06-11 12:21:46 +0000
@@ -235,18 +235,8 @@
         return m_file_length;
     }
 
-    // See docs in movie_definition.h
-    virtual void exportResource(const std::string& symbol, int id);
-
-    /// Get the named exported resource, if we expose it.
-    //
-    /// @return NULL if the label doesn't correspond to an exported
-    ///         resource, or if a timeout occurs while scanning the movie.
-    virtual boost::intrusive_ptr<ExportableResource> get_exported_resource(
-            const std::string& symbol) const;
-
     virtual void importResources(boost::intrusive_ptr<movie_definition> source,
-            Imports& imports);
+            const Imports& imports);
 
     void addDisplayObject(int DisplayObject_id, SWF::DefinitionTag* c);
 
@@ -385,6 +375,26 @@
 
     virtual const std::string& get_url() const { return _url; }
     
+    /// Get the id that corresponds to a symbol.
+    //
+    /// This function is thread-safe.
+    //
+    /// @param symbol   The symbol to lookup in the table.
+    /// @return         The id corresponding to the passed symbol. 0 is not a
+    ///                 valid id and signifies that the symbol was not (yet)
+    ///                 exported.
+    boost::uint16_t exportID(const std::string& symbol) const;
+    
+    /// Register a symbol to refer to a character id
+    //
+    /// This function is thread safe.
+    //
+    /// @param id       The id of the character to map to the symbol. NB: this
+    ///                 must never be 0!
+    /// @param symbol   The symbol to map to the id.
+    void registerExport(const std::string& symbol, boost::uint16_t id);
+
+    
 #ifdef USE_SWFTREE
 
     // These methods attach the contents of the METADATA tag
@@ -433,12 +443,14 @@
     // Mutex protecting access to _namedFrames
     mutable boost::mutex _namedFramesMutex;
 
-    typedef std::map<std::string, boost::intrusive_ptr<ExportableResource>,
-            StringNoCaseLessThan > ExportMap;
-
-    ExportMap _exportedResources;
-
-    // Mutex protecting access to _exportedResources
+    /// Allow mapping symbol to id case insensitively.
+    typedef std::map<std::string, boost::uint16_t,
+            StringNoCaseLessThan> Exports;
+
+    /// A map of symbol to character id.
+    Exports _exportTable;
+
+    // Mutex protecting access to the export map.
     mutable boost::mutex _exportedResourcesMutex;
 
     /// Movies we import from; hold a ref on these,

=== modified file 'libcore/parser/movie_definition.h'
--- a/libcore/parser/movie_definition.h 2010-05-20 10:38:42 +0000
+++ b/libcore/parser/movie_definition.h 2010-06-11 12:21:46 +0000
@@ -52,13 +52,15 @@
 #include "gnashconfig.h" // for USE_SWFTREE
 #endif
 
-#include "DefinitionTag.h"
-
 #include <string>
 #include <memory> // for auto_ptr
 #include <vector> // for PlayList typedef
 #include <set>
 #include <boost/intrusive_ptr.hpp>
+#include <boost/cstdint.hpp>
+
+#include "DefinitionTag.h"
+#include "log.h"
 
 // Forward declarations
 namespace gnash {
@@ -69,7 +71,6 @@
         class ControlTag;
     }
     class Font;
-    class ExportableResource;
     class sound_sample;
     class JpegImageInput;
 }
@@ -100,7 +101,7 @@
 class movie_definition : public SWF::DefinitionTag
 {
 public:
-       typedef std::vector<SWF::ControlTag*> PlayList;
+       typedef std::vector<boost::intrusive_ptr<SWF::ControlTag> > PlayList;
 
        virtual int     get_version() const = 0;
        virtual float get_width_pixels() const = 0;
@@ -157,21 +158,6 @@
                return 0;
        }
 
-       /// Get the named exported resource, if we expose it.
-       //
-       /// @param symbol
-       ///     The symbol name. Matching should be case-insensitive for all
-    /// SWF versions.
-       ///
-       /// @return NULL if the label doesn't correspond to an exported
-       ///         resource. This is the default behaviour.
-       ///
-       virtual boost::intrusive_ptr<ExportableResource> get_exported_resource(
-            const std::string& /*symbol*/) const
-       {
-               return NULL;
-       }
-
 
        typedef std::pair<int, std::string> ImportSpec;
        typedef std::vector< ImportSpec > Imports;
@@ -184,8 +170,13 @@
        /// @param imports
        ///     Resources to import, each with the id to use in our dictionary
        ///
-       virtual void importResources(boost::intrusive_ptr<movie_definition> 
/*source*/, Imports& /*imports*/)
+       virtual void importResources(
+            boost::intrusive_ptr<movie_definition> /*source*/, 
+            const Imports& /*imports*/)
        {
+               IF_VERBOSE_MALFORMED_SWF(
+            log_swferror(_("IMPORT tag appears outside SWF definition"));
+               );
        }
 
 
@@ -396,18 +387,18 @@
                return -1;
        }
 
-       /// Mark the given resource as "exported" with the given linkage name.
-       //
-    /// Note that any previously exported resource with the same linkage
-    /// name will become unreachable (export override).
-    ///
-       /// @see get_exported_resource
-       ///
-       /// The default implementation is a no-op
-       ///
-       virtual void exportResource(const std::string& /*symbol*/, int /*id*/)
-       {
-       }
+    /// Register a symbol to refer to a character id
+    //
+    /// The default implementation does nothing.
+    virtual void registerExport(const std::string&, boost::uint16_t) {}
+    
+    /// Get the id that corresponds to a symbol.
+    //
+    /// @return         The id corresponding to the passed symbol. The default
+    ///                 implementation returns 0, as it has no export table.
+    virtual boost::uint16_t exportID(const std::string& /*symbol*/) const {
+        return 0;
+    }
 
     /// Set whether the SWFMovie should use AVM2 or AVM1.
     //
@@ -468,7 +459,11 @@
        }
 
 #endif
-
+protected:
+    movie_definition(boost::uint16_t id = 0)
+        :
+        DefinitionTag(id)
+    {}
 };
 
 } // namespace gnash

=== modified file 'libcore/parser/sound_definition.h'
--- a/libcore/parser/sound_definition.h 2010-05-20 10:57:04 +0000
+++ b/libcore/parser/sound_definition.h 2010-06-11 09:32:36 +0000
@@ -18,8 +18,7 @@
 #ifndef GNASH_SOUND_H
 #define GNASH_SOUND_H
 
-
-#include "ExportableResource.h"
+#include "ref_counted.h"
 
 // Forward declarations
 namespace gnash {
@@ -46,8 +45,9 @@
 /// @todo move definition to sound_handler.h and possibly nest
 /// inside sound_handler itself ?
 //
-/// This is a resource because it can be exported.
-class sound_sample: public ExportableResource
+/// This is ref_counted because it is an export.
+/// TODO: check whether it really needs to be ref counted.
+class sound_sample : public ref_counted
 {
 public:
 

=== modified file 'libcore/parser/sprite_definition.cpp'
--- a/libcore/parser/sprite_definition.cpp      2010-03-11 01:47:08 +0000
+++ b/libcore/parser/sprite_definition.cpp      2010-06-11 08:10:16 +0000
@@ -58,13 +58,6 @@
 
 sprite_definition::~sprite_definition()
 {
-       // Release our playlist data.
-       for (PlayListMap::iterator i=m_playlist.begin(), e=m_playlist.end();
-            i != e; ++i)
-       {
-               PlayList& pl = i->second;
-        deleteChecked(pl.begin(), pl.end());
-    }
 }
 
 /*private*/
@@ -125,8 +118,9 @@
 }
 
 sprite_definition::sprite_definition(movie_definition& m, SWFStream& in, 
-        const RunResources& runResources)
+        const RunResources& runResources, boost::uint16_t id)
        :
+    movie_definition(id),
        m_movie_def(m),
        m_frame_count(0),
        m_loading_frame(0),

=== modified file 'libcore/parser/sprite_definition.h'
--- a/libcore/parser/sprite_definition.h        2010-05-20 10:38:42 +0000
+++ b/libcore/parser/sprite_definition.h        2010-06-11 12:21:46 +0000
@@ -23,6 +23,7 @@
 
 
 #include <boost/intrusive_ptr.hpp>
+#include <boost/cstdint.hpp>
 #include <string>
 #include <map>
 #include "smart_ptr.h" // GNASH_USE_GC
@@ -65,7 +66,7 @@
        ///     to be already positioned right before the frame count
        ///
        sprite_definition(movie_definition& m, SWFStream& in,
-            const RunResources& runResources);
+            const RunResources& runResources, boost::uint16_t id);
 
        /// Destructor, releases playlist data
        ~sprite_definition();
@@ -194,27 +195,13 @@
                return _loadingSoundStream;
        }
 
-
-       /// Delegate call to associated root movie
-       virtual void exportResource(const std::string& sym, int id)
-       {
-               m_movie_def.exportResource(sym, id);
-       }
-
-       /// Delegate call to associated root movie
-       virtual boost::intrusive_ptr<ExportableResource> get_exported_resource(
-            const std::string& sym) const
-       {
-               return m_movie_def.get_exported_resource(sym);
-       }
-
-       /// Overridden just for complaining  about malformed SWF
-       virtual void importResources(boost::intrusive_ptr<movie_definition> 
/*source*/, Imports& /*imports*/)
-       {
-               IF_VERBOSE_MALFORMED_SWF (
-               log_swferror(_("IMPORT tag appears in DEFINESPRITE tag"));
-               );
-       }
+    virtual boost::uint16_t exportID(const std::string& symbol) const {
+        return m_movie_def.exportID(symbol);
+    }
+    
+    virtual void registerExport(const std::string& s, boost::uint16_t id) {
+        m_movie_def.registerExport(s, id);
+    }
 
        /// \brief
        /// Get a SWF::DefinitionTag from this Sprite's root movie

=== modified file 'libcore/swf/ControlTag.h'
--- a/libcore/swf/ControlTag.h  2010-05-20 09:57:10 +0000
+++ b/libcore/swf/ControlTag.h  2010-06-11 10:15:49 +0000
@@ -19,6 +19,8 @@
 #ifndef GNASH_CONTROL_TAG_H
 #define GNASH_CONTROL_TAG_H
 
+#include <boost/noncopyable.hpp>
+#include "ref_counted.h"
 
 // Forward declarations
 namespace gnash {
@@ -33,7 +35,12 @@
 //
 /// These are the events associated with a frame.
 ///
-class ControlTag
+/// TODO: check whether this needs to be ref_counted. They are generally owned
+/// by a sprite_definition or a SWFMovieDefinition.
+//
+/// TODO: rename this class so it's not the same as the SWF spec. It doesn't
+/// exactly correspond to the ControlTag defined there.
+class ControlTag : public ref_counted, boost::noncopyable
 {
 public:
     

=== modified file 'libcore/swf/DefineButtonTag.cpp'
--- a/libcore/swf/DefineButtonTag.cpp   2010-03-11 01:47:08 +0000
+++ b/libcore/swf/DefineButtonTag.cpp   2010-06-11 07:04:03 +0000
@@ -47,8 +47,9 @@
 }
 
 DefineButtonTag::DefineButtonTag(SWFStream& in, movie_definition& m,
-        TagType tag)
+        TagType tag, boost::uint16_t id)
     :
+    DefinitionTag(id),
     _soundTag(0),
     _trackAsMenu(false),
     _movieDef(m)
@@ -79,13 +80,13 @@
 {
     assert(tag == DEFINEBUTTON);
     in.ensureBytes(2);
-    int id = in.read_u16();
+    const boost::uint16_t id = in.read_u16();
 
     IF_VERBOSE_PARSE(
         log_parse(_("  DefineButton loader: chararacter id = %d"), id);
     );
 
-    std::auto_ptr<DefineButtonTag> bt(new DefineButtonTag(in, m, tag));
+    std::auto_ptr<DefineButtonTag> bt(new DefineButtonTag(in, m, tag, id));
 
     m.addDisplayObject(id, bt.release());
 }
@@ -96,13 +97,13 @@
 {
     assert(tag == DEFINEBUTTON2);
     in.ensureBytes(2);
-    int id = in.read_u16();
+    const boost::uint16_t id = in.read_u16();
 
     IF_VERBOSE_PARSE(
         log_parse(_("  DefineButton2 loader: chararacter id = %d"), id);
     );
 
-    std::auto_ptr<DefineButtonTag> bt(new DefineButtonTag(in, m, tag));
+    std::auto_ptr<DefineButtonTag> bt(new DefineButtonTag(in, m, tag, id));
 
     m.addDisplayObject(id, bt.release());
 }

=== modified file 'libcore/swf/DefineButtonTag.h'
--- a/libcore/swf/DefineButtonTag.h     2010-03-13 18:00:33 +0000
+++ b/libcore/swf/DefineButtonTag.h     2010-06-11 07:04:03 +0000
@@ -264,7 +264,8 @@
     /// Construct a DefineButtonTag (DefinitionTag)
     //
     /// This can only be constructed using a loader() function.
-    DefineButtonTag(SWFStream& in, movie_definition& m, TagType tag);
+    DefineButtonTag(SWFStream& in, movie_definition& m, TagType tag, 
+            boost::uint16_t id);
 
     /// Read a DEFINEBUTTON tag
     void readDefineButtonTag(SWFStream& in, movie_definition& m);

=== modified file 'libcore/swf/DefineEditTextTag.cpp'
--- a/libcore/swf/DefineEditTextTag.cpp 2010-03-11 01:47:08 +0000
+++ b/libcore/swf/DefineEditTextTag.cpp 2010-06-11 07:04:03 +0000
@@ -34,11 +34,11 @@
        assert(tag == SWF::DEFINEEDITTEXT); // 37
 
     in.ensureBytes(2);
-    boost::uint16_t DisplayObjectID = in.read_u16();
-
-    std::auto_ptr<DefineEditTextTag> editText(new DefineEditTextTag(in, m));
-
-    m.addDisplayObject(DisplayObjectID, editText.release());
+    const boost::uint16_t id = in.read_u16();
+
+    std::auto_ptr<DefineEditTextTag> editText(new DefineEditTextTag(in, m, 
id));
+
+    m.addDisplayObject(id, editText.release());
 }
 
 DisplayObject*
@@ -160,8 +160,10 @@
        );
 }
 
-DefineEditTextTag::DefineEditTextTag(SWFStream& in, movie_definition& m)
+DefineEditTextTag::DefineEditTextTag(SWFStream& in, movie_definition& m,
+        boost::uint16_t id)
     :
+    DefinitionTag(id),
        _hasText(true),
        _wordWrap(false),
        _multiline(false),

=== modified file 'libcore/swf/DefineEditTextTag.h'
--- a/libcore/swf/DefineEditTextTag.h   2010-03-11 01:47:08 +0000
+++ b/libcore/swf/DefineEditTextTag.h   2010-06-11 07:04:03 +0000
@@ -189,7 +189,7 @@
     /// Construct a DefineEditTextTag.
     //
     /// This should only be used from the loader() function.
-       DefineEditTextTag(SWFStream& in, movie_definition& m);
+       DefineEditTextTag(SWFStream& in, movie_definition& m, boost::uint16_t 
id);
 
     /// Read a tag from the SWFStream.
     void read(SWFStream& in, movie_definition& m);

=== modified file 'libcore/swf/DefineMorphShapeTag.cpp'
--- a/libcore/swf/DefineMorphShapeTag.cpp       2010-03-11 01:47:08 +0000
+++ b/libcore/swf/DefineMorphShapeTag.cpp       2010-06-11 07:04:03 +0000
@@ -41,18 +41,20 @@
         const RunResources& r)
 {
     in.ensureBytes(2);
-    boost::uint16_t id = in.read_u16();
+    const boost::uint16_t id = in.read_u16();
 
     IF_VERBOSE_PARSE(
             log_parse("DefineMorphShapeTag: id = %d", id);
     );
 
-    DefineMorphShapeTag* morph = new DefineMorphShapeTag(in, tag, md, r);
+    DefineMorphShapeTag* morph = new DefineMorphShapeTag(in, tag, md, r, id);
     md.addDisplayObject(id, morph);
 }
 
 DefineMorphShapeTag::DefineMorphShapeTag(SWFStream& in, TagType tag,
-        movie_definition& md, const RunResources& r)
+        movie_definition& md, const RunResources& r, boost::uint16_t id)
+    :
+    DefinitionTag(id)
 {
     read(in, tag, md, r);
 }

=== modified file 'libcore/swf/DefineMorphShapeTag.h'
--- a/libcore/swf/DefineMorphShapeTag.h 2010-03-13 18:00:33 +0000
+++ b/libcore/swf/DefineMorphShapeTag.h 2010-06-11 07:04:03 +0000
@@ -66,7 +66,7 @@
 private:
 
     DefineMorphShapeTag(SWFStream& in, SWF::TagType tag, movie_definition& md,
-            const RunResources& r);
+            const RunResources& r, boost::uint16_t id);
     
     /// Read a DefineMorphShape tag from stream
     //

=== modified file 'libcore/swf/DefineShapeTag.cpp'
--- a/libcore/swf/DefineShapeTag.cpp    2010-03-11 01:47:08 +0000
+++ b/libcore/swf/DefineShapeTag.cpp    2010-06-11 07:04:03 +0000
@@ -61,7 +61,7 @@
         log_parse(_("DefineShapeTag(%s): id = %d"), tag, id);
     );
 
-    DefineShapeTag* ch = new DefineShapeTag(in, tag, m, r);
+    DefineShapeTag* ch = new DefineShapeTag(in, tag, m, r, id);
     m.addDisplayObject(id, ch);
 
 }
@@ -81,9 +81,9 @@
 
 
 DefineShapeTag::DefineShapeTag(SWFStream& in, TagType tag,
-        movie_definition& m, const RunResources& r)
+        movie_definition& m, const RunResources& r, boost::uint16_t id)
     :
-    DefinitionTag(),
+    DefinitionTag(id),
     _shape(in, tag, m, r)
 {
 }

=== modified file 'libcore/swf/DefineShapeTag.h'
--- a/libcore/swf/DefineShapeTag.h      2010-03-13 18:00:33 +0000
+++ b/libcore/swf/DefineShapeTag.h      2010-06-11 07:04:03 +0000
@@ -55,7 +55,7 @@
 private:
 
     DefineShapeTag(SWFStream& in, TagType tag, movie_definition& m,
-            const RunResources& r);
+            const RunResources& r, boost::uint16_t id);
 
     /// The actual shape data is stored in this record.
     const ShapeRecord _shape;

=== modified file 'libcore/swf/DefineTextTag.cpp'
--- a/libcore/swf/DefineTextTag.cpp     2010-03-11 01:47:08 +0000
+++ b/libcore/swf/DefineTextTag.cpp     2010-06-11 07:04:03 +0000
@@ -44,9 +44,9 @@
     assert(tag == DEFINETEXT);
 
     in.ensureBytes(2);
-    boost::uint16_t id = in.read_u16();
+    const boost::uint16_t id = in.read_u16();
 
-    std::auto_ptr<DefineTextTag> t(new DefineTextTag(in, m, tag));
+    std::auto_ptr<DefineTextTag> t(new DefineTextTag(in, m, tag, id));
     IF_VERBOSE_PARSE(
         log_parse(_("DefineTextTag, id = %d"), id);
     );
@@ -85,9 +85,9 @@
     assert(tag == DEFINETEXT2);
 
     in.ensureBytes(2);
-    boost::uint16_t id = in.read_u16();
+    const boost::uint16_t id = in.read_u16();
 
-    std::auto_ptr<DefineTextTag> t(new DefineTextTag(in, m, tag));
+    std::auto_ptr<DefineTextTag> t(new DefineTextTag(in, m, tag, id));
     IF_VERBOSE_PARSE(
         log_parse(_("Text DisplayObject, id = %d"), id);
     );

=== modified file 'libcore/swf/DefineTextTag.h'
--- a/libcore/swf/DefineTextTag.h       2010-03-11 01:47:08 +0000
+++ b/libcore/swf/DefineTextTag.h       2010-06-11 07:04:03 +0000
@@ -78,7 +78,10 @@
     /// Construct a DefineTextTag.
     //
     /// This should only be constructed using the loader() functions.
-       DefineTextTag(SWFStream& in, movie_definition& m, TagType tag)
+       DefineTextTag(SWFStream& in, movie_definition& m, TagType tag,
+            boost::uint16_t id)
+        :
+        DefinitionTag(id)
     {
         read(in, m, tag);
     }

=== modified file 'libcore/swf/DefineVideoStreamTag.cpp'
--- a/libcore/swf/DefineVideoStreamTag.cpp      2010-03-11 01:47:08 +0000
+++ b/libcore/swf/DefineVideoStreamTag.cpp      2010-06-11 07:04:03 +0000
@@ -59,7 +59,7 @@
 
 DefineVideoStreamTag::DefineVideoStreamTag(SWFStream& in, boost::uint16_t id)
        :
-       m_char_id(id),
+    DefinitionTag(id),
        _width(0),
        _height(0)
 {

=== modified file 'libcore/swf/DefineVideoStreamTag.h'
--- a/libcore/swf/DefineVideoStreamTag.h        2010-01-25 18:52:20 +0000
+++ b/libcore/swf/DefineVideoStreamTag.h        2010-06-11 07:04:03 +0000
@@ -150,13 +150,6 @@
 
        void read(SWFStream& in);
 
-       /// Id of this DisplayObject definition, set by constructor.
-       ///
-       /// The id is currently set to -1 when the definition is actually
-       /// created dynamically (instantiating the ActionScript Video class)
-       ///
-       boost::uint16_t m_char_id;
-
        /// Reserved flags read from DEFINEVIDEOSTREAM tag
        boost::uint8_t m_reserved_flags;
 

=== added file 'libcore/swf/DefinitionTag.cpp'
--- a/libcore/swf/DefinitionTag.cpp     1970-01-01 00:00:00 +0000
+++ b/libcore/swf/DefinitionTag.cpp     2010-06-11 11:42:28 +0000
@@ -0,0 +1,33 @@
+// 
+//   Copyright (C) 2010 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 "DefinitionTag.h"
+#include "MovieClip.h"
+#include "Movie.h"
+
+namespace gnash {
+namespace SWF {
+
+void
+DefinitionTag::executeState(MovieClip* m, DisplayList& /*dlist*/) const
+{
+    m->get_root()->addCharacter(_id);
+}
+
+
+}
+}

=== modified file 'libcore/swf/DefinitionTag.h'
--- a/libcore/swf/DefinitionTag.h       2010-03-10 16:13:07 +0000
+++ b/libcore/swf/DefinitionTag.h       2010-06-11 10:15:49 +0000
@@ -19,9 +19,11 @@
 #ifndef GNASH_DEFINITION_TAG_H
 #define GNASH_DEFINITION_TAG_H
 
-#include "ExportableResource.h"
 
 #include <boost/noncopyable.hpp>
+#include <boost/cstdint.hpp>
+
+#include "ControlTag.h"
 
 // Forward declarations
 
@@ -39,7 +41,10 @@
 namespace SWF {
 
 /// Immutable data representing the definition of a movie display element.
-class DefinitionTag : public ExportableResource, boost::noncopyable
+//
+/// TODO: rename this class so it's not the same as the SWF spec. It doesn't
+/// exactly correspond to the DefinitionTag defined there.
+class DefinitionTag : public ControlTag
 {
 public:
 
@@ -58,6 +63,20 @@
     /// DisplayObject.
        virtual DisplayObject* createDisplayObject(Global_as& gl,
             DisplayObject* parent) const = 0;
+
+       virtual void executeState(MovieClip* m,  DisplayList& /*dlist*/) const;
+
+    boost::uint16_t id() const {
+        return _id;
+    }
+
+protected:
+
+    DefinitionTag(boost::uint16_t id) : _id(id) {}
+
+private:
+
+    const boost::uint16_t _id;
        
 };
 

=== modified file 'libcore/swf/DoInitActionTag.h'
--- a/libcore/swf/DoInitActionTag.h     2010-06-07 10:05:43 +0000
+++ b/libcore/swf/DoInitActionTag.h     2010-06-10 13:07:44 +0000
@@ -73,14 +73,6 @@
         in.ensureBytes(2);
         const boost::uint16_t cid = in.read_u16();
 
-        if (!m.getDefinitionTag(cid)) {
-            IF_VERBOSE_MALFORMED_SWF(
-                log_swferror("SWF contains DoInitAction tag for an unknown"
-                    "id. This will not be executed.");
-            );
-            return;
-        }
-
         // TODO: Currently, tags are only be executed for already parsed
         // character ids. This is known to be wrong: a more accurate
         // description is:

=== modified file 'libcore/swf/tag_loaders.cpp'
--- a/libcore/swf/tag_loaders.cpp       2010-05-20 10:38:42 +0000
+++ b/libcore/swf/tag_loaders.cpp       2010-06-11 12:21:46 +0000
@@ -51,6 +51,7 @@
 #include "MovieFactory.h"
 #include "RunResources.h"
 #include "Renderer.h"
+#include "Movie.h"
 
 #ifdef HAVE_ZLIB_H
 #include <zlib.h>
@@ -759,7 +760,7 @@
     assert(tag == SWF::DEFINESPRITE); // 39 - DefineSprite
 
     in.ensureBytes(2);
-    int    id = in.read_u16();
+    const boost::uint16_t id = in.read_u16();
 
     IF_VERBOSE_PARSE
     (
@@ -780,7 +781,7 @@
     );
 
     // will automatically read the sprite
-    sprite_definition* ch = new sprite_definition(m, in, r);
+    sprite_definition* ch = new sprite_definition(m, in, r, id);
 
     IF_VERBOSE_MALFORMED_SWF(
         if (!ch->get_frame_count()) {
@@ -797,6 +798,78 @@
 // export
 //
 
+class ExportTag : public ControlTag
+{
+public:
+
+    typedef std::vector<std::string> Exports;
+
+    ExportTag(SWFStream& in, movie_definition& m)
+    {
+        read(in, m);
+    }
+
+    // TODO: use Movie to store the actual exports.
+    virtual void executeState(MovieClip* m, DisplayList& /*l*/) const {
+        Movie* mov = m->get_root();
+        for (Exports::const_iterator it = _exports.begin(), e = _exports.end();
+                it != e; ++it) {
+            const boost::uint16_t id = mov->definition()->exportID(*it);
+
+            // We exported it, so we assume it is known.
+            assert(id);
+            mov->addCharacter(id);
+        }
+    }
+
+private:
+    void read(SWFStream& in, movie_definition& m) {
+        
+        // An EXPORT tag as part of a DEFINESPRITE
+        // would be a malformed SWF, anyway to be compatible
+        // we should still allow that. See bug #22468.
+        IF_VERBOSE_MALFORMED_SWF(
+            try {
+                dynamic_cast<SWFMovieDefinition&>(m);
+            }
+            catch (std::bad_cast& e) {
+                log_swferror(_("EXPORT tag inside DEFINESPRITE. Will export in 
"
+                        "top-level symbol table."));
+            }
+        );
+
+        in.ensureBytes(2);
+        const boost::uint16_t count = in.read_u16();
+
+        IF_VERBOSE_PARSE(
+            log_parse(_("  export: count = %d"), count);
+        );
+
+        // Read the exports.
+        for (size_t i = 0; i < count; ++i) {
+            in.ensureBytes(2);
+            const boost::uint16_t id = in.read_u16();
+
+            if (!id) continue;
+
+            std::string symbolName;
+            in.read_string(symbolName);
+
+            IF_VERBOSE_PARSE (
+                log_parse(_("  export: id = %d, name = %s"), id, symbolName);
+            );
+
+            // Register export with global map
+            m.registerExport(symbolName, id);
+
+            // Store export for later execution.
+            _exports.push_back(symbolName);
+        }
+
+    }
+private:
+    Exports _exports;
+};
 
 // Load an export tag (for exposing internal resources of m)
 void export_loader(SWFStream& in, TagType tag, movie_definition& m,
@@ -804,125 +877,134 @@
 {
     assert(tag == SWF::EXPORTASSETS); // 56
 
-    in.ensureBytes(2);
-    const boost::uint16_t count = in.read_u16();
-
-    IF_VERBOSE_PARSE(
-        log_parse(_("  export: count = %d"), count);
-    );
-
-    // An EXPORT tag as part of a DEFINESPRITE
-    // would be a malformed SWF, anyway to be compatible
-    // we should still allow that. See bug #22468.
-    IF_VERBOSE_MALFORMED_SWF(
-        try {
-            dynamic_cast<SWFMovieDefinition&>(m);
-        }
-        catch (std::bad_cast& e) {
-            log_swferror(_("EXPORT tag inside DEFINESPRITE. Will export in "
-                    "top-level symbol table."));
-        }
-    );
-
-    // Read the exports.
-    for (size_t i = 0; i < count; ++i) {
-        in.ensureBytes(2);
-        boost::uint16_t id = in.read_u16();
-        std::string symbolName;
-        in.read_string(symbolName);
-
-        IF_VERBOSE_PARSE (
-            log_parse(_("  export: id = %d, name = %s"), id, symbolName);
-        );
-
-        m.exportResource(symbolName, id);
-
-    }
+    std::auto_ptr<ControlTag> t(new ExportTag(in, m));
+    m.addControlTag(t.release());
 }
 
-
 //
 // import
 //
 
+class ImportTag : public ControlTag
+{
+public:
+
+    typedef std::pair<int, std::string> Import;
+    typedef std::vector<Import> Imports;
+
+    ImportTag(TagType t, SWFStream& in, movie_definition& m,
+            const RunResources& r)
+    {
+        read(t, in, m, r);
+    }
+
+    virtual void executeState(MovieClip* m, DisplayList& /*l*/) const {
+        Movie* mov = m->get_root();
+        for (Imports::const_iterator it = _imports.begin(), e = _imports.end();
+                it != e; ++it) {
+            mov->addCharacter(it->first);
+        }
+    }
+
+    void read(TagType t, SWFStream& in, movie_definition& m,
+            const RunResources& r) {
+
+        std::string source_url;
+        in.read_string(source_url);
+
+        // Resolve relative urls against baseurl
+        URL abs_url(source_url, r.baseURL());
+
+        unsigned char import_version = 0;
+
+        if (t == SWF::IMPORTASSETS2) {
+            in.ensureBytes(2);
+            import_version = in.read_uint(8);
+            boost::uint8_t reserved = in.read_uint(8);
+            UNUSED(reserved);
+        }
+
+        in.ensureBytes(2);
+        const boost::uint16_t count = in.read_u16();
+
+        IF_VERBOSE_PARSE(
+            log_parse(_("  import: version = %u, source_url = %s (%s), "
+                "count = %d"), import_version, abs_url.str(), source_url,
+                count);
+        );
+
+        // Try to load the source movie into the movie library.
+        boost::intrusive_ptr<movie_definition> source_movie;
+
+        try {
+            source_movie = MovieFactory::makeMovie(abs_url, r);
+        }
+        catch (gnash::GnashException& e) {
+            log_error(_("Exception: %s"), e.what());
+        }
+
+        if (!source_movie) {
+            // Give up on imports.
+            log_error(_("can't import movie from url %s"), abs_url.str());
+            return;
+        }
+
+        // Quick consistency check, we might as well do
+        // something smarter, if we agree on semantic
+        if (source_movie == &m) {
+            IF_VERBOSE_MALFORMED_SWF(
+                log_swferror(_("Movie attempts to import symbols from "
+                        "itself."));
+            );
+            return;
+        }
+        
+        // Get the imports.
+        for (size_t i = 0; i < count; ++i)
+        {
+            in.ensureBytes(2);
+            const boost::uint16_t id = in.read_u16();
+
+            // We don't consider 0 valid.
+            if (!id) continue;
+
+            std::string symbolName;
+            in.read_string(symbolName);
+            IF_VERBOSE_PARSE (
+                log_parse(_("  import: id = %d, name = %s"), id, symbolName);
+            );
+            _imports.push_back(std::make_pair(id, symbolName));
+        }
+        // An EXPORT tag as part of a DEFINESPRITE
+        // would be a malformed SWF, anyway to be compatible
+        // we should still allow that. See bug #22468.
+        IF_VERBOSE_MALFORMED_SWF(
+            try {
+                dynamic_cast<SWFMovieDefinition&>(m);
+            }
+            catch (std::bad_cast& e) {
+                log_swferror(_("EXPORT tag inside DEFINESPRITE. Will export in 
"
+                        "top-level symbol table."));
+            }
+        );
+        m.importResources(source_movie, _imports);
+    }
+
+private:
+
+    Imports _imports;
+
+};
 
 void import_loader(SWFStream& in, TagType tag, movie_definition& m,
                const RunResources& r)
 {
     assert(tag == SWF::IMPORTASSETS || tag == SWF::IMPORTASSETS2);
 
-    std::string source_url;
-    in.read_string(source_url);
-
-    // Resolve relative urls against baseurl
-    URL abs_url(source_url, r.baseURL());
-
-    unsigned char import_version = 0;
-
-    if ( tag == SWF::IMPORTASSETS2 )
-    {
-        in.ensureBytes(2);
-        import_version = in.read_uint(8);
-        unsigned char reserved = in.read_uint(8);
-        UNUSED(reserved);
-    }
-
-    in.ensureBytes(2);
-    int count = in.read_u16();
-
-    IF_VERBOSE_PARSE
-    (
-        log_parse(_("  import: version = %u, source_url = %s (%s), count = 
%d"),
-            import_version, abs_url.str(), source_url, count);
-    );
-
-
-    // Try to load the source movie into the movie library.
-    boost::intrusive_ptr<movie_definition> source_movie;
-
-    try {
-        source_movie = MovieFactory::makeMovie(abs_url, r);
-    }
-    catch (gnash::GnashException& e) {
-        log_error(_("Exception: %s"), e.what());
-    }
-
-    if (!source_movie)
-    {
-        // Give up on imports.
-        log_error(_("can't import movie from url %s"), abs_url.str());
-        return;
-    }
-
-    // Quick consistency check, we might as well do
-    // something smarter, if we agree on semantic
-    if (source_movie == &m)
-    {
-        IF_VERBOSE_MALFORMED_SWF(
-            log_swferror(_("Movie attempts to import symbols from itself."));
-        );
-        return;
-    }
-
-    movie_definition::Imports imports;
-
-    // Get the imports.
-    for (int i = 0; i < count; i++)
-    {
-        in.ensureBytes(2);
-        boost::uint16_t    id = in.read_u16();
-        std::string symbolName;
-        in.read_string(symbolName);
-        IF_VERBOSE_PARSE (
-            log_parse(_("  import: id = %d, name = %s"), id, symbolName);
-        );
-        imports.push_back( std::make_pair(id, symbolName) );
-    }
-
-    m.importResources(source_movie, imports);
+    std::auto_ptr<ControlTag> p(new ImportTag(tag, in, m, r));
+    m.addControlTag(p.release());
 }
 
-
 //
 // Sound
 //

=== modified file 'testsuite/misc-ming.all/InitActionTest2.c'
--- a/testsuite/misc-ming.all/InitActionTest2.c 2010-06-08 07:24:38 +0000
+++ b/testsuite/misc-ming.all/InitActionTest2.c 2010-06-10 13:47:23 +0000
@@ -221,8 +221,8 @@
     SWFMovie_nextFrame(mo);
             
     // Check that both initaction tags were executed.
-    xcheck_equals(mo, "_global.init7", "true");
-    xcheck_equals(mo, "_global.init8", "true");
+    check_equals(mo, "_global.init7", "true");
+    check_equals(mo, "_global.init8", "true");
 
     add_actions(mo, "stop();");
   

=== modified file 'testsuite/swfdec/PASSING'
--- a/testsuite/swfdec/PASSING  2010-06-04 12:23:30 +0000
+++ b/testsuite/swfdec/PASSING  2010-06-09 11:16:33 +0000
@@ -505,6 +505,7 @@
 error-properties-7.swf:9258d3f8ea8409484f107168a4526347
 error-properties-8.swf:d011695853e978e0f6006730e37cba8b
 event-order.swf:6cb896771a691dc394226c3f542b1bec
+ExportAssets.swf:e9b7e6652db0b338e791447c9bc3ffe2
 export-case-5.swf:8b37704408e27ffb8b51c63179c7702c
 export-case-6.swf:7c3106de02ed0a94ed0bc816bf526c02
 export-case-7.swf:53ed5af6b3403b69a870da3331efb1c9


reply via email to

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