1 /*
2  *   Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16  *
17  */
18 
19 /*
20  * Test "Jumping backward to the end of a DisplayObject's lifetime (with events: onConstruct, onUnload)"
21  *
22  * Timeline:
23  *
24  *   Frame  | 1 | 2 | 3 | 4 | 5 | 6 |
25  *  --------+---+---+---+---+---+---+
26  *   Event  |   | P | R | * | J |   |
27  *
28  *  P = place (by PlaceObject2)
29  *  R = remove (by RemoveObject* tag)
30  *  J = jump
31  *  * = jump target
32  *
33  * Description:
34  *
35  *  frame2: a static DisplayObjects is placed at depth 3 (-16381) [ a red square ]
36  *          Both onConstruct and onUnload event handlers defined.
37  *  frame3: DisplayObject at depth 3 (-16381) removed
38  *  frame5: jump back to frame 4 and stop
39  *
40  * Expected behaviour:
41  *
42  *   After jump back, the onConstruct event handler for the red square has been invoked twice.
43  *
44  * run as ./loop_test7
45  */
46 
47 
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <ming.h>
51 
52 #include "ming_utils.h"
53 
54 #define OUTPUT_VERSION 6
55 #define OUTPUT_FILENAME "loop_test7.swf"
56 
57 
58 int
main(int argc,char ** argv)59 main(int argc, char** argv)
60 {
61   SWFMovie mo;
62   SWFMovieClip mc1, dejagnuclip;
63   SWFDisplayItem it1;
64   SWFShape sh1;
65 
66   const char *srcdir=".";
67   if ( argc>1 )
68     srcdir=argv[1];
69   else
70   {
71       //fprintf(stderr, "Usage: %s <mediadir>\n", argv[0]);
72       //return 1;
73   }
74 
75   Ming_init();
76   Ming_useSWFVersion (OUTPUT_VERSION);
77 
78   mo = newSWFMovie();
79   SWFMovie_setDimension(mo, 800, 600);
80   SWFMovie_setRate(mo, 6);
81 
82   // Frame 1: Place dejagnu clip
83 
84   dejagnuclip = get_dejagnu_clip((SWFBlock)get_default_font(srcdir), 10, 0, 0, 800, 600);
85   SWFMovie_add(mo, (SWFBlock)dejagnuclip);
86   add_actions(mo, "mc1Constructed=0; mc2Constructed=0; mc3Constructed=0; mc4Constructed=0;");
87   SWFMovie_nextFrame(mo);
88 
89   //
90   // Frame 2:
91   //   Place red static movieClip1 DisplayObject at depth 3 (-16381)
92   //
93   sh1 = make_fill_square (300, 300, 60, 60, 255, 0, 0, 255, 0, 0);
94   mc1 = newSWFMovieClip();
95   SWFMovieClip_add(mc1, (SWFBlock)sh1);
96   SWFMovieClip_nextFrame(mc1);
97 
98   it1 = SWFMovie_add(mo, (SWFBlock)mc1);  //add movieClip1 to the _root
99   SWFDisplayItem_setDepth(it1, 3);
100   SWFDisplayItem_setName(it1, "movieClip1"); //name movieClip1
101   SWFDisplayItem_addAction(it1, newSWFAction(
102     "_root.note(this+' constructed');"
103     "_root.mc1Constructed++;"
104     ), SWFACTION_CONSTRUCT);
105   SWFDisplayItem_addAction(it1, newSWFAction(
106     "_root.note(this+' unloaded');"
107     "_root.mc1Unloaded++;"
108     ), SWFACTION_UNLOAD);
109 
110   check_equals(mo, "typeof(movieClip1)", "'movieclip'");
111   check_equals(mo, "_root.mc1Constructed", "1");
112 
113   SWFMovie_nextFrame(mo);
114 
115   // Frame3: Remove red square
116   SWFDisplayItem_remove(it1);
117   // After compile, the RemoveObject2 tag is *after* the DoAction tag which
118   // contains the following check. So it's not surprise that we can still access
119   // "movieClip1" here when considering the gloabal ActionQueue model! If the
120   // RemoveObject2 is *before* the DoAction, then typeof(movieClip1) will reurn 'undefined'.
121   // So Gnash fails here because of action execution order!
122   // TODO: add testcase for this(RemoveObject2 placed *before* DoAction within the same frame).
123   check_equals(mo, "typeof(movieClip1)", "'movieclip'"); // kept alive for calling onUnload!
124   check_equals(mo, "_root.mc1Constructed", "1");
125   SWFMovie_nextFrame(mo);
126 
127   // Frame4: nothing new
128   SWFMovie_nextFrame(mo);
129 
130   // Frame5: check, gotoAndStop(4), check..
131 
132   check_equals(mo, "typeof(movieClip1)", "'undefined'");
133   SWFMovie_add(mo, (SWFBlock)newSWFAction( "gotoAndStop(4);"));
134   check_equals(mo, "typeof(movieClip1)", "'movieclip'");
135 
136   // onConstruct is called twice
137   check_equals(mo, "_root.mc1Constructed", "2");
138 
139   // this is due to action execution order, it's called twice, but
140   // the second time it's called *after* the end of *this* DOACTION block ..
141   check_equals(mo, "_root.mc1Unloaded", "1");
142 
143   SWFMovie_add(mo, (SWFBlock)newSWFAction( "totals(); stop();" ));
144   SWFMovie_nextFrame(mo);
145 
146   //Output movie
147   puts("Saving " OUTPUT_FILENAME );
148   SWFMovie_save(mo, OUTPUT_FILENAME);
149 
150   return 0;
151 }
152 
153