Flag an error if the FB gui is configured without the rawfb device. For #108015.
[gnash.git] / libcore / DisplayList.h
bloba316e19e7c88c33947680db727f6ed80e81e8295
1 // dlist.h: Display list definitions, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
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_DLIST_H
21 #define GNASH_DLIST_H
23 #include "snappingrange.h"
25 #include <string>
26 #include <list>
27 #include <iosfwd>
28 #if GNASH_PARANOIA_LEVEL > 1 && !defined(NDEBUG)
29 #include "DisplayObject.h"
30 #include <set> // for testInvariant
31 #include <algorithm>
32 #include "log.h"
33 #endif
35 // GNASH_PARANOIA_LEVEL:
36 // 0 : (not unimplemented)
37 // 1 : quick assertions
38 // 2 : add testInvariant
40 #ifndef GNASH_PARANOIA_LEVEL
41 # define GNASH_PARANOIA_LEVEL 1
42 #endif
44 namespace gnash {
45 class SWFCxForm;
46 class Renderer;
47 struct ObjectURI;
48 class Transform;
49 class string_table;
50 class DisplayObject;
51 class SWFMatrix;
54 namespace gnash {
56 /// A list of on-stage DisplayObjects, ordered by depth
58 /// Any MovieClip has an associated DisplayList
59 /// that may change from frame to frame due to control
60 /// tags instructing when to add or remove DisplayObjects
61 /// from the stage.
62 ///
63 class DisplayList
66 public:
68 typedef std::list<DisplayObject*> container_type;
69 typedef container_type::iterator iterator;
70 typedef container_type::const_iterator const_iterator;
71 typedef container_type::reverse_iterator reverse_iterator;
72 typedef container_type::const_reverse_iterator const_reverse_iterator;
74 DisplayList() {}
75 ~DisplayList() {}
77 /// Output operator
78 friend std::ostream& operator<< (std::ostream&, const DisplayList&);
80 /// \brief
81 /// Place a new DisplayObject at the specified depth,
82 /// replacing any existing DisplayObject at the same depth.
84 /// If a DisplayObject is replaced, it's unload() method
85 /// is invoked.
86 ///
87 /// If applicable, the event_id::LOAD event
88 /// associated with the given DisplayObject
89 /// is called as last step of addition.
90 ///
91 /// @param ch
92 /// the new DisplayObject to be added into the list.
93 ///
94 /// @param depth
95 /// depth at which the new DisplayObject is placed.
96 void placeDisplayObject(DisplayObject* ch, int depth);
98 /// \brief
99 /// Replace the old DisplayObject at the specified depth with
100 /// the given new DisplayObject.
102 /// Calls unload on the removed DisplayObject.
104 /// @param ch
105 /// the new DisplayObject to be put
107 /// @param depth
108 /// depth to be replaced
110 /// @param use_old_cxform
111 /// true: set the new DisplayObject's SWFCxForm to the old one.
112 /// false: keep the new DisplayObject's SWFCxForm.
114 /// @param use_old_matrix
115 /// true: set the new DisplayObject's transformation SWFMatrix to the old one.
116 /// false: keep the new DisplayObject's transformation SWFMatrix.
117 void replaceDisplayObject(DisplayObject* ch, int depth, bool use_old_cxform,
118 bool use_old_matrix);
120 /// \brief
121 /// Change depth of the given DisplayObjects in the list,
122 /// swapping with any existing DisplayObject at target depth.
124 /// List ordering will be maintained by this function.
126 /// Any DisplayObject affected by this operation (none on invalid call,
127 /// 1 if new depth is not occupied, 2 otherwise) will be:
128 /// - bounds invalidated (see DisplayObject::set_invalidated)
129 /// - marked as script-transformed (see DisplayObject::transformedByScript)
130 ///
131 /// @param ch
132 /// The DisplayObject to apply depth swapping to.
133 /// If not found in the list, an error is raised
134 /// and no other action is taken.
136 /// @param depth
137 /// The new depth to assign to the given DisplayObject.
138 /// If occupied by another DisplayObject, the target DisplayObject
139 /// will get the current depth of the first.
140 /// If target depth equals the current depth of DisplayObject, an
141 /// assertion fails, as I think the caller should check this instead.
143 void swapDepths(DisplayObject* ch, int depth);
145 /// \brief
146 /// Updates the transform properties of the object at the
147 /// specified depth, unless its get_accept_anim_moves() returns false.
149 /// See DisplayObject::get_accept_anim_moves()
151 /// @param color_xform
152 /// The color tranform to assign to the DisplayObject at the given depth.
153 /// If NULL the orignial color transform will be kept.
155 /// @param mat
156 /// The SWFMatrix tranform to assign to the DisplayObject at the given depth.
157 /// If NULL the orignial SWFMatrix will be kept.
159 /// @param ratio
160 /// The new ratio value to assign to the DisplayObject at the given depth.
161 /// If NULL the original ratio will be kept.
162 void moveDisplayObject(int depth, const SWFCxForm* color_xform,
163 const SWFMatrix* mat, boost::uint16_t* ratio);
165 /// Removes the object at the specified depth.
167 /// Calls unload on the removed DisplayObject.
168 void removeDisplayObject(int depth);
170 /// Remove all unloaded DisplayObject from the list
172 /// Removed DisplayObjects still in the list are those
173 /// on which onUnload event handlers were defined..
175 /// NOTE: we don't call the function recursively in the
176 /// contained elements, as that should not be needed
177 /// (ie: any inned thing will not be accessible anyway)
178 void removeUnloaded();
180 /// Unload the DisplayObjects in this DisplayList removing
181 /// all but the ones with on onUnload event defined
182 /// (checked by calling ::unload on them) and keeping
183 /// the others, w/out depth-shifting them.
185 /// Return true if any child was kept (as they had onUnload defined)
186 bool unload();
188 /// destroy all DisplayObjects in this DisplayList
189 void destroy();
191 /// Add a DisplayObject in the list, maintaining depth-order
194 /// @param ch
195 /// The DisplayObject to add
197 /// @param replace
198 /// If true the given DisplayObject would replace any
199 /// pre-existing DisplayObject at the same depth.
200 void add(DisplayObject* ch, bool replace);
202 /// Inserts a DisplayObject at the specified index (depth)
204 /// If a DisplayObject is already at that index, it is moved up.
205 /// This implements AS3 DisplayObjectContainer.addChildAt().
207 /// @param obj The DisplayObject to insert. This should already be
208 /// removed from any other DisplayLists. It should not be
209 /// the owner of this DisplayList or any parent of that
210 /// owner.
211 /// @param index The index at which to insert the DisplayObject.
212 void insertDisplayObject(DisplayObject* obj, int index);
214 /// Display the list's DisplayObjects.
216 /// Lower depths are obscured by higher depths.
217 void display(Renderer& renderer, const Transform& xform);
219 void omit_display();
221 /// May return NULL.
222 DisplayObject* getDisplayObjectAtDepth(int depth) const;
224 /// If there are multiples, returns the *first* match only!
226 /// @param st
227 /// The string_table to use for finding
228 /// lowercase equivalent of names if
229 /// `caseless' parameter is true.
230 /// @param uri
231 /// Object identifier
232 /// @param caseless
233 /// Wheter comparison must be case-insensitive.
235 DisplayObject* getDisplayObjectByName(string_table& st,
236 const ObjectURI& uri, bool caseless) const;
238 /// \brief
239 /// Visit each DisplayObject in the list in reverse depth
240 /// order (higher depth first).
242 /// The visitor functor
243 /// will receive a DisplayObject pointer; must return true if
244 /// it wants next item or false
245 /// to exit the loop.
247 /// NOTE: all elements in the list are visited, even
248 /// the removed ones (unloaded)
249 /// TODO: inspect if worth providing an arg to skip removed
250 template <class V> inline void visitBackward(V& visitor);
251 template <class V> inline void visitBackward(V& visitor) const;
253 /// \brief
254 /// Visit each and all DisplayObject in the list.
256 /// Scan happens in arbitrary order, if order is
257 /// important use visitBackward or visitForward
259 /// The visitor functor will receive a DisplayObject pointer,
260 /// it's return value is not used so can return void.
262 /// NOTE: all elements in the list are visited, even
263 /// the removed ones (unloaded)
264 /// TODO: inspect if worth providing an arg to skip removed
265 template <class V> inline void visitAll(V& visitor);
266 template <class V> inline void visitAll(V& visitor) const;
268 /// Like DisplayObject_instance::add_invalidated_bounds() this method calls the
269 /// method with the same name of all childs.
270 void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
272 /// Return number of elements in the list
273 size_t size() const {
274 return _charsByDepth.size();
277 /// Return true if the list contains no elements
278 bool empty() const {
279 return _charsByDepth.empty();
282 /// Return the next highest available depth
284 /// Placing an object at the depth returned by
285 /// this function should result in a DisplayObject
286 /// that is displayd above all others
288 int getNextHighestDepth() const;
290 /// Merge the given display list
292 /// Call set_invalidated on the given DisplayObject if this list changes
294 void mergeDisplayList(DisplayList& newList, DisplayObject& o);
296 bool operator==(const DisplayList& other) const {
297 return _charsByDepth == other._charsByDepth;
300 bool operator!=(const DisplayList& other) const {
301 return _charsByDepth != other._charsByDepth;
304 #if GNASH_PARANOIA_LEVEL > 1 && !defined(NDEBUG)
305 DisplayList::const_iterator nonRemoved() const;
307 void testInvariant() const
309 DisplayList sorted = *this;
311 // check no duplicated depths above non-removed zone.
312 std::set<int> depths;
313 for (const_iterator it = nonRemoved(),
314 itEnd = _charsByDepth.end(); it != itEnd; ++it) {
316 DisplayObject* ch = *it;
317 int depth = ch->get_depth();
318 if (!depths.insert(depth).second) {
319 log_debug("Depth %d is duplicated in DisplayList %p",
320 depth, (const void*)this);
321 std::abort();
324 if (_charsByDepth.empty()) return;
325 // check we didn't screw up ordering
326 assert(std::adjacent_find(_charsByDepth.begin(), _charsByDepth.end(),
327 DepthGreaterThan()) == _charsByDepth.end());
329 #else
330 void testInvariant() const {}
331 #endif
333 private:
335 /// Re-insert a removed-from-stage DisplayObject after appropriately
336 /// shifting its depth based on the DisplayObject::removedDepthOffset
337 /// value.
339 /// PRE-CONDITIONS
340 /// - ch::isUnloaded() returns true (assertion fails otherwise)
341 /// - ch is not already in the list (assertion fails otherwise)
343 /// TODO: inspect what should happen if the target depth is already
344 /// occupied
345 void reinsertRemovedCharacter(DisplayObject* ch);
347 container_type _charsByDepth;
350 template <class V>
351 void
352 DisplayList::visitBackward(V& visitor)
354 for (reverse_iterator it = _charsByDepth.rbegin(),
355 itEnd = _charsByDepth.rend(); it != itEnd; ++it) {
356 if (!visitor(*it)) break;
360 template <class V>
361 void
362 DisplayList::visitBackward(V& visitor) const
364 for (const_reverse_iterator it = _charsByDepth.rbegin(),
365 itEnd = _charsByDepth.rend(); it != itEnd; ++it) {
366 if (!visitor(*it)) break;
370 template <class V>
371 void
372 DisplayList::visitAll(V& visitor)
374 for (iterator it = _charsByDepth.begin(), itEnd = _charsByDepth.end();
375 it != itEnd; ++it) {
377 visitor(*it);
381 template <class V>
382 void
383 DisplayList::visitAll(V& visitor) const
385 for (const_iterator it = _charsByDepth.begin(),
386 itEnd = _charsByDepth.end(); it != itEnd; ++it) {
388 visitor(*it);
392 std::ostream& operator<< (std::ostream&, const DisplayList&);
394 } // namespace gnash
397 #endif // GNASH_DLIST_H
401 // Local Variables:
402 // mode: C++
403 // c-basic-offset: 8
404 // tab-width: 8
405 // indent-tabs-mode: t
406 // End: