gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r10680: Refine TextSnapshot implemen


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10680: Refine TextSnapshot implementation. Implement more methods. Fixes new and
Date: Mon, 09 Mar 2009 19:45:37 +0100
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10680
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Mon 2009-03-09 19:45:37 +0100
message:
  Refine TextSnapshot implementation. Implement more methods. Fixes new and
  old tests.
modified:
  libbase/NamingPolicy.h
  libcore/MovieClip.cpp
  libcore/asobj/TextSnapshot_as.cpp
  libcore/asobj/TextSnapshot_as.h
  libcore/character.h
  libcore/generic_character.cpp
  libcore/generic_character.h
  libcore/parser/character_def.h
  libcore/swf/DefineTextTag.cpp
  libcore/swf/DefineTextTag.h
  testsuite/actionscript.all/TextSnapshot.as
  testsuite/misc-ming.all/TextSnapshotTest.c
    ------------------------------------------------------------
    revno: 10674.1.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 07:34:24 +0100
    message:
      Back out noinline.
    modified:
      libbase/NamingPolicy.h
    ------------------------------------------------------------
    revno: 10674.1.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 10:10:44 +0100
    message:
      Stub more methods.
    modified:
      libcore/asobj/TextSnapshot_as.cpp
    ------------------------------------------------------------
    revno: 10674.1.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 10:48:32 +0100
    message:
      Test TextSnapshot more.
    modified:
      testsuite/misc-ming.all/TextSnapshotTest.c
    ------------------------------------------------------------
    revno: 10674.1.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 10:51:43 +0100
    message:
      check->xcheck.
    modified:
      testsuite/misc-ming.all/TextSnapshotTest.c
    ------------------------------------------------------------
    revno: 10674.1.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 13:13:21 +0100
    message:
      Implement getSelected() and setSelected().
    modified:
      libcore/asobj/TextSnapshot_as.cpp
      libcore/asobj/TextSnapshot_as.h
    ------------------------------------------------------------
    revno: 10674.1.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 13:23:03 +0100
    message:
      Corrections and update test results.
    modified:
      libcore/asobj/TextSnapshot_as.cpp
      testsuite/misc-ming.all/TextSnapshotTest.c
    ------------------------------------------------------------
    revno: 10674.1.7
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 14:18:53 +0100
    message:
      Remove obsolete TextFinder struct.
    modified:
      libcore/MovieClip.cpp
    ------------------------------------------------------------
    revno: 10674.1.8
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 15:22:03 +0100
    message:
      Store TextRecords instead of strings in TextSnapshot so that all the 
necessary
      information is available. Decode on demand instead of storing the text
      as a string alongside the TextRecords. This is much more expensive than 
storing
      the string; which option is more appropriate in the end depends on the use
      case, which in turn depends on pp performance. Presently there is no
      information on this.
      
      Move most TextSnapshot-related processing into the TextSnapshot_as class /
      implementation.
    modified:
      libcore/asobj/TextSnapshot_as.cpp
      libcore/asobj/TextSnapshot_as.h
      libcore/character.h
      libcore/generic_character.cpp
      libcore/generic_character.h
      libcore/parser/character_def.h
      libcore/swf/DefineTextTag.cpp
      libcore/swf/DefineTextTag.h
    ------------------------------------------------------------
    revno: 10674.1.9
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 15:59:05 +0100
    message:
      Silence debugging.
    modified:
      libcore/asobj/TextSnapshot_as.cpp
      libcore/swf/DefineTextTag.cpp
    ------------------------------------------------------------
    revno: 10674.1.10
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 17:13:37 +0100
    message:
      Rename class.
    modified:
      libcore/asobj/TextSnapshot_as.cpp
    ------------------------------------------------------------
    revno: 10674.1.11
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 18:14:14 +0100
    message:
      Only decode the required part of the text for efficiency. This also makes
      it easier to get the length correct with and without line breaks. Use a
      function instead of a functor and algorithms, as it is better for breaking
      early.
    modified:
      libcore/asobj/TextSnapshot_as.cpp
      libcore/asobj/TextSnapshot_as.h
      testsuite/misc-ming.all/TextSnapshotTest.c
    ------------------------------------------------------------
    revno: 10674.1.12
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 18:52:50 +0100
    message:
      Implement getSelectedText(). Almost all tests pass.
    modified:
      libcore/asobj/TextSnapshot_as.cpp
      libcore/asobj/TextSnapshot_as.h
      testsuite/misc-ming.all/TextSnapshotTest.c
    ------------------------------------------------------------
    revno: 10674.1.13
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-03-09 19:23:02 +0100
    message:
      Correct getSelectedText() return.
    modified:
      libcore/asobj/TextSnapshot_as.cpp
      testsuite/actionscript.all/TextSnapshot.as
=== modified file 'libbase/NamingPolicy.h'
--- a/libbase/NamingPolicy.h    2009-03-08 19:40:50 +0000
+++ b/libbase/NamingPolicy.h    2009-03-09 06:34:24 +0000
@@ -56,7 +56,7 @@
 class DSOEXPORT IncrementalRename : public NamingPolicy
 {
 public:
-    IncrementalRename(const URL& baseURL) __attribute__((noinline));
+    IncrementalRename(const URL& baseURL);
     virtual std::string operator()(const URL& url) const;
     
 private:

=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp     2009-03-05 16:24:37 +0000
+++ b/libcore/MovieClip.cpp     2009-03-09 13:18:53 +0000
@@ -200,20 +200,6 @@
 
 };
 
-/// Search the DisplayList for static text.
-class StaticTextFinder
-{
-public:
-    StaticTextFinder(std::string& to) : _to(to) {}
-
-    void operator()(character* ch) {
-        ch->getStaticText(_to);
-    }
-
-private:
-    std::string& _to;
-};
-
 /// Find a character hit by the given coordinates.
 //
 /// This class takes care about taking masks layers into

=== modified file 'libcore/asobj/TextSnapshot_as.cpp'
--- a/libcore/asobj/TextSnapshot_as.cpp 2009-03-08 17:18:43 +0000
+++ b/libcore/asobj/TextSnapshot_as.cpp 2009-03-09 18:23:02 +0000
@@ -31,9 +31,13 @@
 #include "generic_character.h"
 #include "DisplayList.h"
 #include "MovieClip.h"
+#include "Font.h"
+#include "swf/TextRecord.h"
 
 #include <boost/algorithm/string/compare.hpp>
+#include <boost/dynamic_bitset.hpp>
 #include <algorithm>
+#include <numeric>
 
 namespace gnash {
 
@@ -54,44 +58,94 @@
     void attachTextSnapshotInterface(as_object& o);
     as_object* getTextSnapshotInterface();
 
-    void setTextReachable( const TextSnapshot_as::TextFields::value_type& vt);
+    size_t getTextFields(const MovieClip* mc,
+            TextSnapshot_as::TextFields& fields);
+
+    void setTextReachable(const TextSnapshot_as::TextFields::value_type& vt);
 
 }
 
 namespace {
 
+/// Accumulate the number of glyphs in a TextRecord.
+struct CountRecords
+{
+    size_t operator()(size_t c, const TextSnapshot_as::Records::value_type t) {
+        const SWF::TextRecord::Glyphs& glyphs = t->glyphs();
+        size_t ret = c + glyphs.size();
+        return ret;
+    }
+};
+
+/// Locate static text in a character.
+//
+/// Static text (TextRecords) are added to a vector, which should 
+/// correspond to a single character. Also keeps count of the total number
+/// of glyphs.
 class TextFinder
 {
 public:
-    TextFinder(TextSnapshot_as::TextFields& fields) : _fields(fields) {}
+    TextFinder(TextSnapshot_as::TextFields& fields)
+        :
+        _fields(fields),
+        _count(0)
+    {}
 
     void operator()(character* ch) {
         if (ch->isUnloaded()) return;
-        std::string text;
+
+        TextSnapshot_as::Records text;
         generic_character* tf;
+
         if ((tf = ch->getStaticText(text))) {
             _fields.push_back(std::make_pair(tf, text));
+            _count = std::accumulate(text.begin(), text.end(), _count,
+                    CountRecords());
         }
     }
 
+    size_t getCount() const { return _count; }
+
 private:
-        TextSnapshot_as::TextFields& _fields;
+    TextSnapshot_as::TextFields& _fields;
+    size_t _count;
 };
 
 } // anonymous namespace
 
-
+/// The member _textFields is initialized here unnecessarily to show
+/// that it is constructed before it is used.
 TextSnapshot_as::TextSnapshot_as(const MovieClip* mc)
     :
     as_object(getTextSnapshotInterface()),
-    _valid(mc)
-{
-    if (mc) {
-        const DisplayList& dl = mc->getDisplayList();
-
-        TextFinder finder(_textFields);
-        dl.visitAll(finder);
-    }
+    _textFields(),
+    _valid(mc),
+    _count(getTextFields(mc, _textFields)),
+    _selected(_count)
+{
+}
+
+void
+TextSnapshot_as::setSelected(size_t start, size_t end, bool selected)
+{
+    start = std::min(start, _selected.size());
+    end = std::min(end, _selected.size());
+
+    for (size_t i = start; i < end; ++i) {
+        _selected.set(i, selected);
+    }
+}
+
+bool
+TextSnapshot_as::getSelected(size_t start, size_t end)
+{
+    start = std::min(start, _selected.size());
+    end = std::min(end, _selected.size());
+
+    for (size_t i = start; i < end; ++i) {
+        if (_selected.test(i)) return true;
+    }
+    return false;
 }
 
 void
@@ -101,13 +155,47 @@
 }
 
 void
-TextSnapshot_as::makeString(std::string& to, bool newline) const
+TextSnapshot_as::makeString(std::string& to, bool newline,
+        std::string::size_type start, std::string::size_type len) const
 {
+
+    std::string::size_type pos = 0;
+
     for (TextFields::const_iterator it = _textFields.begin(),
             e = _textFields.end(); it != e; ++it)
     {
-        if (newline && it != _textFields.begin()) to += '\n';
-        to += it->second;
+        // When newlines are requested, insert one after each individual
+        // text field is processed.
+        if (newline && pos > start) to += '\n';
+
+        const Records& rec = it->second;
+
+        for (Records::const_iterator j = rec.begin(), end = rec.end();
+                j != end; ++j) {
+        
+            const SWF::TextRecord* tr = *j;
+            assert(tr);
+
+            const SWF::TextRecord::Glyphs& glyphs = tr->glyphs();
+            const SWF::TextRecord::Glyphs::size_type numGlyphs = glyphs.size();
+
+            if (pos + numGlyphs < start) {
+                pos += numGlyphs;
+                continue;
+            }
+
+            const Font* font = tr->getFont();
+            assert(font);
+
+            for (SWF::TextRecord::Glyphs::const_iterator k = glyphs.begin(),
+                    e = glyphs.end(); k != e; ++k) {
+                
+                if (pos++ < start) continue;
+                
+                to += font->codeTableLookup(k->index, true);
+                if (pos - start >= len) return;
+            }
+        }
     }
 }
 
@@ -115,23 +203,37 @@
 TextSnapshot_as::getText(boost::int32_t start, boost::int32_t end, bool nl)
     const
 {
-    std::string snapshot;
-    makeString(snapshot, nl);
-
-    const std::string::size_type len = snapshot.size();
-
-    if (len == 0) return std::string();
 
     // Start is always moved to between 0 and len - 1.
     start = std::max<boost::int32_t>(start, 0);
-    start = std::min<std::string::size_type>(len - 1, start);
+    start = std::min<boost::int32_t>(start, _count - 1);
 
     // End is always moved to between start and end. We don't really care
-    // about end.
+    // about the end of the string.
     end = std::max(start + 1, end);
 
-    return snapshot.substr(start, end - start);
-
+    std::string snapshot;
+    makeString(snapshot, nl, start, end - start);
+
+    return snapshot;
+
+}
+
+std::string
+TextSnapshot_as::getSelectedText(bool newline) const
+{
+    std::string sel;
+    
+    for (size_t i = 0, e = _selected.size(); i != e; ++i) {
+        while (!_selected.test(i)) {
+            ++i;
+            if (i == e) return sel;
+        }
+        size_t start = i;
+        while (_selected.test(i) && i != e) ++i;
+        makeString(sel, newline, start, i - start);
+    }        
+    return sel;
 }
 
 boost::int32_t
@@ -260,19 +362,47 @@
         return as_value();
     }
 
-
     return ts->getCount();
 }
 
-as_value textsnapshot_getSelected(const fn_call& /*fn*/) {
-    log_unimpl (__FUNCTION__);
-    return as_value();
-}
-as_value textsnapshot_getSelectedText(const fn_call& /*fn*/) {
-    log_unimpl (__FUNCTION__);
-    return as_value();
-}
-
+/// Returns a boolean value, or undefined if not valid.
+as_value
+textsnapshot_getSelected(const fn_call& fn)
+{
+    boost::intrusive_ptr<TextSnapshot_as> ts =
+        ensureType<TextSnapshot_as>(fn.this_ptr);
+
+    if (!ts->valid()) return as_value();
+
+    if (fn.nargs != 2) {
+        return as_value();
+    }
+
+    size_t start = std::max(0, fn.arg(0).to_int());
+    size_t end = std::max<int>(start + 1, fn.arg(1).to_int());
+
+    return as_value(ts->getSelected(start, end));
+}
+
+/// Returns a string, or undefined if not valid.
+as_value
+textsnapshot_getSelectedText(const fn_call& fn)
+{
+    boost::intrusive_ptr<TextSnapshot_as> ts =
+        ensureType<TextSnapshot_as>(fn.this_ptr);
+
+    if (!ts->valid()) return as_value();
+
+    if (fn.nargs > 1) {
+        return as_value();
+    }
+
+    bool newlines = fn.nargs ? fn.arg(0).to_bool() : false;
+
+    return as_value(ts->getSelectedText(newlines));
+}
+
+/// Returns a string, or undefined if not valid.
 as_value
 textsnapshot_getText(const fn_call& fn)
 {
@@ -299,16 +429,49 @@
 }
 
 
-as_value textsnapshot_hitTestTextNearPos(const fn_call& /*fn*/) {
-    log_unimpl (__FUNCTION__);
-    return as_value();
-}
-as_value textsnapshot_setSelectColor(const fn_call& /*fn*/) {
-    log_unimpl (__FUNCTION__);
-    return as_value();
-}
-as_value textsnapshot_setSelected(const fn_call& /*fn*/) {
-    log_unimpl (__FUNCTION__);
+/// Returns bool, or undefined if not valid.
+as_value
+textsnapshot_hitTestTextNearPos(const fn_call& fn)
+{
+    boost::intrusive_ptr<TextSnapshot_as> ts =
+        ensureType<TextSnapshot_as>(fn.this_ptr);
+
+    if (!ts->valid()) return as_value();
+
+    log_unimpl (__FUNCTION__);
+    return as_value();
+}
+
+/// Returns void.
+as_value
+textsnapshot_setSelectColor(const fn_call& fn)
+{
+    boost::intrusive_ptr<TextSnapshot_as> ts =
+        ensureType<TextSnapshot_as>(fn.this_ptr);
+
+    log_unimpl (__FUNCTION__);
+    return as_value();
+}
+
+
+/// Returns void.
+as_value
+textsnapshot_setSelected(const fn_call& fn)
+{
+    boost::intrusive_ptr<TextSnapshot_as> ts =
+        ensureType<TextSnapshot_as>(fn.this_ptr);
+
+    if (fn.nargs < 2 || fn.nargs > 3) {
+        return as_value();
+    }
+
+    size_t start = std::max(0, fn.arg(0).to_int());
+    size_t end = std::max<int>(start, fn.arg(1).to_int());
+
+    bool selected = (fn.nargs > 2) ? fn.arg(2).to_bool() : true;
+
+    ts->setSelected(start, end, selected);
+
     return as_value();
 }
 
@@ -319,6 +482,19 @@
     return as_value(new TextSnapshot_as(mc));
 }
 
+size_t
+getTextFields(const MovieClip* mc, TextSnapshot_as::TextFields& fields)
+{
+    if (mc) {
+        const DisplayList& dl = mc->getDisplayList();
+
+        TextFinder finder(fields);
+        dl.visitAll(finder);
+        return finder.getCount();
+    }
+    return 0;
+}
+
 void
 setTextReachable(const TextSnapshot_as::TextFields::value_type& vt)
 {

=== modified file 'libcore/asobj/TextSnapshot_as.h'
--- a/libcore/asobj/TextSnapshot_as.h   2009-03-06 06:44:40 +0000
+++ b/libcore/asobj/TextSnapshot_as.h   2009-03-09 17:52:50 +0000
@@ -20,29 +20,38 @@
 #define GNASH_ASOBJ_TEXTSNAPSHOT_H
 
 #include "as_object.h"
-
-namespace gnash {
-
-class generic_character;
+#include <boost/dynamic_bitset.hpp>
+
+
+// Forward declarations.
+namespace gnash {
+    class generic_character;
+    namespace SWF {
+        class TextRecord;
+    }
+}
+
+namespace gnash {
 
 class TextSnapshot_as: public as_object
 {
 
 public:
 
+    typedef std::vector<const SWF::TextRecord*> Records;
+
     /// Should remain in the order of insertion
     /// We should only ever iterate from begin to end, so there's no
     /// performance issue.
-    typedef std::vector<std::pair<generic_character*, std::string> > 
TextFields;
+    typedef std::vector<std::pair<generic_character*, Records> > TextFields;
 
+    /// Construct a TextSnapshot_as from a MovieClip.
+    //
+    /// @param mc       The MovieClip to search for static text. If 0, the
+    ///                 TextSnapshot is invalid, which should be reflected in
+    ///                 AS return values.
     TextSnapshot_as(const MovieClip* mc);
 
-    std::string::size_type getCount() {
-        std::string snapshot;
-        makeString(snapshot);
-        return snapshot.size();
-    }
-
     const std::string getText(boost::int32_t start, boost::int32_t end,
             bool nl) const;
 
@@ -55,13 +64,23 @@
 
     bool valid() const { return _valid; }
 
+    size_t getCount() const { return _count; }
+
+    void setSelected(size_t start, size_t end, bool selected);
+    
+    bool getSelected(size_t start, size_t end);
+
+    std::string getSelectedText(bool newlines) const;
+
 protected:
 
     void markReachableResources() const;
 
 private:
 
-    void makeString(std::string& to, bool newline = false) const;
+    void makeString(std::string& to, bool newline = false,
+            std::string::size_type start = 0,
+            std::string::size_type len = std::string::npos) const;
 
     TextFields _textFields;
 
@@ -71,6 +90,21 @@
     /// to be no point in storing the MovieClip this bool will do instead.
     bool _valid;
 
+    /// The number of characters
+    //
+    /// There is no need to store this, but it is quicker than counting
+    /// afresh every time.
+    size_t _count;
+
+    /// Characters in the text run are selected individually.
+    //
+    /// Storing selection information along with the characters themselves
+    /// means that a separate object is necessary for each character.
+    /// Using a dynamic bitset prevents this, and generally
+    /// saves a lot of memory (32 bytes for boost's dynamic bitset against
+    /// one byte per character, possibly packed, for a bool in an object).
+    boost::dynamic_bitset<> _selected;
+
 };
 
 } // end of gnash namespace

=== modified file 'libcore/character.h'
--- a/libcore/character.h       2009-03-05 14:03:05 +0000
+++ b/libcore/character.h       2009-03-09 14:22:03 +0000
@@ -44,12 +44,15 @@
 
 // Forward declarations
 namespace gnash {
-  class MovieClip;
-  class movie_instance;
-  class ExecutableCode;
-  class action_buffer;
-  class movie_definition;
-  class generic_character;
+    class MovieClip;
+    class movie_instance;
+    class ExecutableCode;
+    class action_buffer;
+    class movie_definition;
+    class generic_character;
+    namespace SWF {
+        class TextRecord;
+    }
 }
 
 namespace gnash {
@@ -415,7 +418,8 @@
     //
     /// Default is a no-op, implemented only for DefineText though
     /// generic_character.
-    virtual generic_character* getStaticText(std::string& /*to*/) {
+    virtual generic_character* getStaticText(
+            std::vector<const SWF::TextRecord*>& /*to*/) {
         return 0;
     }
 

=== modified file 'libcore/generic_character.cpp'
--- a/libcore/generic_character.cpp     2009-03-05 14:03:05 +0000
+++ b/libcore/generic_character.cpp     2009-03-09 14:22:03 +0000
@@ -49,7 +49,7 @@
 
 
 generic_character*
-generic_character::getStaticText(std::string& to)
+generic_character::getStaticText(std::vector<const SWF::TextRecord*>& to)
 {
     if (m_def->extractStaticText(to)) return this;
     return 0;

=== modified file 'libcore/generic_character.h'
--- a/libcore/generic_character.h       2009-03-05 14:03:05 +0000
+++ b/libcore/generic_character.h       2009-03-09 14:22:03 +0000
@@ -26,8 +26,16 @@
 
 namespace gnash {
 
-// Forward declarations
-class character_def;
+    // Forward declarations
+    class character_def;
+
+    namespace SWF {
+        class TextRecord;
+    }
+
+}
+
+namespace gnash {
 
 /// For characters that don't store unusual state in their instances.
 //
@@ -72,7 +80,8 @@
                return false;
        }
 
-    virtual generic_character* getStaticText(std::string& to);
+    virtual generic_character* getStaticText(
+            std::vector<const SWF::TextRecord*>& /*to*/);
 
        virtual void display();
 

=== modified file 'libcore/parser/character_def.h'
--- a/libcore/parser/character_def.h    2009-03-05 14:03:05 +0000
+++ b/libcore/parser/character_def.h    2009-03-09 14:22:03 +0000
@@ -27,6 +27,9 @@
        class character;
        class SWFMatrix;
        class rect;
+    namespace SWF {
+        class TextRecord;
+    }
 }
 
 namespace gnash {
@@ -63,7 +66,7 @@
     //
     /// This is used for MovieClip.getTextSnapshot() and should only be
     /// implemented in DefineTextTag. Default is a no-op
-    virtual bool extractStaticText(std::string& /*to*/)
+    virtual bool extractStaticText(std::vector<const SWF::TextRecord*>& /*to*/)
     {
         return false;
     }

=== modified file 'libcore/swf/DefineTextTag.cpp'
--- a/libcore/swf/DefineTextTag.cpp     2009-03-05 14:03:05 +0000
+++ b/libcore/swf/DefineTextTag.cpp     2009-03-09 14:59:05 +0000
@@ -34,33 +34,23 @@
     m.add_character(id, t.release());
 }
 
-class DecodeRecord
+template<typename T>
+struct CreatePointer
 {
-public:
-
-    DecodeRecord(std::string& to) : _to(to) {}
-
-    void operator()(const TextRecord& tr) {
-
-        const Font* font = tr.getFont();
-        if (!font) return;
-        
-        const TextRecord::Glyphs& glyphs = tr.glyphs();
-
-        for (TextRecord::Glyphs::const_iterator it = glyphs.begin(),
-                e = glyphs.end(); it != e; ++it) {
-            _to += font->codeTableLookup(it->index, true);
-        }
+    const T* operator()(const T& t) { 
+        return &t;
     }
-private:
-    std::string& _to;
 };
 
 
 bool
-DefineTextTag::extractStaticText(std::string& to)
+DefineTextTag::extractStaticText(std::vector<const TextRecord*>& to)
 {
-    std::for_each(_textRecords.begin(), _textRecords.end(), DecodeRecord(to));
+    if (_textRecords.empty()) return false;
+
+    std::transform(_textRecords.begin(), _textRecords.end(),
+            std::back_inserter(to), CreatePointer<TextRecord>());
+
     return true;
 }
 

=== modified file 'libcore/swf/DefineTextTag.h'
--- a/libcore/swf/DefineTextTag.h       2009-03-05 14:03:05 +0000
+++ b/libcore/swf/DefineTextTag.h       2009-03-09 14:22:03 +0000
@@ -58,7 +58,7 @@
     }
 
     /// Extract static text from TextRecords.
-    bool extractStaticText(std::string& to);
+    bool extractStaticText(std::vector<const TextRecord*>& to);
 
 private:
 

=== modified file 'testsuite/actionscript.all/TextSnapshot.as'
--- a/testsuite/actionscript.all/TextSnapshot.as        2009-03-06 06:44:40 
+0000
+++ b/testsuite/actionscript.all/TextSnapshot.as        2009-03-09 18:23:02 
+0000
@@ -149,24 +149,24 @@
  check_equals(typeof(ts.getSelected("a")), "undefined");
  check_equals(typeof(ts.getSelected(new Date())), "undefined");
  check_equals(typeof(ts.getSelected([0, 1])), "undefined");
- xcheck_equals(typeof(ts.getSelected([0, 1], 2)), "boolean");
- xcheck_equals(typeof(ts.getSelected(0, 1)), "boolean");
- xcheck_equals(typeof(ts.getSelected(1, 0)), "boolean");
- xcheck_equals(typeof(ts.getSelected(-1, 3)), "boolean");
- xcheck_equals(typeof(ts.getSelected(1, 0)), "boolean");
- xcheck_equals(typeof(ts.getSelected(1, 0)), "boolean");
- xcheck_equals(typeof(ts.getSelected(0, "a")), "boolean");
- xcheck_equals(typeof(ts.getSelected("b", 0)), "boolean");
- xcheck_equals(typeof(ts.getSelected(true, false)), "boolean");
+ check_equals(typeof(ts.getSelected([0, 1], 2)), "boolean");
+ check_equals(typeof(ts.getSelected(0, 1)), "boolean");
+ check_equals(typeof(ts.getSelected(1, 0)), "boolean");
+ check_equals(typeof(ts.getSelected(-1, 3)), "boolean");
+ check_equals(typeof(ts.getSelected(1, 0)), "boolean");
+ check_equals(typeof(ts.getSelected(1, 0)), "boolean");
+ check_equals(typeof(ts.getSelected(0, "a")), "boolean");
+ check_equals(typeof(ts.getSelected("b", 0)), "boolean");
+ check_equals(typeof(ts.getSelected(true, false)), "boolean");
  check_equals(typeof(ts.getSelected(0, 10, 10)), "undefined");
  check_equals(typeof(ts.getSelected(0, 10, true)), "undefined");
  check_equals(typeof(ts.getSelected(0, 10, "a")), "undefined");
 
- xcheck_equals(typeof(ts.getSelectedText()), "string");
- xcheck_equals(typeof(ts.getSelectedText(0)), "string");
- xcheck_equals(typeof(ts.getSelectedText("a")), "string");
- xcheck_equals(typeof(ts.getSelectedText(new Date())), "string");
- xcheck_equals(typeof(ts.getSelectedText([0, 2])), "string");
+ check_equals(typeof(ts.getSelectedText()), "string");
+ check_equals(typeof(ts.getSelectedText(0)), "string");
+ check_equals(typeof(ts.getSelectedText("a")), "string");
+ check_equals(typeof(ts.getSelectedText(new Date())), "string");
+ check_equals(typeof(ts.getSelectedText([0, 2])), "string");
  check_equals(typeof(ts.getSelectedText(0, 1)), "undefined");
  check_equals(typeof(ts.getSelectedText(1, 0)), "undefined");
  check_equals(typeof(ts.getSelectedText(-1, 3)), "undefined");

=== modified file 'testsuite/misc-ming.all/TextSnapshotTest.c'
--- a/testsuite/misc-ming.all/TextSnapshotTest.c        2009-03-06 06:57:05 
+0000
+++ b/testsuite/misc-ming.all/TextSnapshotTest.c        2009-03-09 17:52:50 
+0000
@@ -144,7 +144,7 @@
           "'First text\nZweites Textfeld\nSome more "
                  "static text here... abcdefgh'");
   
-  xcheck_equals(mo, "ts.getText(0, 14, true)", "'First text\nZwei'");
+  check_equals(mo, "ts.getText(0, 14, true)", "'First text\nZwei'");
 
   check_equals(mo, "ts.findText(0, '', false)", "-1");
   check_equals(mo, "ts.findText(0, 'f', false)", "0");
@@ -156,8 +156,43 @@
   check_equals(mo, "ts.findText(-5, 'Zwei', true)", "-1");
   check_equals(mo, "ts.findText(-5, 'gh', true)", "-1");
 
-
-  add_actions(mo, "ts.setSelected(0, 30, true);");
+  add_actions(mo, "ts.setSelected(5, 30, true);");
+  check_equals(mo, "ts.getSelectedText()", "' textZweites TextfeldSome'");
+  check_equals(mo, "ts.getSelectedText(true)", "' text\nZweites "
+          "Textfeld\nSome'");
+  check_equals(mo, "ts.getSelectedText(false)", "' textZweites TextfeldSome'");
+  check_equals(mo, "ts.getSelected(0, 4)", "false");
+  check_equals(mo, "ts.getSelected(1, 9)", "true");
+  check_equals(mo, "ts.getSelected(-4, 10)", "true");
+  check_equals(mo, "ts.getSelected(-4, 6)", "true");
+  check_equals(mo, "ts.getSelected(28, 23)", "true");
+  check_equals(mo, "ts.getSelected(20, 20)", "true");
+  check_equals(mo, "ts.getSelected(20, 27)", "true");
+  check_equals(mo, "ts.getSelected(-3, -1)", "false");
+  check_equals(mo, "ts.getSelected(30, 31)", "false");
+  check_equals(mo, "ts.getSelected(0, 5)", "false");
+  check_equals(mo, "ts.getSelected(40, 45)", "false");
+  check_equals(mo, "ts.getSelected(31, 34)", "false");
+
+  check_equals(mo, "ts.getSelected(0)", "undefined");
+  check_equals(mo, "ts.getSelected(1)", "undefined");
+  check_equals(mo, "ts.getSelected(-4)", "undefined");
+  check_equals(mo, "ts.getSelected(-4)", "undefined");
+  check_equals(mo, "ts.getSelected(28)", "undefined");
+  check_equals(mo, "ts.getSelected(20)", "undefined");
+
+  // Check that selected text is not a property of the text itself.
+  add_actions(mo, "ts2 = new TextSnapshot(this);");
+  check_equals(mo, "ts2.getCount()", "64");
+  check_equals(mo, "ts2.getSelectedText()", "''");
+  add_actions(mo, "ts2 = this.getTextSnapshot();");
+  check_equals(mo, "ts2.getCount()", "64");
+  check_equals(mo, "ts2.getSelectedText()", "''");
+
+  add_actions(mo, "ts2.setSelected(3, 10);");
+
+  add_actions(mo, "ts.setSelectedColor(0xffff00);");
+  add_actions(mo, "ts2.setSelectedColor(0x0000ff);");
 
   add_actions(mo, "ts = this.getTextSnapshot();");
   check_equals(mo, "typeof(ts)", "'object'");
@@ -181,12 +216,8 @@
   add_actions(mo, "ts = this.getTextSnapshot();");
   check_equals(mo, "typeof(ts)", "'object'");
   
-  
   add_actions(mo, "totals(); stop();");
   
-
-
-  
   SWFMovie_nextFrame(mo); 
 
   /*****************************************************


reply via email to

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