KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openlaszlo > iv > flash > api > Instance


1 /*
2  * $Id: Instance.java,v 1.2 2002/02/15 23:44:27 skavish Exp $
3  *
4  * ==========================================================================
5  *
6  * The JGenerator Software License, Version 1.0
7  *
8  * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if
22  * any, must include the following acknowlegement:
23  * "This product includes software developed by Dmitry Skavish
24  * (skavish@usa.net, http://www.flashgap.com/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The name "The JGenerator" must not be used to endorse or promote
29  * products derived from this software without prior written permission.
30  * For written permission, please contact skavish@usa.net.
31  *
32  * 5. Products derived from this software may not be called "The JGenerator"
33  * nor may "The JGenerator" appear in their names without prior written
34  * permission of Dmitry Skavish.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
40  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  *
49  */

50
51 package org.openlaszlo.iv.flash.api;
52
53 import java.awt.geom.*;
54
55 import java.io.PrintStream JavaDoc;
56 import org.openlaszlo.iv.flash.parser.*;
57 import org.openlaszlo.iv.flash.util.*;
58 import org.openlaszlo.iv.flash.api.action.*;
59 import org.openlaszlo.iv.flash.commands.*;
60 import org.openlaszlo.iv.flash.context.Context;
61
62 /**
63  * Instance of flash definition
64  * <P>
65  * This object represents flash file format's PlaceObject2 as well as PlaceObject tags.
66  * <P>
67  * PlaceObject2 can both add a character to the display list, and modify the attributes of a
68  * character that is already on the display list.
69  * <p>
70  * The tag begins with a group of flags that indicate which fields are present in the tag.
71  * The optional fields are <code>def</code>, <code>matrix</code>, <code>cxform</code>,
72  * <code>ratio</code>, <code>clip</code> and <code>name</code>.
73  * The <code>depth</code> field is the only field that is always required.
74  * <p>
75  * The depth value determines the stacking order of the character. Characters with lower depth values
76  * are displayed underneath characters with higher depth values. A depth value of 1 means the character
77  * is displayed at the bottom of the stack. There can be only one character at any given depth.
78  * This means a character that is already on the display list can be identified by its depth alone.
79  * (i.e. a <code>def</code> is not required).
80  * <p>
81  * Flag Move and flag HasCharacter indicate whether a new character is being added to the display list,
82  * or a character already on the display list is being modified. The meaning of the flags is as follows:<br>
83  * <ul>
84  * <li> PlaceFlagMove = 0 and PlaceFlagHasCharacter = 1<br>
85  * A new character (with ID of CharacterId) is placed on the display list at the specified Depth.
86  * Other fields set the attributes of this new character.
87  * <li> PlaceFlagMove = 1 and PlaceFlagHasCharacter = 0<br>
88  * The character at the specified Depth is modified. Other fields modify the attributes of this character.
89  * Because there can be only one character at any given depth, no CharacterId is required.
90  * <li> PlaceFlagMove = 1 and PlaceFlagHasCharacter = 1<br>
91  * The character at the specified Depth is removed, and a new character (with ID of CharacterId) is
92  * placed at that depth. Other fields set the attributes of this new character.
93  * </ul>
94  * <p>
95  * The optional fields in PlaceObject2 have the following meaning:<br>
96  * <ul>
97  * <li>The <code>def</code> field specifies the character to be added to the display list.
98  * It only used only when a new character is being added. If a character that is already on
99  * the display list is being modified, the <code>def</code> field is absent.
100  * <li>The <code>matrix</code> field specifies the position, scale and rotation of the character being added or modified.
101  * <li>The <code>cxform</code> field specifies the color effect applied to the character being added or modified.
102  * <li>The <code>ratio</code> field specifies a morph ratio for the character being added or modified.
103  * This field applies only to characters defined with DefineMorphShape,
104  * and controls how far the morph has progressed.
105  * A ratio of zero displays the character at the start of the morph. A ratio of 65535 displays the character
106  * at the end of the morph. For values between zero and 65535 the player interpolates between the start and end
107  * shapes, and displays an 'in-between' shape.
108  * <li>The <code>clip</code> field specifies the top-most depth that will be masked by the character being added.
109  * A clip of zero indicates no clipping.
110  * <li>The <code>name</code> field specifies a name for the character being added or modified. This field is typically used
111  * with sprite characters, and is used to identify the sprite for SetTarget actions.
112  * It allows the main movie (or other sprites) to perform actions inside the sprite.
113  * </ul>
114  *
115  * @author Dmitry Skavish
116  * @see RemoveObject
117  */

118 public class Instance extends FlashObject {
119
120     public static final int HAS_CLIPACTIONS = 0x80;
121     public static final int HAS_CLIP = 0x40;
122     public static final int HAS_NAME = 0x20;
123     public static final int HAS_RATIO = 0x10;
124     public static final int HAS_COLOR_TRANSF = 0x08;
125     public static final int HAS_MATRIX = 0x04;
126     public static final int HAS_CHARACTER = 0x02;
127     public static final int MOVE = 0x01;
128
129     /**
130      * true if this instance just for changing an object properties,
131      * such as transformation etc.
132      */

133     public boolean isMove;
134
135     /**
136      * Transformation matrix
137      */

138     public AffineTransform matrix;
139
140     /**
141      * Color transformation matrix or null
142      */

143     public CXForm cxform;
144
145     /**
146      * Morphing ratio or -1
147      */

148     public int ratio = -1;
149
150     /**
151      * Clip layer number or -1
152      */

153     public int clip = -1;
154
155     /**
156      * Layer depth
157      */

158     public int depth;
159
160     /**
161      * Instance name or null
162      */

163     public String JavaDoc name;
164
165     /**
166      * Flash definition or null
167      */

168     public FlashDef def;
169
170     /**
171      * Clip actions or null
172      */

173     public ClipActions actions;
174
175     /**
176      * Generator command applied to this instance or null
177      */

178     public GenericCommand command;
179
180     public Instance() {}
181
182     public int getTag() {
183         return Tag.PLACEOBJECT2;
184     }
185
186     /**
187      * Parses PlaceObject tag
188      *
189      * @param p parser
190      * @return parser tag
191      */

192     public static Instance parse( Parser p ) {
193         Instance o = new Instance();
194         o.def = p.getDef(p.getUWord());
195         o.depth = p.getUWord();
196         o.matrix = p.getMatrix();
197         if( p.getPos() < p.getTagEndPos() ) {
198             o.cxform = CXForm.parse(p,false);
199         }
200         return o;
201     }
202
203     /**
204      * Parses PlaceObject2 tag
205      *
206      * @param p parser
207      * @return parser tag
208      */

209     public static Instance parse2( Parser p ) {
210         Instance o = new Instance();
211         int flags = p.getUByte();
212         o.depth = p.getUWord();
213         if( (flags&HAS_CHARACTER) != 0 ) {
214             o.def = p.getDef(p.getUWord());
215         }
216         if( (flags&HAS_MATRIX) != 0 ) {
217             o.matrix = p.getMatrix();
218         }
219         if( (flags&HAS_COLOR_TRANSF) != 0 ) {
220             o.cxform = CXForm.parse(p, true);
221         }
222         if( (flags&HAS_RATIO) != 0 ) {
223             o.ratio = p.getUWord();
224         }
225         if( (flags&HAS_CLIP) != 0 ) {
226             o.clip = p.getUWord();
227         }
228         if( (flags&HAS_NAME) != 0 ) {
229             o.name = p.getString();
230         }
231         if( (flags&HAS_CLIPACTIONS) != 0 ) {
232             o.actions = ClipActions.parse(p);
233         }
234         o.isMove = (flags&MOVE) != 0;
235         return o;
236     }
237
238
239     /**
240      * Returns true if this is instance of a script
241      *
242      * @return true if this is instance of a script
243      */

244     public boolean isScript() {
245         return def instanceof Script;
246     }
247
248     /**
249      * Returns flash definition as a Script
250      *
251      * @return definition as a Script
252      */

253     public Script getScript() {
254         return (Script) def;
255     }
256
257     /**
258      * Sets specified script as flash definition of this instance
259      *
260      * @param script specified script
261      * @return specified script
262      */

263     public Script setScript( Script script ) {
264         def = script;
265         return script;
266     }
267
268     /**
269      * Makes a copy of a script which is the flash definition of this instance
270      *
271      * @return copy of the script
272      */

273     public Script copyScript() {
274         def = ((Script)def).copyScript();
275         return (Script) def;
276     }
277
278     /**
279      * Return true if there is generator command attached to this instance
280      *
281      * @return true if there is generator command attached to this instance
282      */

283     public boolean isCommand() {
284         return command != null;
285     }
286
287     /**
288      * Attaches generator command to this instance
289      *
290      * @param command generator command to be attached
291      */

292     public void setCommand( GenericCommand command ) {
293         this.command = command;
294     }
295
296     /**
297      * Returns attached generator command
298      *
299      * @return attached generator command
300      */

301     public GenericCommand getCommand() {
302         return command;
303     }
304
305     /**
306      * Returns first nested non-script of this instance
307      * and its transformation matrix beginning from this instance
308      *
309      * @param m collect transformations in this matrix
310      * @return first nested non-script
311      */

312     public FlashDef getFirstNestedFlashDef( AffineTransform m ) {
313         if( def == null ) return null;
314
315         if( matrix != null ) m.concatenate(matrix);
316
317         if( def instanceof Script ) {
318             Script script = (Script) def;
319             if( script.getFrameCount() > 0 ) {
320                 Frame frame = script.getFrameAt(0);
321                 for( int i=0; i<frame.size(); i++ ) {
322                     FlashObject fo = frame.getFlashObjectAt(i);
323                     if( fo instanceof Instance ) {
324                         FlashDef df = ((Instance)fo).getFirstNestedFlashDef(m);
325                         if( df != null ) return df;
326                     } else if( fo instanceof FlashDef ) {
327                         return (FlashDef) fo;
328                     }
329                 }
330             }
331             return null;
332         } else {
333             return def;
334         }
335     }
336
337     public void collectDeps( DepsCollector dc ) {
338         // if this instance is mask (clip!=-1), then we need to get first nested
339
// FlashDef, preserve its transformation and discard everything else
340
if( clip != -1 && def instanceof Script ) {
341             AffineTransform m = new AffineTransform();
342             def = getFirstNestedFlashDef(m);
343             matrix = m;
344         }
345         if( def != null ) {
346             dc.addDep(def);
347             //System.out.println( "Instance.collectDeps: def="+def.getID() );
348
}
349     }
350
351     public void collectFonts( FontsCollector fc ) {
352         if( def != null ) def.collectFonts( fc );
353     }
354
355     public void write( FlashOutput fob ) {
356         int tagPos = fob.getPos();
357         // quick guess: if name's length more than 8 or there are clip actions, we generate long tag
358
boolean longtag = (name != null && name.length() > 8) || actions != null;
359         if( longtag ) {
360             fob.skip(6);
361         } else {
362             fob.skip(2);
363         }
364         int flags = (actions!= null? HAS_CLIPACTIONS : 0) |
365                     (def != null? HAS_CHARACTER : 0) |
366                     (matrix != null? HAS_MATRIX : 0) |
367                     (cxform != null? HAS_COLOR_TRANSF: 0) |
368                     (name != null? HAS_NAME : 0) |
369                     (ratio != -1 ? HAS_RATIO : 0) |
370                     (clip != -1 ? HAS_CLIP : 0) |
371                     (isMove ? MOVE : 0);
372         fob.writeByte(flags);
373         fob.writeWord(depth);
374         if( def != null ) fob.writeDefID(def);
375         if( matrix != null ) fob.write(matrix);
376         if( cxform != null ) cxform.write(fob);
377         if( ratio != -1 ) fob.writeWord(ratio);
378         if( clip != -1 ) fob.writeWord(clip);
379         if( name != null ) fob.writeStringZ(name);
380         if( actions!= null ) actions.write(fob);
381
382         if( longtag ) {
383             fob.writeLongTagAt( Tag.PLACEOBJECT2, fob.getPos()-tagPos-6, tagPos );
384         } else {
385             fob.writeShortTagAt( Tag.PLACEOBJECT2, fob.getPos()-tagPos-2, tagPos );
386         }
387     }
388
389     public void printContent( PrintStream JavaDoc out, String JavaDoc indent ) {
390         out.println( indent+"Instance: depth="+depth );
391         if( matrix != null ) out.println( indent+" "+matrix.toString() );
392         if( cxform != null ) cxform.printContent(out, indent+" ");
393         if( def != null ) out.println( indent+" charID="+def.getID() );
394         if( ratio != -1 ) out.println( indent+" ratio="+ratio );
395         if( clip != -1 ) out.println( indent+" clip="+clip );
396         if( name != null ) out.println( indent+" name="+name );
397         if( actions != null ) actions.printContent( out, indent+" " );
398         if( command != null ) command.printContent( out, indent );
399     }
400
401     protected boolean _isConstant() {
402         if( isCommand() ) return false;
403         if( name != null && Util.hasVar(name) ) return false;
404         if( actions != null && !actions.isConstant() ) return false;
405         if( def != null ) return def.isConstant();
406         return true;
407     }
408
409     public void process( FlashFile file, Context context ) throws IVException {
410         if( def != null && !isCommand() ) {
411             def.process(file,context);
412         }
413     }
414
415     public boolean isProcessed() {
416         if( def != null && !isCommand() ) {
417             return def.isProcessed();
418         }
419         return true;
420     }
421
422     public void setProcessed() {
423         if( def != null && !isCommand() ) {
424             def.setProcessed();
425         }
426     }
427
428     public void apply( Context context ) {
429         if( isCommand() ) return;
430         super.apply(context);
431         name = context.apply(name);
432         if( actions != null ) actions.apply(context);
433         if( def != null ) def.apply(context);
434     }
435
436     public Rectangle2D getBounds() {
437         if( def == null ) return null;
438         if( matrix == null ) return def.getBounds();
439
440         return GeomHelper.calcBounds(matrix, def.getBounds());
441     }
442
443     protected FlashItem copyInto( FlashItem item, ScriptCopier copier ) {
444         super.copyInto( item, copier );
445         ((Instance)item).matrix = matrix!=null? (AffineTransform) matrix.clone(): null;
446         ((Instance)item).cxform = cxform!=null? (CXForm) cxform.getCopy(copier): null;
447         ((Instance)item).isMove = isMove;
448         ((Instance)item).ratio = ratio;
449         ((Instance)item).clip = clip;
450         ((Instance)item).depth = depth;
451         ((Instance)item).name = name;
452         ((Instance)item).actions = actions != null? (ClipActions) actions.getCopy( copier ): null;
453         ((Instance)item).def = copier.copy(def);
454         GenericCommand myCommand = command!=null? (GenericCommand) command.getCopy(copier): null;
455         if( myCommand != null ) myCommand.setInstance((Instance)item);
456         ((Instance)item).command = myCommand;
457         return item;
458     }
459
460     public FlashItem getCopy( ScriptCopier copier ) {
461         return copyInto( new Instance(), copier );
462     }
463 }
464
Popular Tags