1 //
2 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 //   Free Software Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 //
19 
20 #ifndef GNASH_SWF_SHAPERECORD_H
21 #define GNASH_SWF_SHAPERECORD_H
22 
23 #include "Geometry.h"
24 #include "LineStyle.h"
25 #include "FillStyle.h"
26 #include "SWFRect.h"
27 
28 #include <vector>
29 
30 
31 namespace gnash {
32     class movie_definition;
33     class RunResources;
34 }
35 
36 namespace gnash {
37 namespace SWF {
38 
39 
40 
41 class Subshape {
42 
43 public:
44     typedef std::vector<FillStyle> FillStyles;
45     typedef std::vector<LineStyle> LineStyles;
46     typedef std::vector<Path> Paths;
47 
fillStyles()48     const FillStyles& fillStyles() const {
49         return _fillStyles;
50     }
51 
fillStyles()52     FillStyles& fillStyles() {
53         return _fillStyles;
54     }
55 
lineStyles()56     const LineStyles& lineStyles() const {
57         return _lineStyles;
58     }
59 
lineStyles()60     LineStyles& lineStyles() {
61         return _lineStyles;
62     }
63 
paths()64     const Paths& paths() const {
65         return _paths;
66     }
67 
paths()68     Paths& paths() {
69         return _paths;
70     }
71 
72     /// For DynamicShape
73     //
74     /// TODO: rewrite DynamicShape to push paths when they're
75     /// finished and drop this.
currentPath()76     Path& currentPath() {
77         return _paths.back();
78     }
79 
80     void addFillStyle(const FillStyle& fs);
81 
addPath(const Path & path)82     void addPath(const Path& path) {
83         _paths.push_back(path);
84     }
85 
addLineStyle(const LineStyle & ls)86     void addLineStyle(const LineStyle& ls) {
87         _lineStyles.push_back(ls);
88     }
89 
clear()90     void clear() {
91     	_fillStyles.clear();
92     	_lineStyles.clear();
93     	_paths.clear();
94     }
95 
96     SWFRect computeBounds(int swfVersion) const;
97 
98 private:
99     FillStyles _fillStyles;
100     LineStyles _lineStyles;
101     Paths _paths;
102 };
103 
104 
105 
106 /// Holds information needed to draw a shape.
107 //
108 /// This does not correspond exactly to parsed record in a SWF file, but
109 /// is used to create both mutable and immutable shapes.
110 //
111 /// A ShapeRecord should have enough methods to implement the AS3 Graphics
112 /// object (the drawing API of Shape and Sprite). This is restricted to
113 /// adding fills, paths and line styles (which must be constructed outside
114 /// this ShapeRecord before being added) and clearing everything. There
115 /// is no support for removing single elements.
116 //
117 /// ShapeRecord objects are not ref-counted, so they may be stack-allocated
118 /// or used in smart pointers.
119 //
120 /// A shape can have sub-shapes. This can happen when there are multiple
121 /// layers of the same frame count. Flash combines them to one single shape.
122 /// The problem with sub-shapes is, that outlines can be hidden by other
123 /// layers so they must be rendered separately. In order to be sure outlines
124 /// are show correctly, draw the subshapes contained in the ShapeRecord in
125 /// sequence.
126 class ShapeRecord
127 {
128 public:
129     typedef Subshape::FillStyles FillStyles;
130     typedef Subshape::LineStyles LineStyles;
131     typedef Subshape::Paths Paths;
132     typedef std::vector<Subshape> Subshapes;
133 
134     /// Construct a ShapeRecord.
135     //
136     /// This should only really be used for DynamicShapes.
137     //
138     /// Ideally all immutable ShapeRecords should be constructed with the
139     /// ctor taking an SWFStream, but some tag formats do not allow this.
140     ShapeRecord();
141 
142     /// Construct a ShapeRecord from a SWFStream.
143     //
144     /// This is useful for constructing immutable tags.
145     ShapeRecord(SWFStream& in, SWF::TagType tag, movie_definition& m,
146             const RunResources& r);
147 
148 
149     ~ShapeRecord();
150 
151     /// Parse path data from a SWFStream.
152     //
153     /// This is used by DefineMorphShapeTag as part of parsing its
154     /// more complex ShapeRecords.
155     void read(SWFStream& in, SWF::TagType tag, movie_definition& m,
156             const RunResources& r);
157 
subshapes()158     const Subshapes& subshapes() const {
159     	return _subshapes;
160     }
161 
addSubshape(const Subshape & subshape)162     void addSubshape(const Subshape& subshape) {
163     	_subshapes.push_back(subshape);
164     }
165 
getBounds()166     const SWFRect& getBounds() const {
167         return _bounds;
168     }
169 
170     /// Set to the lerp of two ShapeRecords.
171     //
172     /// Used in shape morphing.
173     void setLerp(const ShapeRecord& a, const ShapeRecord& b,
174             const double ratio);
175 
176     /// Reset all shape data.
177     void clear();
178 
setBounds(const SWFRect & bounds)179     void setBounds(const SWFRect& bounds) {
180         _bounds = bounds;
181     }
182 
pointTest(std::int32_t x,std::int32_t y,const SWFMatrix & wm)183     bool pointTest(std::int32_t x, std::int32_t y,
184                    const SWFMatrix& wm) const {
185         for (const Subshape& subshape : _subshapes) {
186 
187             if (geometry::pointTest(subshape.paths(), subshape.lineStyles(), x, y, wm)) {
188         	    return true;
189             }
190         }
191         return false;
192     }
193 
194 private:
195 
196     unsigned readStyleChange(SWFStream& in, size_t num_fill_bits, size_t numStyles);
197 
198     /// Shape record flags for use in parsing.
199     enum ShapeRecordFlags {
200         SHAPE_END = 0x00,
201         SHAPE_MOVE = 0x01,
202         SHAPE_FILLSTYLE0_CHANGE = 0x02,
203         SHAPE_FILLSTYLE1_CHANGE = 0x04,
204         SHAPE_LINESTYLE_CHANGE = 0x08,
205         SHAPE_HAS_NEW_STYLES = 0x10
206     };
207 
208     SWFRect _bounds;
209     Subshapes _subshapes;
210 };
211 
212 std::ostream& operator<<(std::ostream& o, const ShapeRecord& sh);
213 
214 } // namespace SWF
215 } // namespace gnash
216 
217 #endif
218