~ubuntu-branches/ubuntu/karmic/gnash/karmic

« back to all changes in this revision

Viewing changes to libcore/DisplayList.h

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2008-10-13 14:29:49 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20081013142949-f6qdvnu4mn05ltdc
Tags: 0.8.4~~bzr9980-0ubuntu1
* new upstream release 0.8.4 (LP: #240325)
* ship new lib usr/lib/gnash/libmozsdk.so.* in mozilla-plugin-gnash
  - update debian/mozilla-plugin-gnash.install
* ship new lib usr/lib/gnash/libgnashnet.so.* in gnash-common
  - update debian/gnash-common.install
* add basic debian/build_head script to build latest CVS head packages.
  - add debian/build_head
* new sound architecture requires build depend on libsdl1.2-dev
  - update debian/control
* head build script now has been completely migrated to bzr (upstream +
  ubuntu)
  - update debian/build_head
* disable kde gui until klash/qt4 has been fixed; keep kde packages as empty
  packages for now.
  - update debian/rules
  - debian/klash.install
  - debian/klash.links
  - debian/klash.manpages
  - debian/konqueror-plugin-gnash.install
* drop libkonq5-dev build dependency accordingly
  - update debian/control
* don't install headers manually anymore. gnash doesnt provide a -dev
  package after all
  - update debian/rules
* update libs installed in gnash-common; libgnashserver-*.so is not available
  anymore (removed); in turn we add the new libgnashcore-*.so
  - update debian/gnash-common.install
* use -Os for optimization and properly pass CXXFLAGS=$(CFLAGS) to configure
  - update debian/rules
* touch firefox .autoreg in postinst of mozilla plugin
  - update debian/mozilla-plugin-gnash.postinst
* link gnash in ubufox plugins directory for the plugin alternative switcher
  - add debian/mozilla-plugin-gnash.links
* suggest ubufox accordingly
  - update debian/control
* add new required build-depends on libgif-dev
  - update debian/control
* add Xb-Npp-Description and Xb-Npp-File as new plugin database meta data
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// dlist.h:  Display list definitions, for Gnash.
 
2
// 
 
3
//   Copyright (C) 2005, 2006, 2007, 2008 Free Software 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
 
18
//
 
19
 
 
20
#ifndef GNASH_DLIST_H
 
21
#define GNASH_DLIST_H
 
22
 
 
23
#include "types.h"
 
24
#include "impl.h"
 
25
#include "snappingrange.h"
 
26
#include "character.h"
 
27
 
 
28
#include <list>
 
29
#include <iosfwd>
 
30
#ifndef NDEBUG
 
31
#include "log.h"
 
32
#include <set>  // for testInvariant
 
33
#endif
 
34
 
 
35
// GNASH_PARANOIA_LEVEL:
 
36
// 0 : (not unimplemented)
 
37
// 1 : quick assertions
 
38
// 2 : add testInvariant
 
39
//
 
40
#ifndef GNASH_PARANOIA_LEVEL
 
41
# define GNASH_PARANOIA_LEVEL 1
 
42
#endif
 
43
 
 
44
namespace gnash {
 
45
        class cxform;
 
46
}
 
47
 
 
48
namespace gnash {
 
49
 
 
50
/// A DisplayItem is simply a character object 
 
51
typedef boost::intrusive_ptr<character> DisplayItem;
 
52
 
 
53
/// A list of on-stage characters, ordered by depth
 
54
//
 
55
/// Any sprite_instance has an associated DisplayList
 
56
/// that may change from frame to frame due to control
 
57
/// tags instructing when to add or remove characters
 
58
/// from the stage.
 
59
///
 
60
class DisplayList {
 
61
 
 
62
public:
 
63
 
 
64
        void testInvariant() const
 
65
        {
 
66
#if GNASH_PARANOIA_LEVEL > 1
 
67
#ifndef NDEBUG
 
68
                DisplayList sorted = *this;
 
69
                // check no duplicated depths above non-removed zone.
 
70
                std::set<int> depths;
 
71
                for (const_iterator it=beginNonRemoved(_charsByDepth), itEnd=_charsByDepth.end(); it!=itEnd; ++it)
 
72
                {
 
73
                        boost::intrusive_ptr<character> ch = *it;
 
74
                        int depth = ch->get_depth();
 
75
                        if ( ! depths.insert(depth).second )
 
76
                        {
 
77
                                log_debug("Depth %d is duplicated in DisplayList %p", depth, (const void*)this);
 
78
                                abort();
 
79
                        }
 
80
                }
 
81
                assert(isSorted()); // check we didn't screw up ordering
 
82
#endif
 
83
#endif // GNASH_PARANOIA_LEVEL > 1
 
84
        }
 
85
 
 
86
        /// Output operator
 
87
        friend std::ostream& operator<< (std::ostream&, const DisplayList&);
 
88
 
 
89
        /// \brief
 
90
        /// Place a new character at the specified depth,
 
91
        /// replacing any existing character at the same depth.
 
92
        //
 
93
        /// If a character is replaced, it's unload() method
 
94
        /// is invoked.
 
95
        ///
 
96
        /// If applicable, the event_id::LOAD event
 
97
        /// associated with the given character
 
98
        /// is called as last step of addition. 
 
99
        ///
 
100
        /// @param ch 
 
101
        ///     the new character to be added into the list.
 
102
        ///
 
103
        /// @param depth 
 
104
        ///     depth at which the new character is placed.
 
105
        ///
 
106
        void    place_character(character* ch, int depth);
 
107
 
 
108
        /// \brief
 
109
        /// Replace the old character at the specified depth with
 
110
        /// the given new character.
 
111
        //
 
112
        /// Calls unload on the removed character.
 
113
        ///
 
114
        /// @param ch 
 
115
        ///     the new character to be put
 
116
        ///
 
117
        /// @param depth 
 
118
        ///     depth to be replaced
 
119
        ///
 
120
        /// @param use_old_cxform
 
121
        /// true:  set the new character's cxform to the old one.
 
122
        /// false: keep the new character's cxform.
 
123
        ///
 
124
        /// @param use_old_matrix
 
125
        /// true:  set the new character's transformation matrix to the old one.
 
126
        /// false: keep the new character's transformation matrix.
 
127
        ///
 
128
        void replace_character(character* ch, int depth, 
 
129
                bool use_old_cxform,
 
130
                bool use_old_matrix);
 
131
 
 
132
        /// \brief
 
133
        /// Change depth of the given characters in the list,
 
134
        /// swapping with any existing character at target depth.
 
135
        //
 
136
        /// List ordering will be maintained by this function.
 
137
        ///
 
138
        /// Any character affected by this operation (none on invalid call,
 
139
        /// 1 if new depth is not occupied, 2 otherwise) will be:
 
140
        ///     - bounds invalidated (see character::set_invalidated)
 
141
        ///     - marked as script-transformed (see character::transformedByScript)
 
142
        /// 
 
143
        /// @param ch
 
144
        ///     The character to apply depth swapping to.
 
145
        ///     If not found in the list, an error is raised
 
146
        ///     and no other action is taken.
 
147
        ///
 
148
        /// @param depth
 
149
        ///     The new depth to assign to the given character.
 
150
        ///     If occupied by another character, the target character
 
151
        ///     will get the current depth of the first.
 
152
        ///     If target depth equals the current depth of character, an
 
153
        ///     assertion fails, as I think the caller should check this instead.
 
154
        ///
 
155
        void swapDepths(character* ch, int depth);
 
156
 
 
157
        /// \brief
 
158
        /// Updates the transform properties of the object at the
 
159
        /// specified depth, unless its get_accept_anim_moves() returns false.
 
160
        //
 
161
        ///  See character::get_accept_anim_moves()
 
162
        ///
 
163
        /// @param color_xform
 
164
        ///     The color tranform to assign to the character at the given depth.
 
165
        ///     If NULL the orignial color transform will be kept.
 
166
        //
 
167
        /// @param mat
 
168
        ///     The matrix tranform to assign to the character at the given depth.
 
169
        ///     If NULL the orignial matrix will be kept.
 
170
        ///
 
171
        /// @param ratio
 
172
        /// The new ratio value to assign to the character at the given depth.
 
173
        /// If NULL the original ratio will be kept.
 
174
        ///
 
175
        /// @clip_depth
 
176
        /// Not used at the moment.
 
177
        /// 
 
178
        void    move_character(
 
179
                int depth,
 
180
                const cxform* color_xform,
 
181
                const matrix* mat,
 
182
                int* ratio,
 
183
                int* clip_depth);
 
184
 
 
185
        /// Removes the object at the specified depth.
 
186
        //
 
187
        /// Calls unload on the removed character.
 
188
        ///
 
189
        void    remove_character(int depth);
 
190
 
 
191
        /// Remove all unloaded character from the list
 
192
        //
 
193
        /// Removed characters still in the list are those
 
194
        /// on which onUnload event handlers were defined..
 
195
        ///
 
196
        /// NOTE: we don't call the function recursively in the 
 
197
        ///       contained elements, as that should not be needed
 
198
        ///       (ie: any inned thing will not be accessible anyway)
 
199
        ///
 
200
        void removeUnloaded();
 
201
 
 
202
        /// Unload the characters in this DisplayList removing
 
203
        /// all but the ones with on onUnload event defined
 
204
        /// (checked by calling ::unload on them) and keeping
 
205
        /// the others, w/out depth-shifting them.
 
206
        ///
 
207
        /// Return true if any child was kept (as they had onUnload defined)
 
208
        ///
 
209
        bool unload();
 
210
 
 
211
        /// destroy all characters in this DisplayList
 
212
        void destroy();
 
213
 
 
214
        /// Add all characters in the list, maintaining depth-order
 
215
        //
 
216
        /// @param chars
 
217
        ///     The characters to add
 
218
        ///
 
219
        /// @param replace
 
220
        ///     If true the given characters would replace any
 
221
        ///     pre-existing character at the same depth.
 
222
        ///
 
223
        void addAll(std::vector<character*>& chars, bool replace);
 
224
 
 
225
        /// Add a character in the list, maintaining depth-order
 
226
        //
 
227
        ///
 
228
        /// @param ch
 
229
        ///     The character to add
 
230
        ///
 
231
        /// @param replace
 
232
        ///     If true the given character would replace any
 
233
        ///     pre-existing character at the same depth.
 
234
        ///
 
235
        void add(character* ch, bool replace);
 
236
 
 
237
        /// \brief
 
238
        /// Display the referenced characters.
 
239
        /// Lower depths are obscured by higher depths.
 
240
        void display();
 
241
        
 
242
        void omit_display();
 
243
 
 
244
        /// May return NULL.
 
245
        character* get_character_at_depth(int depth);
 
246
 
 
247
        const character* get_character_at_depth(int depth) const {
 
248
                return const_cast<DisplayList*>(this)->get_character_at_depth(depth);
 
249
        }
 
250
 
 
251
        /// \brief
 
252
        /// May return NULL.
 
253
        /// If there are multiples, returns the *first* match only!
 
254
        character* get_character_by_name(const std::string& name);
 
255
 
 
256
        const character* get_character_by_name(const std::string& name) const
 
257
        {
 
258
                return const_cast<DisplayList*>(this)->get_character_by_name(name);
 
259
        }
 
260
 
 
261
        /// \brief
 
262
        /// May return NULL.
 
263
        /// If there are multiples, returns the *first* match only!
 
264
        character* get_character_by_name_i(const std::string& name);
 
265
 
 
266
        /// \brief 
 
267
        /// Visit each character in the list in depth order
 
268
        /// (lower depth first).
 
269
        //
 
270
        /// The visitor functor will 
 
271
        /// receive a character pointer; must return true if
 
272
        /// it wants next item or false to exit the loop.
 
273
        ///
 
274
        /// NOTE: all elements in the list are visited, even
 
275
        ///       the removed ones (unloaded)
 
276
        /// TODO: inspect if worth providing an arg to skip removed
 
277
        ///
 
278
        template <class V>
 
279
        inline void visitForward(V& visitor);
 
280
 
 
281
        /// \brief 
 
282
        /// Visit each character in the list in reverse depth
 
283
        /// order (higher depth first).
 
284
        //
 
285
        /// The visitor functor
 
286
        /// will receive a character pointer; must return true if
 
287
        /// it wants next item or false
 
288
        /// to exit the loop.
 
289
        ///
 
290
        /// NOTE: all elements in the list are visited, even
 
291
        ///       the removed ones (unloaded)
 
292
        /// TODO: inspect if worth providing an arg to skip removed
 
293
        ///
 
294
        template <class V>
 
295
        inline void visitBackward(V& visitor);
 
296
        template <class V>
 
297
        inline void visitBackward(V& visitor) const;
 
298
 
 
299
        /// \brief 
 
300
        /// Visit each and all character in the list.
 
301
        //
 
302
        /// Scan happens in arbitrary order, if order is
 
303
        /// important use visitBackward or visitForward
 
304
        ///
 
305
        /// The visitor functor will receive a character pointer,
 
306
        /// it's return value is not used so can return void.
 
307
        ///
 
308
        /// NOTE: all elements in the list are visited, even
 
309
        ///       the removed ones (unloaded)
 
310
        /// TODO: inspect if worth providing an arg to skip removed
 
311
        ///
 
312
        template <class V>
 
313
        inline void visitAll(V& visitor);
 
314
 
 
315
        template <class V>
 
316
        inline void visitAll(V& visitor) const;
 
317
 
 
318
        /// dump list to logfile/stderr
 
319
        void dump() const;
 
320
 
 
321
  /// Like character_instance::add_invalidated_bounds() this method calls the
 
322
  /// method with the same name of all childs.  
 
323
        void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);     
 
324
        
 
325
        void dump_character_tree(const std::string prefix) const;
 
326
        
 
327
 
 
328
        /// Return number of elements in the list
 
329
        size_t size() const
 
330
        { 
 
331
                return _charsByDepth.size();
 
332
        }
 
333
 
 
334
        /// Return true if the list contains no elements 
 
335
        bool empty() const 
 
336
        {
 
337
                return _charsByDepth.empty();
 
338
        }
 
339
 
 
340
        /// Return the next highest available depth
 
341
        //
 
342
        /// Placing an object at the depth returned by
 
343
        /// this function should result in a character
 
344
        /// that is displayd above all others
 
345
        ///
 
346
        int getNextHighestDepth() const;
 
347
 
 
348
        /// Sort list by depth (lower depths first)
 
349
        //
 
350
        /// You only need calling this method if depth
 
351
        /// of characters on the list has been externally
 
352
        /// changed. Usually it is DisplayList itself
 
353
        /// assigning depths, so won't need to call it.
 
354
        ///
 
355
        /// A notable use for this is backing up a specific
 
356
        /// state and restoring it later. Restore step would
 
357
        /// need reordering.
 
358
        ///
 
359
        void sort ();
 
360
        
 
361
        /// \brief
 
362
        /// merge the given display list
 
363
        void mergeDisplayList(DisplayList& newList);
 
364
 
 
365
        bool operator==(const DisplayList& other) const { return _charsByDepth == other._charsByDepth; }
 
366
 
 
367
        bool operator!=(const DisplayList& other) const { return _charsByDepth != other._charsByDepth; }
 
368
 
 
369
private:
 
370
 
 
371
        typedef std::list<DisplayItem> container_type;
 
372
        typedef container_type::iterator iterator;
 
373
        typedef container_type::const_iterator const_iterator;
 
374
        typedef container_type::reverse_iterator reverse_iterator;
 
375
        typedef container_type::const_reverse_iterator const_reverse_iterator;
 
376
 
 
377
        /// Return an iterator to the first element of the container NOT in the "removed" depth zone
 
378
        static iterator beginNonRemoved(container_type& c);
 
379
 
 
380
        /// Return an constant iterator to the first element of the container NOT in the "removed" depth zone
 
381
        static const_iterator beginNonRemoved(const container_type& c);
 
382
 
 
383
        /// Return an iterator succeeding the last element in zone (-16384, 0xffff-16384)
 
384
        static iterator dlistTagsEffectivZoneEnd(container_type& c);
 
385
        
 
386
        /// Return an constant iterator succeeding the last element in (-16384, 0xffff-16384)
 
387
        static const_iterator dlistTagsEffectivZoneEnd(const container_type& c);
 
388
 
 
389
 
 
390
        /// Re-insert a removed-from-stage character after appropriately
 
391
        /// shifting its depth based on the character::removedDepthOffset
 
392
        /// value.
 
393
        //
 
394
        /// PRE-CONDITIONS 
 
395
        ///     - ch::isUnloaded() returns true (assertion fails otherwise)
 
396
        ///     - ch is not already in the list (assertion fails otherwise)
 
397
        ///
 
398
        /// TODO: inspect what should happen if the target depth is already occupied
 
399
        ///
 
400
        void reinsertRemovedCharacter(boost::intrusive_ptr<character> ch);
 
401
 
 
402
        container_type _charsByDepth;
 
403
 
 
404
        /// Check that the list is sorted by depth
 
405
        bool isSorted() const;
 
406
};
 
407
 
 
408
template <class V>
 
409
void
 
410
DisplayList::visitForward(V& visitor)
 
411
{
 
412
        for (iterator it = _charsByDepth.begin(),
 
413
                        itEnd = _charsByDepth.end();
 
414
                it != itEnd; ++it)
 
415
        {
 
416
                DisplayItem& di = *it;
 
417
                if ( ! visitor(di.get()) ) break;
 
418
        }
 
419
}
 
420
 
 
421
template <class V>
 
422
void
 
423
DisplayList::visitBackward(V& visitor)
 
424
{
 
425
        for (reverse_iterator it = _charsByDepth.rbegin(),
 
426
                        itEnd = _charsByDepth.rend();
 
427
                it != itEnd; ++it)
 
428
        {
 
429
                DisplayItem& di = *it;
 
430
                if ( ! visitor(di.get()) ) break;
 
431
        }
 
432
}
 
433
 
 
434
template <class V>
 
435
void
 
436
DisplayList::visitBackward(V& visitor) const
 
437
{
 
438
        for (const_reverse_iterator it = _charsByDepth.rbegin(),
 
439
                        itEnd = _charsByDepth.rend();
 
440
                it != itEnd; ++it)
 
441
        {
 
442
                const DisplayItem& di = *it;
 
443
                if ( ! visitor(di.get()) ) break;
 
444
        }
 
445
}
 
446
 
 
447
template <class V>
 
448
void
 
449
DisplayList::visitAll(V& visitor)
 
450
{
 
451
        for (iterator it = _charsByDepth.begin(),
 
452
                        itEnd = _charsByDepth.end();
 
453
                it != itEnd; ++it)
 
454
        {
 
455
                visitor(it->get());
 
456
        }
 
457
}
 
458
 
 
459
template <class V>
 
460
void
 
461
DisplayList::visitAll(V& visitor) const
 
462
{
 
463
        for (const_iterator it = _charsByDepth.begin(),
 
464
                        itEnd = _charsByDepth.end();
 
465
                it != itEnd; ++it)
 
466
        {
 
467
                visitor(it->get());
 
468
        }
 
469
}
 
470
 
 
471
std::ostream& operator<< (std::ostream&, const DisplayList&);
 
472
 
 
473
} // namespace gnash
 
474
 
 
475
 
 
476
#endif // GNASH_DLIST_H
 
477
 
 
478
 
 
479
 
 
480
// Local Variables:
 
481
// mode: C++
 
482
// c-basic-offset: 8 
 
483
// tab-width: 8
 
484
// indent-tabs-mode: t
 
485
// End: