CVSROOT: /sources/gnash Module name: gnash Changes by: Sandro Santilli <strk> 07/04/06 15:36:05
Modified files: . : ChangeLog server : sprite_instance.cpp sprite_instance.h server/vm : ASHandlers.cpp testsuite/misc-ming.all: displaylist_depths_test.c Log message: Good stuff: * testsuite/misc-ming.all/displaylist_depths_test.c: Add a bunch of new tests about removing from protected depth ranges and using swapDepth to move between ranges. * server/sprite_instance.{h,cpp}: Add a removeMovieClip public method for common use by ActionRemoveClip tag, global removeMovieClip function and MovieClip.removeMovieClip method; fix swapDepths to accept a depth as argument; fix removeMovieClip to check for allowed depth bounds. * server/vm/ASHandlers.cpp (ActionRemoveClip): use the new sprite_instance::removeMovieClip method. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2798&r2=1.2799 http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.cpp?cvsroot=gnash&r1=1.225&r2=1.226 http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.h?cvsroot=gnash&r1=1.89&r2=1.90 http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/ASHandlers.cpp?cvsroot=gnash&r1=1.82&r2=1.83 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/displaylist_depths_test.c?cvsroot=gnash&r1=1.1&r2=1.2 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.2798 retrieving revision 1.2799 diff -u -b -r1.2798 -r1.2799 --- ChangeLog 6 Apr 2007 11:43:44 -0000 1.2798 +++ ChangeLog 6 Apr 2007 15:36:05 -0000 1.2799 @@ -1,5 +1,18 @@ 2007-04-06 Sandro Santilli <[EMAIL PROTECTED]> + * testsuite/misc-ming.all/displaylist_depths_test.c: + Add a bunch of new tests about removing from protected + depth ranges and using swapDepth to move between ranges. + * server/sprite_instance.{h,cpp}: Add a removeMovieClip + public method for common use by ActionRemoveClip tag, + global removeMovieClip function and MovieClip.removeMovieClip + method; fix swapDepths to accept a depth as argument; + fix removeMovieClip to check for allowed depth bounds. + * server/vm/ASHandlers.cpp (ActionRemoveClip): use the new + sprite_instance::removeMovieClip method. + +2007-04-06 Sandro Santilli <[EMAIL PROTECTED]> + * server/: character.h, dlist.{cpp,h}, sprite_instance.{cpp,h}: Character instance depth is a _signed_ value ! Add a character::staticDepthOffset constant to use for converting Index: server/sprite_instance.cpp =================================================================== RCS file: /sources/gnash/gnash/server/sprite_instance.cpp,v retrieving revision 1.225 retrieving revision 1.226 diff -u -b -r1.225 -r1.226 --- server/sprite_instance.cpp 6 Apr 2007 11:43:44 -0000 1.225 +++ server/sprite_instance.cpp 6 Apr 2007 15:36:05 -0000 1.226 @@ -130,12 +130,7 @@ static as_value sprite_remove_movieclip(const fn_call& fn) { boost::intrusive_ptr<sprite_instance> sprite = ensureType<sprite_instance>(fn.this_ptr); - - sprite_instance* parent = dynamic_cast<sprite_instance*>(sprite->get_parent()); - if (parent) - { - parent->remove_display_object(sprite->get_depth(), 0); - } + sprite->removeMovieClip(); return as_value(); } @@ -286,69 +281,108 @@ //swapDepths(target:Object) : Void static as_value sprite_swap_depths(const fn_call& fn) { - boost::intrusive_ptr<sprite_instance> sprite = ensureType<sprite_instance>(fn.this_ptr); + typedef boost::intrusive_ptr<sprite_instance> SpritePtr; + typedef boost::intrusive_ptr<character> CharPtr; + + SpritePtr sprite = ensureType<sprite_instance>(fn.this_ptr); + int this_depth = sprite->get_depth(); + + // Lower bound of source depth below which swapDepth has no effect + static const int lowerDepthBound = -16384; as_value rv; + if (fn.nargs < 1) { IF_VERBOSE_ASCODING_ERRORS( - log_aserror("swapDepths needs one arg"); + log_aserror("%s.swapDepths() needs one arg.", sprite->getTarget().c_str()); ); return rv; } - boost::intrusive_ptr<character> target = NULL; - if (fn.arg(0).is_object() ) + if ( this_depth < lowerDepthBound ) { - target = boost::dynamic_pointer_cast<character>(fn.arg(0).to_object()); + IF_VERBOSE_ASCODING_ERRORS( + stringstream ss; fn.dump_args(ss); + log_aserror("%s.swapDepths(%s) : won't swap a clip below depth %d (%d).", + sprite->getTarget().c_str(), ss.str().c_str(), lowerDepthBound, this_depth); + ); + return rv; } - else if (fn.arg(0).is_number() ) - { - // Macromedia Flash help says: depth starts at -16383 (0x3FFF) - int target_depth = int(fn.arg(0).to_number()) + 16383 + 1; - boost::intrusive_ptr<sprite_instance> parent = dynamic_cast<sprite_instance*>(sprite->get_parent()); - if ( parent ) - { - target = parent->get_character_at_depth(target_depth); - } - } - else + + SpritePtr this_parent = dynamic_cast<sprite_instance*>(sprite->get_parent()); + if ( ! this_parent ) { IF_VERBOSE_ASCODING_ERRORS( - log_aserror("swapDepths has received invalid arg\n"); + stringstream ss; fn.dump_args(ss); + log_aserror("%s.swapDepths(%s): this sprite has no parent, " + "swapping depth of root ?", + sprite->getTarget().c_str(), + ss.str().c_str()); ); return rv; } - if (sprite == NULL || target == NULL) + + CharPtr target = NULL; + int target_depth = 0; + + // sprite.swapDepth(sprite) + if ( SpritePtr target_sprite = fn.arg(0).to_sprite() ) + { + if ( sprite == target_sprite ) { IF_VERBOSE_ASCODING_ERRORS( - log_aserror("It is impossible to swap NULL character"); + log_aserror("%s.swapDepths(%s): invalid call, swapping to self?", + sprite->getTarget().c_str(), target_sprite->getTarget().c_str()); ); return rv; } - if (sprite->get_parent() == target->get_parent() && sprite->get_parent() != NULL) + SpritePtr target_parent = dynamic_cast<sprite_instance*>(sprite->get_parent()); + if ( this_parent != target_parent ) { - int target_depth = target->get_depth(); - target->set_depth(sprite->get_depth()); - sprite->set_depth(target_depth); - - boost::intrusive_ptr<sprite_instance> parent = dynamic_cast<sprite_instance*>(sprite->get_parent()); - if ( parent ) - { - parent->swap_characters(sprite.get(), target.get()); + IF_VERBOSE_ASCODING_ERRORS( + log_aserror("%s.swapDepths(%s): invalid call, the two characters don't have the same parent", + sprite->getTarget().c_str(), target_sprite->getTarget().c_str()); + ); + return rv; } + + target_depth = target_sprite->get_depth(); + target = boost::dynamic_pointer_cast<character>(target_sprite); } else { + // sprite.swapDepth(depth) + double td = fn.arg(0).to_number(&(fn.env())); + if ( isnan(td) ) + { IF_VERBOSE_ASCODING_ERRORS( - log_aserror("Can't swap depth of MovieClips " - "with different parents"); + stringstream ss; fn.dump_args(ss); + log_aserror("%s.swapDepths(%s): first argument invalid " + "(neither a sprite nor a number).", + sprite->getTarget().c_str(), + ss.str().c_str()); ); + return rv; + } + + // TODO : check other kind of validities ? + + target_depth = int(td); + target = this_parent->get_character_at_depth(target_depth); + } + + sprite->set_depth(target_depth); + if ( target ) + { + target->set_depth(this_depth); + this_parent->swap_characters(sprite.get(), target.get()); } return rv; + } // TODO: wrap the functionality in a sprite_instance method @@ -3439,4 +3473,33 @@ } } +void +sprite_instance::removeMovieClip() +{ + int depth = get_depth(); + if ( depth < 0 || depth > 1048575 ) + { + IF_VERBOSE_ASCODING_ERRORS( + log_aserror("removeMovieClip(%s): sprite depth (%d) out of the " + "'dynamic' zone [0..1048575], won't remove", + getTarget().c_str(), depth); + ); + return; + } + + sprite_instance* parent = dynamic_cast<sprite_instance*>(get_parent()); + if (parent) + { + // second argument is arbitrary, see comments above + // the function declaration in sprite_instance.h + parent->remove_display_object(depth, 0); + } + else + { + // I guess this can only happen if someone uses _root.swapDepth([0..1048575]) + log_error("Can't remove sprite %s as it has no parent!", getTarget().c_str()); + } + +} + } // namespace gnash Index: server/sprite_instance.h =================================================================== RCS file: /sources/gnash/gnash/server/sprite_instance.h,v retrieving revision 1.89 retrieving revision 1.90 diff -u -b -r1.89 -r1.90 --- server/sprite_instance.h 6 Apr 2007 11:43:44 -0000 1.89 +++ server/sprite_instance.h 6 Apr 2007 15:36:05 -0000 1.90 @@ -17,7 +17,7 @@ // // -/* $Id: sprite_instance.h,v 1.89 2007/04/06 11:43:44 strk Exp $ */ +/* $Id: sprite_instance.h,v 1.90 2007/04/06 15:36:05 strk Exp $ */ // Stateful live Sprite instance @@ -666,6 +666,30 @@ /// _target and _target_dot. virtual void set_name(const char* name); + /// Remove this sprite from the stage. + // + /// This function is intended to be called by + /// effect of a removeMovieClip() ActionScript call + /// and implements the checks required for this specific + /// case. + /// + /// Callers are: + /// - The ActionRemoveClip tag handler. + /// - The global removeMovieClip(target) function. + /// - The MovieClip.removeMovieClip() method. + /// + /// The removal will not occur if the depth of this + /// characters is not in the "dynamic" range [0..1048575] + /// as described at the following URL: + /// + /// http://www.senocular.com/flash/tutorials/depths/?page=2 + /// + /// A testcases for this behaviour can be found in + /// + /// testsuite/misc-ming.all/displaylist_depths_test.swf + /// + void removeMovieClip(); + /// @{ Drawing API void lineStyle(uint16_t thickness, const rgba& color) Index: server/vm/ASHandlers.cpp =================================================================== RCS file: /sources/gnash/gnash/server/vm/ASHandlers.cpp,v retrieving revision 1.82 retrieving revision 1.83 diff -u -b -r1.82 -r1.83 --- server/vm/ASHandlers.cpp 5 Apr 2007 19:33:54 -0000 1.82 +++ server/vm/ASHandlers.cpp 6 Apr 2007 15:36:05 -0000 1.83 @@ -14,7 +14,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -/* $Id: ASHandlers.cpp,v 1.82 2007/04/05 19:33:54 strk Exp $ */ +/* $Id: ASHandlers.cpp,v 1.83 2007/04/06 15:36:05 strk Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -1164,7 +1164,7 @@ void SWFHandlers::ActionRemoveClip(ActionExec& thread) { -// GNASH_REPORT_FUNCTION; + //GNASH_REPORT_FUNCTION; as_environment& env = thread.env; thread.ensureStack(1); @@ -1191,12 +1191,7 @@ return; } - sprite_instance* parent = dynamic_cast<sprite_instance*>(sprite->get_parent()); - if (parent) - { - parent->remove_display_object(sprite->get_depth(), 0); - } - + sprite->removeMovieClip(); } /// \brief Trace messages from the Flash movie using trace(); Index: testsuite/misc-ming.all/displaylist_depths_test.c =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/displaylist_depths_test.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -b -r1.1 -r1.2 --- testsuite/misc-ming.all/displaylist_depths_test.c 6 Apr 2007 09:56:00 -0000 1.1 +++ testsuite/misc-ming.all/displaylist_depths_test.c 6 Apr 2007 15:36:05 -0000 1.2 @@ -33,20 +33,49 @@ #define OUTPUT_VERSION 6 #define OUTPUT_FILENAME "displaylist_depths_test.swf" -static SWFMovieClip get_static_mc(void); +void add_dynamic_mc(SWFMovie mo, const char* name, int depth, int x, int y, int width, int height); +void add_static_mc(SWFMovie mo, const char* name, int depth, int x, int y, int width, int height); -SWFMovieClip -get_static_mc() +void +add_dynamic_mc(SWFMovie mo, const char* name, int depth, int x, int y, int width, int height) +{ + SWFAction ac = compile_actions("createEmptyMovieClip('%s', %d);" + "with (%s) {" + " lineStyle(1, 0x000000, 100);" + " beginFill(0x00FF00, 100);" + " moveTo(%d, %d);" + " lineTo(%d, %d);" + " lineTo(%d, %d);" + " lineTo(%d, %d);" + " lineTo(%d, %d);" + " endFill();" + "}", + name, depth, name, + x, y, + x, y+height, + x+width, y+height, + x+width, y, + x, y); + + SWFMovie_add(mo, (SWFBlock)ac); +} + +void +add_static_mc(SWFMovie mo, const char* name, int depth, int x, int y, int width, int height) { SWFShape sh; SWFMovieClip mc; + SWFDisplayItem it; - sh = make_fill_square (0, 300, 60, 60, 255, 0, 0, 255, 0, 0); + sh = make_fill_square (x, y, width, height, 255, 0, 0, 255, 0, 0); mc = newSWFMovieClip(); SWFMovieClip_add(mc, (SWFBlock)sh); SWFMovieClip_nextFrame(mc); + it = SWFMovie_add(mo, (SWFBlock)mc); + SWFDisplayItem_setDepth(it, depth); + SWFDisplayItem_setName(it, name); - return mc; + SWFMovie_add(mo, (SWFBlock)mc); } @@ -55,8 +84,6 @@ { SWFMovie mo; SWFMovieClip dejagnuclip; - SWFMovieClip mc1; - SWFDisplayItem it; const char *srcdir="."; if ( argc>1 ) @@ -70,44 +97,140 @@ Ming_init(); mo = newSWFMovieWithVersion(OUTPUT_VERSION); SWFMovie_setDimension(mo, 800, 600); - SWFMovie_setRate (mo, 12); + SWFMovie_setRate (mo, 2); dejagnuclip = get_dejagnu_clip((SWFBlock)get_default_font(srcdir), 10, 0, 0, 800, 600); SWFMovie_add(mo, (SWFBlock)dejagnuclip); - SWFMovie_nextFrame(mo); // end of frame 1 + SWFMovie_nextFrame(mo); + add_actions(mo, "note('Test placement of static and dynamic objects at different depth ranges.');"); + add_actions(mo, "note('Characters placed in *reserved* zones will not be removed');"); + add_actions(mo, "note('');"); + add_actions(mo, "note('WARNING: Adobe flash player 9 seems to fail this test, but flash player 7 succeeds.');"); + add_actions(mo, "note(' Remember this before blaming Gnash for breaking compatibility ;)');"); + add_actions(mo, "note('');"); - // Add a static red square at depth 3 - mc1 = get_static_mc(); - it = SWFMovie_add(mo, (SWFBlock)mc1); - SWFDisplayItem_setDepth(it, 3); - SWFDisplayItem_setName(it, "staticmc"); - SWFMovie_nextFrame(mo); // end of frame 2 - - // Create an (dynamic) green movieclip at depth 3 - add_actions(mo, "createEmptyMovieClip('dynamicmc', 3);" - "with (dynamicmc) {" - " lineStyle(1, 0x000000, 100);" - " beginFill(0x00FF00, 100);" - " moveTo(20, 320);" - " lineTo(80, 320);" - " lineTo(80, 380);" - " lineTo(20, 380);" - " lineTo(20, 320);" - "}"); - SWFMovie_nextFrame(mo); // end of frame 3 + // Add a static red square at depth 3 and another one at depth 4 + add_static_mc(mo, "staticmc", 3, 0, 300, 60, 60); + + // Create a dynamic green movieclip at depth 3 + add_dynamic_mc(mo, "dynamicmc", 3, 20, 320, 60, 60); + + // Create a dynamic green movieclip at depth -2000 (just below the static one) + // The renderer seems to be still rendering this ABOVE the static one ! + add_dynamic_mc(mo, "dynamicmc_2000", -2000, 20, 280, 60, 60); + + // Create a dynamic green movieclip at depth -30000 (below the static range) + add_dynamic_mc(mo, "dynamicmc_30000", -30000, 20, 280, 60, 60); + + // Create a dynamic green movieclip at depth 0 (first in "dynamic" zone) + add_dynamic_mc(mo, "dynamicmc0", 0, 90, 320, 60, 60); - // Check that both exist + // Create a dynamic green movieclip at depth 1048575 (last in "dynamic" zone) + add_dynamic_mc(mo, "dynamicmc1048575", 1048575, 160, 320, 60, 60); + + // Create a dynamic green movieclip at depth 1048576 (first in "reserve" zone) + add_dynamic_mc(mo, "dynamicmc1048576", 1048576, 0, 390, 60, 60); + + // Create a dynamic green movieclip at depth 2130690045 (last in "reserve" zone) + // This seems to create the empty clip, but NOT render anything ! + add_dynamic_mc(mo, "dynamicmc2130690045", 2130690045, 0, 390, 60, 60); + + // Create a static red movieclip at depth 0 + add_static_mc(mo, "staticmc0", 0, 0, 230, 60, 60); + + // Check what depth has been each char created in check_equals(mo, "typeof(staticmc)", "'movieclip'"); + check_equals(mo, "staticmc.getDepth()", "-16381"); // converted at negative depth ! check_equals(mo, "typeof(dynamicmc)", "'movieclip'"); - - // Check that the static one had been moved at negative depth ! - check_equals(mo, "staticmc.getDepth()", "-16381"); check_equals(mo, "dynamicmc.getDepth()", "3"); + check_equals(mo, "typeof(dynamicmc_2000)", "'movieclip'"); + check_equals(mo, "dynamicmc_2000.getDepth()", "-2000"); + check_equals(mo, "typeof(dynamicmc_30000)", "'movieclip'"); + check_equals(mo, "dynamicmc_30000.getDepth()", "-30000"); + check_equals(mo, "typeof(dynamicmc0)", "'movieclip'"); + check_equals(mo, "dynamicmc0.getDepth()", "0"); + check_equals(mo, "typeof(dynamicmc1048575)", "'movieclip'"); + check_equals(mo, "dynamicmc1048575.getDepth()", "1048575"); + check_equals(mo, "typeof(dynamicmc1048576)", "'movieclip'"); + check_equals(mo, "dynamicmc1048576.getDepth()", "1048576"); + check_equals(mo, "typeof(dynamicmc2130690045)", "'movieclip'"); + check_equals(mo, "dynamicmc2130690045.getDepth()", "2130690045"); + check_equals(mo, "typeof(staticmc0)", "'movieclip'"); + check_equals(mo, "staticmc0.getDepth()", "-16384"); // converted at negative depth ! + + SWFMovie_nextFrame(mo); + + // Try removing all characters + add_actions(mo, "removeMovieClip(staticmc);" + "removeMovieClip(dynamicmc);" + "removeMovieClip(dynamicmc_2000);" + "removeMovieClip(dynamicmc_30000);" + "removeMovieClip(dynamicmc0);" + "removeMovieClip(dynamicmc1048575);" + "removeMovieClip(dynamicmc1048576);" + "removeMovieClip(dynamicmc2130690045);" + "removeMovieClip(staticmc0);" + ); + + // Check what gets removed and what not + check_equals(mo, "typeof(staticmc)", "'movieclip'"); + check_equals(mo, "typeof(dynamicmc)", "'undefined'"); + check_equals(mo, "typeof(dynamicmc_2000)", "'movieclip'"); // clip at negative depth is not removed + check_equals(mo, "typeof(dynamicmc_30000)", "'movieclip'"); // clip at negative depth is not removed + check_equals(mo, "typeof(dynamicmc0)", "'undefined'"); + check_equals(mo, "typeof(dynamicmc1048575)", "'undefined'"); + check_equals(mo, "typeof(dynamicmc1048576)", "'movieclip'"); // clip in "reserved" zone not removed + check_equals(mo, "typeof(dynamicmc2130690045)", "'movieclip'"); // clip in "reserved" zone not removed + check_equals(mo, "typeof(staticmc0)", "'movieclip'"); + + SWFMovie_nextFrame(mo); + + // Move all non-removed chars to the "dynamic" depth range + // and try removing them again. + add_actions(mo, "staticmc.swapDepths(1000);" + "dynamicmc_2000.swapDepths(1001);" + "dynamicmc1048576.swapDepths(1002);" + "dynamicmc2130690045.swapDepths(1003);" + "staticmc0.swapDepths(1004);" + "dynamicmc_30000.swapDepths(1005);" + ); + + check_equals(mo, "staticmc.getDepth()", "1000"); + check_equals(mo, "dynamicmc_2000.getDepth()", "1001"); + check_equals(mo, "dynamicmc1048576.getDepth()", "1002"); + // MM bug: swapDepths aginst this char (in reserved zone) doesn't do + // anything with player9. It works fine with player7. + check_equals(mo, "dynamicmc2130690045.getDepth()", "1003"); + check_equals(mo, "staticmc0.getDepth()", "1004"); + // swapDepth doesn't work for the clip at -30000 !! + check_equals(mo, "dynamicmc_30000.getDepth()", "-30000"); + + add_actions(mo, "removeMovieClip(staticmc);" + "removeMovieClip(dynamicmc_2000);" + "removeMovieClip(dynamicmc1048576);" + "removeMovieClip(dynamicmc2130690045);" + "removeMovieClip(staticmc0);" + ); + + // Check if we cleaned them all now + check_equals(mo, "typeof(staticmc)", "'undefined'"); + check_equals(mo, "typeof(dynamicmc_2000)", "'undefined'"); + check_equals(mo, "typeof(dynamicmc1048576)", "'undefined'"); + // MM bug: swapDepths against this char (in reserved zone) didn't do + // anything with player9, so the removeMovieClip call against + // it still doesn't work. It works fine with player7. + check_equals(mo, "typeof(dynamicmc2130690045)", "'undefined'"); + // MM bug?: altought the staticmc0 results undefined after the call + // to removeMovieClip, it is sill rendered !! + check_equals(mo, "typeof(staticmc0)", "'undefined'"); add_actions(mo, "_root.totals(); stop();"); SWFMovie_nextFrame(mo); + // TODO: + // - test the MovieClip and global version of removeMovieClip ! + //Output movie puts("Saving " OUTPUT_FILENAME ); SWFMovie_save(mo, OUTPUT_FILENAME); _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit