gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] [SCM] Gnash branch, master, updated. release_0_8_9_final-


From: Bastiaan Jacques
Subject: [Gnash-commit] [SCM] Gnash branch, master, updated. release_0_8_9_final-1695-g1fe4c1d
Date: Wed, 31 Jul 2013 20:58:32 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Gnash".

The branch, master has been updated
       via  1fe4c1d27afd9fa97741df52c543382d94bc9be2 (commit)
       via  368216f46f76b7efeeafcf84d061857277ab7bcd (commit)
       via  22eac818afa08d15c55ae03091ea5a8d576dea20 (commit)
       via  31ce0628c76253052579065a0c2bf944357452b1 (commit)
       via  73da624b50cf46cba878143d7a2acf6f8b8de981 (commit)
      from  319726dcfa33883051a2717010deb6ae765fdd88 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit//commit/?id=1fe4c1d27afd9fa97741df52c543382d94bc9be2


commit 1fe4c1d27afd9fa97741df52c543382d94bc9be2
Author: Bastiaan Jacques <address@hidden>
Date:   Wed Jul 31 22:56:31 2013 +0200

    Adjust the remaining users of Path and ShapeRecord to the new
    handling of Subshapes.

diff --git a/libcore/Bitmap.cpp b/libcore/Bitmap.cpp
index dc93441..faf5864 100644
--- a/libcore/Bitmap.cpp
+++ b/libcore/Bitmap.cpp
@@ -90,13 +90,14 @@ Bitmap::construct(as_object* /*init*/)
 
     const size_t fillLeft = _shape.addFillStyle(fill);
 
-    Path bmpath(w, h, fillLeft, 0, 0, false);
+    Path bmpath(w, h, fillLeft, 0, 0);
     bmpath.drawLineTo(w, 0);
     bmpath.drawLineTo(0, 0);
     bmpath.drawLineTo(0, h);
     bmpath.drawLineTo(w, h);
 
     _shape.add_path(bmpath);
+    _shape.setBounds(SWFRect(0, 0, w, h));
     _shape.finalize();
 
     set_invalidated();
diff --git a/libcore/DynamicShape.cpp b/libcore/DynamicShape.cpp
index 4b5e1fc..10bc3cb 100644
--- a/libcore/DynamicShape.cpp
+++ b/libcore/DynamicShape.cpp
@@ -41,6 +41,7 @@ DynamicShape::clear()
        _shape.clear();
        _currpath = 0; 
        _currfill = _currline = 0; 
+       _currsubshape.clear();
        // TODO: worth setting _changed=true ? 
 }
 
@@ -53,8 +54,9 @@ DynamicShape::display(Renderer& renderer, const Transform& 
xform) const
 void
 DynamicShape::add_path(const Path& pth)
 {
-       _shape.addPath(pth);
-       _currpath = &_shape.currentPath();
+       _currsubshape.addPath(pth);
+       _currpath = &_currsubshape.currentPath();
+       _changed = true;
 }
 
 void
@@ -80,6 +82,11 @@ DynamicShape::endFill()
                _y = _currpath->ap.y;
        }
 
+       if (_currline) {
+               _shape.addSubshape(_currsubshape);
+               _currsubshape.paths().clear(); // Retain style info
+       }
+
        // Remove reference to the "current" path, as
        // next drawing will happen on a different one
        _currpath = 0;
@@ -93,12 +100,13 @@ DynamicShape::beginFill(const FillStyle& f)
        // End previous fill
        endFill();
 
+
        _currfill = addFillStyle(f);
 
        // TODO: how to know wheter the fill should be set
        //       as *left* or *right* fill ?
        //       A quick test shows that *left* always work fine !
-       Path newPath(_x, _y, _currfill, 0, _currline, true); 
+       Path newPath(_x, _y, _currfill, 0, _currline);
        add_path(newPath);
 }
 
@@ -112,12 +120,18 @@ DynamicShape::startNewPath(bool newShape)
                _currpath->close();
        }
 
+       if (newShape) {
+               _shape.addSubshape(_currsubshape);
+               _currsubshape.paths().clear(); // Retain style info
+       }
+
+
        // The DrawingApiTest.swf file shows we should not
        // end the current fill when starting a new path.
 
        // A quick test shows that *left* always work fine !
        // More than that, using a *right* fill seems to break the tests !
-       Path newPath(_x, _y, _currfill, 0, _currline, newShape);
+       Path newPath(_x, _y, _currfill, 0, _currline);
        add_path(newPath);
 }
 
@@ -130,11 +144,16 @@ DynamicShape::finalize() const
        // Close any pending filled path (_currpath should be last path)
        if ( _currpath && _currfill)
        {
-               assert(!_shape.paths().empty());
-               assert(_currpath == &(_shape.paths().back()));
+               assert(!_currsubshape.paths().empty());
+               assert(_currpath == &(_currsubshape.paths().back()));
                _currpath->close();
        }
 
+       // This function being const seems to be at odds with its purpose...
+       _shape.addSubshape(_currsubshape);
+
+       _currsubshape.clear();
+
        // TODO: check consistency of fills and such !
 
        _changed = false;
@@ -176,7 +195,7 @@ DynamicShape::moveTo(boost::int32_t x, boost::int32_t y)
 void
 DynamicShape::lineTo(boost::int32_t x, boost::int32_t y, int swfVersion)
 {
-       if (!_currpath) startNewPath(true); 
+       if (!_currpath) startNewPath(false);
        assert(_currpath);
 
        _currpath->drawLineTo(x, y);
@@ -185,7 +204,7 @@ DynamicShape::lineTo(boost::int32_t x, boost::int32_t y, 
int swfVersion)
     SWFRect bounds = _shape.getBounds();
 
        unsigned thickness = _currline ? 
-        _shape.lineStyles().back().getThickness() : 0;
+        _currsubshape.lineStyles().back().getThickness() : 0;
 
        if (_currpath->size() == 1) {
                _currpath->expandBounds(bounds, thickness, swfVersion);
@@ -208,7 +227,7 @@ void
 DynamicShape::curveTo(boost::int32_t cx, boost::int32_t cy, 
                       boost::int32_t ax, boost::int32_t ay, int swfVersion)
 {
-       if (!_currpath) startNewPath(true); 
+       if (!_currpath) startNewPath(false);
        assert(_currpath);
 
        _currpath->drawCurveTo(cx, cy, ax, ay);
@@ -216,7 +235,7 @@ DynamicShape::curveTo(boost::int32_t cx, boost::int32_t cy,
     SWFRect bounds = _shape.getBounds();
 
        unsigned thickness = _currline ? 
-        _shape.lineStyles().back().getThickness() : 0;
+        _currsubshape.lineStyles().back().getThickness() : 0;
 
        if (_currpath->size() == 1) {
                _currpath->expandBounds(bounds, thickness, swfVersion);
@@ -241,15 +260,15 @@ DynamicShape::curveTo(boost::int32_t cx, boost::int32_t 
cy,
 size_t
 DynamicShape::addFillStyle(const FillStyle& stl)
 {
-    _shape.addFillStyle(stl);
-    return _shape.fillStyles().size();
+    _currsubshape.addFillStyle(stl);
+    return _currsubshape.fillStyles().size();
 }
 
 size_t
 DynamicShape::add_line_style(const LineStyle& stl)
 {
-    _shape.addLineStyle(stl);
-    return _shape.lineStyles().size();
+    _currsubshape.addLineStyle(stl);
+    return _currsubshape.lineStyles().size();
 }
        
 }      // end namespace gnash
diff --git a/libcore/DynamicShape.h b/libcore/DynamicShape.h
index 0eb3d20..50dcb89 100644
--- a/libcore/DynamicShape.h
+++ b/libcore/DynamicShape.h
@@ -148,8 +148,7 @@ public:
             const SWFMatrix& wm) const
        {
                finalize();
-               return geometry::pointTest(_shape.paths(), _shape.lineStyles(), 
x, y,
-                wm);
+               return _shape.pointTest(x, y, wm);
        }
 
     const SWF::ShapeRecord& shapeRecord() const {
@@ -182,6 +181,8 @@ private:
        /// If newShape is true the new shape will start a new subshape.
        void startNewPath(bool newShape);
 
+
+
        Path* _currpath;
 
        size_t _currfill;
@@ -196,6 +197,8 @@ private:
 
        mutable bool _changed;
 
+       mutable SWF::Subshape _currsubshape;
+
     /// The actual SWF::ShapeRecord wrapped by this class.
     //
     /// Mutable for lazy finalization.
diff --git a/libcore/FreetypeGlyphsProvider.cpp 
b/libcore/FreetypeGlyphsProvider.cpp
index 608019d..273bd10 100644
--- a/libcore/FreetypeGlyphsProvider.cpp
+++ b/libcore/FreetypeGlyphsProvider.cpp
@@ -99,14 +99,15 @@ public:
     {
         /// A default fill style is solid white.
         FillStyle f = SolidFill(rgba());
-        _shape.addFillStyle(f);
-        _shape.addPath(Path(_x, _y, 1, 0, 0, true));
-        _currPath = &_shape.currentPath();
+        _subshape.addFillStyle(f);
+        _subshape.addPath(Path(_x, _y, 1, 0, 0));
+        _currPath = &_subshape.currentPath();
     }
 
     void finish() 
     {
         _currPath->close();
+        _shape.addSubshape(_subshape);
     }
 
     ~OutlineWalker() {}
@@ -158,8 +159,8 @@ private:
         _x = static_cast<boost::int32_t>(to->x * _scale);
         _y = - static_cast<boost::int32_t>(to->y * _scale);
         _currPath->close();
-        _shape.addPath(Path(_x, _y, 1, 0, 0, false));
-        _currPath = &_shape.currentPath();
+        _subshape.addPath(Path(_x, _y, 1, 0, 0));
+        _currPath = &_subshape.currentPath();
         return 0;
     }
 
@@ -227,6 +228,7 @@ private:
         _shape.setBounds(bounds);
     }
 
+    SWF::Subshape _subshape;
     SWF::ShapeRecord& _shape;
 
     const float _scale;
diff --git a/libcore/MorphShape.cpp b/libcore/MorphShape.cpp
index 98f4914..f1f67ee 100644
--- a/libcore/MorphShape.cpp
+++ b/libcore/MorphShape.cpp
@@ -55,8 +55,7 @@ MorphShape::pointInShape(boost::int32_t x, boost::int32_t y) 
const
     //       shape).
     if (!_shape.getBounds().point_test(lp.x, lp.y)) return false;
 
-    return geometry::pointTest(_shape.paths(), _shape.lineStyles(),
-            lp.x, lp.y, wm);
+    return _shape.pointTest(lp.x, lp.y, wm);
 }
 
 void  
diff --git a/libcore/swf/DefineMorphShapeTag.cpp 
b/libcore/swf/DefineMorphShapeTag.cpp
index 1315b85..b7e0ee5 100644
--- a/libcore/swf/DefineMorphShapeTag.cpp
+++ b/libcore/swf/DefineMorphShapeTag.cpp
@@ -106,26 +106,32 @@ DefineMorphShapeTag::read(SWFStream& in, TagType tag, 
movie_definition& md,
     }
 
     in.ensureBytes(4);
-    // Offset. What is this for?
+    // Spec: Indicates offset to the second Shape.
     static_cast<void>(in.read_u32());
 
     // Next line will throw ParserException on malformed SWF
     const boost::uint16_t fillCount = in.read_variable_count();
     
+    SWF::Subshape subshape1;
+    SWF::Subshape subshape2;
+
     for (size_t i = 0; i < fillCount; ++i) {
         OptionalFillPair fp = readFills(in, tag, md, true);
-        _shape1.addFillStyle(fp.first);
-        _shape2.addFillStyle(*fp.second);
+        subshape1.addFillStyle(fp.first);
+        subshape2.addFillStyle(*fp.second);
     }
 
     const boost::uint16_t lineCount = in.read_variable_count();
     LineStyle ls1, ls2;
     for (size_t i = 0; i < lineCount; ++i) {
         ls1.read_morph(in, tag, md, r, &ls2);
-        _shape1.addLineStyle(ls1);
-        _shape2.addLineStyle(ls2);
+        subshape1.addLineStyle(ls1);
+        subshape2.addLineStyle(ls2);
     }
 
+    _shape1.addSubshape(subshape1);
+    _shape2.addSubshape(subshape2);
+
     _shape1.read(in, tag, md, r);
     in.align();
     _shape2.read(in, tag, md, r);
@@ -139,9 +145,8 @@ DefineMorphShapeTag::read(SWFStream& in, TagType tag, 
movie_definition& md,
     // Starting bounds are the same as shape1
     _bounds = bounds1;
 
-    assert(_shape1.fillStyles().size() == _shape2.fillStyles().size());
-    assert(_shape1.lineStyles().size() == _shape2.lineStyles().size());
-
+    assert(_shape1.subshapes().size() == _shape2.subshapes().size() == 1);
+    assert(_shape1.subshapes().size() == _shape2.subshapes().size() == 1);
 }
 
 } // namespace SWF
diff --git a/libcore/swf/DefineShapeTag.cpp b/libcore/swf/DefineShapeTag.cpp
index 49ab8b5..faa279a 100644
--- a/libcore/swf/DefineShapeTag.cpp
+++ b/libcore/swf/DefineShapeTag.cpp
@@ -73,7 +73,7 @@ bool
 DefineShapeTag::pointTestLocal(boost::int32_t x, boost::int32_t y, 
      const SWFMatrix& wm) const
 {
-    return geometry::pointTest(_shape.paths(), _shape.lineStyles(), x, y, wm);
+    return _shape.pointTest(x, y, wm);
 }
 
 

http://git.savannah.gnu.org/cgit//commit/?id=368216f46f76b7efeeafcf84d061857277ab7bcd


commit 368216f46f76b7efeeafcf84d061857277ab7bcd
Author: Bastiaan Jacques <address@hidden>
Date:   Wed Jul 31 22:56:00 2013 +0200

    Update pointTest.

diff --git a/libcore/Geometry.cpp b/libcore/Geometry.cpp
index 350d249..d8cb7e3 100644
--- a/libcore/Geometry.cpp
+++ b/libcore/Geometry.cpp
@@ -161,17 +161,6 @@ pointTest(const std::vector<Path>& paths,
         float next_pen_y = pth.ap.y;
         float pen_x, pen_y;
 
-        if (pth.m_new_shape)
-        {
-            if (( even_odd && (counter % 2) != 0) ||
-                 (!even_odd && (counter != 0)) )
-            {
-                // the point is inside the previous subshape, so exit now
-                return true;
-            }
-
-            counter=0;
-        }
         if (pth.empty()) continue;
 
         // If the path has a line style, check for strokes there

http://git.savannah.gnu.org/cgit//commit/?id=22eac818afa08d15c55ae03091ea5a8d576dea20


commit 22eac818afa08d15c55ae03091ea5a8d576dea20
Author: Bastiaan Jacques <address@hidden>
Date:   Wed Jul 31 22:55:31 2013 +0200

    Cease recording the start of a subshape inside Paths.

diff --git a/libcore/Geometry.h b/libcore/Geometry.h
index 5836303..5ec7ca6 100644
--- a/libcore/Geometry.h
+++ b/libcore/Geometry.h
@@ -185,16 +185,13 @@ public:
     /// All paths with a higher index in the list belong to the same 
     /// shape unless they have m_new_shape==true on their own.
     /// Sub-shapes affect the order in which outlines and shapes are rendered.
-    bool m_new_shape;
     
     /// Default constructor
     //
     /// @param newShape
     ///    True if this path starts a new subshape
     ///
-    Path(bool newShape = false)
-        : 
-        m_new_shape(newShape)
+    Path()
     {
         reset(0, 0, 0, 0, 0);
     }
@@ -205,8 +202,7 @@ public:
         m_fill1(from.m_fill1),
         m_line(from.m_line),
         ap(from.ap),
-        m_edges(from.m_edges),
-        m_new_shape(from.m_new_shape)                
+        m_edges(from.m_edges)
     {
     }
     
@@ -233,10 +229,7 @@ public:
     /// @param newShape
     ///    True if this path starts a new subshape
     Path(boost::int32_t ax, boost::int32_t ay, 
-            unsigned fill0, unsigned fill1, unsigned line, 
-            bool newShape)
-        :
-        m_new_shape(newShape)
+            unsigned fill0, unsigned fill1, unsigned line)
     {
         reset(ax, ay, fill0, fill1, line);
     }
@@ -462,18 +455,6 @@ public:
         {
             (*it).transform(mat);
         }
-    }        
-
-    /// Set this path as the start of a new (sub)shape
-    void setNewShape() 
-    { 
-            m_new_shape=true; 
-    }
-
-    /// Return true if this path starts a new (sub)shape
-    bool getNewShape() const 
-    { 
-        return m_new_shape; 
     }
 
     /// Return true if this path contains no edges
@@ -556,13 +537,6 @@ public:
     {
         return m_edges[n];
     }
-
-    /// Returns true if this path begins a new subshape. <-- VERIFYME
-    bool isNewShape() const
-    {
-        return m_new_shape;
-    }
-
 }; // end of class Path
 
 namespace geometry

http://git.savannah.gnu.org/cgit//commit/?id=31ce0628c76253052579065a0c2bf944357452b1


commit 31ce0628c76253052579065a0c2bf944357452b1
Author: Bastiaan Jacques <address@hidden>
Date:   Wed Jul 31 22:54:37 2013 +0200

    Render subshapes as laid out by the ShapeRecord.

diff --git a/librender/agg/Renderer_agg.cpp b/librender/agg/Renderer_agg.cpp
index 0809767..546e1a8 100644
--- a/librender/agg/Renderer_agg.cpp
+++ b/librender/agg/Renderer_agg.cpp
@@ -116,6 +116,7 @@ AGG resources
 #include <climits>
 #include <boost/scoped_array.hpp>
 #include <boost/bind.hpp>
+
 #include <agg_rendering_buffer.h>
 #include <agg_renderer_base.h>
 #include <agg_pixfmt_gray.h>
@@ -1022,6 +1023,8 @@ public:
   void drawGlyph(const SWF::ShapeRecord& shape, const rgba& color,
           const SWFMatrix& mat) 
   {
+    if (shape.subshapes().empty()) return;
+    assert(shape.subshapes().size() == 1);
     
     // select relevant clipping bounds
     if (shape.getBounds().is_null()) {
@@ -1032,7 +1035,7 @@ public:
     if (_clipbounds_selected.empty()) return; 
       
     GnashPaths paths;
-    apply_matrix_to_path(shape.paths(), paths, mat);
+    apply_matrix_to_path(shape.subshapes().front().paths(), paths, mat);
 
     // If it's a mask, we don't need the rest.
     if (m_drawing_mask) {
@@ -1050,7 +1053,7 @@ public:
     StyleHandler sh;
     build_agg_styles(sh, v, mat, SWFCxForm());
     
-    draw_shape(-1, paths, agg_paths, sh, false);
+    draw_shape(paths, agg_paths, sh, false);
     
     // NOTE: Do not use even-odd filling rule for glyphs!
     
@@ -1118,18 +1121,22 @@ public:
         if (!bounds_in_clipping_area(cur_bounds.getRange()))
         {
             return; // no need to draw
-        }        
-        
-        const SWF::ShapeRecord::FillStyles& fillStyles = shape.fillStyles();
-        const SWF::ShapeRecord::LineStyles& lineStyles = shape.lineStyles();
-        const SWF::ShapeRecord::Paths& paths = shape.paths();
-        
-        // select ranges
-        select_clipbounds(shape.getBounds(), xform.matrix);
+        }
+
+        for (SWF::ShapeRecord::Subshapes::const_iterator it = 
shape.subshapes().begin(),
+             end = shape.subshapes().end(); it != end; ++it ) {
 
-        // render the DisplayObject's shape.
-        drawShape(fillStyles, lineStyles, paths, xform.matrix,
-                xform.colorTransform);
+            const SWF::ShapeRecord::FillStyles& fillStyles = it->fillStyles();
+            const SWF::ShapeRecord::LineStyles& lineStyles = it->lineStyles();
+            const SWF::ShapeRecord::Paths& paths = it->paths();
+
+            // select ranges
+            select_clipbounds(shape.getBounds(), xform.matrix);
+
+            // render the DisplayObject's subshape.
+            drawShape(fillStyles, lineStyles, paths, xform.matrix,
+                      xform.colorTransform);
+        }
     }
 
     void drawShape(const std::vector<FillStyle>& FillStyles,
@@ -1145,7 +1152,7 @@ public:
         if (!have_shape && !have_outline) {
             // Early return for invisible character.
             return; 
-        }        
+        }
 
         GnashPaths paths;
         apply_matrix_to_path(objpaths, paths, mat);
@@ -1185,19 +1192,14 @@ public:
         StyleHandler sh;
         if (have_shape) build_agg_styles(sh, FillStyles, mat, cx);
 
-        // We need to separate sub-shapes during rendering. 
-        const unsigned int subshape_count = count_sub_shapes(paths);
 
-        for (unsigned int subshape=0; subshape<subshape_count; ++subshape)
-        {
             if (have_shape) {
-                draw_shape(subshape, paths, agg_paths, sh, true);        
+                draw_shape(paths, agg_paths, sh, true);        
             }
             if (have_outline)            {
-                draw_outlines(subshape, paths, agg_paths_rounded,
+                draw_outlines(paths, agg_paths_rounded,
                         line_styles, cx, mat);
             }
-        }
 
         // Clear selected clipbounds to ease debugging 
         _clipbounds_selected.clear();
@@ -1224,26 +1226,6 @@ public:
                 boost::bind(&Path::transform, _1, mat));
     } 
 
-
-  /// A shape can have sub-shapes. This can happen when there are multiple
-  /// layers of the same frame count. Flash combines them to one single shape.
-  /// The problem with sub-shapes is, that outlines can be hidden by other
-  /// layers so they must be rendered separately. 
-  unsigned int count_sub_shapes(const GnashPaths &path_in)
-  {
-    unsigned int sscount=1;
-    const size_t pcnt = path_in.size();
-    
-    for (size_t pno=0; pno<pcnt; ++pno) {
-      const Path& this_path = path_in[pno];
-      
-      if (this_path.m_new_shape)
-        sscount++;
-    }
-    
-    return sscount;
-  }
-
   // Version of buildPaths that uses rounded coordinates (pixel hinting)
   // for line styles that want it.  
   // This is used for outlines which are aligned to the pixel grid to avoid
@@ -1431,7 +1413,7 @@ public:
   /// @param subshape_id
   ///    Defines which subshape to draw. -1 means all subshapes.
   ///
-  void draw_shape(int subshape_id, const GnashPaths &paths,
+  void draw_shape(const GnashPaths &paths,
     const AggPaths& agg_paths,  
     StyleHandler& sh, bool even_odd) {
     
@@ -1443,7 +1425,7 @@ public:
       
       scanline_type sl;
       
-      draw_shape_impl<scanline_type> (subshape_id, paths, agg_paths, 
+      draw_shape_impl<scanline_type> (paths, agg_paths, 
         sh, even_odd, sl);
         
     } else {
@@ -1454,7 +1436,7 @@ public:
       
       scanline_type sl(_alphaMasks.back().getMask());
       
-      draw_shape_impl<scanline_type> (subshape_id, paths, agg_paths, 
+      draw_shape_impl<scanline_type> (paths, agg_paths, 
         sh, even_odd, sl);
         
     }
@@ -1465,7 +1447,7 @@ public:
   /// one with and one without an alpha mask. This makes drawing without masks
   /// much faster.  
   template <class scanline_type>
-  void draw_shape_impl(int subshape_id, const GnashPaths &paths,
+  void draw_shape_impl(const GnashPaths &paths,
     const AggPaths& agg_paths,
     StyleHandler& sh, bool even_odd, scanline_type& sl) {
     /*
@@ -1507,8 +1489,6 @@ public:
       
       applyClipBox<ras_type> (rasc, *bounds);
       
-      int current_subshape=0;
-        
       // push paths to AGG
       const size_t pcount = paths.size();
   
@@ -1519,19 +1499,11 @@ public:
           const_cast<agg::path_storage&>(agg_paths[pno]);
         
         agg::conv_curve<agg::path_storage> curve(this_path_agg);        
-        
-        if (this_path_gnash.m_new_shape) ++current_subshape;
-          
-        if ((subshape_id >= 0) && (current_subshape!=subshape_id)) {
-          // Skip this path as it is not part of the requested sub-shape.
-          continue;
-        }
-        
+
         if ((this_path_gnash.m_fill0==0) && (this_path_gnash.m_fill1==0)) {
           // Skip this path as it contains no fill style
           continue;
         } 
-                
         
         // Tell the rasterizer which styles the following path will use.
         // The good thing is, that it already supports two fill styles out of
@@ -1543,7 +1515,7 @@ public:
         rasc.add_path(curve);
       
       }
-              
+
       agg::render_scanlines_compound_layered(rasc, sl, rbase, alloc, sh);
     }
     
@@ -1651,7 +1623,7 @@ public:
 
 
   /// Just like draw_shapes() except that it draws an outline.
-  void draw_outlines(int subshape_id, const GnashPaths &paths,
+  void draw_outlines(const GnashPaths &paths,
     const AggPaths& agg_paths,
     const std::vector<LineStyle> &line_styles, const SWFCxForm& cx,
     const SWFMatrix& linestyle_matrix) {
@@ -1664,7 +1636,7 @@ public:
       
       scanline_type sl;
       
-      draw_outlines_impl<scanline_type> (subshape_id, paths, agg_paths, 
+      draw_outlines_impl<scanline_type> (paths, agg_paths, 
         line_styles, cx, linestyle_matrix, sl);
         
     } else {
@@ -1675,7 +1647,7 @@ public:
       
       scanline_type sl(_alphaMasks.back().getMask());
       
-      draw_outlines_impl<scanline_type> (subshape_id, paths, agg_paths,
+      draw_outlines_impl<scanline_type> (paths, agg_paths,
         line_styles, cx, linestyle_matrix, sl);
         
     }
@@ -1685,7 +1657,7 @@ public:
 
   /// Template for draw_outlines(), see draw_shapes_impl().
   template <class scanline_type>
-  void draw_outlines_impl(int subshape_id, const GnashPaths &paths,
+  void draw_outlines_impl(const GnashPaths &paths,
     const AggPaths& agg_paths,
     const std::vector<LineStyle> &line_styles, const SWFCxForm& cx, 
     const SWFMatrix& linestyle_matrix, scanline_type& sl) {
@@ -1722,8 +1694,6 @@ public:
           
       applyClipBox<ras_type> (ras, *bounds);
       
-      int current_subshape=0;
-
       for (size_t pno=0, pcount=paths.size(); pno<pcount; ++pno) {
 
         const Path& this_path_gnash = paths[pno];
@@ -1731,14 +1701,6 @@ public:
         agg::path_storage &this_path_agg = 
           const_cast<agg::path_storage&>(agg_paths[pno]);
         
-        if (this_path_gnash.m_new_shape)
-          ++current_subshape;
-          
-        if ((subshape_id>=0) && (current_subshape!=subshape_id)) {
-          // Skip this path as it is not part of the requested sub-shape.
-          continue;
-        }
-        
         if (this_path_gnash.m_line==0) {
           // Skip this path as it contains no line style
           continue;
@@ -1747,7 +1709,7 @@ public:
         agg::conv_curve< agg::path_storage > curve(this_path_agg); // to 
render curves
         agg::conv_stroke< agg::conv_curve < agg::path_storage > > 
           stroke(curve);  // to get an outline
-        
+
         const LineStyle& lstyle = line_styles[this_path_gnash.m_line-1];
           
         int thickness = lstyle.getThickness();
diff --git a/librender/cairo/Renderer_cairo.cpp 
b/librender/cairo/Renderer_cairo.cpp
index 99c1301..c597dd4 100644
--- a/librender/cairo/Renderer_cairo.cpp
+++ b/librender/cairo/Renderer_cairo.cpp
@@ -950,31 +950,6 @@ Renderer_cairo::draw_subshape(const PathVec& path_vec, 
const SWFMatrix& mat,
     draw_outlines(path_vec, line_styles, cx, mat);
 }
 
-
-std::vector<PathVec::const_iterator>
-Renderer_cairo::find_subshapes(const PathVec& path_vec)
-{
-    std::vector<PathVec::const_iterator> subshapes;
-    
-    PathVec::const_iterator it = path_vec.begin();
-    PathVec::const_iterator end = path_vec.end();
-    
-    subshapes.push_back(it);
-    ++it;
-
-    for (;it != end; ++it) {
-        const Path& cur_path = *it;
-  
-        if (cur_path.m_new_shape) {
-            subshapes.push_back(it); 
-        }  
-    } 
-  
-    subshapes.push_back(end);
-    
-    return subshapes;
-}
-
 void
 Renderer_cairo::draw_mask(const PathVec& path_vec)
 {    
@@ -1011,40 +986,23 @@ Renderer_cairo::apply_matrix_to_paths(std::vector<Path>& 
paths,
 void
 Renderer_cairo::drawShape(const SWF::ShapeRecord& shape, const Transform& 
xform)
 {
-    const PathVec& path_vec = shape.paths();
-    
-    if (!path_vec.size()) {
-        return;    
-    }
-    
     cairo_set_fill_rule(_cr, CAIRO_FILL_RULE_EVEN_ODD); // TODO: Move to init
-        
-    if (_drawing_mask) {      
-        PathVec scaled_path_vec = path_vec;
-        
-        apply_matrix_to_paths(scaled_path_vec, xform.matrix);
-        draw_mask(scaled_path_vec); 
-        return;
-    }
     
     CairoScopeMatrix mat_transformer(_cr, xform.matrix);
 
-    std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
-    
-    const std::vector<FillStyle>& FillStyles = shape.fillStyles();
-    const std::vector<LineStyle>& line_styles = shape.lineStyles();
+    for (SWF::ShapeRecord::Subshapes::const_iterator it = 
shape.subshapes().begin(),
+         end = shape.subshapes().end(); it != end; ++it) {
 
-    for (size_t i = 0; i < subshapes.size()-1; ++i) {
-        PathVec subshape_paths;
+        if (_drawing_mask) {      
+            PathVec scaled_path_vec = it->paths();
         
-        if (subshapes[i] != subshapes[i+1]) {
-            subshape_paths = PathVec(subshapes[i], subshapes[i+1]);
-        } else {
-            subshape_paths.push_back(*subshapes[i]);
+            apply_matrix_to_paths(scaled_path_vec, xform.matrix);
+            draw_mask(scaled_path_vec); 
+            continue;
         }
-        
-        draw_subshape(subshape_paths, xform.matrix, xform.colorTransform,
-                FillStyles, line_styles);
+
+        draw_subshape(it->paths(), xform.matrix, xform.colorTransform,
+                it->fillStyles(), it->lineStyles());
     }
 }
   
@@ -1052,14 +1010,18 @@ void
 Renderer_cairo::drawGlyph(const SWF::ShapeRecord& rec, const rgba& color,
                           const SWFMatrix& mat)
 {
+    if (rec.subshapes().empty() || rec.getBounds().is_null()) {
+        return;
+    }
+
     SWFCxForm dummy_cx;
     std::vector<FillStyle> glyph_fs;
     
     FillStyle coloring = FillStyle(SolidFill(color));
     
     glyph_fs.push_back(coloring);
-    
-    const PathVec& path_vec = rec.paths();
+
+    const PathVec& path_vec = rec.subshapes().front().paths();
     
     std::vector<LineStyle> dummy_ls;
     
diff --git a/librender/opengl/Renderer_ogl.cpp 
b/librender/opengl/Renderer_ogl.cpp
index a15057c..1d4102e 100644
--- a/librender/opengl/Renderer_ogl.cpp
+++ b/librender/opengl/Renderer_ogl.cpp
@@ -1256,7 +1256,7 @@ public:
     float prev_cx = cur_end.cp.x;
     float prev_cy = cur_end.cp.y;        
                 
-    Path newpath(cur_end.ap.x, cur_end.ap.y, cur_path.m_fill1, 
cur_path.m_fill0, cur_path.m_line, cur_path.m_new_shape);
+    Path newpath(cur_end.ap.x, cur_end.ap.y, cur_path.m_fill1, 
cur_path.m_fill0, cur_path.m_line);
     
     float prev_ax = cur_end.ap.x;
     float prev_ay = cur_end.ap.y; 
@@ -1629,32 +1629,6 @@ public:
   }
   
   
-  std::vector<PathVec::const_iterator>
-  find_subshapes(const PathVec& path_vec)
-  {
-    std::vector<PathVec::const_iterator> subshapes;
-    
-    PathVec::const_iterator it = path_vec.begin(),
-                            end = path_vec.end();
-    
-    subshapes.push_back(it);
-    ++it;
-
-    for (;it != end; ++it) {
-      const Path& cur_path = *it;
-    
-      if (cur_path.m_new_shape) {
-        subshapes.push_back(it); 
-      } 
-    }
-
-    if (subshapes.back() != end) {
-      subshapes.push_back(end);
-    }
-    
-    return subshapes;
-  }
-  
   /// Takes a path and translates it using the given SWFMatrix.
   void
   apply_matrix_to_paths(std::vector<Path>& paths, const SWFMatrix& mat)
@@ -1749,54 +1723,48 @@ public:
 
   virtual void drawShape(const SWF::ShapeRecord& shape, const Transform& xform)
   {
-  
-    const PathVec& path_vec = shape.paths();
-
-    if (!path_vec.size()) {
-      // No paths. Nothing to draw...
-      return;
+    if (shape.subshapes().empty()) {
+        return;
     }
     
-    if (_drawing_mask) {
-      PathVec scaled_path_vec = path_vec;
-      
-      apply_matrix_to_paths(scaled_path_vec, xform.matrix);
-      draw_mask(scaled_path_vec); 
-      return;
-    }    
+    oglScopeMatrix scope_mat(xform.matrix);
+
+    for (SWF::ShapeRecord::Subshapes::const_iterator it = 
shape.subshapes().begin(),
+         end = shape.subshapes().end(); it != end; ++it) {
+        const PathVec& path_vec = it->paths();
+
+        if (!path_vec.size()) {
+            // No paths. Nothing to draw...
+            return;
+        }
     
-    bool have_shape, have_outline;
+        if (_drawing_mask) {
+            PathVec scaled_path_vec = path_vec;
+      
+            apply_matrix_to_paths(scaled_path_vec, xform.matrix);
+            draw_mask(scaled_path_vec); 
+            continue;
+        }    
     
-    analyze_paths(path_vec, have_shape, have_outline);
+        bool have_shape, have_outline;
     
-    if (!have_shape && !have_outline) {
-      return; // invisible character
-    }    
+        analyze_paths(path_vec, have_shape, have_outline);
     
-    oglScopeMatrix scope_mat(xform.matrix);
+        if (!have_shape && !have_outline) {
+            continue; // invisible character
+        }  
 
-    std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
-    
-    const std::vector<FillStyle>& FillStyles = shape.fillStyles();
-    const std::vector<LineStyle>& line_styles = shape.lineStyles();
-    
-    for (size_t i = 0; i < subshapes.size()-1; ++i) {
-      PathVec subshape_paths;
-      
-      if (subshapes[i] != subshapes[i+1]) {
-        subshape_paths = PathVec(subshapes[i], subshapes[i+1]);
-      } else {
-        subshape_paths.push_back(*subshapes[i]);
-      }
-      
-      draw_subshape(subshape_paths, xform.matrix, xform.colorTransform,
-              FillStyles, line_styles);
+        draw_subshape(it->paths(), xform.matrix, xform.colorTransform,
+                      it->fillStyles(), it->lineStyles());
     }
   }
 
   virtual void drawGlyph(const SWF::ShapeRecord& rec, const rgba& c,
          const SWFMatrix& mat)
   {
+    if (rec.subshapes().empty()) {
+        return;
+    }
     if (_drawing_mask) abort();
     SWFCxForm dummy_cx;
     std::vector<FillStyle> glyph_fs;
@@ -1809,7 +1777,7 @@ public:
     
     oglScopeMatrix scope_mat(mat);
     
-    draw_subshape(rec.paths(), mat, dummy_cx, glyph_fs, dummy_ls);
+    draw_subshape(rec.subshapes().front().paths(), mat, dummy_cx, glyph_fs, 
dummy_ls);
   }
 
   virtual void set_scale(float xscale, float yscale) {

http://git.savannah.gnu.org/cgit//commit/?id=73da624b50cf46cba878143d7a2acf6f8b8de981


commit 73da624b50cf46cba878143d7a2acf6f8b8de981
Author: Bastiaan Jacques <address@hidden>
Date:   Wed Jul 31 22:52:15 2013 +0200

    Separate subshapes, so that renderers do not have to concern
    themselves with keeping track of them.

diff --git a/libcore/swf/ShapeRecord.cpp b/libcore/swf/ShapeRecord.cpp
index 5b74e85..dac29fd 100644
--- a/libcore/swf/ShapeRecord.cpp
+++ b/libcore/swf/ShapeRecord.cpp
@@ -138,7 +138,6 @@ private:
 
 } // anonymous namespace
 
-
 ShapeRecord::ShapeRecord(SWFStream& in, SWF::TagType tag, movie_definition& m,
         const RunResources& r)
 {
@@ -153,60 +152,73 @@ ShapeRecord::~ShapeRecord()
 {
 }
 
-ShapeRecord::ShapeRecord(const ShapeRecord& other)
-    :
-    _fillStyles(other._fillStyles),
-    _lineStyles(other._lineStyles),
-    _paths(other._paths),
-    _bounds(other._bounds)
-{
-}
-    
-ShapeRecord&
-ShapeRecord::operator=(const ShapeRecord& other)
-{
-    _fillStyles = other._fillStyles;
-    _lineStyles = other._lineStyles;
-    _paths = other._paths;
-    _bounds = other._bounds;
-    return *this;
-}
-
 void
 ShapeRecord::clear()
 {
-    _fillStyles.clear();
-    _lineStyles.clear();
-    _paths.clear();
     _bounds.set_null();
+    _subshapes.clear();
 }
 
 void
-ShapeRecord::addFillStyle(const FillStyle& fs)
+Subshape::addFillStyle(const FillStyle& fs)
 {
     _fillStyles.push_back(fs);
 }
 
+
+/// Find the bounds of this subhape, and return them in a rectangle.
+SWFRect
+Subshape::computeBounds(int swfVersion) const
+{
+    SWFRect bounds;
+
+    for (unsigned int i = 0; i < _paths.size(); i++) {
+        const Path& p = _paths[i];
+
+        unsigned thickness = 0;
+        if ( p.m_line ) {
+            // For glyph shapes m_line is allowed to be 1
+            // while no defined line styles are allowed.
+            if (lineStyles().empty()) {
+                // This is either a Glyph, for which m_line==1 is valid
+                // or a bug in the parser, which we have no way to
+                // check at this time
+                assert(p.m_line == 1);
+            }
+            else
+            {
+                thickness = lineStyles()[p.m_line-1].getThickness();
+            }
+        }
+        p.expandBounds(bounds, thickness, swfVersion);
+    }
+
+    return bounds;
+}
+
 void
-ShapeRecord::setLerp(const ShapeRecord& a, const ShapeRecord& b,
+ShapeRecord::setLerp(const ShapeRecord& aa, const ShapeRecord& bb,
         const double ratio)
 {
+       assert(_subshapes.size() == 1);
 
     // Update current bounds.
-    _bounds.set_lerp(a.getBounds(), b.getBounds(), ratio);
+    _bounds.set_lerp(aa.getBounds(), bb.getBounds(), ratio);
+    const Subshape& a = aa.subshapes().front();
+    const Subshape& b = bb.subshapes().front();
 
     // fill styles
     const FillStyles::const_iterator fs1 = a.fillStyles().begin();
     const FillStyles::const_iterator fs2 = b.fillStyles().begin();
 
-    std::for_each(_fillStyles.begin(), _fillStyles.end(),
+    std::for_each(_subshapes.front().fillStyles().begin(), 
_subshapes.front().fillStyles().end(),
             Lerp<FillStyles>(fs1, fs2, ratio));
 
     // line styles
     const LineStyles::const_iterator ls1 = a.lineStyles().begin();
     const LineStyles::const_iterator ls2 = b.lineStyles().begin();
 
-    std::for_each(_lineStyles.begin(), _lineStyles.end(),
+    std::for_each(_subshapes.front().lineStyles().begin(), 
_subshapes.front().lineStyles().end(),
             Lerp<LineStyles>(ls1, ls2, ratio));
 
     // This is used for cases in which number
@@ -218,8 +230,8 @@ ShapeRecord::setLerp(const ShapeRecord& a, const 
ShapeRecord& b,
     // shape
     const Paths& paths1 = a.paths();
     const Paths& paths2 = b.paths();
-    for (size_t i = 0, k = 0, n = 0; i < _paths.size(); i++) {
-        Path& p = _paths[i];
+    for (size_t i = 0, k = 0, n = 0; i < _subshapes.front().paths().size(); 
i++) {
+        Path& p = _subshapes.front().paths()[i];
         const Path& p1 = i < paths1.size() ? paths1[i] : empty_path;
         const Path& p2 = n < paths2.size() ? paths2[n] : empty_path;
 
@@ -251,7 +263,6 @@ ShapeRecord::setLerp(const ShapeRecord& a, const 
ShapeRecord& b,
             }
         }
     }
-
 }
 
 void
@@ -266,6 +277,14 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
                             tag == SWF::DEFINESHAPE4 ||
                             tag == SWF::DEFINESHAPE4_);
 
+    Subshape subshape;
+    if (!_subshapes.empty()) {
+       // This is a little naughty. In case we're reading DEFINEMORPH, we'll
+       // have been provided with styles, which are now copied....
+       subshape = _subshapes.front();
+       _subshapes.clear();
+    }
+
     if (styleInfo) {
         _bounds = readRect(in);
     
@@ -283,8 +302,8 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
             LOG_ONCE(log_unimpl("DEFINESHAPE4 edge boundaries and scales"));
         }
     
-        readFillStyles(_fillStyles, in, tag, m, r);
-        readLineStyles(_lineStyles, in, tag, m, r);
+        readFillStyles(subshape.fillStyles(), in, tag, m, r);
+        readLineStyles(subshape.lineStyles(), in, tag, m, r);
     }
 
     if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2 ) {
@@ -350,15 +369,17 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
             if (flags == SHAPE_END) {  
                 // Store the current path if any.
                 if (! current_path.empty()) {
-                    _paths.push_back(current_path);
+                    subshape.paths().push_back(current_path);
                     current_path.m_edges.resize(0);
+                    _subshapes.push_back(subshape);
+                    subshape.clear();
                 }
                 break;
             }
             if (flags & SHAPE_MOVE) {  
                 // Store the current path if any, and prepare a fresh one.
                 if (! current_path.empty()) {
-                    _paths.push_back(current_path);
+                    subshape.paths().push_back(current_path);
                     current_path.m_edges.resize(0);
                 }
                 in.ensureBits(5);
@@ -383,7 +404,7 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
             if ((flags & SHAPE_FILLSTYLE0_CHANGE) && num_fill_bits > 0) {
                 // FillStyle_0_change = 1;
                 if (! current_path.empty()) {
-                    _paths.push_back(current_path);
+                    subshape.paths().push_back(current_path);
                     current_path.m_edges.resize(0);
                     current_path.ap.x = x;
                     current_path.ap.y = y;
@@ -405,11 +426,11 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
                     }
                 } else {
                     // 1-based index
-                    if ( style > _fillStyles.size() ) {
+                    if ( style > subshape.fillStyles().size() ) {
                         IF_VERBOSE_MALFORMED_SWF(
                              log_swferror(_("Invalid fill style %d in "
                                      "fillStyle0Change record - %d defined. "
-                                     "Set to 0."), style, _fillStyles.size());
+                                     "Set to 0."), style, 
subshape.fillStyles().size());
                         );
                         style = 0;
                     }
@@ -426,7 +447,7 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
             if ((flags & SHAPE_FILLSTYLE1_CHANGE) && num_fill_bits > 0) {
                 // FillStyle_1_change = 1;
                 if (! current_path.empty()) {
-                    _paths.push_back(current_path);
+                    subshape.paths().push_back(current_path);
                     current_path.m_edges.resize(0);
                     current_path.ap.x = x;
                     current_path.ap.y = y;
@@ -448,11 +469,11 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
                     }
                 } else {
                     // 1-based index
-                    if ( style > _fillStyles.size() ) {
+                    if ( style > subshape.fillStyles().size() ) {
                         IF_VERBOSE_MALFORMED_SWF(
                             log_swferror(_("Invalid fill style %d in "
                                     "fillStyle1Change record - %d defined. "
-                                    "Set to 0."), style, _fillStyles.size());
+                                    "Set to 0."), style, 
subshape.fillStyles().size());
                         );
                         style = 0;
                     }
@@ -468,7 +489,7 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
             if ((flags & SHAPE_LINESTYLE_CHANGE) && num_line_bits > 0) {
                 // line_style_change = 1;
                 if (! current_path.empty()) {
-                    _paths.push_back(current_path);
+                    subshape.paths().push_back(current_path);
                     current_path.m_edges.resize(0);
                     current_path.ap.x = x;
                     current_path.ap.y = y;
@@ -489,11 +510,11 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
                     }
                 } else {
                     // 1-based index
-                    if (style > _lineStyles.size()) {
+                    if (style > subshape.lineStyles().size()) {
                         IF_VERBOSE_MALFORMED_SWF(
                             log_swferror(_("Invalid fill style %d in "
                                     "lineStyleChange record - %d defined. "
-                                    "Set to 0."), style, _lineStyles.size());
+                                    "Set to 0."), style, 
subshape.lineStyles().size());
                         );
                         style = 0;
                     }
@@ -520,20 +541,15 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
     
                 // Store the current path if any.
                 if (! current_path.empty()) {
-                    _paths.push_back(current_path);
+                    subshape.paths().push_back(current_path);
                     current_path.clear();
                 }
     
-                // Tack on an empty path signalling a new shape.
-                // @@ need better understanding of whether this is 
correct??!?!!
-                // @@ i.e., we should just start a whole new shape here, right?
-                _paths.push_back(Path());
-                _paths.back().m_new_shape = true;
+                _subshapes.push_back(subshape);
+                subshape.clear();
     
-                fill_base = _fillStyles.size();
-                line_base = _lineStyles.size();
-                readFillStyles(_fillStyles, in, tag, m, r);
-                readLineStyles(_lineStyles, in, tag, m, r);
+                readFillStyles(subshape.fillStyles(), in, tag, m, r);
+                readLineStyles(subshape.lineStyles(), in, tag, m, r);
     
                 in.ensureBits(8);
                 num_fill_bits = in.read_uint(4);
@@ -605,7 +621,12 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, 
movie_definition& m,
     if (!styleInfo) {
         // TODO: performance would be improved by computing
         //       the bounds as edges are parsed.
-        computeBounds(_bounds, _paths, _lineStyles, m.get_version());
+       _bounds.set_null();
+       for (Subshapes::const_iterator it = _subshapes.begin(),
+                       end = _subshapes.end(); it != end; ++it) {
+            SWFRect bounds = it->computeBounds(m.get_version());
+            _bounds.expand_to_rect(bounds);
+       }
     }
 
 #ifdef GNASH_DEBUG_SHAPE_BOUNDS
@@ -680,34 +701,6 @@ readLineStyles(ShapeRecord::LineStyles& styles, SWFStream& 
in,
     }
 }
 
-// Find the bounds of this shape, and store them in the given rectangle.
-void
-computeBounds(SWFRect& bounds, const ShapeRecord::Paths& paths,
-        const ShapeRecord::LineStyles& lineStyles, int swfVersion)
-{
-    bounds.set_null();
-
-    for (unsigned int i = 0; i < paths.size(); i++) {
-        const Path& p = paths[i];
-
-        unsigned thickness = 0;
-        if ( p.m_line ) {
-            // For glyph shapes m_line is allowed to be 1
-            // while no defined line styles are allowed.
-            if (lineStyles.empty()) {
-                // This is either a Glyph, for which m_line==1 is valid
-                // or a bug in the parser, which we have no way to
-                // check at this time
-                assert(p.m_line == 1);
-            }
-            else
-            {
-                thickness = lineStyles[p.m_line-1].getThickness();
-            }
-        }
-        p.expandBounds(bounds, thickness, swfVersion);
-    }
-}
 
 
 } // anonymous namespace
@@ -717,9 +710,14 @@ operator<<(std::ostream& o, const ShapeRecord& sh)
 {
     o << boost::format("Shape Record: bounds %1%") % sh.getBounds();
 
-    const ShapeRecord::FillStyles& fills = sh.fillStyles();
-    std::copy(fills.begin(), fills.end(),
-            std::ostream_iterator<FillStyle>(o, ","));
+
+    for (ShapeRecord::Subshapes::const_iterator it = sh.subshapes().begin(),
+         end = sh.subshapes().end(); it != end; ++it) {
+
+        const ShapeRecord::FillStyles& fills = it->fillStyles();
+        std::copy(fills.begin(), fills.end(),
+                std::ostream_iterator<FillStyle>(o, ","));
+       }
 
     return o;
 }
diff --git a/libcore/swf/ShapeRecord.h b/libcore/swf/ShapeRecord.h
index b43cb58..2d9be20 100644
--- a/libcore/swf/ShapeRecord.h
+++ b/libcore/swf/ShapeRecord.h
@@ -22,6 +22,7 @@
 
 #include "Geometry.h"
 #include "LineStyle.h"
+#include "FillStyle.h"
 #include "SWFRect.h"
 
 #include <vector>
@@ -30,12 +31,78 @@
 namespace gnash {
     class movie_definition;
     class RunResources;
-    class FillStyle;
 }
 
 namespace gnash {
 namespace SWF {
 
+
+
+class Subshape {
+
+public:
+    typedef std::vector<FillStyle> FillStyles;
+    typedef std::vector<LineStyle> LineStyles;
+    typedef std::vector<Path> Paths;
+
+    const FillStyles& fillStyles() const {
+        return _fillStyles;
+    }
+
+    FillStyles& fillStyles() {
+        return _fillStyles;
+    }
+
+    const LineStyles& lineStyles() const {
+        return _lineStyles;
+    }
+
+    LineStyles& lineStyles() {
+        return _lineStyles;
+    }
+
+    const Paths& paths() const {
+        return _paths;
+    }
+
+    Paths& paths() {
+        return _paths;
+    }
+
+    /// For DynamicShape
+    //
+    /// TODO: rewrite DynamicShape to push paths when they're
+    /// finished and drop this.
+    Path& currentPath() {
+        return _paths.back();
+    }
+
+    void addFillStyle(const FillStyle& fs);
+
+    void addPath(const Path& path) {
+        _paths.push_back(path);
+    }
+
+    void addLineStyle(const LineStyle& ls) {
+        _lineStyles.push_back(ls);
+    }
+
+    void clear() {
+       _fillStyles.clear();
+       _lineStyles.clear();
+       _paths.clear();
+    }
+
+    SWFRect computeBounds(int swfVersion) const;
+
+private:
+    FillStyles _fillStyles;
+    LineStyles _lineStyles;
+    Paths _paths;
+};
+
+
+
 /// Holds information needed to draw a shape.
 //
 /// This does not correspond exactly to parsed record in a SWF file, but
@@ -49,13 +116,20 @@ namespace SWF {
 //
 /// ShapeRecord objects are not ref-counted, so they may be stack-allocated
 /// or used in smart pointers.
+//
+/// A shape can have sub-shapes. This can happen when there are multiple
+/// layers of the same frame count. Flash combines them to one single shape.
+/// The problem with sub-shapes is, that outlines can be hidden by other
+/// layers so they must be rendered separately. In order to be sure outlines
+/// are show correctly, draw the subshapes contained in the ShapeRecord in
+/// sequence.
 class ShapeRecord
 {
 public:
-
-    typedef std::vector<FillStyle> FillStyles;
-    typedef std::vector<LineStyle> LineStyles;
-    typedef std::vector<Path> Paths;
+    typedef Subshape::FillStyles FillStyles;
+    typedef Subshape::LineStyles LineStyles;
+    typedef Subshape::Paths Paths;
+    typedef std::vector<Subshape> Subshapes;
 
     /// Construct a ShapeRecord.
     //
@@ -71,11 +145,6 @@ public:
     ShapeRecord(SWFStream& in, SWF::TagType tag, movie_definition& m,
             const RunResources& r);
 
-    /// Copy constructor
-    ShapeRecord(const ShapeRecord& other);
-    
-    /// Assignment operator
-    ShapeRecord& operator=(const ShapeRecord& other);
 
     ~ShapeRecord();
 
@@ -86,30 +155,18 @@ public:
     void read(SWFStream& in, SWF::TagType tag, movie_definition& m,
             const RunResources& r);
 
-    const FillStyles& fillStyles() const {
-        return _fillStyles;
-    }
-    
-    const LineStyles& lineStyles() const {
-        return _lineStyles;
+    const Subshapes& subshapes() const {
+       return _subshapes;
     }
 
-    const Paths& paths() const {
-        return _paths;
+    void addSubshape(const Subshape& subshape) {
+       _subshapes.push_back(subshape);
     }
 
     const SWFRect& getBounds() const {
         return _bounds;
     }
 
-    /// For DynamicShape
-    //
-    /// TODO: rewrite DynamicShape to push paths when they're
-    /// finished and drop this.
-    Path& currentPath() {
-        return _paths.back();
-    }
-
     /// Set to the lerp of two ShapeRecords.
     //
     /// Used in shape morphing.
@@ -119,18 +176,20 @@ public:
     /// Reset all shape data.
     void clear();
 
-    void addFillStyle(const FillStyle& fs);
-
-    void addPath(const Path& path) {
-        _paths.push_back(path);
+    void setBounds(const SWFRect& bounds) {
+        _bounds = bounds;
     }
 
-    void addLineStyle(const LineStyle& ls) {
-        _lineStyles.push_back(ls);
-    }
+    bool pointTest(boost::int32_t x, boost::int32_t y,
+                   const SWFMatrix& wm) const {
+        for (SWF::ShapeRecord::Subshapes::const_iterator it = 
_subshapes.begin(),
+             end = _subshapes.end(); it != end; ++it) {
 
-    void setBounds(const SWFRect& bounds) {
-        _bounds = bounds;
+            if (geometry::pointTest(it->paths(), it->lineStyles(), x, y, wm)) {
+                   return true;
+            }
+        }
+        return false;
     }
 
 private:
@@ -144,12 +203,9 @@ private:
         SHAPE_LINESTYLE_CHANGE = 0x08,
         SHAPE_HAS_NEW_STYLES = 0x10
     };
-    
-    FillStyles _fillStyles;
-    LineStyles _lineStyles;
-    Paths _paths;
-    SWFRect _bounds;
 
+    SWFRect _bounds;
+    Subshapes _subshapes;
 };
 
 std::ostream& operator<<(std::ostream& o, const ShapeRecord& sh);

-----------------------------------------------------------------------

Summary of changes:
 libcore/Bitmap.cpp                  |    3 +-
 libcore/DynamicShape.cpp            |   47 +++++++---
 libcore/DynamicShape.h              |    7 +-
 libcore/FreetypeGlyphsProvider.cpp  |   12 ++-
 libcore/Geometry.cpp                |   11 ---
 libcore/Geometry.h                  |   32 +------
 libcore/MorphShape.cpp              |    3 +-
 libcore/swf/DefineMorphShapeTag.cpp |   21 +++--
 libcore/swf/DefineShapeTag.cpp      |    2 +-
 libcore/swf/ShapeRecord.cpp         |  170 +++++++++++++++++------------------
 libcore/swf/ShapeRecord.h           |  136 ++++++++++++++++++++--------
 librender/agg/Renderer_agg.cpp      |  106 +++++++---------------
 librender/cairo/Renderer_cairo.cpp  |   70 ++++-----------
 librender/opengl/Renderer_ogl.cpp   |   94 +++++++-------------
 14 files changed, 326 insertions(+), 388 deletions(-)


hooks/post-receive
-- 
Gnash



reply via email to

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