1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: set ts=2 sw=2 et tw=78:
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Novell code.
17 : *
18 : * The Initial Developer of the Original Code is Novell Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2006
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * robert@ocallahan.org
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK *****
38 : */
39 :
40 : /*
41 : * structures that represent things to be painted (ordered in z-order),
42 : * used during painting and hit testing
43 : */
44 :
45 : #ifndef NSDISPLAYLIST_H_
46 : #define NSDISPLAYLIST_H_
47 :
48 : #include "nsCOMPtr.h"
49 : #include "nsIFrame.h"
50 : #include "nsPoint.h"
51 : #include "nsRect.h"
52 : #include "nsISelection.h"
53 : #include "nsCaret.h"
54 : #include "plarena.h"
55 : #include "Layers.h"
56 : #include "nsRegion.h"
57 : #include "FrameLayerBuilder.h"
58 : #include "nsThemeConstants.h"
59 :
60 : #include <stdlib.h>
61 :
62 : class nsIPresShell;
63 : class nsIContent;
64 : class nsRenderingContext;
65 : class nsDeviceContext;
66 : class nsDisplayTableItem;
67 : class nsDisplayItem;
68 :
69 : /*
70 : * An nsIFrame can have many different visual parts. For example an image frame
71 : * can have a background, border, and outline, the image itself, and a
72 : * translucent selection overlay. In general these parts can be drawn at
73 : * discontiguous z-levels; see CSS2.1 appendix E:
74 : * http://www.w3.org/TR/CSS21/zindex.html
75 : *
76 : * We construct a display list for a frame tree that contains one item
77 : * for each visual part. The display list is itself a tree since some items
78 : * are containers for other items; however, its structure does not match
79 : * the structure of its source frame tree. The display list items are sorted
80 : * by z-order. A display list can be used to paint the frames, to determine
81 : * which frame is the target of a mouse event, and to determine what areas
82 : * need to be repainted when scrolling. The display lists built for each task
83 : * may be different for efficiency; in particular some frames need special
84 : * display list items only for event handling, and do not create these items
85 : * when the display list will be used for painting (the common case). For
86 : * example, when painting we avoid creating nsDisplayBackground items for
87 : * frames that don't display a visible background, but for event handling
88 : * we need those backgrounds because they are not transparent to events.
89 : *
90 : * We could avoid constructing an explicit display list by traversing the
91 : * frame tree multiple times in clever ways. However, reifying the display list
92 : * reduces code complexity and reduces the number of times each frame must be
93 : * traversed to one, which seems to be good for performance. It also means
94 : * we can share code for painting, event handling and scroll analysis.
95 : *
96 : * Display lists are short-lived; content and frame trees cannot change
97 : * between a display list being created and destroyed. Display lists should
98 : * not be created during reflow because the frame tree may be in an
99 : * inconsistent state (e.g., a frame's stored overflow-area may not include
100 : * the bounds of all its children). However, it should be fine to create
101 : * a display list while a reflow is pending, before it starts.
102 : *
103 : * A display list covers the "extended" frame tree; the display list for a frame
104 : * tree containing FRAME/IFRAME elements can include frames from the subdocuments.
105 : */
106 :
107 : // All types are defined in nsDisplayItemTypes.h
108 : #ifdef MOZ_DUMP_PAINTING
109 : #define NS_DISPLAY_DECL_NAME(n, e) \
110 : virtual const char* Name() { return n; } \
111 : virtual Type GetType() { return e; }
112 : #else
113 : #define NS_DISPLAY_DECL_NAME(n, e) \
114 : virtual Type GetType() { return e; }
115 : #endif
116 :
117 : /**
118 : * This manages a display list and is passed as a parameter to
119 : * nsIFrame::BuildDisplayList.
120 : * It contains the parameters that don't change from frame to frame and manages
121 : * the display list memory using a PLArena. It also establishes the reference
122 : * coordinate system for all display list items. Some of the parameters are
123 : * available from the prescontext/presshell, but we copy them into the builder
124 : * for faster/more convenient access.
125 : */
126 : class nsDisplayListBuilder {
127 : public:
128 : typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
129 : typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
130 : typedef nsIWidget::ThemeGeometry ThemeGeometry;
131 :
132 : /**
133 : * @param aReferenceFrame the frame at the root of the subtree; its origin
134 : * is the origin of the reference coordinate system for this display list
135 : * @param aIsForEvents true if we're creating this list in order to
136 : * determine which frame is under the mouse position
137 : * @param aBuildCaret whether or not we should include the caret in any
138 : * display lists that we make.
139 : */
140 : enum Mode {
141 : PAINTING,
142 : EVENT_DELIVERY,
143 : PLUGIN_GEOMETRY,
144 : OTHER
145 : };
146 : nsDisplayListBuilder(nsIFrame* aReferenceFrame, Mode aMode, bool aBuildCaret);
147 : ~nsDisplayListBuilder();
148 :
149 : /**
150 : * @return true if the display is being built in order to determine which
151 : * frame is under the mouse position.
152 : */
153 0 : bool IsForEventDelivery() { return mMode == EVENT_DELIVERY; }
154 : /**
155 : * @return true if the display list is being built to compute geometry
156 : * for plugins.
157 : */
158 0 : bool IsForPluginGeometry() { return mMode == PLUGIN_GEOMETRY; }
159 : /**
160 : * @return true if the display list is being built for painting.
161 : */
162 0 : bool IsForPainting() { return mMode == PAINTING; }
163 : /**
164 : * @return true if "painting is suppressed" during page load and we
165 : * should paint only the background of the document.
166 : */
167 0 : bool IsBackgroundOnly() {
168 0 : NS_ASSERTION(mPresShellStates.Length() > 0,
169 : "don't call this if we're not in a presshell");
170 0 : return CurrentPresShellState()->mIsBackgroundOnly;
171 : }
172 : /**
173 : * @return true if the currently active BuildDisplayList call is being
174 : * applied to a frame at the root of a pseudo stacking context. A pseudo
175 : * stacking context is either a real stacking context or basically what
176 : * CSS2.1 appendix E refers to with "treat the element as if it created
177 : * a new stacking context
178 : */
179 0 : bool IsAtRootOfPseudoStackingContext() { return mIsAtRootOfPseudoStackingContext; }
180 :
181 : /**
182 : * @return the selection that painting should be restricted to (or nsnull
183 : * in the normal unrestricted case)
184 : */
185 0 : nsISelection* GetBoundingSelection() { return mBoundingSelection; }
186 : /**
187 : * @return the root of the display list's frame (sub)tree, whose origin
188 : * establishes the coordinate system for the display list
189 : */
190 0 : nsIFrame* ReferenceFrame() const { return mReferenceFrame; }
191 : /**
192 : * @return a point pt such that adding pt to a coordinate relative to aFrame
193 : * makes it relative to ReferenceFrame(), i.e., returns
194 : * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
195 : * the appunits of aFrame. It may be optimized to be faster than
196 : * aFrame->GetOffsetToCrossDoc(ReferenceFrame()) (but currently isn't).
197 : */
198 0 : nsPoint ToReferenceFrame(const nsIFrame* aFrame) const {
199 0 : return aFrame->GetOffsetToCrossDoc(ReferenceFrame());
200 : }
201 : /**
202 : * When building the display list, the scrollframe aFrame will be "ignored"
203 : * for the purposes of clipping, and its scrollbars will be hidden. We use
204 : * this to allow RenderOffscreen to render a whole document without beign
205 : * clipped by the viewport or drawing the viewport scrollbars.
206 : */
207 0 : void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
208 : /**
209 : * Get the scrollframe to ignore, if any.
210 : */
211 0 : nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
212 : /**
213 : * Calling this setter makes us include all out-of-flow descendant
214 : * frames in the display list, wherever they may be positioned (even
215 : * outside the dirty rects).
216 : */
217 0 : void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
218 0 : bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
219 : /**
220 : * Calling this setter makes us exclude all leaf frames that aren't
221 : * selected.
222 : */
223 0 : void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
224 0 : bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
225 : /**
226 : * Calling this setter makes us compute accurate visible regions at the cost
227 : * of performance if regions get very complex.
228 : */
229 0 : void SetAccurateVisibleRegions() { mAccurateVisibleRegions = true; }
230 0 : bool GetAccurateVisibleRegions() { return mAccurateVisibleRegions; }
231 : /**
232 : * Allows callers to selectively override the regular paint suppression checks,
233 : * so that methods like GetFrameForPoint work when painting is suppressed.
234 : */
235 0 : void IgnorePaintSuppression() { mIgnoreSuppression = true; }
236 : /**
237 : * @return Returns if this builder will ignore paint suppression.
238 : */
239 0 : bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; }
240 : /**
241 : * @return Returns if this builder had to ignore painting suppression on some
242 : * document when building the display list.
243 : */
244 0 : bool GetHadToIgnorePaintSuppression() { return mHadToIgnoreSuppression; }
245 : /**
246 : * Call this if we're doing normal painting to the window.
247 : */
248 0 : void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
249 0 : bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
250 : /**
251 : * Display the caret if needed.
252 : */
253 0 : nsresult DisplayCaret(nsIFrame* aFrame, const nsRect& aDirtyRect,
254 : nsDisplayList* aList) {
255 0 : nsIFrame* frame = GetCaretFrame();
256 0 : if (aFrame != frame) {
257 0 : return NS_OK;
258 : }
259 0 : return frame->DisplayCaret(this, aDirtyRect, aList);
260 : }
261 : /**
262 : * Get the frame that the caret is supposed to draw in.
263 : * If the caret is currently invisible, this will be null.
264 : */
265 0 : nsIFrame* GetCaretFrame() {
266 0 : return CurrentPresShellState()->mCaretFrame;
267 : }
268 : /**
269 : * Get the caret associated with the current presshell.
270 : */
271 : nsCaret* GetCaret();
272 : /**
273 : * Notify the display list builder that we're entering a presshell.
274 : * aReferenceFrame should be a frame in the new presshell and aDirtyRect
275 : * should be the current dirty rect in aReferenceFrame's coordinate space.
276 : */
277 : void EnterPresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect);
278 : /**
279 : * Notify the display list builder that we're leaving a presshell.
280 : */
281 : void LeavePresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect);
282 :
283 : /**
284 : * Returns true if we're currently building a display list that's
285 : * directly or indirectly under an nsDisplayTransform or SVG
286 : * foreignObject.
287 : */
288 0 : bool IsInTransform() { return mInTransform; }
289 : /**
290 : * Indicate whether or not we're directly or indirectly under and
291 : * nsDisplayTransform or SVG foreignObject.
292 : */
293 0 : void SetInTransform(bool aInTransform) { mInTransform = aInTransform; }
294 :
295 : /**
296 : * Call this if using display port for scrolling.
297 : */
298 : void SetDisplayPort(const nsRect& aDisplayPort);
299 0 : const nsRect* GetDisplayPort() { return mHasDisplayPort ? &mDisplayPort : nsnull; }
300 :
301 : /**
302 : * Call this if ReferenceFrame() is a viewport frame with fixed-position
303 : * children, or when we construct an item which will return true from
304 : * ShouldFixToViewport()
305 : */
306 0 : void SetHasFixedItems() { mHasFixedItems = true; }
307 0 : bool GetHasFixedItems() { return mHasFixedItems; }
308 :
309 : /**
310 : * Returns true if snapping is enabled for the final drawing context.
311 : * The default is true.
312 : */
313 0 : bool IsSnappingEnabled() { return mSnappingEnabled; }
314 : /**
315 : * Set if snapping is enabled for the final drawing context.
316 : */
317 0 : void SetSnappingEnabled(bool aSnappingEnabled) { mSnappingEnabled = aSnappingEnabled; }
318 :
319 : /**
320 : * @return true if images have been set to decode synchronously.
321 : */
322 0 : bool ShouldSyncDecodeImages() { return mSyncDecodeImages; }
323 :
324 : /**
325 : * Indicates whether we should synchronously decode images. If true, we decode
326 : * and draw whatever image data has been loaded. If false, we just draw
327 : * whatever has already been decoded.
328 : */
329 0 : void SetSyncDecodeImages(bool aSyncDecodeImages) {
330 0 : mSyncDecodeImages = aSyncDecodeImages;
331 0 : }
332 :
333 : /**
334 : * Helper method to generate background painting flags based on the
335 : * information available in the display list builder. Currently only
336 : * accounts for mSyncDecodeImages.
337 : */
338 : PRUint32 GetBackgroundPaintFlags();
339 :
340 : /**
341 : * Subtracts aRegion from *aVisibleRegion. We avoid letting
342 : * aVisibleRegion become overcomplex by simplifying it if necessary ---
343 : * unless mAccurateVisibleRegions is set, in which case we let it
344 : * get arbitrarily complex.
345 : */
346 : void SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
347 : const nsRegion& aRegion);
348 :
349 : /**
350 : * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
351 : * (which is relative to aDirtyFrame). If the frames have placeholders
352 : * that might not be displayed, we mark the placeholders and their ancestors
353 : * to ensure that display list construction descends into them
354 : * anyway. nsDisplayListBuilder will take care of unmarking them when it is
355 : * destroyed.
356 : */
357 : void MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
358 : const nsFrameList& aFrames,
359 : const nsRect& aDirtyRect);
360 :
361 : /**
362 : * Return the FrameLayerBuilder.
363 : */
364 0 : FrameLayerBuilder* LayerBuilder() { return &mLayerBuilder; }
365 :
366 : /**
367 : * Get the area of the final transparent region.
368 : */
369 0 : const nsRegion* GetFinalTransparentRegion() { return mFinalTransparentRegion; }
370 : /**
371 : * Record the area of the final transparent region after all visibility
372 : * calculations were performed.
373 : */
374 0 : void SetFinalTransparentRegion(const nsRegion& aFinalTransparentRegion)
375 : {
376 0 : mFinalTransparentRegion = &aFinalTransparentRegion;
377 0 : }
378 :
379 0 : const nsTArray<ThemeGeometry>& GetThemeGeometries() { return mThemeGeometries; }
380 :
381 : /**
382 : * Returns true if we need to descend into this frame when building
383 : * the display list, even though it doesn't intersect the dirty
384 : * rect, because it may have out-of-flows that do so.
385 : */
386 0 : bool ShouldDescendIntoFrame(nsIFrame* aFrame) const {
387 : return
388 0 : (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
389 0 : GetIncludeAllOutOfFlows();
390 : }
391 :
392 : /**
393 : * Notifies the builder that a particular themed widget exists
394 : * at the given rectangle within the currently built display list.
395 : * For certain appearance values (currently only
396 : * NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR and NS_THEME_TOOLBAR) this gets
397 : * called during every display list construction, for every themed widget of
398 : * the right type within the display list, except for themed widgets which
399 : * are transformed or have effects applied to them (e.g. CSS opacity or
400 : * filters).
401 : *
402 : * @param aWidgetType the -moz-appearance value for the themed widget
403 : * @param aRect the device-pixel rect relative to the widget's displayRoot
404 : * for the themed widget
405 : */
406 0 : void RegisterThemeGeometry(PRUint8 aWidgetType,
407 : const nsIntRect& aRect) {
408 0 : if (mIsPaintingToWindow && mPresShellStates.Length() == 1) {
409 0 : ThemeGeometry geometry(aWidgetType, aRect);
410 0 : mThemeGeometries.AppendElement(geometry);
411 : }
412 0 : }
413 :
414 : /**
415 : * Allocate memory in our arena. It will only be freed when this display list
416 : * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
417 : * destructors are called as soon as the item is no longer used.
418 : */
419 : void* Allocate(size_t aSize);
420 :
421 : /**
422 : * A helper class to temporarily set the value of
423 : * mIsAtRootOfPseudoStackingContext.
424 : */
425 : class AutoIsRootSetter;
426 : friend class AutoIsRootSetter;
427 : class AutoIsRootSetter {
428 : public:
429 0 : AutoIsRootSetter(nsDisplayListBuilder* aBuilder, bool aIsRoot)
430 0 : : mBuilder(aBuilder), mOldValue(aBuilder->mIsAtRootOfPseudoStackingContext) {
431 0 : aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
432 0 : }
433 0 : ~AutoIsRootSetter() {
434 0 : mBuilder->mIsAtRootOfPseudoStackingContext = mOldValue;
435 0 : }
436 : private:
437 : nsDisplayListBuilder* mBuilder;
438 : bool mOldValue;
439 : };
440 :
441 : /**
442 : * A helper class to temporarily set the value of mInTransform.
443 : */
444 : class AutoInTransformSetter;
445 : friend class AutoInTransformSetter;
446 : class AutoInTransformSetter {
447 : public:
448 0 : AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
449 0 : : mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
450 0 : aBuilder->mInTransform = aInTransform;
451 0 : }
452 0 : ~AutoInTransformSetter() {
453 0 : mBuilder->mInTransform = mOldValue;
454 0 : }
455 : private:
456 : nsDisplayListBuilder* mBuilder;
457 : bool mOldValue;
458 : };
459 :
460 : // Helpers for tables
461 0 : nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
462 0 : void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
463 :
464 0 : NS_DECLARE_FRAME_PROPERTY(OutOfFlowDirtyRectProperty, nsIFrame::DestroyRect)
465 :
466 0 : nsPresContext* CurrentPresContext() {
467 0 : return CurrentPresShellState()->mPresShell->GetPresContext();
468 : }
469 :
470 : /**
471 : * Accumulates the bounds of box frames that have moz-appearance
472 : * -moz-win-exclude-glass style. Used in setting glass margins on
473 : * Windows.
474 : */
475 0 : void AddExcludedGlassRegion(nsRect &bounds) {
476 0 : mExcludedGlassRegion.Or(mExcludedGlassRegion, bounds);
477 0 : }
478 0 : const nsRegion& GetExcludedGlassRegion() {
479 0 : return mExcludedGlassRegion;
480 : }
481 :
482 : private:
483 : void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
484 : const nsRect& aDirtyRect);
485 :
486 0 : struct PresShellState {
487 : nsIPresShell* mPresShell;
488 : nsIFrame* mCaretFrame;
489 : PRUint32 mFirstFrameMarkedForDisplay;
490 : bool mIsBackgroundOnly;
491 : };
492 0 : PresShellState* CurrentPresShellState() {
493 0 : NS_ASSERTION(mPresShellStates.Length() > 0,
494 : "Someone forgot to enter a presshell");
495 0 : return &mPresShellStates[mPresShellStates.Length() - 1];
496 : }
497 :
498 : FrameLayerBuilder mLayerBuilder;
499 : nsIFrame* mReferenceFrame;
500 : nsIFrame* mIgnoreScrollFrame;
501 : PLArenaPool mPool;
502 : nsCOMPtr<nsISelection> mBoundingSelection;
503 : nsAutoTArray<PresShellState,8> mPresShellStates;
504 : nsAutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
505 : nsAutoTArray<ThemeGeometry,2> mThemeGeometries;
506 : nsDisplayTableItem* mCurrentTableItem;
507 : const nsRegion* mFinalTransparentRegion;
508 : nsRect mDisplayPort;
509 : nsRegion mExcludedGlassRegion;
510 : Mode mMode;
511 : bool mBuildCaret;
512 : bool mIgnoreSuppression;
513 : bool mHadToIgnoreSuppression;
514 : bool mIsAtRootOfPseudoStackingContext;
515 : bool mIncludeAllOutOfFlows;
516 : bool mSelectedFramesOnly;
517 : bool mAccurateVisibleRegions;
518 : // True when we're building a display list that's directly or indirectly
519 : // under an nsDisplayTransform
520 : bool mInTransform;
521 : bool mSyncDecodeImages;
522 : bool mIsPaintingToWindow;
523 : bool mSnappingEnabled;
524 : bool mHasDisplayPort;
525 : bool mHasFixedItems;
526 : };
527 :
528 : class nsDisplayItem;
529 : class nsDisplayList;
530 : /**
531 : * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
532 : * nsDisplayItemLink holds the link. The lists are linked from lowest to
533 : * highest in z-order.
534 : */
535 : class nsDisplayItemLink {
536 : // This is never instantiated directly, so no need to count constructors and
537 : // destructors.
538 : protected:
539 0 : nsDisplayItemLink() : mAbove(nsnull) {}
540 : nsDisplayItem* mAbove;
541 :
542 : friend class nsDisplayList;
543 : };
544 :
545 : /**
546 : * This is the unit of rendering and event testing. Each instance of this
547 : * class represents an entity that can be drawn on the screen, e.g., a
548 : * frame's CSS background, or a frame's text string.
549 : *
550 : * nsDisplayListItems can be containers --- i.e., they can perform hit testing
551 : * and painting by recursively traversing a list of child items.
552 : *
553 : * These are arena-allocated during display list construction. A typical
554 : * subclass would just have a frame pointer, so its object would be just three
555 : * pointers (vtable, next-item, frame).
556 : *
557 : * Display items belong to a list at all times (except temporarily as they
558 : * move from one list to another).
559 : */
560 : class nsDisplayItem : public nsDisplayItemLink {
561 : public:
562 : typedef mozilla::layers::FrameMetrics::ViewID ViewID;
563 : typedef mozilla::layers::Layer Layer;
564 : typedef mozilla::layers::LayerManager LayerManager;
565 : typedef mozilla::LayerState LayerState;
566 :
567 : // This is never instantiated directly (it has pure virtual methods), so no
568 : // need to count constructors and destructors.
569 0 : nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
570 : : mFrame(aFrame)
571 : #ifdef MOZ_DUMP_PAINTING
572 0 : , mPainted(false)
573 : #endif
574 : {
575 0 : if (aFrame) {
576 0 : mToReferenceFrame = aBuilder->ToReferenceFrame(aFrame);
577 : }
578 0 : }
579 0 : virtual ~nsDisplayItem() {}
580 :
581 0 : void* operator new(size_t aSize,
582 : nsDisplayListBuilder* aBuilder) CPP_THROW_NEW {
583 0 : return aBuilder->Allocate(aSize);
584 : }
585 :
586 : // Contains all the type integers for each display list item type
587 : #include "nsDisplayItemTypes.h"
588 :
589 : struct HitTestState {
590 : typedef nsTArray<ViewID> ShadowArray;
591 :
592 0 : HitTestState(ShadowArray* aShadows = NULL)
593 0 : : mShadows(aShadows) {
594 0 : }
595 :
596 0 : ~HitTestState() {
597 0 : NS_ASSERTION(mItemBuffer.Length() == 0,
598 : "mItemBuffer should have been cleared");
599 0 : }
600 :
601 : nsAutoTArray<nsDisplayItem*, 100> mItemBuffer;
602 :
603 : // It is sometimes useful to hit test for frames that are not in this
604 : // process. Display items may append IDs into this array if it is
605 : // non-null.
606 : ShadowArray* mShadows;
607 : };
608 :
609 : /**
610 : * Some consecutive items should be rendered together as a unit, e.g.,
611 : * outlines for the same element. For this, we need a way for items to
612 : * identify their type. We use the type for other purposes too.
613 : */
614 : virtual Type GetType() = 0;
615 : /**
616 : * If this returns a non-zero value, then pairing this with the
617 : * GetUnderlyingFrame() pointer gives a key that uniquely identifies
618 : * this display item in the display item tree.
619 : * This will only return a zero value for items which wrap display lists
620 : * and do not create a CSS stacking context, therefore requiring
621 : * display items to be individually wrapped --- currently nsDisplayClip
622 : * and nsDisplayClipRoundedRect only.
623 : */
624 0 : virtual PRUint32 GetPerFrameKey() { return PRUint32(GetType()); }
625 : /**
626 : * This is called after we've constructed a display list for event handling.
627 : * When this is called, we've already ensured that aRect intersects the
628 : * item's bounds.
629 : *
630 : * @param aRect the point or rect being tested, relative to the reference
631 : * frame. If the width and height are both 1 app unit, it indicates we're
632 : * hit testing a point, not a rect.
633 : * @param aState must point to a HitTestState. If you don't have one,
634 : * just create one with the default constructor and pass it in.
635 : * @param aOutFrames each item appends the frame(s) in this display item that
636 : * the rect is considered over (if any) to aOutFrames.
637 : */
638 0 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
639 0 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {}
640 : /**
641 : * @return the frame that this display item is based on. This is used to sort
642 : * items by z-index and content order and for some other uses. For some items
643 : * that wrap item lists, this could return nsnull because there is no single
644 : * underlying frame; for leaf items it will never return nsnull.
645 : */
646 0 : inline nsIFrame* GetUnderlyingFrame() const { return mFrame; }
647 : /**
648 : * The default bounds is the frame border rect.
649 : * @return a rectangle relative to aBuilder->ReferenceFrame() that
650 : * contains the area drawn by this display item
651 : */
652 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
653 0 : return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
654 : }
655 : /**
656 : * @return a region of the item that is opaque --- every pixel painted
657 : * with an opaque color. This is useful for determining when one piece
658 : * of content completely obscures another so that we can do occlusion
659 : * culling.
660 : */
661 0 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
662 : bool* aForceTransparentSurface = nsnull)
663 : {
664 0 : if (aForceTransparentSurface) {
665 0 : *aForceTransparentSurface = false;
666 : }
667 0 : return nsRegion();
668 : }
669 : /**
670 : * If this returns true, then aColor is set to the uniform color
671 : * @return true if the item is guaranteed to paint every pixel in its
672 : * bounds with the same (possibly translucent) color
673 : */
674 0 : virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) { return false; }
675 : /**
676 : * @return false if the painting performed by the item is invariant
677 : * when the item's underlying frame is moved relative to aFrame.
678 : * In other words, if you render the item at locations P and P', the rendering
679 : * only differs by the translation.
680 : * It return true for all wrapped lists.
681 : */
682 0 : virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
683 : nsIFrame* aFrame)
684 0 : { return false; }
685 : /**
686 : * @return true if the contents of this item are rendered fixed relative
687 : * to the nearest viewport *and* they cover the viewport's scrollport.
688 : * Only return true if the contents actually vary when scrolling in the viewport.
689 : */
690 0 : virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
691 0 : { return false; }
692 :
693 : /**
694 : * @return LAYER_NONE if BuildLayer will return null. In this case
695 : * there is no layer for the item, and Paint should be called instead
696 : * to paint the content using Thebes.
697 : * Return LAYER_INACTIVE if there is a layer --- BuildLayer will
698 : * not return null (unless there's an error) --- but the layer contents
699 : * are not changing frequently. In this case it makes sense to composite
700 : * the layer into a ThebesLayer with other content, so we don't have to
701 : * recomposite it every time we paint.
702 : * Note: GetLayerState is only allowed to return LAYER_INACTIVE if all
703 : * descendant display items returned LAYER_INACTIVE or LAYER_NONE. Also,
704 : * all descendant display item frames must have an active scrolled root
705 : * that's either the same as this item's frame's active scrolled root, or
706 : * a descendant of this item's frame. This ensures that the entire
707 : * set of display items can be collapsed onto a single ThebesLayer.
708 : * Return LAYER_ACTIVE if the layer is active, that is, its contents are
709 : * changing frequently. In this case it makes sense to keep the layer
710 : * as a separate buffer in VRAM and composite it into the destination
711 : * every time we paint.
712 : */
713 0 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
714 : LayerManager* aManager)
715 0 : { return mozilla::LAYER_NONE; }
716 : /**
717 : * Actually paint this item to some rendering context.
718 : * Content outside mVisibleRect need not be painted.
719 : * aCtx must be set up as for nsDisplayList::Paint.
720 : */
721 0 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) {}
722 :
723 : #ifdef MOZ_DUMP_PAINTING
724 : /**
725 : * Mark this display item as being painted via FrameLayerBuilder::DrawThebesLayer.
726 : */
727 0 : bool Painted() { return mPainted; }
728 :
729 : /**
730 : * Check if this display item has been painted.
731 : */
732 0 : void SetPainted() { mPainted = true; }
733 : #endif
734 :
735 : /**
736 : * Get the layer drawn by this display item. Call this only if
737 : * GetLayerState() returns something other than LAYER_NONE.
738 : * If GetLayerState returned LAYER_NONE then Paint will be called
739 : * instead.
740 : * This is called while aManager is in the construction phase.
741 : *
742 : * The caller (nsDisplayList) is responsible for setting the visible
743 : * region of the layer.
744 : *
745 : * @param aContainerParameters should be passed to
746 : * FrameLayerBuilder::BuildContainerLayerFor if a ContainerLayer is
747 : * constructed.
748 : */
749 : typedef mozilla::FrameLayerBuilder::ContainerParameters ContainerParameters;
750 0 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
751 : LayerManager* aManager,
752 : const ContainerParameters& aContainerParameters)
753 0 : { return nsnull; }
754 :
755 : /**
756 : * On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
757 : * which may be visible. If the display item opaquely covers an area, it
758 : * can remove that area from aVisibleRegion before returning.
759 : * nsDisplayList::ComputeVisibility automatically subtracts the region
760 : * returned by GetOpaqueRegion, and automatically removes items whose bounds
761 : * do not intersect the visible area, so implementations of
762 : * nsDisplayItem::ComputeVisibility do not need to do these things.
763 : * nsDisplayList::ComputeVisibility will already have set mVisibleRect on
764 : * this item to the intersection of *aVisibleRegion and this item's bounds.
765 : * We rely on that, so this should only be called by
766 : * nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility.
767 : * aAllowVisibleRegionExpansion is a rect where we are allowed to
768 : * expand the visible region and is only used for making sure the
769 : * background behind a plugin is visible.
770 : *
771 : * @return true if the item is visible, false if no part of the item
772 : * is visible.
773 : */
774 0 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
775 : nsRegion* aVisibleRegion,
776 : const nsRect& aAllowVisibleRegionExpansion)
777 0 : { return !mVisibleRect.IsEmpty(); }
778 :
779 : /**
780 : * Try to merge with the other item (which is below us in the display
781 : * list). This gets used by nsDisplayClip to coalesce clipping operations
782 : * (optimization), by nsDisplayOpacity to merge rendering for the same
783 : * content element into a single opacity group (correctness), and will be
784 : * used by nsDisplayOutline to merge multiple outlines for the same element
785 : * (also for correctness).
786 : * @return true if the merge was successful and the other item should be deleted
787 : */
788 0 : virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
789 0 : return false;
790 : }
791 :
792 : /**
793 : * During the visibility computation and after TryMerge, display lists may
794 : * return true here to flatten themselves away, removing them. This
795 : * flattening is distinctly different from FlattenTo, which occurs before
796 : * items are merged together.
797 : */
798 0 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
799 0 : return false;
800 : }
801 :
802 : /**
803 : * If this is a leaf item we return null, otherwise we return the wrapped
804 : * list.
805 : */
806 0 : virtual nsDisplayList* GetList() { return nsnull; }
807 :
808 : /**
809 : * Returns the visible rect. Should only be called after ComputeVisibility
810 : * has happened.
811 : */
812 0 : const nsRect& GetVisibleRect() { return mVisibleRect; }
813 :
814 : #ifdef MOZ_DUMP_PAINTING
815 : /**
816 : * For debugging and stuff
817 : */
818 : virtual const char* Name() = 0;
819 : #endif
820 :
821 0 : nsDisplayItem* GetAbove() { return mAbove; }
822 :
823 : /**
824 : * Like ComputeVisibility, but does the work that nsDisplayList
825 : * does per-item:
826 : * -- Intersects GetBounds with aVisibleRegion and puts the result
827 : * in mVisibleRect
828 : * -- Subtracts bounds from aVisibleRegion if the item is opaque
829 : */
830 : bool RecomputeVisibility(nsDisplayListBuilder* aBuilder,
831 : nsRegion* aVisibleRegion);
832 :
833 : /**
834 : * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
835 : */
836 0 : const nsPoint& ToReferenceFrame() const {
837 0 : NS_ASSERTION(mFrame, "No frame?");
838 0 : return mToReferenceFrame;
839 : }
840 :
841 : /**
842 : * Checks if this display item (or any children) contains content that might
843 : * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
844 : * bounds of the area that needs component alpha, or an empty rect if nothing
845 : * in the item does.
846 : */
847 0 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) { return nsRect(); }
848 :
849 : /**
850 : * Disable usage of component alpha. Currently only relevant for items that have text.
851 : */
852 0 : virtual void DisableComponentAlpha() {}
853 :
854 : protected:
855 : friend class nsDisplayList;
856 :
857 : nsDisplayItem() {
858 : mAbove = nsnull;
859 : }
860 :
861 : nsIFrame* mFrame;
862 : // Result of ToReferenceFrame(mFrame), if mFrame is non-null
863 : nsPoint mToReferenceFrame;
864 : // This is the rectangle that needs to be painted.
865 : // nsDisplayList::ComputeVisibility sets this to the visible region
866 : // of the item by intersecting the current visible region with the bounds
867 : // of the item. Paint implementations can use this to limit their drawing.
868 : // Guaranteed to be contained in GetBounds().
869 : nsRect mVisibleRect;
870 : #ifdef MOZ_DUMP_PAINTING
871 : // True if this frame has been painted.
872 : bool mPainted;
873 : #endif
874 : };
875 :
876 : /**
877 : * Manages a singly-linked list of display list items.
878 : *
879 : * mSentinel is the sentinel list value, the first value in the null-terminated
880 : * linked list of items. mTop is the last item in the list (whose 'above'
881 : * pointer is null). This class has no virtual methods. So list objects are just
882 : * two pointers.
883 : *
884 : * Stepping upward through this list is very fast. Stepping downward is very
885 : * slow so we don't support it. The methods that need to step downward
886 : * (HitTest(), ComputeVisibility()) internally build a temporary array of all
887 : * the items while they do the downward traversal, so overall they're still
888 : * linear time. We have optimized for efficient AppendToTop() of both
889 : * items and lists, with minimal codesize. AppendToBottom() is efficient too.
890 : */
891 : class nsDisplayList {
892 : public:
893 : typedef mozilla::layers::Layer Layer;
894 : typedef mozilla::layers::LayerManager LayerManager;
895 : typedef mozilla::layers::ThebesLayer ThebesLayer;
896 :
897 : /**
898 : * Create an empty list.
899 : */
900 0 : nsDisplayList() :
901 0 : mIsOpaque(false)
902 : {
903 0 : mTop = &mSentinel;
904 0 : mSentinel.mAbove = nsnull;
905 : #ifdef DEBUG
906 0 : mDidComputeVisibility = false;
907 : #endif
908 0 : }
909 0 : ~nsDisplayList() {
910 0 : if (mSentinel.mAbove) {
911 0 : NS_WARNING("Nonempty list left over?");
912 : }
913 0 : DeleteAll();
914 0 : }
915 :
916 : /**
917 : * Append an item to the top of the list. The item must not currently
918 : * be in a list and cannot be null.
919 : */
920 0 : void AppendToTop(nsDisplayItem* aItem) {
921 0 : NS_ASSERTION(aItem, "No item to append!");
922 0 : NS_ASSERTION(!aItem->mAbove, "Already in a list!");
923 0 : mTop->mAbove = aItem;
924 0 : mTop = aItem;
925 0 : }
926 :
927 : /**
928 : * Append a new item to the top of the list. If the item is null we return
929 : * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToTop(new ...);
930 : */
931 0 : nsresult AppendNewToTop(nsDisplayItem* aItem) {
932 0 : if (!aItem)
933 0 : return NS_ERROR_OUT_OF_MEMORY;
934 0 : AppendToTop(aItem);
935 0 : return NS_OK;
936 : }
937 :
938 : /**
939 : * Append a new item to the bottom of the list. If the item is null we return
940 : * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToBottom(new ...);
941 : */
942 0 : nsresult AppendNewToBottom(nsDisplayItem* aItem) {
943 0 : if (!aItem)
944 0 : return NS_ERROR_OUT_OF_MEMORY;
945 0 : AppendToBottom(aItem);
946 0 : return NS_OK;
947 : }
948 :
949 : /**
950 : * Append a new item to the bottom of the list. The item must be non-null
951 : * and not already in a list.
952 : */
953 0 : void AppendToBottom(nsDisplayItem* aItem) {
954 0 : NS_ASSERTION(aItem, "No item to append!");
955 0 : NS_ASSERTION(!aItem->mAbove, "Already in a list!");
956 0 : aItem->mAbove = mSentinel.mAbove;
957 0 : mSentinel.mAbove = aItem;
958 0 : if (mTop == &mSentinel) {
959 0 : mTop = aItem;
960 : }
961 0 : }
962 :
963 : /**
964 : * Removes all items from aList and appends them to the top of this list
965 : */
966 0 : void AppendToTop(nsDisplayList* aList) {
967 0 : if (aList->mSentinel.mAbove) {
968 0 : mTop->mAbove = aList->mSentinel.mAbove;
969 0 : mTop = aList->mTop;
970 0 : aList->mTop = &aList->mSentinel;
971 0 : aList->mSentinel.mAbove = nsnull;
972 : }
973 0 : }
974 :
975 : /**
976 : * Removes all items from aList and prepends them to the bottom of this list
977 : */
978 0 : void AppendToBottom(nsDisplayList* aList) {
979 0 : if (aList->mSentinel.mAbove) {
980 0 : aList->mTop->mAbove = mSentinel.mAbove;
981 0 : mTop = aList->mTop;
982 0 : mSentinel.mAbove = aList->mSentinel.mAbove;
983 :
984 0 : aList->mTop = &aList->mSentinel;
985 0 : aList->mSentinel.mAbove = nsnull;
986 : }
987 0 : }
988 :
989 : /**
990 : * Remove an item from the bottom of the list and return it.
991 : */
992 : nsDisplayItem* RemoveBottom();
993 :
994 : /**
995 : * Remove all items from the list and call their destructors.
996 : */
997 : void DeleteAll();
998 :
999 : /**
1000 : * @return the item at the top of the list, or null if the list is empty
1001 : */
1002 0 : nsDisplayItem* GetTop() const {
1003 0 : return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nsnull;
1004 : }
1005 : /**
1006 : * @return the item at the bottom of the list, or null if the list is empty
1007 : */
1008 0 : nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
1009 0 : bool IsEmpty() const { return mTop == &mSentinel; }
1010 :
1011 : /**
1012 : * This is *linear time*!
1013 : * @return the number of items in the list
1014 : */
1015 : PRUint32 Count() const;
1016 : /**
1017 : * Stable sort the list by the z-order of GetUnderlyingFrame() on
1018 : * each item. 'auto' is counted as zero. Content order is used as the
1019 : * secondary order.
1020 : * @param aCommonAncestor a common ancestor of all the content elements
1021 : * associated with the display items, for speeding up tree order
1022 : * checks, or nsnull if not known; it's only a hint, if it is not an
1023 : * ancestor of some elements, then we lose performance but not correctness
1024 : */
1025 : void SortByZOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
1026 : /**
1027 : * Stable sort the list by the tree order of the content of
1028 : * GetUnderlyingFrame() on each item. z-index is ignored.
1029 : * @param aCommonAncestor a common ancestor of all the content elements
1030 : * associated with the display items, for speeding up tree order
1031 : * checks, or nsnull if not known; it's only a hint, if it is not an
1032 : * ancestor of some elements, then we lose performance but not correctness
1033 : */
1034 : void SortByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
1035 :
1036 : /**
1037 : * Generic stable sort. Take care, because some of the items might be nsDisplayLists
1038 : * themselves.
1039 : * aCmp(item1, item2) should return true if item1 <= item2. We sort the items
1040 : * into increasing order.
1041 : */
1042 : typedef bool (* SortLEQ)(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
1043 : void* aClosure);
1044 : void Sort(nsDisplayListBuilder* aBuilder, SortLEQ aCmp, void* aClosure);
1045 :
1046 : /**
1047 : * Compute visiblity for the items in the list.
1048 : * We put this logic here so it can be shared by top-level
1049 : * painting and also display items that maintain child lists.
1050 : * This is also a good place to put ComputeVisibility-related logic
1051 : * that must be applied to every display item. In particular, this
1052 : * sets mVisibleRect on each display item.
1053 : * This sets mIsOpaque if the entire visible area of this list has
1054 : * been removed from aVisibleRegion when we return.
1055 : * This does not remove any items from the list, so we can recompute
1056 : * visiblity with different regions later (see
1057 : * FrameLayerBuilder::DrawThebesLayer).
1058 : *
1059 : * @param aVisibleRegion the area that is visible, relative to the
1060 : * reference frame; on return, this contains the area visible under the list.
1061 : * I.e., opaque contents of this list are subtracted from aVisibleRegion.
1062 : * @param aListVisibleBounds must be equal to the bounds of the intersection
1063 : * of aVisibleRegion and GetBounds() for this list.
1064 : * @return true if any item in the list is visible.
1065 : */
1066 : bool ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
1067 : nsRegion* aVisibleRegion,
1068 : const nsRect& aListVisibleBounds,
1069 : const nsRect& aAllowVisibleRegionExpansion);
1070 :
1071 : /**
1072 : * As ComputeVisibilityForSublist, but computes visibility for a root
1073 : * list (a list that does not belong to an nsDisplayItem).
1074 : *
1075 : * @param aVisibleRegion the area that is visible
1076 : */
1077 : bool ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
1078 : nsRegion* aVisibleRegion);
1079 :
1080 : /**
1081 : * Returns true if the visible region output from ComputeVisiblity was
1082 : * empty, i.e. everything visible in this list is opaque.
1083 : */
1084 0 : bool IsOpaque() const {
1085 0 : NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility");
1086 0 : return mIsOpaque;
1087 : }
1088 :
1089 : /**
1090 : * Returns true if during ComputeVisibility any display item
1091 : * set the surface to be transparent.
1092 : */
1093 0 : bool NeedsTransparentSurface() const {
1094 0 : NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility");
1095 0 : return mForceTransparentSurface;
1096 : }
1097 : /**
1098 : * Paint the list to the rendering context. We assume that (0,0) in aCtx
1099 : * corresponds to the origin of the reference frame. For best results,
1100 : * aCtx's current transform should make (0,0) pixel-aligned. The
1101 : * rectangle in aDirtyRect is painted, which *must* be contained in the
1102 : * dirty rect used to construct the display list.
1103 : *
1104 : * If aFlags contains PAINT_USE_WIDGET_LAYERS and
1105 : * ShouldUseWidgetLayerManager() is set, then we will paint using
1106 : * the reference frame's widget's layer manager (and ctx may be null),
1107 : * otherwise we will use a temporary BasicLayerManager and ctx must
1108 : * not be null.
1109 : *
1110 : * If PAINT_FLUSH_LAYERS is set, we'll force a completely new layer
1111 : * tree to be created for this paint *and* the next paint.
1112 : *
1113 : * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
1114 : * layer manager has already had BeginTransaction() called on it and
1115 : * we should not call it again.
1116 : *
1117 : * ComputeVisibility must be called before Paint.
1118 : *
1119 : * This must only be called on the root display list of the display list
1120 : * tree.
1121 : */
1122 : enum {
1123 : PAINT_DEFAULT = 0,
1124 : PAINT_USE_WIDGET_LAYERS = 0x01,
1125 : PAINT_FLUSH_LAYERS = 0x02,
1126 : PAINT_EXISTING_TRANSACTION = 0x04
1127 : };
1128 : void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
1129 : PRUint32 aFlags) const;
1130 : /**
1131 : * Like PaintRoot, but used for internal display sublists.
1132 : * aForFrame is the frame that the list is associated with.
1133 : */
1134 : void PaintForFrame(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
1135 : nsIFrame* aForFrame, PRUint32 aFlags) const;
1136 : /**
1137 : * Get the bounds. Takes the union of the bounds of all children.
1138 : */
1139 : nsRect GetBounds(nsDisplayListBuilder* aBuilder) const;
1140 : /**
1141 : * Find the topmost display item that returns a non-null frame, and return
1142 : * the frame.
1143 : */
1144 : void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
1145 : nsDisplayItem::HitTestState* aState,
1146 : nsTArray<nsIFrame*> *aOutFrames) const;
1147 :
1148 : #ifdef DEBUG
1149 0 : bool DidComputeVisibility() const { return mDidComputeVisibility; }
1150 : #endif
1151 :
1152 : private:
1153 : // This class is only used on stack, so we don't have to worry about leaking
1154 : // it. Don't let us be heap-allocated!
1155 : void* operator new(size_t sz) CPP_THROW_NEW;
1156 :
1157 : // Utility function used to massage the list during ComputeVisibility.
1158 : void FlattenTo(nsTArray<nsDisplayItem*>* aElements);
1159 : // Utility function used to massage the list during sorting, to rewrite
1160 : // any wrapper items with null GetUnderlyingFrame
1161 : void ExplodeAnonymousChildLists(nsDisplayListBuilder* aBuilder);
1162 :
1163 : nsDisplayItemLink mSentinel;
1164 : nsDisplayItemLink* mTop;
1165 :
1166 : // This is set by ComputeVisibility
1167 : nsRect mVisibleRect;
1168 : // This is set to true by ComputeVisibility if the final visible region
1169 : // is empty (i.e. everything that was visible is covered by some
1170 : // opaque content in this list).
1171 : bool mIsOpaque;
1172 : // This is set to true by ComputeVisibility if any display item in this
1173 : // list needs to force the surface to be transparent (e.g. if the
1174 : // item "punch holes" on the surface by clearing part of its area).
1175 : bool mForceTransparentSurface;
1176 : #ifdef DEBUG
1177 : bool mDidComputeVisibility;
1178 : #endif
1179 : };
1180 :
1181 : /**
1182 : * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
1183 : * will put any generated items onto the appropriate list given here. It's
1184 : * basically just a collection with one list for each separate stacking layer.
1185 : * The lists themselves are external to this object and thus can be shared
1186 : * with others. Some of the list pointers may even refer to the same list.
1187 : */
1188 : class nsDisplayListSet {
1189 : public:
1190 : /**
1191 : * @return a list where one should place the border and/or background for
1192 : * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
1193 : */
1194 0 : nsDisplayList* BorderBackground() const { return mBorderBackground; }
1195 : /**
1196 : * @return a list where one should place the borders and/or backgrounds for
1197 : * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
1198 : */
1199 0 : nsDisplayList* BlockBorderBackgrounds() const { return mBlockBorderBackgrounds; }
1200 : /**
1201 : * @return a list where one should place descendant floats (step 5 of
1202 : * CSS 2.1 appendix E)
1203 : */
1204 0 : nsDisplayList* Floats() const { return mFloats; }
1205 : /**
1206 : * @return a list where one should place the (pseudo) stacking contexts
1207 : * for descendants of this frame (everything from steps 3, 7 and 8
1208 : * of CSS 2.1 appendix E)
1209 : */
1210 0 : nsDisplayList* PositionedDescendants() const { return mPositioned; }
1211 : /**
1212 : * @return a list where one should place the outlines
1213 : * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
1214 : */
1215 0 : nsDisplayList* Outlines() const { return mOutlines; }
1216 : /**
1217 : * @return a list where one should place all other content
1218 : */
1219 0 : nsDisplayList* Content() const { return mContent; }
1220 :
1221 0 : nsDisplayListSet(nsDisplayList* aBorderBackground,
1222 : nsDisplayList* aBlockBorderBackgrounds,
1223 : nsDisplayList* aFloats,
1224 : nsDisplayList* aContent,
1225 : nsDisplayList* aPositionedDescendants,
1226 : nsDisplayList* aOutlines) :
1227 : mBorderBackground(aBorderBackground),
1228 : mBlockBorderBackgrounds(aBlockBorderBackgrounds),
1229 : mFloats(aFloats),
1230 : mContent(aContent),
1231 : mPositioned(aPositionedDescendants),
1232 0 : mOutlines(aOutlines) {
1233 0 : }
1234 :
1235 : /**
1236 : * A copy constructor that lets the caller override the BorderBackground
1237 : * list.
1238 : */
1239 0 : nsDisplayListSet(const nsDisplayListSet& aLists,
1240 : nsDisplayList* aBorderBackground) :
1241 : mBorderBackground(aBorderBackground),
1242 0 : mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),
1243 0 : mFloats(aLists.Floats()),
1244 0 : mContent(aLists.Content()),
1245 0 : mPositioned(aLists.PositionedDescendants()),
1246 0 : mOutlines(aLists.Outlines()) {
1247 0 : }
1248 :
1249 : /**
1250 : * Move all display items in our lists to top of the corresponding lists in the
1251 : * destination.
1252 : */
1253 : void MoveTo(const nsDisplayListSet& aDestination) const;
1254 :
1255 : private:
1256 : // This class is only used on stack, so we don't have to worry about leaking
1257 : // it. Don't let us be heap-allocated!
1258 : void* operator new(size_t sz) CPP_THROW_NEW;
1259 :
1260 : protected:
1261 : nsDisplayList* mBorderBackground;
1262 : nsDisplayList* mBlockBorderBackgrounds;
1263 : nsDisplayList* mFloats;
1264 : nsDisplayList* mContent;
1265 : nsDisplayList* mPositioned;
1266 : nsDisplayList* mOutlines;
1267 : };
1268 :
1269 : /**
1270 : * A specialization of nsDisplayListSet where the lists are actually internal
1271 : * to the object, and all distinct.
1272 : */
1273 0 : struct nsDisplayListCollection : public nsDisplayListSet {
1274 0 : nsDisplayListCollection() :
1275 : nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4],
1276 0 : &mLists[5]) {}
1277 : nsDisplayListCollection(nsDisplayList* aBorderBackground) :
1278 : nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4],
1279 : &mLists[5]) {}
1280 :
1281 : /**
1282 : * Sort all lists by content order.
1283 : */
1284 0 : void SortAllByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor) {
1285 0 : for (PRInt32 i = 0; i < 6; ++i) {
1286 0 : mLists[i].SortByContentOrder(aBuilder, aCommonAncestor);
1287 : }
1288 0 : }
1289 :
1290 : private:
1291 : // This class is only used on stack, so we don't have to worry about leaking
1292 : // it. Don't let us be heap-allocated!
1293 : void* operator new(size_t sz) CPP_THROW_NEW;
1294 :
1295 : nsDisplayList mLists[6];
1296 : };
1297 :
1298 : /**
1299 : * Use this class to implement not-very-frequently-used display items
1300 : * that are not opaque, do not receive events, and are bounded by a frame's
1301 : * border-rect.
1302 : *
1303 : * This should not be used for display items which are created frequently,
1304 : * because each item is one or two pointers bigger than an item from a
1305 : * custom display item class could be, and fractionally slower. However it does
1306 : * save code size. We use this for infrequently-used item types.
1307 : */
1308 : class nsDisplayGeneric : public nsDisplayItem {
1309 : public:
1310 : typedef void (* PaintCallback)(nsIFrame* aFrame, nsRenderingContext* aCtx,
1311 : const nsRect& aDirtyRect, nsPoint aFramePt);
1312 :
1313 0 : nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1314 : PaintCallback aPaint, const char* aName, Type aType)
1315 : : nsDisplayItem(aBuilder, aFrame), mPaint(aPaint)
1316 : #ifdef MOZ_DUMP_PAINTING
1317 : , mName(aName)
1318 : #endif
1319 0 : , mType(aType)
1320 : {
1321 0 : MOZ_COUNT_CTOR(nsDisplayGeneric);
1322 0 : }
1323 : #ifdef NS_BUILD_REFCNT_LOGGING
1324 0 : virtual ~nsDisplayGeneric() {
1325 0 : MOZ_COUNT_DTOR(nsDisplayGeneric);
1326 0 : }
1327 : #endif
1328 :
1329 0 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) {
1330 0 : mPaint(mFrame, aCtx, mVisibleRect, ToReferenceFrame());
1331 0 : }
1332 0 : NS_DISPLAY_DECL_NAME(mName, mType)
1333 :
1334 0 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) {
1335 0 : if (mType == nsDisplayItem::TYPE_HEADER_FOOTER)
1336 0 : return GetBounds(aBuilder);
1337 0 : return nsRect();
1338 : }
1339 :
1340 : protected:
1341 : PaintCallback mPaint;
1342 : #ifdef MOZ_DUMP_PAINTING
1343 : const char* mName;
1344 : #endif
1345 : Type mType;
1346 : };
1347 :
1348 : #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
1349 : /**
1350 : * This class implements painting of reflow counts. Ideally, we would simply
1351 : * make all the frame names be those returned by nsFrame::GetFrameName
1352 : * (except that tosses in the content tag name!) and support only one color
1353 : * and eliminate this class altogether in favor of nsDisplayGeneric, but for
1354 : * the time being we can't pass args to a PaintCallback, so just have a
1355 : * separate class to do the right thing. Sadly, this alsmo means we need to
1356 : * hack all leaf frame classes to handle this.
1357 : *
1358 : * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
1359 : * here... I could switch it all to nscolor, but why bother?
1360 : */
1361 : class nsDisplayReflowCount : public nsDisplayItem {
1362 : public:
1363 0 : nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1364 : const char* aFrameName,
1365 : PRUint32 aColor = 0)
1366 : : nsDisplayItem(aBuilder, aFrame),
1367 : mFrameName(aFrameName),
1368 0 : mColor(aColor)
1369 : {
1370 0 : MOZ_COUNT_CTOR(nsDisplayReflowCount);
1371 0 : }
1372 : #ifdef NS_BUILD_REFCNT_LOGGING
1373 0 : virtual ~nsDisplayReflowCount() {
1374 0 : MOZ_COUNT_DTOR(nsDisplayReflowCount);
1375 0 : }
1376 : #endif
1377 :
1378 0 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) {
1379 0 : mFrame->PresContext()->PresShell()->PaintCount(mFrameName, aCtx,
1380 : mFrame->PresContext(),
1381 0 : mFrame, ToReferenceFrame(),
1382 0 : mColor);
1383 0 : }
1384 0 : NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT)
1385 : protected:
1386 : const char* mFrameName;
1387 : nscolor mColor;
1388 : };
1389 :
1390 : #define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
1391 : PR_BEGIN_MACRO \
1392 : if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
1393 : PresContext()->PresShell()->IsPaintingFrameCounts()) { \
1394 : nsresult _rv = \
1395 : aLists.Outlines()->AppendNewToTop( \
1396 : new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name)); \
1397 : NS_ENSURE_SUCCESS(_rv, _rv); \
1398 : } \
1399 : PR_END_MACRO
1400 :
1401 : #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
1402 : PR_BEGIN_MACRO \
1403 : if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
1404 : PresContext()->PresShell()->IsPaintingFrameCounts()) { \
1405 : nsresult _rv = \
1406 : aLists.Outlines()->AppendNewToTop( \
1407 : new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name, _color)); \
1408 : NS_ENSURE_SUCCESS(_rv, _rv); \
1409 : } \
1410 : PR_END_MACRO
1411 :
1412 : /*
1413 : Macro to be used for classes that don't actually implement BuildDisplayList
1414 : */
1415 : #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
1416 : NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, \
1417 : const nsRect& aDirtyRect, \
1418 : const nsDisplayListSet& aLists) { \
1419 : DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
1420 : return _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
1421 : }
1422 :
1423 : #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
1424 :
1425 : #define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
1426 : #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
1427 : #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
1428 :
1429 : #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
1430 :
1431 : class nsDisplayCaret : public nsDisplayItem {
1432 : public:
1433 0 : nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame,
1434 : nsCaret *aCaret)
1435 0 : : nsDisplayItem(aBuilder, aCaretFrame), mCaret(aCaret) {
1436 0 : MOZ_COUNT_CTOR(nsDisplayCaret);
1437 0 : }
1438 : #ifdef NS_BUILD_REFCNT_LOGGING
1439 0 : virtual ~nsDisplayCaret() {
1440 0 : MOZ_COUNT_DTOR(nsDisplayCaret);
1441 0 : }
1442 : #endif
1443 :
1444 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
1445 : // The caret returns a rect in the coordinates of mFrame.
1446 0 : return mCaret->GetCaretRect() + ToReferenceFrame();
1447 : }
1448 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
1449 0 : NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
1450 : protected:
1451 : nsRefPtr<nsCaret> mCaret;
1452 : };
1453 :
1454 : /**
1455 : * The standard display item to paint the CSS borders of a frame.
1456 : */
1457 : class nsDisplayBorder : public nsDisplayItem {
1458 : public:
1459 0 : nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
1460 : nsDisplayItem(aBuilder, aFrame),
1461 0 : mSnappingEnabled(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform()) {
1462 0 : MOZ_COUNT_CTOR(nsDisplayBorder);
1463 0 : }
1464 : #ifdef NS_BUILD_REFCNT_LOGGING
1465 0 : virtual ~nsDisplayBorder() {
1466 0 : MOZ_COUNT_DTOR(nsDisplayBorder);
1467 0 : }
1468 : #endif
1469 :
1470 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1471 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
1472 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1473 : nsRegion* aVisibleRegion,
1474 : const nsRect& aAllowVisibleRegionExpansion);
1475 0 : NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
1476 :
1477 : protected:
1478 : bool mSnappingEnabled;
1479 : };
1480 :
1481 : /**
1482 : * A simple display item that just renders a solid color across the
1483 : * specified bounds. For canvas frames (in the CSS sense) we split off the
1484 : * drawing of the background color into this class (from nsDisplayBackground
1485 : * via nsDisplayCanvasBackground). This is done so that we can always draw a
1486 : * background color to avoid ugly flashes of white when we can't draw a full
1487 : * frame tree (ie when a page is loading). The bounds can differ from the
1488 : * frame's bounds -- this is needed when a frame/iframe is loading and there
1489 : * is not yet a frame tree to go in the frame/iframe so we use the subdoc
1490 : * frame of the parent document as a standin.
1491 : */
1492 : class nsDisplaySolidColor : public nsDisplayItem {
1493 : public:
1494 0 : nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1495 : const nsRect& aBounds, nscolor aColor)
1496 : : nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor),
1497 0 : mSnappingEnabled(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform()) {
1498 0 : NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!");
1499 0 : MOZ_COUNT_CTOR(nsDisplaySolidColor);
1500 0 : }
1501 : #ifdef NS_BUILD_REFCNT_LOGGING
1502 0 : virtual ~nsDisplaySolidColor() {
1503 0 : MOZ_COUNT_DTOR(nsDisplaySolidColor);
1504 0 : }
1505 : #endif
1506 :
1507 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1508 :
1509 0 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
1510 : bool* aOutTransparentBackground = nsnull) {
1511 0 : if (aOutTransparentBackground) {
1512 0 : *aOutTransparentBackground = false;
1513 : }
1514 0 : nsRegion result;
1515 0 : if (NS_GET_A(mColor) == 255) {
1516 0 : result = GetBounds(aBuilder);
1517 : }
1518 : return result;
1519 : }
1520 :
1521 0 : virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
1522 : {
1523 0 : *aColor = mColor;
1524 0 : return true;
1525 : }
1526 :
1527 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
1528 :
1529 0 : NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
1530 :
1531 : private:
1532 : nsRect mBounds;
1533 : nscolor mColor;
1534 : bool mSnappingEnabled;
1535 : };
1536 :
1537 : /**
1538 : * The standard display item to paint the CSS background of a frame.
1539 : */
1540 : class nsDisplayBackground : public nsDisplayItem {
1541 : public:
1542 : nsDisplayBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
1543 : #ifdef NS_BUILD_REFCNT_LOGGING
1544 0 : virtual ~nsDisplayBackground() {
1545 0 : MOZ_COUNT_DTOR(nsDisplayBackground);
1546 0 : }
1547 : #endif
1548 :
1549 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
1550 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
1551 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1552 : nsRegion* aVisibleRegion,
1553 : const nsRect& aAllowVisibleRegionExpansion);
1554 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
1555 : bool* aForceTransparentSurface = nsnull);
1556 : virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
1557 : nsIFrame* aFrame);
1558 : virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
1559 : virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder);
1560 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1561 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
1562 0 : NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
1563 : protected:
1564 : nsRegion GetInsideClipRegion(nsPresContext* aPresContext, PRUint8 aClip,
1565 : const nsRect& aRect);
1566 :
1567 : /* Used to cache mFrame->IsThemed() since it isn't a cheap call */
1568 : bool mIsThemed;
1569 : bool mSnappingEnabled;
1570 : nsITheme::Transparency mThemeTransparency;
1571 : };
1572 :
1573 : /**
1574 : * The standard display item to paint the outer CSS box-shadows of a frame.
1575 : */
1576 : class nsDisplayBoxShadowOuter : public nsDisplayItem {
1577 : public:
1578 0 : nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
1579 0 : : nsDisplayItem(aBuilder, aFrame) {
1580 0 : MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
1581 0 : }
1582 : #ifdef NS_BUILD_REFCNT_LOGGING
1583 0 : virtual ~nsDisplayBoxShadowOuter() {
1584 0 : MOZ_COUNT_DTOR(nsDisplayBoxShadowOuter);
1585 0 : }
1586 : #endif
1587 :
1588 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
1589 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1590 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1591 : nsRegion* aVisibleRegion,
1592 : const nsRect& aAllowVisibleRegionExpansion);
1593 0 : NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
1594 :
1595 : private:
1596 : nsRegion mVisibleRegion;
1597 : };
1598 :
1599 : /**
1600 : * The standard display item to paint the inner CSS box-shadows of a frame.
1601 : */
1602 : class nsDisplayBoxShadowInner : public nsDisplayItem {
1603 : public:
1604 0 : nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
1605 0 : : nsDisplayItem(aBuilder, aFrame) {
1606 0 : MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
1607 0 : }
1608 : #ifdef NS_BUILD_REFCNT_LOGGING
1609 0 : virtual ~nsDisplayBoxShadowInner() {
1610 0 : MOZ_COUNT_DTOR(nsDisplayBoxShadowInner);
1611 0 : }
1612 : #endif
1613 :
1614 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
1615 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1616 : nsRegion* aVisibleRegion,
1617 : const nsRect& aAllowVisibleRegionExpansion);
1618 0 : NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
1619 :
1620 : private:
1621 : nsRegion mVisibleRegion;
1622 : };
1623 :
1624 : /**
1625 : * The standard display item to paint the CSS outline of a frame.
1626 : */
1627 : class nsDisplayOutline : public nsDisplayItem {
1628 : public:
1629 0 : nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
1630 0 : nsDisplayItem(aBuilder, aFrame) {
1631 0 : MOZ_COUNT_CTOR(nsDisplayOutline);
1632 0 : }
1633 : #ifdef NS_BUILD_REFCNT_LOGGING
1634 0 : virtual ~nsDisplayOutline() {
1635 0 : MOZ_COUNT_DTOR(nsDisplayOutline);
1636 0 : }
1637 : #endif
1638 :
1639 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1640 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
1641 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1642 : nsRegion* aVisibleRegion,
1643 : const nsRect& aAllowVisibleRegionExpansion);
1644 0 : NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
1645 : };
1646 :
1647 : /**
1648 : * A class that lets you receive events within the frame bounds but never paints.
1649 : */
1650 : class nsDisplayEventReceiver : public nsDisplayItem {
1651 : public:
1652 0 : nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
1653 0 : : nsDisplayItem(aBuilder, aFrame) {
1654 0 : MOZ_COUNT_CTOR(nsDisplayEventReceiver);
1655 0 : }
1656 : #ifdef NS_BUILD_REFCNT_LOGGING
1657 0 : virtual ~nsDisplayEventReceiver() {
1658 0 : MOZ_COUNT_DTOR(nsDisplayEventReceiver);
1659 0 : }
1660 : #endif
1661 :
1662 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
1663 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
1664 0 : NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER)
1665 : };
1666 :
1667 : /**
1668 : * A class that lets you wrap a display list as a display item.
1669 : *
1670 : * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
1671 : * list has many items, it's not clear which one has the 'underlying frame'.
1672 : * Thus we force the creator to specify what the underlying frame is. The
1673 : * underlying frame should be the root of a stacking context, because sorting
1674 : * a list containing this item will not get at the children.
1675 : *
1676 : * In some cases (e.g., clipping) we want to wrap a list but we don't have a
1677 : * particular underlying frame that is a stacking context root. In that case
1678 : * we allow the frame to be nsnull. Callers to GetUnderlyingFrame must
1679 : * detect and handle this case.
1680 : */
1681 : class nsDisplayWrapList : public nsDisplayItem {
1682 : // This is never instantiated directly, so no need to count constructors and
1683 : // destructors.
1684 :
1685 : public:
1686 : /**
1687 : * Takes all the items from aList and puts them in our list.
1688 : */
1689 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1690 : nsDisplayList* aList);
1691 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1692 : nsDisplayItem* aItem);
1693 : nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
1694 : virtual ~nsDisplayWrapList();
1695 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
1696 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
1697 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1698 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
1699 : bool* aForceTransparentSurface = nsnull);
1700 : virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
1701 : virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
1702 : nsIFrame* aFrame);
1703 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
1704 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1705 : nsRegion* aVisibleRegion,
1706 : const nsRect& aAllowVisibleRegionExpansion);
1707 0 : virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
1708 0 : NS_WARNING("This list should already have been flattened!!!");
1709 0 : return false;
1710 : }
1711 0 : NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
1712 :
1713 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder);
1714 :
1715 0 : virtual nsDisplayList* GetList() { return &mList; }
1716 :
1717 : /**
1718 : * This creates a copy of this item, but wrapping aItem instead of
1719 : * our existing list. Only gets called if this item returned nsnull
1720 : * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
1721 : * GetUnderlyingFrame().
1722 : */
1723 0 : virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
1724 : nsDisplayItem* aItem) {
1725 0 : NS_NOTREACHED("We never returned nsnull for GetUnderlyingFrame!");
1726 0 : return nsnull;
1727 : }
1728 :
1729 : /**
1730 : * Returns true if all descendant display items can be placed in the same
1731 : * ThebesLayer --- GetLayerState returns LAYER_INACTIVE or LAYER_NONE,
1732 : * and they all have the given aActiveScrolledRoot.
1733 : */
1734 : static bool ChildrenCanBeInactive(nsDisplayListBuilder* aBuilder,
1735 : LayerManager* aManager,
1736 : const nsDisplayList& aList,
1737 : nsIFrame* aActiveScrolledRoot);
1738 :
1739 : protected:
1740 : nsDisplayWrapList() {}
1741 :
1742 : nsDisplayList mList;
1743 : };
1744 :
1745 : /**
1746 : * We call WrapDisplayList on the in-flow lists: BorderBackground(),
1747 : * BlockBorderBackgrounds() and Content().
1748 : * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
1749 : * and Floats(). This is done to support special wrapping processing for frames
1750 : * that may not be in-flow descendants of the current frame.
1751 : */
1752 : class nsDisplayWrapper {
1753 : public:
1754 : // This is never instantiated directly (it has pure virtual methods), so no
1755 : // need to count constructors and destructors.
1756 :
1757 0 : virtual bool WrapBorderBackground() { return true; }
1758 : virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
1759 : nsIFrame* aFrame, nsDisplayList* aList) = 0;
1760 : virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
1761 : nsDisplayItem* aItem) = 0;
1762 :
1763 : nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1764 : const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
1765 : nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1766 : const nsDisplayListSet& aLists);
1767 : protected:
1768 0 : nsDisplayWrapper() {}
1769 : };
1770 :
1771 : /**
1772 : * The standard display item to paint a stacking context with translucency
1773 : * set by the stacking context root frame's 'opacity' style.
1774 : */
1775 : class nsDisplayOpacity : public nsDisplayWrapList {
1776 : public:
1777 : nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1778 : nsDisplayList* aList);
1779 : #ifdef NS_BUILD_REFCNT_LOGGING
1780 : virtual ~nsDisplayOpacity();
1781 : #endif
1782 :
1783 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
1784 : bool* aForceTransparentSurface = nsnull);
1785 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
1786 : LayerManager* aManager,
1787 : const ContainerParameters& aContainerParameters);
1788 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
1789 : LayerManager* aManager);
1790 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1791 : nsRegion* aVisibleRegion,
1792 : const nsRect& aAllowVisibleRegionExpansion);
1793 : virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
1794 0 : NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
1795 : };
1796 :
1797 : /**
1798 : * A display item that has no purpose but to ensure its contents get
1799 : * their own layer.
1800 : */
1801 : class nsDisplayOwnLayer : public nsDisplayWrapList {
1802 : public:
1803 : nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1804 : nsDisplayList* aList);
1805 : #ifdef NS_BUILD_REFCNT_LOGGING
1806 : virtual ~nsDisplayOwnLayer();
1807 : #endif
1808 :
1809 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
1810 : LayerManager* aManager,
1811 : const ContainerParameters& aContainerParameters);
1812 0 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
1813 : LayerManager* aManager)
1814 : {
1815 0 : return mozilla::LAYER_ACTIVE;
1816 : }
1817 0 : virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
1818 : {
1819 : // Don't allow merging, each sublist must have its own layer
1820 0 : return false;
1821 : }
1822 0 : NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
1823 : };
1824 :
1825 : /**
1826 : * This potentially creates a layer for the given list of items, whose
1827 : * visibility is determined by the displayport for the given frame instead of
1828 : * what is passed in to ComputeVisibility.
1829 : *
1830 : * Here in content, we can use this to render more content than is actually
1831 : * visible. Then, the compositing process can manipulate the generated layer
1832 : * through transformations so that asynchronous scrolling can be implemented.
1833 : *
1834 : * Note that setting the displayport will not change any hit testing! The
1835 : * content process will know nothing about what the user is actually seeing,
1836 : * so it can only do hit testing for what is supposed to be the visible region.
1837 : *
1838 : * It is possible for scroll boxes to have content that can be both above and
1839 : * below content outside of the scroll box. We cannot create layers for these
1840 : * cases. This is accomplished by wrapping display items with
1841 : * nsDisplayScrollLayers. nsDisplayScrollLayers with the same scroll frame will
1842 : * be merged together. If more than one nsDisplayScrollLayer exists after
1843 : * merging, all nsDisplayScrollLayers will be flattened out so that no new
1844 : * layer is created at all.
1845 : */
1846 : class nsDisplayScrollLayer : public nsDisplayWrapList
1847 : {
1848 : public:
1849 : /**
1850 : * @param aScrolledFrame This will determine what the displayport is. It should be
1851 : * the root content frame of the scrolled area. Note
1852 : * that nsDisplayScrollLayer will expect for
1853 : * ScrollLayerCount to be defined on aScrolledFrame.
1854 : * @param aScrollFrame The viewport frame you see this content through.
1855 : */
1856 : nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
1857 : nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
1858 : nsIFrame* aScrollFrame);
1859 : nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
1860 : nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
1861 : nsIFrame* aScrollFrame);
1862 : nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
1863 : nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
1864 : nsIFrame* aScrollFrame);
1865 0 : NS_DISPLAY_DECL_NAME("ScrollLayer", TYPE_SCROLL_LAYER)
1866 :
1867 : #ifdef NS_BUILD_REFCNT_LOGGING
1868 : virtual ~nsDisplayScrollLayer();
1869 : #endif
1870 :
1871 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
1872 : LayerManager* aManager,
1873 : const ContainerParameters& aContainerParameters);
1874 :
1875 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1876 : nsRegion* aVisibleRegion,
1877 : const nsRect& aAllowVisibleRegionExpansion);
1878 :
1879 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
1880 : LayerManager* aManager);
1881 :
1882 : virtual bool TryMerge(nsDisplayListBuilder* aBuilder,
1883 : nsDisplayItem* aItem);
1884 :
1885 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder);
1886 :
1887 : // Get the number of nsDisplayScrollLayers for a scroll frame. Note that this
1888 : // number does not include nsDisplayScrollInfoLayers. If this number is not 1
1889 : // after merging, all the nsDisplayScrollLayers should flatten away.
1890 : PRWord GetScrollLayerCount();
1891 : PRWord RemoveScrollLayerCount();
1892 :
1893 : private:
1894 : nsIFrame* mScrollFrame;
1895 : nsIFrame* mScrolledFrame;
1896 : };
1897 :
1898 : /**
1899 : * Like nsDisplayScrollLayer, but only has metadata on the scroll frame. This
1900 : * creates a layer that has no Thebes child layer, but still allows the
1901 : * compositor process to know of the scroll frame's existence.
1902 : *
1903 : * After visibility computation, nsDisplayScrollInfoLayers should only exist if
1904 : * nsDisplayScrollLayers were all flattened away.
1905 : *
1906 : * Important!! Add info layers to the bottom of the list so they are only
1907 : * considered after the others have flattened out!
1908 : */
1909 : class nsDisplayScrollInfoLayer : public nsDisplayScrollLayer
1910 : {
1911 : public:
1912 : nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder,
1913 : nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame);
1914 0 : NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER)
1915 :
1916 : #ifdef NS_BUILD_REFCNT_LOGGING
1917 : virtual ~nsDisplayScrollInfoLayer();
1918 : #endif
1919 :
1920 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
1921 : LayerManager* aManager);
1922 :
1923 : virtual bool TryMerge(nsDisplayListBuilder* aBuilder,
1924 : nsDisplayItem* aItem);
1925 :
1926 : virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder);
1927 : };
1928 :
1929 : /**
1930 : * nsDisplayClip can clip a list of items, but we take a single item
1931 : * initially and then later merge other items into it when we merge
1932 : * adjacent matching nsDisplayClips
1933 : */
1934 : class nsDisplayClip : public nsDisplayWrapList {
1935 : public:
1936 : /**
1937 : * @param aFrame the frame that should be considered the underlying
1938 : * frame for this content, e.g. the frame whose z-index we have. This
1939 : * is *not* the frame that is inducing the clipping.
1940 : */
1941 : nsDisplayClip(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1942 : nsDisplayItem* aItem, const nsRect& aRect);
1943 : nsDisplayClip(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1944 : nsDisplayList* aList, const nsRect& aRect);
1945 : #ifdef NS_BUILD_REFCNT_LOGGING
1946 : virtual ~nsDisplayClip();
1947 : #endif
1948 :
1949 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1950 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
1951 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1952 : nsRegion* aVisibleRegion,
1953 : const nsRect& aAllowVisibleRegionExpansion);
1954 : virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
1955 0 : NS_DISPLAY_DECL_NAME("Clip", TYPE_CLIP)
1956 0 : virtual PRUint32 GetPerFrameKey() { return 0; }
1957 :
1958 0 : const nsRect& GetClipRect() { return mClip; }
1959 0 : void SetClipRect(const nsRect& aRect) { mClip = aRect; }
1960 :
1961 : virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
1962 : nsDisplayItem* aItem);
1963 :
1964 : protected:
1965 : nsRect mClip;
1966 : };
1967 :
1968 : /**
1969 : * A display item to clip a list of items to the border-radius of a
1970 : * frame.
1971 : */
1972 : class nsDisplayClipRoundedRect : public nsDisplayClip {
1973 : public:
1974 : /**
1975 : * @param aFrame the frame that should be considered the underlying
1976 : * frame for this content, e.g. the frame whose z-index we have. This
1977 : * is *not* the frame that is inducing the clipping.
1978 : */
1979 : nsDisplayClipRoundedRect(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1980 : nsDisplayItem* aItem,
1981 : const nsRect& aRect, nscoord aRadii[8]);
1982 : nsDisplayClipRoundedRect(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1983 : nsDisplayList* aList,
1984 : const nsRect& aRect, nscoord aRadii[8]);
1985 : #ifdef NS_BUILD_REFCNT_LOGGING
1986 : virtual ~nsDisplayClipRoundedRect();
1987 : #endif
1988 :
1989 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
1990 : bool* aForceTransparentSurface = nsnull);
1991 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
1992 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
1993 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1994 : nsRegion* aVisibleRegion,
1995 : const nsRect& aAllowVisibleRegionExpansion);
1996 : virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
1997 0 : NS_DISPLAY_DECL_NAME("ClipRoundedRect", TYPE_CLIP_ROUNDED_RECT)
1998 :
1999 : virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
2000 : nsDisplayItem* aItem);
2001 :
2002 0 : void GetRadii(nscoord aRadii[8]) {
2003 0 : memcpy(aRadii, mRadii, sizeof(mRadii));
2004 0 : }
2005 :
2006 : private:
2007 : nscoord mRadii[8];
2008 : };
2009 :
2010 : /**
2011 : * nsDisplayZoom is used for subdocuments that have a different full zoom than
2012 : * their parent documents. This item creates a container layer.
2013 : */
2014 : class nsDisplayZoom : public nsDisplayOwnLayer {
2015 : public:
2016 : /**
2017 : * @param aFrame is the root frame of the subdocument.
2018 : * @param aList contains the display items for the subdocument.
2019 : * @param aAPD is the app units per dev pixel ratio of the subdocument.
2020 : * @param aParentAPD is the app units per dev pixel ratio of the parent
2021 : * document.
2022 : */
2023 : nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2024 : nsDisplayList* aList,
2025 : PRInt32 aAPD, PRInt32 aParentAPD);
2026 : #ifdef NS_BUILD_REFCNT_LOGGING
2027 : virtual ~nsDisplayZoom();
2028 : #endif
2029 :
2030 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
2031 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
2032 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2033 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
2034 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2035 : nsRegion* aVisibleRegion,
2036 : const nsRect& aAllowVisibleRegionExpansion);
2037 0 : NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM)
2038 :
2039 : // Get the app units per dev pixel ratio of the child document.
2040 : PRInt32 GetChildAppUnitsPerDevPixel() { return mAPD; }
2041 : // Get the app units per dev pixel ratio of the parent document.
2042 0 : PRInt32 GetParentAppUnitsPerDevPixel() { return mParentAPD; }
2043 :
2044 : private:
2045 : PRInt32 mAPD, mParentAPD;
2046 : };
2047 :
2048 : /**
2049 : * A display item to paint a stacking context with effects
2050 : * set by the stacking context root frame's style.
2051 : */
2052 : class nsDisplaySVGEffects : public nsDisplayWrapList {
2053 : public:
2054 : nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2055 : nsDisplayList* aList);
2056 : #ifdef NS_BUILD_REFCNT_LOGGING
2057 : virtual ~nsDisplaySVGEffects();
2058 : #endif
2059 :
2060 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2061 : bool* aForceTransparentSurface = nsnull);
2062 : virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2063 : HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
2064 0 : virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
2065 0 : return mBounds + aBuilder->ToReferenceFrame(mEffectsFrame);
2066 : }
2067 : virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
2068 : virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2069 : nsRegion* aVisibleRegion,
2070 : const nsRect& aAllowVisibleRegionExpansion);
2071 : virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
2072 0 : NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS)
2073 :
2074 : nsIFrame* GetEffectsFrame() { return mEffectsFrame; }
2075 :
2076 : #ifdef MOZ_DUMP_PAINTING
2077 : void PrintEffects(FILE* aOutput);
2078 : #endif
2079 :
2080 : private:
2081 : nsIFrame* mEffectsFrame;
2082 : // relative to mEffectsFrame
2083 : nsRect mBounds;
2084 : };
2085 :
2086 : /* A display item that applies a transformation to all of its descendant
2087 : * elements. This wrapper should only be used if there is a transform applied
2088 : * to the root element.
2089 : *
2090 : * The reason that a "bounds" rect is involved in transform calculations is
2091 : * because CSS-transforms allow percentage values for the x and y components
2092 : * of <translation-value>s, where percentages are percentages of the element's
2093 : * border box.
2094 : *
2095 : * INVARIANT: The wrapped frame is transformed.
2096 : * INVARIANT: The wrapped frame is non-null.
2097 : */
2098 : class nsDisplayTransform: public nsDisplayItem
2099 : {
2100 : public:
2101 : /* Constructor accepts a display list, empties it, and wraps it up. It also
2102 : * ferries the underlying frame to the nsDisplayItem constructor.
2103 : */
2104 0 : nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
2105 : nsDisplayList *aList, PRUint32 aIndex = 0) :
2106 0 : nsDisplayItem(aBuilder, aFrame), mStoredList(aBuilder, aFrame, aList), mIndex(aIndex)
2107 : {
2108 0 : MOZ_COUNT_CTOR(nsDisplayTransform);
2109 0 : NS_ABORT_IF_FALSE(aFrame, "Must have a frame!");
2110 0 : }
2111 :
2112 : nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
2113 : nsDisplayItem *aItem, PRUint32 aIndex = 0) :
2114 : nsDisplayItem(aBuilder, aFrame), mStoredList(aBuilder, aFrame, aItem), mIndex(aIndex)
2115 : {
2116 : MOZ_COUNT_CTOR(nsDisplayTransform);
2117 : NS_ABORT_IF_FALSE(aFrame, "Must have a frame!");
2118 : }
2119 :
2120 : #ifdef NS_BUILD_REFCNT_LOGGING
2121 0 : virtual ~nsDisplayTransform()
2122 0 : {
2123 0 : MOZ_COUNT_DTOR(nsDisplayTransform);
2124 0 : }
2125 : #endif
2126 :
2127 0 : NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM);
2128 :
2129 0 : virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
2130 : {
2131 0 : if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty())
2132 0 : return nsRect();
2133 0 : return GetBounds(aBuilder);
2134 : }
2135 :
2136 0 : nsDisplayWrapList* GetStoredList() { return &mStoredList; }
2137 :
2138 : virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
2139 : HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames);
2140 : virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder);
2141 : virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
2142 : bool* aForceTransparentSurface = nsnull);
2143 : virtual bool IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor);
2144 : virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2145 : LayerManager* aManager);
2146 : virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2147 : LayerManager* aManager,
2148 : const ContainerParameters& aContainerParameters);
2149 : virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder,
2150 : nsRegion *aVisibleRegion,
2151 : const nsRect& aAllowVisibleRegionExpansion);
2152 : virtual bool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem);
2153 :
2154 0 : virtual PRUint32 GetPerFrameKey() { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); }
2155 :
2156 : enum {
2157 : INDEX_MAX = PR_UINT32_MAX >> nsDisplayItem::TYPE_BITS
2158 : };
2159 :
2160 : const gfx3DMatrix& GetTransform(float aAppUnitsPerPixel);
2161 :
2162 : float GetHitDepthAtPoint(const nsPoint& aPoint);
2163 :
2164 : /**
2165 : * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
2166 : * space) and returns the smallest rectangle (in aFrame's coordinate space)
2167 : * containing the transformed image of that rectangle. That is, it takes
2168 : * the four corners of the rectangle, transforms them according to the
2169 : * matrix associated with the specified frame, then returns the smallest
2170 : * rectangle containing the four transformed points.
2171 : *
2172 : * @param untransformedBounds The rectangle (in app units) to transform.
2173 : * @param aFrame The frame whose transformation should be applied. This
2174 : * function raises an assertion if aFrame is null or doesn't have a
2175 : * transform applied to it.
2176 : * @param aOrigin The origin of the transform relative to aFrame's local
2177 : * coordinate space.
2178 : * @param aBoundsOverride (optional) Rather than using the frame's computed
2179 : * bounding rect as frame bounds, use this rectangle instead. Pass
2180 : * nsnull (or nothing at all) to use the default.
2181 : */
2182 : static nsRect TransformRect(const nsRect &aUntransformedBounds,
2183 : const nsIFrame* aFrame,
2184 : const nsPoint &aOrigin,
2185 : const nsRect* aBoundsOverride = nsnull);
2186 :
2187 : static nsRect TransformRectOut(const nsRect &aUntransformedBounds,
2188 : const nsIFrame* aFrame,
2189 : const nsPoint &aOrigin,
2190 : const nsRect* aBoundsOverride = nsnull);
2191 :
2192 : /* UntransformRect is like TransformRect, except that it inverts the
2193 : * transform.
2194 : */
2195 : static bool UntransformRect(const nsRect &aUntransformedBounds,
2196 : const nsIFrame* aFrame,
2197 : const nsPoint &aOrigin,
2198 : nsRect* aOutRect);
2199 :
2200 : static bool UntransformRectMatrix(const nsRect &aUntransformedBounds,
2201 : const gfx3DMatrix& aMatrix,
2202 : float aAppUnitsPerPixel,
2203 : nsRect* aOutRect);
2204 :
2205 : /**
2206 : * Returns the bounds of a frame as defined for resolving percentage
2207 : * <translation-value>s in CSS transforms. If
2208 : * UNIFIED_CONTINUATIONS is not defined, this is simply the frame's bounding
2209 : * rectangle, translated to the origin. Otherwise, returns the smallest
2210 : * rectangle containing a frame and all of its continuations. For example,
2211 : * if there is a <span> element with several continuations split over
2212 : * several lines, this function will return the rectangle containing all of
2213 : * those continuations. This rectangle is relative to the origin of the
2214 : * frame's local coordinate space.
2215 : *
2216 : * @param aFrame The frame to get the bounding rect for.
2217 : * @return The frame's bounding rect, as described above.
2218 : */
2219 : static nsRect GetFrameBoundsForTransform(const nsIFrame* aFrame);
2220 :
2221 : /**
2222 : * Given a frame with the -moz-transform property, returns the
2223 : * transformation matrix for that frame.
2224 : *
2225 : * @param aFrame The frame to get the matrix from.
2226 : * @param aOrigin Relative to which point this transform should be applied.
2227 : * @param aAppUnitsPerPixel The number of app units per graphics unit.
2228 : * @param aBoundsOverride [optional] If this is nsnull (the default), the
2229 : * computation will use the value of GetFrameBoundsForTransform(aFrame)
2230 : * for the frame's bounding rectangle. Otherwise, it will use the
2231 : * value of aBoundsOverride. This is mostly for internal use and in
2232 : * most cases you will not need to specify a value.
2233 : */
2234 : static gfx3DMatrix GetResultingTransformMatrix(const nsIFrame* aFrame,
2235 : const nsPoint& aOrigin,
2236 : float aAppUnitsPerPixel,
2237 : const nsRect* aBoundsOverride = nsnull,
2238 : nsIFrame** aOutAncestor = nsnull);
2239 : /**
2240 : * Return true when we should try to prerender the entire contents of the
2241 : * transformed frame even when it's not completely visible (yet).
2242 : */
2243 : static bool ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
2244 : nsIFrame* aFrame);
2245 :
2246 : private:
2247 : nsDisplayWrapList mStoredList;
2248 : gfx3DMatrix mTransform;
2249 : float mCachedAppUnitsPerPixel;
2250 : PRUint32 mIndex;
2251 : };
2252 :
2253 : /**
2254 : * This class adds basic support for limiting the rendering to the part inside
2255 : * the specified edges. It's a base class for the display item classes that
2256 : * does the actual work. The two members, mLeftEdge and mRightEdge, are
2257 : * relative to the edges of the frame's scrollable overflow rectangle and is
2258 : * the amount to suppress on each side.
2259 : *
2260 : * Setting none, both or only one edge is allowed.
2261 : * The values must be non-negative.
2262 : * The default value for both edges is zero, which means everything is painted.
2263 : */
2264 0 : class nsCharClipDisplayItem : public nsDisplayItem {
2265 : public:
2266 0 : nsCharClipDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
2267 0 : : nsDisplayItem(aBuilder, aFrame), mLeftEdge(0), mRightEdge(0) {}
2268 :
2269 : struct ClipEdges {
2270 0 : ClipEdges(const nsDisplayItem& aItem,
2271 : nscoord aLeftEdge, nscoord aRightEdge) {
2272 0 : nsRect r = aItem.GetUnderlyingFrame()->GetScrollableOverflowRect() +
2273 0 : aItem.ToReferenceFrame();
2274 0 : mX = aLeftEdge > 0 ? r.x + aLeftEdge : nscoord_MIN;
2275 0 : mXMost = aRightEdge > 0 ? NS_MAX(r.XMost() - aRightEdge, mX) : nscoord_MAX;
2276 0 : }
2277 0 : void Intersect(nscoord* aX, nscoord* aWidth) const {
2278 0 : nscoord xmost1 = *aX + *aWidth;
2279 0 : *aX = NS_MAX(*aX, mX);
2280 0 : *aWidth = NS_MAX(NS_MIN(xmost1, mXMost) - *aX, 0);
2281 0 : }
2282 : nscoord mX;
2283 : nscoord mXMost;
2284 : };
2285 :
2286 : ClipEdges Edges() const { return ClipEdges(*this, mLeftEdge, mRightEdge); }
2287 :
2288 0 : static nsCharClipDisplayItem* CheckCast(nsDisplayItem* aItem) {
2289 0 : nsDisplayItem::Type t = aItem->GetType();
2290 : return (t == nsDisplayItem::TYPE_TEXT ||
2291 : t == nsDisplayItem::TYPE_TEXT_DECORATION ||
2292 : t == nsDisplayItem::TYPE_TEXT_SHADOW)
2293 0 : ? static_cast<nsCharClipDisplayItem*>(aItem) : nsnull;
2294 : }
2295 :
2296 : nscoord mLeftEdge; // length from the left side
2297 : nscoord mRightEdge; // length from the right side
2298 : };
2299 :
2300 : #endif /*NSDISPLAYLIST_H_*/
|