1 /* libsswf_tag_sprite.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2008 */
2 
3 /*
4 
5 Copyright (c) 2002-2008 Made to Order Software Corp.
6 
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16 
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31 
32 */
33 
34 /** \file
35  *
36  * \brief The implementation of the sswf::TagSprite class
37  *
38  * This file declares the body of the functions which are not
39  * inline. It is part of the SSWF library.
40  */
41 
42 #include	"sswf/libsswf.h"
43 
44 using namespace sswf;
45 
46 
47 
48 /////////////////////////////////////////// TagSprite
49 
50 /** \class sswf::TagSprite
51  *
52  * \brief Group shapes, sprites, texts, buttons, sound, etc.
53  *
54  * The TagSprite is the SWF object used to group other objects
55  * in one single entity. The sprite is given an ID which can
56  * later be used to display the sprite.
57  *
58  * A sprite can be viewed as a group, though it only includes
59  * a set of control tags used to define a display list.
60  *
61  * For instance, to include a TagSprite inside another TagSprite
62  * you actually need to use a TagPlace which reference the
63  * TagSprite to be inserted.
64  *
65  * There is one special case sprite: the empty sprite. This is
66  * required if you want to use the CreateEmptyMovie() function
67  * in some ActionScript!
68  *
69  * Since version 1.8.0, a Sprite derives from the sswf::TagScalingGrid.
70  * This means you can define a scaling rectangle with a call
71  * to the
72  * void sswf::TagScalingGrid::SetGrid(const SRectangle& rect)
73  * function.
74  *
75  * \sa <a href="../SWFalexref.html#tag_definesprite">SWF Alexis' Reference&mdash;Define Sprite</a>
76  * \sa <a href="../SWFalexref.html#swf_tag">SWF Alexis' Reference&mdash;swf_tag</a>
77  */
78 
79 
80 /** \brief Initialize a sprite
81  *
82  * By default, a TagSprite is created empty. You can
83  * add objects using the Sprite object as the parent
84  * of other objects (instead of the TagHeader.)
85  */
TagSprite(TagBase * parent)86 TagSprite::TagSprite(TagBase *parent)
87 	: TagBaseID("sprite", parent)
88 {
89 }
90 
91 
92 
93 /** \brief Returns the flags defining a TagSprite object
94  *
95  * A Sprite is a definition, it includes references to
96  * other objects, it accept scripts, it is a sprite
97  * and it has an identifier.
98  *
99  * \return The set of flags that the TagSprite support
100  */
TypeFlags(void) const101 TagBase::swf_type_t TagSprite::TypeFlags(void) const
102 {
103 	return SWF_TYPE_DEFINE | SWF_TYPE_REFERENCE | SWF_TYPE_SCRIPT | SWF_TYPE_SPRITE | SWF_TYPE_HAS_ID;
104 }
105 
106 
107 /** \brief Check that the child is valid for a TagSprite
108  *
109  * A sswf::TagSprite accepts only a few control tags as defined in
110  * <a href="../SWFalexref.html#tag_definesprite">my reference</a>.
111  *
112  * This function returns an error if the child is not one of these
113  * control tags:
114  *
115  *	\li TagDoAction
116  *	\li TagEnd
117  *	\li TagFrameLabel
118  *	\li TagPlace
119  *	\li TagRemove
120  *	\li TagShowFrame
121  *	\li TagSoundStream [not implemented]
122  *	\li TagStartSound
123  *
124  * \param child_name The name of the child to be added to this parent
125  *
126  * \return An error code: ErrorManager::ERROR_CODE_NONE or
127  *		ErrorManager::ERROR_CODE_INCOMPATIBLE_CHILD
128  *
129  * \sa sswf::TagBase::OnNewChild(const char *child)
130  * \sa sswf::TagSprite::OnNewChild(const char *child)
131  */
OnNewChild(const char * child_name) const132 ErrorManager::error_code_t TagSprite::OnNewChild(const char *child_name) const
133 {
134 	if(strcmp(child_name, "doaction") == 0
135 	|| strcmp(child_name, "end") == 0
136 	|| strcmp(child_name, "framelabel") == 0
137 	|| strcmp(child_name, "place") == 0
138 	|| strcmp(child_name, "remove") == 0
139 	|| strcmp(child_name, "showframe") == 0
140 	|| strcmp(child_name, "soundstream") == 0	// Not yet implemented
141 	|| strcmp(child_name, "startsound") == 0) {
142 		// valid for a sprite!
143 		return ErrorManager::ERROR_CODE_NONE;
144 	}
145 
146 	// a sprite doesn't like those!
147 	return ErrorManager::ERROR_CODE_INCOMPATIBLE_CHILD;
148 }
149 
150 
151 
152 /** \brief Defines the minimum version necessary to save this sprite
153  *
154  * Sprites appeared in version 3 of SWF.
155  *
156  * Since version 8 of SWF, it is possible to attached a scaling grid
157  * to a sprite (by referencing the sprite in the scaling grid.)
158  *
159  * When no grid is defined, then a version 3 movie is sufficient.
160  *
161  * When a grid is defined, then a version 8 or better is required.
162  */
PreSave(void)163 ErrorManager::error_code_t TagSprite::PreSave(void)
164 {
165 	ErrorManager::error_code_t	r;
166 
167 	MinimumVersion(3);
168 
169 	r = GridPreSave();
170 	if(r != 0) {
171 		return r;
172 	}
173 
174 	return TagBase::PreSave();
175 }
176 
177 
178 /** \brief Save a Sprite control list
179  *
180  * This function saves all the children defined in this sprite,
181  * the Sprite header and when the user did not specify them, the
182  * TagShowFrame and TagEnd at the end of the list.
183  *
184  * \warning
185  * The size of the sub-list of tags within a sprite is limited
186  * to 64Kb.
187  *
188  * \param data The Data buffer in which the sprite is to be saved
189  *
190  * \return An error manager code
191  */
Save(Data & data)192 ErrorManager::error_code_t TagSprite::Save(Data& data)
193 {
194 	TagBase				*child, *last;
195 	Data				sub_data;
196 	ErrorManager::error_code_t	ec;
197 
198 // reset the counter in case the user saves multiple times
199 	ResetFrames();
200 
201 	SaveID(sub_data);
202 	sub_data.PutShort(1);		// the frame counter (undefined at this point)
203 		// Note: I use a default of 1 so that way I do not have to fix this
204 		//	 number is case you are creating an empty sprite!
205 
206 // save all the children first
207 	last = 0;
208 	child = Children();
209 	while(child != 0) {
210 		ec = child->Save(sub_data);
211 		if(ec != ErrorManager::ERROR_CODE_NONE) {
212 			return ec;
213 		}
214 		last = child;
215 		child = child->Next();
216 	}
217 
218 // there is nothing in there?!?
219 	if(last == 0) {
220 		// this is a valid case to create objects in your
221 		// actionscripts (see the assembler)
222 		sub_data.PutShort(SWF_TAG_END);
223 		SaveTag(data, SWF_TAG_DEFINE_SPRITE, sub_data.ByteSize());
224 		data.Append(sub_data);
225 		return GridSave(data, Identification());
226 	}
227 
228 // add the SHOW FRAME and END tags so it works properly with any player
229 	// NOTE: if the list ends with and "end" but not "show frame" then there
230 	//       simply won't be any "show frame".
231 	if(strcmp(last->Name(), "end") != 0) {
232 		if(strcmp(last->Name(), "showframe") != 0) {
233 			ShowFrame();
234 			SaveTag(sub_data, SWF_TAG_SHOW_FRAME, 0);
235 		}
236 		sub_data.PutShort(SWF_TAG_END);
237 	}
238 
239 	// write the frame count after the sprite ID
240 	sub_data.OverwriteShort(sizeof(sswf_id_t), FrameCount());
241 
242 	SaveTag(data, SWF_TAG_DEFINE_SPRITE, sub_data.ByteSize());
243 	data.Append(sub_data);
244 
245 // now we can save our grid if any
246 	return GridSave(data, Identification());
247 }
248 
249 
250 
251 
252 /* The following options fold the documentation; use 'zi' to turn on and off
253  *
254  * vim: foldexpr=getline(v\:lnum)!~'^/\\*\\*'&&getline(v\:lnum)!~'^\ \\*'?0\:1 foldcolumn=2 foldmethod=expr
255  */
256