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