Fix test for bug #32625
[gnash.git] / libcore / DisplayObject.h
blob1138abf0d15f11069d409b1974735f0bd97fe131
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // 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
20 #ifndef GNASH_DISPLAY_OBJECT_H
21 #define GNASH_DISPLAY_OBJECT_H
23 #ifdef HAVE_CONFIG_H
24 #include "gnashconfig.h" // USE_SWFTREE
25 #endif
27 #include <vector>
28 #include <map>
29 #include <string>
30 #include <cassert>
31 #include <boost/cstdint.hpp> // For C99 int types
32 #include <boost/noncopyable.hpp>
34 #include "ObjectURI.h"
35 #include "GC.h"
36 #include "Transform.h"
37 #include "event_id.h"
38 #include "SWFRect.h"
39 #include "SWFMatrix.h"
40 #include "SWFCxForm.h"
41 #include "dsodefs.h"
42 #include "snappingrange.h"
43 #ifdef USE_SWFTREE
44 # include "tree.hh"
45 #endif
48 //#define DEBUG_SET_INVALIDATED 1
50 // Forward declarations
51 namespace gnash {
52 class MovieClip;
53 class movie_root;
54 class fn_call;
55 class Movie;
56 class ExecutableCode;
57 class action_buffer;
58 class movie_definition;
59 class StaticText;
60 class InteractiveObject;
61 class Renderer;
62 class as_object;
63 class as_value;
64 class as_environment;
65 class DisplayObject;
66 class KeyVisitor;
67 namespace SWF {
68 class TextRecord;
72 namespace gnash {
74 /// Returns true if the DisplayObject is referenceable in ActionScript
76 /// A DisplayObject is referenceable if it has an associated object.
77 bool isReferenceable(const DisplayObject& d);
79 /// Set special properties
81 /// This sets the magic properties of DisplayObjects.
83 /// @param key The string table key of the property to set.
84 /// @param obj The DisplayObject whose property should be set
85 /// @param val An as_value representing the new value of the property.
86 /// Some values may be rejected.
87 bool setDisplayObjectProperty(DisplayObject& obj, const ObjectURI& uri,
88 const as_value& val);
90 /// Get special properties
92 /// This gets the magic properties of DisplayObjects and handles special
93 /// MovieClip properties such as DisplayList members.
95 /// @param key The uri of the property to get.
96 /// @param obj The DisplayObject whose property should be got
97 /// @param val An as_value to be set to the value of the property.
98 bool getDisplayObjectProperty(DisplayObject& obj, const ObjectURI& uri,
99 as_value& val);
101 /// Get a property by its numeric index.
103 /// Used by ASHandlers to get the DisplayObject properties indexed by number
105 /// @param index The index of the property to get.
106 /// @param o The DisplayObject whose property should be got
107 /// @param val An as_value to be set to the value of the property.
108 void getIndexedProperty(size_t index, DisplayObject& o, as_value& val);
110 /// Set a property by its numeric index.
112 /// Used by ASHandlers to set the DisplayObject properties indexed by number
114 /// @param index The index of the property to set.
115 /// @param o The DisplayObject whose property should be set
116 /// @param val An as_value representing the new value of the property.
117 /// Some values may be rejected.
118 void setIndexedProperty(size_t index, DisplayObject& o, const as_value& val);
120 /// Copy SWFMatrix and caches from given DisplayObjecta
122 /// @param from The DisplayObject to copy from
123 /// @param to The DisplayObject to copy to.
124 void copyMatrix(const DisplayObject& from, DisplayObject& to);
126 /// Get concatenated SWFMatrix (all ancestor transforms and our SWFMatrix)
128 /// Maps from our local space into "world" space
129 /// (i.e. root movie space).
131 /// @param includeRoot Whether the transform of the Stage (_root)
132 /// should be concatenated. This is required to be
133 /// false for pointInBounds.
134 SWFMatrix getWorldMatrix(const DisplayObject& d, bool includeRoot = true);
136 /// Get concatenated color transform of a DisplayObject
138 /// Maps from our local space into normal color space.
139 SWFCxForm getWorldCxForm(const DisplayObject& d);
141 /// DisplayObject is the base class for all DisplayList objects.
143 /// It represents a single active element in a movie. This class does not
144 /// supply any interactivity. The hierarchy of DisplayObjects in a movie
145 /// provides all visual elements in a SWF. The DisplayObject hierarchy
146 /// is independent of ActionScript resources, but can be controlled via AS.
148 /// DisplayObjects that can be controlled through ActionScript have an
149 /// associated as_object. DisplayObjects such as Shape, do not have an
150 /// associated object and cannot be referenced in AS.
152 /// Derived classes include InteractiveObject, StaticText, Bitmap,
153 /// Video, and Shape.
155 /// All DisplayObjects may be constructed during SWF parsing. In this case
156 /// they are constructed using an immutable, non-copyable SWF::DefinitionTag.
157 /// This tag should never be changed!
159 /// Most DisplayObjects may also be constructed dynamically. In AS3, Bitmaps
160 /// and Shapes can be dynamically created. Dynamically-created DisplayObjects
161 /// must not have a SWF::DefinitionTag!
163 /// The presence of a definition tag may be used to distinguish static from
164 /// dynamic DisplayObjects, but tags are not always stored. They are not
165 /// stored in most InteractiveObjects because most properties can be
166 /// overridden during SWF execution.
167 class DisplayObject : public GcResource, boost::noncopyable
169 public:
171 /// Construct a DisplayObject
173 /// @param mr The movie_root containing the DisplayObject hierarchy.
174 /// All DisplayObjects may need movie_root resources.
175 /// @param object An object to be associated with this DisplayObject.
176 /// If this is non-null, the DisplayObject will be
177 /// referenceable in ActionScript. Referenceable
178 /// DisplayObjects may access AS resources through their
179 /// associated object.
180 /// @param parent The parent of the new DisplayObject. This may be null.
181 DisplayObject(movie_root& mr, as_object* object, DisplayObject* parent);
183 virtual ~DisplayObject() {}
185 /// The lowest placeable and accessible depth for a DisplayObject.
186 /// Macromedia Flash help says: depth starts at -16383 (0x3FFF)
188 /// See: http://www.senocular.com/flash/tutorials/depths/?page=2
190 /// See also http://www.kirupa.com/developer/actionscript/depths2.htm
192 /// The only way to exceed these bounds is with createEmptyMoveClip(),
193 /// which can be placed at any depth within +/- 2**31.
194 static const int lowerAccessibleBound = -16384;
196 /// This is the maximum depth a MovieClip DisplayObject can be placed
197 /// at (attachMovie). Kirupa (see above) says 2130690045, but this
198 /// seems not to be included in the range.
199 static const int upperAccessibleBound = 2130690044;
201 /// This is the amount added to displaylist tag defined depths.
202 /// DisplayObjects placed by tags (vs. DisplayObjects instantiated by
203 /// ActionScript) always have negative depths by effect of this offset.
204 static const int staticDepthOffset = lowerAccessibleBound;
206 /// This is the offset at which DisplayObject's depth is
207 /// shifted when a DisplayObject is removed from stage but
208 /// an onUnload event handler is defined.
210 /// Example: a DisplayObject at depth 60 gets moved to
211 /// depth -32829 (-32769-60) when unloaded and
212 /// an onUnload event handler is defined for it
213 /// or any of its childs.
215 /// So, to recap:
216 /// 1: -32769 to -16385 are removed
217 /// 2: -16384 to 0 are statics
218 /// 3: Max depth for a PlaceObject call is 16384 (which becomes
219 /// 0 in the statics)
220 /// (all of the above correct?)
221 static const int removedDepthOffset = -32769;
223 /// This value is used for m_clip_depth when
224 /// the DisplayObject is not a layer mask.
226 /// Depths below -16384 are illegal, so this
227 /// value should not collide with real depths.
229 static const int noClipDepthValue = -1000000;
231 /// Return a reference to the variable scope of this DisplayObject.
232 virtual as_environment& get_environment() {
233 // MovieClip must override this
234 // and any other DisplayObject will have
235 // a parent!
236 assert(_parent != NULL);
237 return _parent->get_environment();
240 /// Enumerate any non-proper properties
242 /// This function allows enumeration of properties that are
243 /// derived from the DisplayObject type, e.g. DisplayList members.
245 /// The default implementation adds nothing
246 virtual void visitNonProperties(KeyVisitor&) const {}
248 /// \brief
249 /// Return the parent of this DisplayObject, or NULL if
250 /// the DisplayObject has no parent.
251 DisplayObject* parent() const
253 return _parent;
256 /// Set the parent of this DisplayObject
258 /// In AS3, DisplayObjects may be created before being attached to
259 /// a parent. In AS2, this is only used for external movies
260 void set_parent(DisplayObject* parent)
262 _parent = parent;
265 virtual MovieClip* to_movie() { return 0; }
267 int get_depth() const { return _depth; }
269 void set_depth(int d) { _depth = d; }
271 /// Get sound volume for this DisplayObject
272 int getVolume() const { return _volume; }
274 /// Set sound volume for this DisplayObject
275 void setVolume(int vol) { _volume = vol; }
277 /// Get concatenated sound volume for this DisplayObject
279 /// NOTE: the concatenated volume does NOT include
280 /// global volume settings, which is the one
281 /// controlled by Sound instances created passing
282 /// null, undefined or no argument to constructor.
284 int getWorldVolume() const;
286 /// DisplayObjects can return the version of the SWF they were parsed from.
287 virtual int getDefinitionVersion() const {
288 return -1;
291 const Transform& transform() const {
292 return _transform;
296 /// Set local transform SWFMatrix for this DisplayObject
298 /// @param m the new SWFMatrix to assign to this DisplayObject
300 /// @param updateCache if true, updates the cache values
301 /// from the SWFMatrix (only if SWFMatrix != current SWFMatrix)
303 void setMatrix(const SWFMatrix& m, bool updateCache = false);
305 /// Set the xscale value of current SWFMatrix
307 /// This is used when setting _xscale.
308 /// See xscale_getset.
310 /// @param factor scale factor, in percent
312 void set_x_scale(double factor);
314 /// Set the yscale value of current SWFMatrix
316 /// This is used when setting _yscale
317 /// See yscale_getset.
319 /// @param factor scale factor, in percent
321 void set_y_scale(double factor);
323 /// Set the rotation value of current SWFMatrix
326 /// This is used when setting _rotation
327 /// See rotation_getset
329 /// @param rot rotation in degrees. will be trimmed to
330 /// the -180 .. 180 range, can be passed outside it.
332 void set_rotation(double rot);
334 /// Set the width of this DisplayObject, modifying its SWFMatrix
336 /// This is used when setting _width
338 /// @param w new width, in TWIPS.
340 /// TextField does this differently (caches not updated).
341 virtual void setWidth(double width);
343 /// Set the height of this DisplayObject, modifying its SWFMatrix
345 /// This is used when setting _height
347 /// @param h new height, in TWIPS.
349 virtual void setHeight(double height);
351 void setCxForm(const SWFCxForm& cx)
353 if (_transform.colorTransform != cx) {
354 set_invalidated();
355 _transform.colorTransform = cx;
359 boost::uint16_t get_ratio() const { return _ratio; }
361 void set_ratio(boost::uint16_t r) {
362 if (r != _ratio) set_invalidated();
363 _ratio = r;
366 /// Returns the clipping depth (if any) of this DisplayObject.
367 /// The parameter tells us to use the DisplayObject as a mask for
368 /// all the objects contained in the display list from _depth
369 /// to m_clipping_depth inclusive.
370 ///
371 /// The value returned by get_clip_depth() is only valid when isMaskLayer()
372 /// returns true!
373 ///
374 int get_clip_depth() const { return m_clip_depth; }
376 /// See get_clip_depth()
377 void set_clip_depth(int d)
379 m_clip_depth = d;
382 /// Returns true when the DisplayObject (and its childs) is used as a mask
383 /// for other DisplayObjects at higher depth (up to get_clip_depth).
384 /// isMaskLayer() does not return true when one of its
385 /// parents is a mask and the DisplayObject itself is not.
387 /// See also isDynamicMask() and isMask()
388 ///
389 bool isMaskLayer() const
391 return (m_clip_depth != noClipDepthValue && !_maskee);
394 /// Returns true when the DisplayObject (and its childs) is used as a mask
395 /// for another DisplayObject.
396 /// isDynamicMask() does not return true when one of its
397 /// parents is a mask and the DisplayObject itself is not.
399 /// NOTE: there's no way to obtain the maskee from a dynamic mask
401 /// See also isMaskLayer() and isMask()
402 ///
403 bool isDynamicMask() const
405 return (_maskee);
408 /// Return the DisplayObject masking this instance (if any)
409 DisplayObject* getMask() const
411 #if GNASH_PARANOIA_LEVEL > 1
412 if (_mask) assert(_mask->_maskee == this);
413 #endif
414 return _mask;
417 /// Register a DisplayObject as a mask for this instance.
419 /// @param mask The DisplayObject to use as a mask, possibly NULL.
420 /// A reference to us will be registered with the mask, if
421 /// not null, so it'll know it's a mask for us, and would stop
422 /// being a mask for anything else.
424 void setMask(DisplayObject* mask);
426 /// Set DisplayObject name, initializing the original target member
427 void set_name(const ObjectURI& uri) {
428 _name = uri;
431 const ObjectURI& get_name() const { return _name; }
433 /// Get the built-in function handlers code for the given event
435 /// NOTE: this function is only for getting statically-defined
436 /// event handlers, which are the ones attached to a DisplayObject
437 /// with a PlaceObject2. It's the DisplayObject's responsibility
438 /// to properly fetch any user-defined event handler, which
439 /// are the ones attached to a DisplayObject with ActionScript code.
441 std::auto_ptr<ExecutableCode> get_event_handler(const event_id& id) const;
443 /// Set a built-in function handler for the given event
445 /// Mark the DisplayObject as having mouse or Key event
446 /// handlers if this is the case.
448 /// NOTE: this function is only for registering statically-defined
449 /// event handlers, which are the ones attached to a DisplayObject
450 /// with a PlaceObject2. It's the DisplayObject's responsibility
451 /// to properly invoke any user-defined event handler, which
452 /// are the ones attached to a DisplayObject with ActionScript code.
454 /// @param id
455 /// The event triggering the handler.
457 /// @param code
458 /// An action buffer to execute when given event is triggered.
459 /// The buffer is externally owned (not copied), make sure it
460 /// is kept alive for the whole lifetime of this DisplayObject.
462 void add_event_handler(const event_id& id, const action_buffer& code);
464 /// Render the DisplayObject.
466 /// All DisplayObjects must have a display() function.
467 virtual void display(Renderer& renderer, const Transform& xform) = 0;
469 /// Search for StaticText objects
471 /// If this is a StaticText object and contains SWF::TextRecords, these
472 /// are written to the passed parameter.
473 /// @ return 0 if this object is not a StaticText or contains no text.
474 virtual StaticText* getStaticText(std::vector<const SWF::TextRecord*>&,
475 size_t&) {
476 return 0;
479 virtual SWFRect getBounds() const = 0;
481 /// Return true if the given point falls in this DisplayObject's bounds
483 /// @param x Point x coordinate in world space
484 /// @param y Point y coordinate in world space
485 /// @return Whether (x, y) is within the DisplayObject's bounds.
486 /// This ignores _root's transform.
487 bool pointInBounds(boost::int32_t x, boost::int32_t y) const
489 SWFRect bounds = getBounds();
490 const SWFMatrix wm = getWorldMatrix(*this, false);
491 wm.transform(bounds);
492 return bounds.point_test(x, y);
495 /// Return true if the given point falls in this DisplayObject's shape
497 /// @param x Point x coordinate in world space
498 /// @param y Point y coordinate in world space
499 /// @return Whether (x, y) is within the DisplayObject's bounds.
500 virtual bool pointInShape(boost::int32_t x, boost::int32_t y) const = 0;
502 /// true if the given point falls in this DisplayObject's visible shape
504 /// Point coordinates are in world TWIPS
506 /// The default implementation returns false if the DisplayObject is
507 /// not visible, calling pointInShape() otherwise.
509 /// Note that this is good for simple DisplayObjects but needs
510 /// to be overridden for DisplayObjects with childs. When a
511 /// DisplayObject has childs it must take into account the case
512 /// in which some childs are visible and some are not.
514 virtual bool pointInVisibleShape(boost::int32_t x, boost::int32_t y) const
516 if (!visible()) return false;
517 if (isDynamicMask() || isMaskLayer()) return false;
518 return pointInShape(x, y);
521 /// Return the relative root of this DisplayObject
523 /// The "relative" is the Movie created by
524 /// the same SWF definition that contained the
525 /// definition of this DisplayObject.
527 /// The default implementation is to invoke get_root
528 /// against this DisplayObject's parent.
530 virtual Movie* get_root() const {
531 return parent()->get_root();
534 /// Return the _root ActionScript property of this DisplayObject.
536 /// By default calls get_root(). The resulting MovieClip may be passed
537 /// to actionscript methods, so it is not const. As the override in
538 /// MovieClip may return this, the method cannot be const either.
539 virtual MovieClip* getAsRoot();
541 /// Find the object which is one degree removed from us,
542 /// given the relative pathname.
544 /// If the pathname is "..", then return our parent.
545 /// If the pathname is ".", then return ourself. If
546 /// the pathname is "_level0" or "_root", then return
547 /// the root movie.
549 /// Otherwise, the name should refer to one our our
550 /// named DisplayObjects, so we return it.
552 /// NOTE: In ActionScript 2.0, top level names (like
553 /// "_root" and "_level0") are CASE SENSITIVE.
554 /// Character names in a display list are CASE
555 /// SENSITIVE. Member names are CASE INSENSITIVE. Gah.
557 /// In ActionScript 1.0, everything seems to be CASE
558 /// INSENSITIVE.
560 virtual as_object* pathElement(const ObjectURI& uri);
562 /// \brief
563 /// Return true if PlaceObjects tag are allowed to move
564 /// this DisplayObject.
566 /// Once a DisplayObject has been transformed by ActionScript,
567 /// further transformation trought non-action SWF constrol tags
568 /// is not allowed.
570 /// See scriptTransformed()
572 bool get_accept_anim_moves() const
574 return ! _scriptTransformed && ! _dynamicallyCreated;
577 /// Was this DisplayObject dynamically created ?
579 /// "Dynamically created" means created trough ActionScript.
581 /// NOTE, With current code:
582 /// - Characters created by means of a loadMovie are
583 /// NOT set as dynamic (should check if they should)
584 /// - Characters created by attachMovie ARE dynamic
585 /// - Characters created by duplicateMovieClip ARE dynamic
586 /// - Characters created by createEmptyMovieClip ARE dynamic
587 /// - Characters created by new Video ARE dynamic
588 /// - Characters created by createTextField ARE dynamic
591 bool isDynamic() const {
592 return _dynamicallyCreated;
595 /// Mark this DisplayObject as dynamically created
596 void setDynamic() {
597 _dynamicallyCreated = true;
600 /// \brief
601 /// Call this function when the sprite has been
602 /// transformed due to ActionScript code.
604 /// This information will be used while executing
605 /// PlaceObject tags in that ActionScript-transformed
606 /// DisplayObjects won't be allowed to be moved.
608 /// TODO: make protected
610 void transformedByScript()
612 _scriptTransformed = true;
615 /// Set whether this DisplayObject should be rendered
617 /// TODO: handle all visible getter/setters in DisplayObject, not in
618 /// subclasses, and drop this / make it private.
619 void set_visible(bool visible);
621 // Return true if this DisplayObject should be rendered
622 bool visible() const { return _visible; }
624 /// Notify clip events (and also user-defined ones).
625 virtual void notifyEvent(const event_id& /*id*/)
629 /// Queue event in the global action queue.
631 /// notifyEvent(id) will be called by execution of the queued
632 /// action
633 void queueEvent(const event_id& id, int lvl);
635 /// Return true if an handler for the given event is defined
637 /// NOTE that we look for both clip-defined and user-defined
638 /// handlers, which is likely error prone since we're doing
639 /// this in a non-virtual function. Main use for this method
640 /// is for being called by ::unload() to verify an Unload handler
641 /// is available.
642 bool hasEventHandler(const event_id& id) const;
644 /// DisplayObjects are not a mouse entity by default.
646 /// Override this function for InteractiveObjects.
647 virtual InteractiveObject* topmostMouseEntity(boost::int32_t,
648 boost::int32_t) {
649 return 0;
652 /// Find highest depth DisplayObject whose shape contains the given
653 /// point and is not the DisplayObject being dragged or any of its childs.
655 /// Point coordinates in global twips.
656 virtual const DisplayObject* findDropTarget(boost::int32_t x,
657 boost::int32_t y, DisplayObject* dragging) const
659 if (this != dragging && visible() && pointInVisibleShape(x, y)) {
660 return this;
663 return 0;
666 /// Return whether this DisplayObject has been invalidated or not
667 bool invalidated() const {
668 return _invalidated;
671 /// Return whether this DisplayObject has and invalidated child or not
672 bool childInvalidated() const {
673 return _child_invalidated;
676 /// Notify a change in the DisplayObject's appearance.
677 virtual void update() {
678 set_invalidated();
681 /// \brief
682 /// This function marks the DisplayObject as being modified in aspect
683 /// and keeps track of current invalidated bounds the first time
684 /// it's called after each call to clear_invalidated().
686 /// Call this function *before* any change in this DisplayObject
687 /// that modifies its rendering. This information will be used
688 /// to detect visual changes that need to be redrawn.
690 /// It is *important* to call this function *before* the change
691 /// rather then after as it will also take care of updating the
692 /// previously invalidated bounds (m_old_invalidated_bounds)
694 /// Calling this function multiple time is a no-op, unless
695 /// clear_invalidated() is called in between.
697 /// NOTE: Marking a DisplayObject as invalidated automatically marks
698 /// its parent as being invalidated.
700 /// @see \ref region_update
702 void set_invalidated();
703 void set_invalidated(const char* debug_file, int debug_line);
706 /// Calls set_invalidated() and extends old_invalidated_ranges to the
707 /// given value so that also this area gets re-rendered (used when
708 /// replacing DisplayObjects).
709 void extend_invalidated_bounds(const InvalidatedRanges& ranges);
712 /// Called by a child to signalize it has changed visibily. The
713 /// difference to set_invalidated() is that *this* DisplayObject does
714 /// not need to redraw itself completely. This function will
715 /// recursively inform all its parents of the change.
716 void set_child_invalidated();
718 /// Clear invalidated flag and reset m_old_invalidated_bounds to null.
720 /// It is very important that each DisplayObject with any m_XXXX_invalidated
721 /// flag set calls clear_invalidated() during the rendering of one frame.
722 /// Basically this means each call to display() must match a call to
723 /// clear_invalidated. This includes no-op display() calls, i.e. when the
724 /// DisplayObject is outside of the screen. The DisplayList must still call
725 /// clear_invalidated() even if display() is not necessary.
727 /// Not doing so will result in a stale invalidated flag which in turn will
728 /// prevent the parent to be informed when this DisplayObject (or a
729 /// child) is invalidated again (see set_invalidated() recursion).
730 void clear_invalidated() {
731 _invalidated = false;
732 _child_invalidated = false;
733 m_old_invalidated_ranges.setNull();
736 /// \brief
737 /// Add the DisplayObject's invalidated bounds *to* the given ranges list.
739 /// NOTE that this method should include the bounds that it
740 /// covered the last time clear_invalidated() was called,
741 /// as those need to be rerendered as well (to clear the region
742 /// previously occupied by this DisplayObject).
744 /// That's why it returns the *union* of old_invalidated_ranges and
745 /// the current bounds. The function is also used internally by
746 /// set_invalidated() to update m_old_invalidated_ranges itself (you may
747 /// notice some kind of circular reference), but that's no problem since
748 /// old_invalidated_ranges is NULL during that call.
750 /// It is used to determine what area needs to be re-rendered.
751 /// The coordinates are world coordinates (in TWIPS).
752 /// Only instances with _invalidated flag set are checked unless
753 /// force is set.
755 virtual void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
757 /// Called instead of display() when the DisplayObject is not visible
758 /// on stage.
759 /// Used to clear the invalidated flags.
760 virtual void omit_display() { clear_invalidated(); };
762 /// Callback invoked whenever a DisplayObject is placed on stage
764 /// This function must be called when the DisplayObject is placed on
765 /// stage for the first time.
767 /// The DisplayObject version of this call sets the original target
768 /// of the DisplayObject, for soft references to work.
769 /// If you override the method remember to call saveOriginalTarget()
770 /// as the first thing.
772 /// This handles all ActionScript construction and initialization events.
773 virtual void construct(as_object* /*init*/ = 0)
775 saveOriginalTarget();
778 /// Unload this instance from the stage.
780 /// This function must be called when the DisplayObject is removed
781 /// from the stage.
782 /// It will take care of properly calling
783 /// unload against any child DisplayObjects and queuing the
784 /// 'UNLOAD' event handler.
786 /// @return true if any onUnload event handler was defined
787 /// by either this or any child DisplayObjects, false
788 /// otherwise.
789 bool unload();
791 /// Accept a loaded Movie
792 virtual void getLoadedMovie(Movie* newMovie);
794 /// Return true if this DisplayObject was unloaded from the stage
795 bool unloaded() const {
796 return _unloaded;
799 /// Mark this DisplayObject as destroyed
801 /// A DisplayObject should be destroyed when is removed from the display
802 /// list and is not more needed for names (target) resolutions.
803 /// Sprites are needed for names resolution whenever themselves
804 /// or a contained object has an onUnload event handler defined,
805 /// in which case we want the event handler to find the 'this'
806 /// variable w/out attempting to rebind it.
808 /// Note: this function can safely release most memory associated
809 /// with the DisplayObject as it will not be needed anymore.
811 virtual void destroy();
813 /// Return true if this DisplayObject was destroyed.
815 /// See destroy() for more info.
817 bool isDestroyed() const { return _destroyed; }
819 /// Returns true when the DisplayObject bounds intersect with the current
820 /// rendering clipping area.
822 /// There is no need to do any rendering for this DisplayObject when this
823 /// function returns false because the renderer will not change any pixels
824 /// in the area where this DisplayObject is placed.
825 bool boundsInClippingArea(Renderer& renderer) const;
827 /// Return full path to this object, in slash notation
829 /// e.g. "/sprite1/sprite2/ourSprite"
831 std::string getTargetPath() const;
833 /// Return original target path to this object, in dot notation
834 /// as of at construction time.
836 /// This is needed to properly dereference dangling soft-references
837 /// See testcase misc-swfc.all/soft_reference_test1.sc
839 const std::string& getOrigTarget() const
841 return _origTarget;
844 /// Return full path to this object, in dot notation
846 /// e.g. "_level0.sprite1.sprite2.ourSprite"
848 std::string DSOEXPORT getTarget() const;
850 /// Return true if this DisplayObject is a selectable TextField
852 /// This method is used by Gui to set up an appropriate cursor
853 /// for input textfields.
855 virtual bool isSelectableTextField() const { return false; }
857 /// \brief
858 /// Return true if this DisplayObject allows turning the cursor
859 /// into an hand shape when it happens to be the one receiving
860 /// mouse events.
861 bool DSOEXPORT allowHandCursor() const;
863 #ifdef USE_SWFTREE
864 typedef tree<std::pair<std::string, std::string> > InfoTree;
865 /// Append DisplayObject info in the tree
867 /// @param tr
868 /// The tree to append movie to
870 /// @param it
871 /// The iterator to append info to.
873 /// @return iterator the appended subtree
874 virtual InfoTree::iterator getMovieInfo(InfoTree& tr,
875 InfoTree::iterator it);
876 #endif
878 /// Used to assign a name to unnamed instances
879 ObjectURI getNextUnnamedInstanceName();
881 enum BlendMode
883 BLENDMODE_UNDEFINED = 0,
884 BLENDMODE_NORMAL = 1,
885 BLENDMODE_LAYER,
886 BLENDMODE_MULTIPLY,
887 BLENDMODE_SCREEN,
888 BLENDMODE_LIGHTEN,
889 BLENDMODE_DARKEN,
890 BLENDMODE_DIFFERENCE,
891 BLENDMODE_ADD,
892 BLENDMODE_SUBTRACT,
893 BLENDMODE_INVERT,
894 BLENDMODE_ALPHA,
895 BLENDMODE_ERASE,
896 BLENDMODE_OVERLAY,
897 BLENDMODE_HARDLIGHT = 14
900 BlendMode getBlendMode() const {
901 return _blendMode;
904 void setBlendMode(BlendMode bm) {
905 _blendMode = bm;
908 // action_buffer is externally owned
909 typedef std::vector<const action_buffer*> BufferList;
910 typedef std::map<event_id, BufferList> Events;
912 /// Set the current focus to this DisplayObject.
914 /// @return false if the DisplayObject cannot receive focus, true if it can
915 /// (and does).
917 /// Button, Textfield and MovieClip can receive focus. In SWF6 and above,
918 /// MovieClip can only receive focus if the focusEnabled property
919 /// evaluates to true.
920 virtual bool handleFocus() {
921 return false;
924 /// Some DisplayObjects require actions on losing focus.
926 /// Default is a no-op. TextField implements this function.
927 virtual void killFocus() {}
929 double rotation() const {
930 return _rotation;
933 double scaleX() const {
934 return _xscale;
937 double scaleY() const {
938 return _yscale;
941 as_object* object() const {
942 return _object;
945 /// Getter-setter for blendMode.
946 static as_value blendMode(const fn_call& fn);
948 /// Mark all reachable resources.
950 /// Try not to override this function in derived classes. This always
951 /// marks the base class's resources and calls markOwnResources() to
952 /// take care of any further GC resources.
953 virtual void markReachableResources() const;
955 /// Called by markReachableResources()
957 /// DisplayObjects should mark their own resources in this function.
958 virtual void markOwnResources() const {}
960 protected:
962 /// Render a dynamic mask for a specified DisplayObject
964 /// Dynamic masks are rendered out-of-turn when the object they are masking
965 /// is drawn.
967 /// A MaskRenderer object should be constructed at the beginning of
968 /// relevant display() functions; it then takes care of rendering the
969 /// mask with the appropriate transform and cleaning up afterwards.
970 class MaskRenderer
972 public:
973 MaskRenderer(Renderer& r, const DisplayObject& o);
974 ~MaskRenderer();
975 private:
976 Renderer& _renderer;
977 DisplayObject* _mask;
980 virtual bool unloadChildren() { return false; }
982 /// Get the movie_root to which this DisplayObject belongs.
983 movie_root& stage() const {
984 return _stage;
987 /// Register currently computable target as
988 /// the "original" one. This will be used by
989 /// soft references (as_value) and should be
990 /// called as soon as the stagePlacementCallback
991 /// is invoked.
993 void saveOriginalTarget()
995 _origTarget=getTarget();
998 const Events& get_event_handlers() const
1000 return _event_handlers;
1003 void set_event_handlers(const Events& copyfrom);
1005 /// Name of this DisplayObject (if any)
1006 ObjectURI _name;
1008 DisplayObject* _parent;
1010 /// look for '.', 'this', '..', '_parent', '_level0' and '_root'
1012 /// NOTE: case insensitive up to SWF6, sensitive from SWF7 up
1014 as_object* getPathElementSeparator(string_table::key key);
1016 /// \brief
1017 /// Bounds of this DisplayObject instance before first invalidation
1018 /// since last call to clear_invalidated().
1020 /// This stores the bounds of the DisplayObject before it has been
1021 /// changed, ie. the position when set_invalidated() is being called.
1022 /// While drawing, both the old and the new bounds are updated (rendered).
1023 /// When moving a DisplayObject A to B then both the position A needs
1024 /// to be re-rendered (to reveal the backgrond) and the position B
1025 /// needs to be re-rendered (to show the DisplayObject in its new
1026 /// position). The bounds may be identical or overlap, but
1027 /// SnappingRanges takes care of that.
1028 ///
1029 /// Will be set by set_invalidated() and used by
1030 /// get_invalidated_bounds().
1031 InvalidatedRanges m_old_invalidated_ranges;
1033 private:
1035 /// Register a DisplayObject masked by this instance
1036 void setMaskee(DisplayObject* maskee);
1038 /// The as_object to which this DisplayObject is attached.
1039 as_object* _object;
1041 /// The movie_root to which this DisplayObject belongs.
1042 movie_root& _stage;
1044 Transform _transform;
1046 Events _event_handlers;
1048 /// Cache values for ActionScript access.
1049 /// NOTE: not all DisplayObjects need this, just the
1050 /// ones which are ActionScript-referenceable
1051 double _xscale, _yscale, _rotation;
1053 /// The depth of this DisplayObject.
1054 boost::int32_t _depth;
1056 /// Volume control associated to this DisplayObject
1058 /// This is used by Sound objects
1060 /// NOTE: probably only ActionScript-referenceable DisplayObjects
1061 /// need this (assuming soft ref don't rebind to other
1062 /// kind of DisplayObjects).
1064 int _volume;
1066 boost::uint16_t _ratio;
1067 int m_clip_depth;
1069 /// The DisplayObject masking this instance (if any)
1070 DisplayObject* _mask;
1072 /// The DisplayObject masked by this instance (if any)
1073 DisplayObject* _maskee;
1075 /// Original target, as at construction time
1076 std::string _origTarget;
1078 BlendMode _blendMode;
1080 bool _visible;
1082 /// Whether this DisplayObject has been transformed by ActionScript code
1084 /// Once we've been moved by ActionScript,
1085 /// Don't accept moves from anim tags (PlaceObject)
1087 /// See get_accept_anim_moves() function
1089 bool _scriptTransformed;
1091 bool _dynamicallyCreated;
1093 /// Set to yes when this instance has been unloaded
1094 bool _unloaded;
1096 /// This flag should be set to true by a call to destroy()
1097 bool _destroyed;
1099 /// \brief
1100 /// Set when the visual aspect of this particular DisplayObject or movie
1101 /// has been changed and redrawing is necessary.
1103 /// This is initialized to true as the initial state for
1104 /// any DisplayObject is the "invisible" state (it wasn't there)
1105 /// so it starts in invalidated mode.
1107 bool _invalidated;
1109 /// Just like _invalidated but set when a child is invalidated instead
1110 /// of this DisplayObject instance. _invalidated and _child_invalidated
1111 /// can be set at the same time.
1112 bool _child_invalidated;
1117 /// Get local transform SWFMatrix for this DisplayObject
1118 inline const SWFMatrix&
1119 getMatrix(const DisplayObject& o)
1121 return o.transform().matrix;
1124 inline const SWFCxForm&
1125 getCxForm(const DisplayObject& o)
1127 return o.transform().colorTransform;
1130 inline SWFMatrix
1131 getWorldMatrix(const DisplayObject& d, bool includeRoot)
1133 SWFMatrix m = d.parent() ?
1134 getWorldMatrix(*d.parent(), includeRoot) : SWFMatrix();
1136 if (d.parent() || includeRoot) m.concatenate(getMatrix(d));
1137 return m;
1140 inline SWFCxForm
1141 getWorldCxForm(const DisplayObject& d)
1143 SWFCxForm cx = d.parent() ? getWorldCxForm(*d.parent()) : SWFCxForm();
1144 cx.concatenate(getCxForm(d));
1145 return cx;
1148 inline bool
1149 isReferenceable(const DisplayObject& d)
1151 return d.object();
1154 /// Return the as_object associated with a DisplayObject if it exists
1156 /// @param d The DisplayObject to check. May be null.
1157 /// @return null if either the DisplayObject or the associated object is
1158 /// null. Otherwise the associated object.
1159 inline as_object*
1160 getObject(const DisplayObject* d)
1162 return d ? d->object() : 0;
1165 /// Stream operator for DisplayObject blend mode.
1166 std::ostream&
1167 operator<<(std::ostream& o, DisplayObject::BlendMode bm);
1169 } // end namespace gnash
1172 #ifdef DEBUG_SET_INVALIDATED
1173 #define set_invalidated() set_invalidated(__FILE__, __LINE__)
1174 #endif
1177 #endif // GNASH_CHARACTER_H
1180 // Local Variables:
1181 // mode: C++
1182 // indent-tabs-mode: t
1183 // End: