Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / base / nsDisplayList.h
blob0db24067be4173984e116150b3271a314c8a0199
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
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/
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.
16 * The Original Code is Novell code.
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.
22 * Contributor(s):
23 * robert@ocallahan.org
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.
37 * ***** END LICENSE BLOCK *****
41 * structures that represent things to be painted (ordered in z-order),
42 * used during painting and hit testing
45 #ifndef NSDISPLAYLIST_H_
46 #define NSDISPLAYLIST_H_
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 "nsLayoutUtils.h"
57 #include <stdlib.h>
59 class nsIPresShell;
60 class nsIContent;
61 class nsRegion;
62 class nsIRenderingContext;
63 class nsIDeviceContext;
64 class nsDisplayTableItem;
67 * An nsIFrame can have many different visual parts. For example an image frame
68 * can have a background, border, and outline, the image itself, and a
69 * translucent selection overlay. In general these parts can be drawn at
70 * discontiguous z-levels; see CSS2.1 appendix E:
71 * http://www.w3.org/TR/CSS21/zindex.html
73 * We construct a display list for a frame tree that contains one item
74 * for each visual part. The display list is itself a tree since some items
75 * are containers for other items; however, its structure does not match
76 * the structure of its source frame tree. The display list items are sorted
77 * by z-order. A display list can be used to paint the frames, to determine
78 * which frame is the target of a mouse event, and to determine what areas
79 * need to be repainted when scrolling. The display lists built for each task
80 * may be different for efficiency; in particular some frames need special
81 * display list items only for event handling, and do not create these items
82 * when the display list will be used for painting (the common case). For
83 * example, when painting we avoid creating nsDisplayBackground items for
84 * frames that don't display a visible background, but for event handling
85 * we need those backgrounds because they are not transparent to events.
87 * We could avoid constructing an explicit display list by traversing the
88 * frame tree multiple times in clever ways. However, reifying the display list
89 * reduces code complexity and reduces the number of times each frame must be
90 * traversed to one, which seems to be good for performance. It also means
91 * we can share code for painting, event handling and scroll analysis.
93 * Display lists are short-lived; content and frame trees cannot change
94 * between a display list being created and destroyed. Display lists should
95 * not be created during reflow because the frame tree may be in an
96 * inconsistent state (e.g., a frame's stored overflow-area may not include
97 * the bounds of all its children). However, it should be fine to create
98 * a display list while a reflow is pending, before it starts.
100 * A display list covers the "extended" frame tree; the display list for a frame
101 * tree containing FRAME/IFRAME elements can include frames from the subdocuments.
104 #ifdef NS_DEBUG
105 #define NS_DISPLAY_DECL_NAME(n) virtual const char* Name() { return n; }
106 #else
107 #define NS_DISPLAY_DECL_NAME(n)
108 #endif
111 * This manages a display list and is passed as a parameter to
112 * nsIFrame::BuildDisplayList.
113 * It contains the parameters that don't change from frame to frame and manages
114 * the display list memory using a PLArena. It also establishes the reference
115 * coordinate system for all display list items. Some of the parameters are
116 * available from the prescontext/presshell, but we copy them into the builder
117 * for faster/more convenient access.
119 class NS_STACK_CLASS nsDisplayListBuilder {
120 public:
122 * @param aReferenceFrame the frame at the root of the subtree; its origin
123 * is the origin of the reference coordinate system for this display list
124 * @param aIsForEvents PR_TRUE if we're creating this list in order to
125 * determine which frame is under the mouse position
126 * @param aBuildCaret whether or not we should include the caret in any
127 * display lists that we make.
128 * @param aMovingFrame a frame whose subtree should be regarded as
129 * moving; moving frames are not allowed to clip or cover (during
130 * OptimizeVisibility) non-moving frames. E.g. when we're constructing
131 * a display list to see what should be repainted during a scroll
132 * operation, we specify the scrolled frame as the moving frame.
134 nsDisplayListBuilder(nsIFrame* aReferenceFrame, PRBool aIsForEvents,
135 PRBool aBuildCaret);
136 ~nsDisplayListBuilder();
139 * @return PR_TRUE if the display is being built in order to determine which
140 * frame is under the mouse position.
142 PRBool IsForEventDelivery() { return mEventDelivery; }
144 * @return PR_TRUE if "painting is suppressed" during page load and we
145 * should paint only the background of the document.
147 PRBool IsBackgroundOnly() { return mIsBackgroundOnly; }
149 * Set to PR_TRUE if painting should be suppressed during page load.
150 * Set to PR_FALSE if painting should not be suppressed.
152 void SetBackgroundOnly(PRBool aIsBackgroundOnly) { mIsBackgroundOnly = aIsBackgroundOnly; }
154 * @return PR_TRUE if the currently active BuildDisplayList call is being
155 * applied to a frame at the root of a pseudo stacking context. A pseudo
156 * stacking context is either a real stacking context or basically what
157 * CSS2.1 appendix E refers to with "treat the element as if it created
158 * a new stacking context
160 PRBool IsAtRootOfPseudoStackingContext() { return mIsAtRootOfPseudoStackingContext; }
163 * Indicate that we'll use this display list to analyze the effects
164 * of aMovingFrame moving by aMoveDelta. The move has already been
165 * applied to the frame tree.
167 void SetMovingFrame(nsIFrame* aMovingFrame, const nsPoint& aMoveDelta) {
168 mMovingFrame = aMovingFrame;
169 mMoveDelta = aMoveDelta;
173 * @return PR_TRUE if we are doing analysis of moving frames
175 PRBool HasMovingFrames() { return mMovingFrame != nsnull; }
177 * @return the frame that was moved
179 nsIFrame* GetRootMovingFrame() { return mMovingFrame; }
181 * @return the amount by which mMovingFrame was moved.
182 * Only valid when GetRootMovingFrame() returns non-null.
184 const nsPoint& GetMoveDelta() { return mMoveDelta; }
186 * @return PR_TRUE if aFrame is, or is a descendant of, the hypothetical
187 * moving frame
189 PRBool IsMovingFrame(nsIFrame* aFrame) {
190 return aFrame == mMovingFrame || (mMovingFrame &&
191 nsLayoutUtils::IsProperAncestorFrameCrossDoc(mMovingFrame, aFrame, mReferenceFrame));
194 * @return the selection that painting should be restricted to (or nsnull
195 * in the normal unrestricted case)
197 nsISelection* GetBoundingSelection() { return mBoundingSelection; }
199 * @return the root of the display list's frame (sub)tree, whose origin
200 * establishes the coordinate system for the display list
202 nsIFrame* ReferenceFrame() { return mReferenceFrame; }
204 * @return a point pt such that adding pt to a coordinate relative to aFrame
205 * makes it relative to ReferenceFrame(), i.e., returns
206 * aFrame->GetOffsetTo(ReferenceFrame()). It may be optimized to be faster
207 * than aFrame->GetOffsetTo(ReferenceFrame()) (but currently isn't).
209 nsPoint ToReferenceFrame(const nsIFrame* aFrame) {
210 return aFrame->GetOffsetTo(ReferenceFrame());
213 * When building the display list, the scrollframe aFrame will be "ignored"
214 * for the purposes of clipping, and its scrollbars will be hidden. We use
215 * this to allow RenderOffscreen to render a whole document without beign
216 * clipped by the viewport or drawing the viewport scrollbars.
218 void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
220 * Get the scrollframe to ignore, if any.
222 nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
224 * Calling this setter makes us ignore all dirty rects and include all
225 * descendant frames in the display list, wherever they may be positioned.
227 void SetPaintAllFrames() { mPaintAllFrames = PR_TRUE; }
228 PRBool GetPaintAllFrames() { return mPaintAllFrames; }
230 * Allows callers to selectively override the regular paint suppression checks,
231 * so that methods like GetFrameForPoint work when painting is suppressed.
233 void IgnorePaintSuppression() { mIsBackgroundOnly = PR_FALSE; }
235 * Display the caret if needed.
237 nsresult DisplayCaret(nsIFrame* aFrame, const nsRect& aDirtyRect,
238 const nsDisplayListSet& aLists) {
239 nsIFrame* frame = GetCaretFrame();
240 if (aFrame != frame) {
241 return NS_OK;
243 return frame->DisplayCaret(this, aDirtyRect, aLists);
246 * Get the frame that the caret is supposed to draw in.
247 * If the caret is currently invisible, this will be null.
249 nsIFrame* GetCaretFrame() {
250 return CurrentPresShellState()->mCaretFrame;
253 * Get the caret associated with the current presshell.
255 nsCaret* GetCaret();
257 * Notify the display list builder that we're entering a presshell.
258 * aReferenceFrame should be a frame in the new presshell and aDirtyRect
259 * should be the current dirty rect in aReferenceFrame's coordinate space.
261 void EnterPresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect);
263 * Notify the display list builder that we're leaving a presshell.
265 void LeavePresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect);
268 * Mark aFrames and its (next) siblings to be displayed if they
269 * intersect aDirtyRect (which is relative to aDirtyFrame). If the
270 * frame(s) have placeholders that might not be displayed, we mark the
271 * placeholders and their ancestors to ensure that display list construction
272 * descends into them anyway. nsDisplayListBuilder will take care of
273 * unmarking them when it is destroyed.
275 void MarkFramesForDisplayList(nsIFrame* aDirtyFrame, nsIFrame* aFrames,
276 const nsRect& aDirtyRect);
279 * Allocate memory in our arena. It will only be freed when this display list
280 * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
281 * destructors are called as soon as the item is no longer used.
283 void* Allocate(size_t aSize);
286 * A helper class to temporarily set the value of
287 * mIsAtRootOfPseudoStackingContext.
289 class AutoIsRootSetter;
290 friend class AutoIsRootSetter;
291 class AutoIsRootSetter {
292 public:
293 AutoIsRootSetter(nsDisplayListBuilder* aBuilder, PRBool aIsRoot)
294 : mBuilder(aBuilder), mOldValue(aBuilder->mIsAtRootOfPseudoStackingContext) {
295 aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
297 ~AutoIsRootSetter() {
298 mBuilder->mIsAtRootOfPseudoStackingContext = mOldValue;
300 private:
301 nsDisplayListBuilder* mBuilder;
302 PRPackedBool mOldValue;
305 // Helpers for tables
306 nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
307 void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
309 private:
310 // This class is only used on stack, so we don't have to worry about leaking
311 // it. Don't let us be heap-allocated!
312 void* operator new(size_t sz) CPP_THROW_NEW;
314 struct PresShellState {
315 nsIPresShell* mPresShell;
316 nsIFrame* mCaretFrame;
317 PRUint32 mFirstFrameMarkedForDisplay;
319 PresShellState* CurrentPresShellState() {
320 NS_ASSERTION(mPresShellStates.Length() > 0,
321 "Someone forgot to enter a presshell");
322 return &mPresShellStates[mPresShellStates.Length() - 1];
325 nsIFrame* mReferenceFrame;
326 nsIFrame* mMovingFrame;
327 nsIFrame* mIgnoreScrollFrame;
328 nsPoint mMoveDelta; // only valid when mMovingFrame is non-null
329 PLArenaPool mPool;
330 nsCOMPtr<nsISelection> mBoundingSelection;
331 nsAutoTArray<PresShellState,8> mPresShellStates;
332 nsAutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
333 nsDisplayTableItem* mCurrentTableItem;
334 PRPackedBool mBuildCaret;
335 PRPackedBool mEventDelivery;
336 PRPackedBool mIsBackgroundOnly;
337 PRPackedBool mIsAtRootOfPseudoStackingContext;
338 PRPackedBool mPaintAllFrames;
341 class nsDisplayItem;
342 class nsDisplayList;
344 * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
345 * nsDisplayItemLink holds the link. The lists are linked from lowest to
346 * highest in z-order.
348 class nsDisplayItemLink {
349 // This is never instantiated directly, so no need to count constructors and
350 // destructors.
351 protected:
352 nsDisplayItemLink() : mAbove(nsnull) {}
353 nsDisplayItem* mAbove;
355 friend class nsDisplayList;
359 * This is the unit of rendering and event testing. Each instance of this
360 * class represents an entity that can be drawn on the screen, e.g., a
361 * frame's CSS background, or a frame's text string.
363 * nsDisplayListItems can be containers --- i.e., they can perform hit testing
364 * and painting by recursively traversing a list of child items.
366 * These are arena-allocated during display list construction. A typical
367 * subclass would just have a frame pointer, so its object would be just three
368 * pointers (vtable, next-item, frame).
370 * Display items belong to a list at all times (except temporarily as they
371 * move from one list to another).
373 class nsDisplayItem : public nsDisplayItemLink {
374 public:
375 // This is never instantiated directly (it has pure virtual methods), so no
376 // need to count constructors and destructors.
377 nsDisplayItem(nsIFrame* aFrame) : mFrame(aFrame) {}
378 virtual ~nsDisplayItem() {}
380 void* operator new(size_t aSize,
381 nsDisplayListBuilder* aBuilder) CPP_THROW_NEW {
382 return aBuilder->Allocate(aSize);
386 * It's useful to be able to dynamically check the type of certain items.
387 * For items whose type never gets checked, TYPE_GENERIC will suffice.
389 enum Type {
390 TYPE_GENERIC,
391 TYPE_OUTLINE,
392 TYPE_CLIP,
393 TYPE_OPACITY,
394 #ifdef MOZ_SVG
395 TYPE_SVG_EFFECTS,
396 #endif
397 TYPE_WRAPLIST,
398 TYPE_TRANSFORM
401 struct HitTestState {
402 ~HitTestState() {
403 NS_ASSERTION(mItemBuffer.Length() == 0,
404 "mItemBuffer should have been cleared");
406 nsAutoTArray<nsDisplayItem*, 100> mItemBuffer;
410 * Some consecutive items should be rendered together as a unit, e.g.,
411 * outlines for the same element. For this, we need a way for items to
412 * identify their type.
414 virtual Type GetType() { return TYPE_GENERIC; }
416 * This is called after we've constructed a display list for event handling.
417 * When this is called, we've already ensured that aPt is in the item's bounds.
419 * @param aState must point to a HitTestState. If you don't have one,
420 * just create one with the default constructor and pass it in.
421 * @return the frame that the point is considered over, or nsnull if
422 * this is not over any frame
424 virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
425 HitTestState* aState) { return nsnull; }
427 * @return the frame that this display item is based on. This is used to sort
428 * items by z-index and content order and for some other uses. For some items
429 * that wrap item lists, this could return nsnull because there is no single
430 * underlying frame; for leaf items it will never return nsnull.
432 inline nsIFrame* GetUnderlyingFrame() { return mFrame; }
434 * The default bounds is the frame border rect.
435 * @return a rectangle relative to aBuilder->ReferenceFrame() that
436 * contains the area drawn by this display item
438 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
439 nsIFrame* f = GetUnderlyingFrame();
440 return nsRect(aBuilder->ToReferenceFrame(f), f->GetSize());
443 * @return PR_TRUE if the item is definitely opaque --- i.e., paints
444 * every pixel within its bounds opaquely
446 virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) { return PR_FALSE; }
448 * @return PR_TRUE if the item is guaranteed to paint every pixel in its
449 * bounds with the same (possibly translucent) color
451 virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder) { return PR_FALSE; }
453 * @return PR_FALSE if the painting performed by the item is invariant
454 * when frame aFrame is moved relative to aBuilder->GetRootMovingFrame().
455 * This can only be called when aBuilder->IsMovingFrame(mFrame) is true.
456 * It return PR_TRUE for all wrapped lists.
458 virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder)
459 { return PR_FALSE; }
461 * Actually paint this item to some rendering context.
462 * @param aDirtyRect relative to aBuilder->ReferenceFrame()
464 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
465 const nsRect& aDirtyRect) {}
468 * Only to be (re)implemented by items that contain child display lists.
469 * Do not reimplement for leaf items.
470 * The default implementation calls GetBounds() and IsOpaque().
471 * On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
472 * which may be visible. If the display item opaquely covers an area, it
473 * can remove that area from aVisibleRegion before returning.
474 * @return PR_TRUE if the item is visible, PR_FALSE if no part of the item
475 * is visible
477 virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
478 nsRegion* aVisibleRegion);
480 * Try to merge with the other item (which is below us in the display
481 * list). This gets used by nsDisplayClip to coalesce clipping operations
482 * (optimization), by nsDisplayOpacity to merge rendering for the same
483 * content element into a single opacity group (correctness), and will be
484 * used by nsDisplayOutline to merge multiple outlines for the same element
485 * (also for correctness).
486 * @return PR_TRUE if the merge was successful and the other item should be deleted
488 virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
489 return PR_FALSE;
493 * If this is a leaf item we return null, otherwise we return the wrapped
494 * list.
496 virtual nsDisplayList* GetList() { return nsnull; }
498 #ifdef NS_DEBUG
500 * For debugging and stuff
502 virtual const char* Name() = 0;
503 #endif
505 nsDisplayItem* GetAbove() { return mAbove; }
507 protected:
508 friend class nsDisplayList;
510 nsDisplayItem() {
511 mAbove = nsnull;
514 static PRBool ComputeVisibilityFromBounds(nsIFrame* aFrame,
515 const nsRect& aRect, nsRegion& aCovered, PRBool aIsOpaque);
517 nsIFrame* mFrame;
521 * Manages a singly-linked list of display list items.
523 * mSentinel is the sentinel list value, the first value in the null-terminated
524 * linked list of items. mTop is the last item in the list (whose 'above'
525 * pointer is null). This class has no virtual methods. So list objects are just
526 * two pointers.
528 * Stepping upward through this list is very fast. Stepping downward is very
529 * slow so we don't support it. The methods that need to step downward
530 * (HitTest(), OptimizeVisibility()) internally build a temporary array of all
531 * the items while they do the downward traversal, so overall they're still
532 * linear time. We have optimized for efficient AppendToTop() of both
533 * items and lists, with minimal codesize. AppendToBottom() is efficient too.
535 class nsDisplayList {
536 public:
538 * Create an empty list.
540 nsDisplayList() { mTop = &mSentinel; mSentinel.mAbove = nsnull; }
541 ~nsDisplayList() {
542 if (mSentinel.mAbove) {
543 NS_WARNING("Nonempty list left over?");
545 DeleteAll();
549 * Append an item to the top of the list. The item must not currently
550 * be in a list and cannot be null.
552 void AppendToTop(nsDisplayItem* aItem) {
553 NS_ASSERTION(aItem, "No item to append!");
554 NS_ASSERTION(!aItem->mAbove, "Already in a list!");
555 mTop->mAbove = aItem;
556 mTop = aItem;
560 * Append a new item to the top of the list. If the item is null we return
561 * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToTop(new ...);
563 nsresult AppendNewToTop(nsDisplayItem* aItem) {
564 if (!aItem)
565 return NS_ERROR_OUT_OF_MEMORY;
566 AppendToTop(aItem);
567 return NS_OK;
571 * Append a new item to the bottom of the list. If the item is null we return
572 * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToBottom(new ...);
574 nsresult AppendNewToBottom(nsDisplayItem* aItem) {
575 if (!aItem)
576 return NS_ERROR_OUT_OF_MEMORY;
577 AppendToBottom(aItem);
578 return NS_OK;
582 * Append a new item to the bottom of the list. The item must be non-null
583 * and not already in a list.
585 void AppendToBottom(nsDisplayItem* aItem) {
586 NS_ASSERTION(aItem, "No item to append!");
587 NS_ASSERTION(!aItem->mAbove, "Already in a list!");
588 aItem->mAbove = mSentinel.mAbove;
589 mSentinel.mAbove = aItem;
590 if (mTop == &mSentinel) {
591 mTop = aItem;
596 * Removes all items from aList and appends them to the top of this list
598 void AppendToTop(nsDisplayList* aList) {
599 if (aList->mSentinel.mAbove) {
600 mTop->mAbove = aList->mSentinel.mAbove;
601 mTop = aList->mTop;
602 aList->mTop = &aList->mSentinel;
603 aList->mSentinel.mAbove = nsnull;
608 * Removes all items from aList and prepends them to the bottom of this list
610 void AppendToBottom(nsDisplayList* aList) {
611 if (aList->mSentinel.mAbove) {
612 aList->mTop->mAbove = mSentinel.mAbove;
613 mTop = aList->mTop;
614 mSentinel.mAbove = aList->mSentinel.mAbove;
616 aList->mTop = &aList->mSentinel;
617 aList->mSentinel.mAbove = nsnull;
622 * Remove an item from the bottom of the list and return it.
624 nsDisplayItem* RemoveBottom();
627 * Remove an item from the bottom of the list and call its destructor.
629 void DeleteBottom();
631 * Remove all items from the list and call their destructors.
633 void DeleteAll();
636 * @return the item at the top of the list, or null if the list is empty
638 nsDisplayItem* GetTop() const {
639 return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nsnull;
642 * @return the item at the bottom of the list, or null if the list is empty
644 nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
645 PRBool IsEmpty() const { return mTop == &mSentinel; }
648 * This is *linear time*!
649 * @return the number of items in the list
651 PRUint32 Count() const;
653 * Stable sort the list by the z-order of GetUnderlyingFrame() on
654 * each item. 'auto' is counted as zero. Content order is used as the
655 * secondary order.
656 * @param aCommonAncestor a common ancestor of all the content elements
657 * associated with the display items, for speeding up tree order
658 * checks, or nsnull if not known; it's only a hint, if it is not an
659 * ancestor of some elements, then we lose performance but not correctness
661 void SortByZOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
663 * Stable sort the list by the tree order of the content of
664 * GetUnderlyingFrame() on each item. z-index is ignored.
665 * @param aCommonAncestor a common ancestor of all the content elements
666 * associated with the display items, for speeding up tree order
667 * checks, or nsnull if not known; it's only a hint, if it is not an
668 * ancestor of some elements, then we lose performance but not correctness
670 void SortByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
673 * Generic stable sort. Take care, because some of the items might be nsDisplayLists
674 * themselves.
675 * aCmp(item1, item2) should return true if item1 <= item2. We sort the items
676 * into increasing order.
678 typedef PRBool (* SortLEQ)(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
679 void* aClosure);
680 void Sort(nsDisplayListBuilder* aBuilder, SortLEQ aCmp, void* aClosure);
683 * Optimize the display list for visibility, removing any elements that
684 * are not visible. We put this logic here so it can be shared by top-level
685 * painting and also display items that maintain child lists.
687 * @param aVisibleRegion the area that is visible, relative to the
688 * reference frame; on return, this contains the area visible under the list
690 void OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
692 * Paint the list to the rendering context. We assume that (0,0) in aCtx
693 * corresponds to the origin of the reference frame. For best results,
694 * aCtx's current transform should make (0,0) pixel-aligned. The
695 * rectangle in aDirtyRect is painted, which *must* be contained in the
696 * dirty rect used to construct the display list.
698 void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
699 const nsRect& aDirtyRect) const;
701 * Get the bounds. Takes the union of the bounds of all children.
703 nsRect GetBounds(nsDisplayListBuilder* aBuilder) const;
705 * Find the topmost display item that returns a non-null frame, and return
706 * the frame.
708 nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
709 nsDisplayItem::HitTestState* aState) const;
711 private:
712 // This class is only used on stack, so we don't have to worry about leaking
713 // it. Don't let us be heap-allocated!
714 void* operator new(size_t sz) CPP_THROW_NEW;
716 // Utility function used to massage the list during OptimizeVisibility.
717 void FlattenTo(nsTArray<nsDisplayItem*>* aElements);
718 // Utility function used to massage the list during sorting, to rewrite
719 // any wrapper items with null GetUnderlyingFrame
720 void ExplodeAnonymousChildLists(nsDisplayListBuilder* aBuilder);
722 nsDisplayItemLink mSentinel;
723 nsDisplayItemLink* mTop;
727 * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
728 * will put any generated items onto the appropriate list given here. It's
729 * basically just a collection with one list for each separate stacking layer.
730 * The lists themselves are external to this object and thus can be shared
731 * with others. Some of the list pointers may even refer to the same list.
733 class nsDisplayListSet {
734 public:
736 * @return a list where one should place the border and/or background for
737 * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
739 nsDisplayList* BorderBackground() const { return mBorderBackground; }
741 * @return a list where one should place the borders and/or backgrounds for
742 * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
744 nsDisplayList* BlockBorderBackgrounds() const { return mBlockBorderBackgrounds; }
746 * @return a list where one should place descendant floats (step 5 of
747 * CSS 2.1 appendix E)
749 nsDisplayList* Floats() const { return mFloats; }
751 * @return a list where one should place the (pseudo) stacking contexts
752 * for descendants of this frame (everything from steps 3, 7 and 8
753 * of CSS 2.1 appendix E)
755 nsDisplayList* PositionedDescendants() const { return mPositioned; }
757 * @return a list where one should place the outlines
758 * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
760 nsDisplayList* Outlines() const { return mOutlines; }
762 * @return a list where one should place all other content
764 nsDisplayList* Content() const { return mContent; }
766 nsDisplayListSet(nsDisplayList* aBorderBackground,
767 nsDisplayList* aBlockBorderBackgrounds,
768 nsDisplayList* aFloats,
769 nsDisplayList* aContent,
770 nsDisplayList* aPositionedDescendants,
771 nsDisplayList* aOutlines) :
772 mBorderBackground(aBorderBackground),
773 mBlockBorderBackgrounds(aBlockBorderBackgrounds),
774 mFloats(aFloats),
775 mContent(aContent),
776 mPositioned(aPositionedDescendants),
777 mOutlines(aOutlines) {
781 * A copy constructor that lets the caller override the BorderBackground
782 * list.
784 nsDisplayListSet(const nsDisplayListSet& aLists,
785 nsDisplayList* aBorderBackground) :
786 mBorderBackground(aBorderBackground),
787 mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),
788 mFloats(aLists.Floats()),
789 mContent(aLists.Content()),
790 mPositioned(aLists.PositionedDescendants()),
791 mOutlines(aLists.Outlines()) {
795 * Move all display items in our lists to top of the corresponding lists in the
796 * destination.
798 void MoveTo(const nsDisplayListSet& aDestination) const;
800 private:
801 // This class is only used on stack, so we don't have to worry about leaking
802 // it. Don't let us be heap-allocated!
803 void* operator new(size_t sz) CPP_THROW_NEW;
805 protected:
806 nsDisplayList* mBorderBackground;
807 nsDisplayList* mBlockBorderBackgrounds;
808 nsDisplayList* mFloats;
809 nsDisplayList* mContent;
810 nsDisplayList* mPositioned;
811 nsDisplayList* mOutlines;
815 * A specialization of nsDisplayListSet where the lists are actually internal
816 * to the object, and all distinct.
818 struct nsDisplayListCollection : public nsDisplayListSet {
819 nsDisplayListCollection() :
820 nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4],
821 &mLists[5]) {}
822 nsDisplayListCollection(nsDisplayList* aBorderBackground) :
823 nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4],
824 &mLists[5]) {}
827 * Sort all lists by content order.
829 void SortAllByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor) {
830 for (PRInt32 i = 0; i < 6; ++i) {
831 mLists[i].SortByContentOrder(aBuilder, aCommonAncestor);
835 private:
836 // This class is only used on stack, so we don't have to worry about leaking
837 // it. Don't let us be heap-allocated!
838 void* operator new(size_t sz) CPP_THROW_NEW;
840 nsDisplayList mLists[6];
844 * Use this class to implement not-very-frequently-used display items
845 * that are not opaque, do not receive events, and are bounded by a frame's
846 * border-rect.
848 * This should not be used for display items which are created frequently,
849 * because each item is one or two pointers bigger than an item from a
850 * custom display item class could be, and fractionally slower. However it does
851 * save code size. We use this for infrequently-used item types.
853 class nsDisplayGeneric : public nsDisplayItem {
854 public:
855 typedef void (* PaintCallback)(nsIFrame* aFrame, nsIRenderingContext* aCtx,
856 const nsRect& aDirtyRect, nsPoint aFramePt);
858 nsDisplayGeneric(nsIFrame* aFrame, PaintCallback aPaint, const char* aName)
859 : nsDisplayItem(aFrame), mPaint(aPaint)
860 #ifdef DEBUG
861 , mName(aName)
862 #endif
864 MOZ_COUNT_CTOR(nsDisplayGeneric);
866 #ifdef NS_BUILD_REFCNT_LOGGING
867 virtual ~nsDisplayGeneric() {
868 MOZ_COUNT_DTOR(nsDisplayGeneric);
870 #endif
872 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
873 const nsRect& aDirtyRect) {
874 mPaint(mFrame, aCtx, aDirtyRect, aBuilder->ToReferenceFrame(mFrame));
876 NS_DISPLAY_DECL_NAME(mName)
877 protected:
878 PaintCallback mPaint;
879 #ifdef DEBUG
880 const char* mName;
881 #endif
884 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
886 * This class implements painting of reflow counts. Ideally, we would simply
887 * make all the frame names be those returned by nsIFrameDebug::GetFrameName
888 * (except that tosses in the content tag name!) and support only one color
889 * and eliminate this class altogether in favor of nsDisplayGeneric, but for
890 * the time being we can't pass args to a PaintCallback, so just have a
891 * separate class to do the right thing. Sadly, this alsmo means we need to
892 * hack all leaf frame classes to handle this.
894 * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
895 * here... I could switch it all to nscolor, but why bother?
897 class nsDisplayReflowCount : public nsDisplayItem {
898 public:
899 nsDisplayReflowCount(nsIFrame* aFrame, const char* aFrameName,
900 PRUint32 aColor = 0)
901 : nsDisplayItem(aFrame),
902 mFrameName(aFrameName),
903 mColor(aColor)
905 MOZ_COUNT_CTOR(nsDisplayReflowCount);
907 #ifdef NS_BUILD_REFCNT_LOGGING
908 virtual ~nsDisplayReflowCount() {
909 MOZ_COUNT_DTOR(nsDisplayReflowCount);
911 #endif
913 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
914 const nsRect& aDirtyRect) {
915 nsPoint pt = aBuilder->ToReferenceFrame(mFrame);
916 nsIRenderingContext::AutoPushTranslation translate(aCtx, pt.x, pt.y);
917 mFrame->PresContext()->PresShell()->PaintCount(mFrameName, aCtx,
918 mFrame->PresContext(),
919 mFrame, mColor);
921 NS_DISPLAY_DECL_NAME("nsDisplayReflowCount")
922 protected:
923 const char* mFrameName;
924 nscolor mColor;
927 #define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
928 PR_BEGIN_MACRO \
929 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery()) { \
930 nsresult _rv = \
931 aLists.Outlines()->AppendNewToTop(new (aBuilder) \
932 nsDisplayReflowCount(this, _name)); \
933 NS_ENSURE_SUCCESS(_rv, _rv); \
935 PR_END_MACRO
937 #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
938 PR_BEGIN_MACRO \
939 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery()) { \
940 nsresult _rv = \
941 aLists.Outlines()->AppendNewToTop(new (aBuilder) \
942 nsDisplayReflowCount(this, _name, \
943 _color)); \
944 NS_ENSURE_SUCCESS(_rv, _rv); \
946 PR_END_MACRO
949 Macro to be used for classes that don't actually implement BuildDisplayList
951 #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
952 NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, \
953 const nsRect& aDirtyRect, \
954 const nsDisplayListSet& aLists) { \
955 DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
956 return _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
959 #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
961 #define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
962 #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
963 #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
965 #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
967 class nsDisplayCaret : public nsDisplayItem {
968 public:
969 nsDisplayCaret(nsIFrame* aCaretFrame, nsCaret *aCaret)
970 : nsDisplayItem(aCaretFrame), mCaret(aCaret) {
971 MOZ_COUNT_CTOR(nsDisplayCaret);
973 #ifdef NS_BUILD_REFCNT_LOGGING
974 virtual ~nsDisplayCaret() {
975 MOZ_COUNT_DTOR(nsDisplayCaret);
977 #endif
979 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
980 // The caret returns a rect in the coordinates of mFrame.
981 return mCaret->GetCaretRect() + aBuilder->ToReferenceFrame(mFrame);
983 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
984 const nsRect& aDirtyRect);
985 NS_DISPLAY_DECL_NAME("Caret")
986 protected:
987 nsRefPtr<nsCaret> mCaret;
991 * The standard display item to paint the CSS borders of a frame.
993 class nsDisplayBorder : public nsDisplayItem {
994 public:
995 nsDisplayBorder(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
996 MOZ_COUNT_CTOR(nsDisplayBorder);
998 #ifdef NS_BUILD_REFCNT_LOGGING
999 virtual ~nsDisplayBorder() {
1000 MOZ_COUNT_DTOR(nsDisplayBorder);
1002 #endif
1004 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
1005 const nsRect& aDirtyRect);
1006 virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
1007 NS_DISPLAY_DECL_NAME("Border")
1011 * The standard display item to paint the CSS background of a frame.
1013 class nsDisplayBackground : public nsDisplayItem {
1014 public:
1015 nsDisplayBackground(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
1016 mIsThemed = mFrame->IsThemed();
1017 MOZ_COUNT_CTOR(nsDisplayBackground);
1019 #ifdef NS_BUILD_REFCNT_LOGGING
1020 virtual ~nsDisplayBackground() {
1021 MOZ_COUNT_DTOR(nsDisplayBackground);
1023 #endif
1025 virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
1026 HitTestState* aState) { return mFrame; }
1027 virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
1028 virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder);
1029 virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder);
1030 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1031 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
1032 const nsRect& aDirtyRect);
1033 NS_DISPLAY_DECL_NAME("Background")
1034 private:
1035 /* Used to cache mFrame->IsThemed() since it isn't a cheap call */
1036 PRPackedBool mIsThemed;
1040 * The standard display item to paint the CSS box-shadow of a frame.
1042 class nsDisplayBoxShadow : public nsDisplayItem {
1043 public:
1044 nsDisplayBoxShadow(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
1045 MOZ_COUNT_CTOR(nsDisplayBoxShadow);
1047 #ifdef NS_BUILD_REFCNT_LOGGING
1048 virtual ~nsDisplayBoxShadow() {
1049 MOZ_COUNT_DTOR(nsDisplayBoxShadow);
1051 #endif
1053 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
1054 const nsRect& aDirtyRect);
1055 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1056 NS_DISPLAY_DECL_NAME("BoxShadow")
1060 * The standard display item to paint the CSS outline of a frame.
1062 class nsDisplayOutline : public nsDisplayItem {
1063 public:
1064 nsDisplayOutline(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
1065 MOZ_COUNT_CTOR(nsDisplayOutline);
1067 #ifdef NS_BUILD_REFCNT_LOGGING
1068 virtual ~nsDisplayOutline() {
1069 MOZ_COUNT_DTOR(nsDisplayOutline);
1071 #endif
1073 virtual Type GetType() { return TYPE_OUTLINE; }
1074 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1075 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
1076 const nsRect& aDirtyRect);
1077 virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
1078 NS_DISPLAY_DECL_NAME("Outline")
1082 * A class that lets you receive events within the frame bounds but never paints.
1084 class nsDisplayEventReceiver : public nsDisplayItem {
1085 public:
1086 nsDisplayEventReceiver(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
1087 MOZ_COUNT_CTOR(nsDisplayEventReceiver);
1089 #ifdef NS_BUILD_REFCNT_LOGGING
1090 virtual ~nsDisplayEventReceiver() {
1091 MOZ_COUNT_DTOR(nsDisplayEventReceiver);
1093 #endif
1095 virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
1096 HitTestState* aState) { return mFrame; }
1097 NS_DISPLAY_DECL_NAME("EventReceiver")
1101 * A class that lets you wrap a display list as a display item.
1103 * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
1104 * list has many items, it's not clear which one has the 'underlying frame'.
1105 * Thus we force the creator to specify what the underlying frame is. The
1106 * underlying frame should be the root of a stacking context, because sorting
1107 * a list containing this item will not get at the children.
1109 * In some cases (e.g., clipping) we want to wrap a list but we don't have a
1110 * particular underlying frame that is a stacking context root. In that case
1111 * we allow the frame to be nsnull. Callers to GetUnderlyingFrame must
1112 * detect and handle this case.
1114 class nsDisplayWrapList : public nsDisplayItem {
1115 // This is never instantiated directly, so no need to count constructors and
1116 // destructors.
1118 public:
1120 * Takes all the items from aList and puts them in our list.
1122 nsDisplayWrapList(nsIFrame* aFrame, nsDisplayList* aList);
1123 nsDisplayWrapList(nsIFrame* aFrame, nsDisplayItem* aItem);
1124 virtual ~nsDisplayWrapList();
1125 virtual Type GetType() { return TYPE_WRAPLIST; }
1126 virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
1127 HitTestState* aState);
1128 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1129 virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
1130 virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder);
1131 virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder);
1132 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
1133 const nsRect& aDirtyRect);
1134 virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
1135 nsRegion* aVisibleRegion);
1136 virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
1137 NS_WARNING("This list should already have been flattened!!!");
1138 return PR_FALSE;
1140 NS_DISPLAY_DECL_NAME("WrapList")
1142 virtual nsDisplayList* GetList() { return &mList; }
1145 * This creates a copy of this item, but wrapping aItem instead of
1146 * our existing list. Only gets called if this item returned nsnull
1147 * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
1148 * GetUnderlyingFrame().
1150 virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
1151 nsDisplayItem* aItem) {
1152 NS_NOTREACHED("We never returned nsnull for GetUnderlyingFrame!");
1153 return nsnull;
1156 protected:
1157 nsDisplayWrapList() {}
1159 nsDisplayList mList;
1163 * We call WrapDisplayList on the in-flow lists: BorderBackground(),
1164 * BlockBorderBackgrounds() and Content().
1165 * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
1166 * and Floats(). This is done to support special wrapping processing for frames
1167 * that may not be in-flow descendants of the current frame.
1169 class nsDisplayWrapper {
1170 public:
1171 // This is never instantiated directly (it has pure virtual methods), so no
1172 // need to count constructors and destructors.
1174 virtual PRBool WrapBorderBackground() { return PR_TRUE; }
1175 virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
1176 nsIFrame* aFrame, nsDisplayList* aList) = 0;
1177 virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
1178 nsDisplayItem* aItem) = 0;
1180 nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1181 const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
1182 nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1183 const nsDisplayListSet& aLists);
1184 protected:
1185 nsDisplayWrapper() {}
1189 * The standard display item to paint a stacking context with translucency
1190 * set by the stacking context root frame's 'opacity' style.
1192 class nsDisplayOpacity : public nsDisplayWrapList {
1193 public:
1194 nsDisplayOpacity(nsIFrame* aFrame, nsDisplayList* aList);
1195 #ifdef NS_BUILD_REFCNT_LOGGING
1196 virtual ~nsDisplayOpacity();
1197 #endif
1199 virtual Type GetType() { return TYPE_OPACITY; }
1200 virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
1201 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
1202 const nsRect& aDirtyRect);
1203 virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
1204 nsRegion* aVisibleRegion);
1205 virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
1206 NS_DISPLAY_DECL_NAME("Opacity")
1208 private:
1210 * We set this to PR_FALSE if we can prove that our children cover our bounds
1211 * completely and opaquely, therefore no alpha channel is required in the
1212 * intermediate surface.
1214 PRPackedBool mNeedAlpha;
1218 * nsDisplayClip can clip a list of items, but we take a single item
1219 * initially and then later merge other items into it when we merge
1220 * adjacent matching nsDisplayClips
1222 class nsDisplayClip : public nsDisplayWrapList {
1223 public:
1225 * @param aFrame the frame that should be considered the underlying
1226 * frame for this content, e.g. the frame whose z-index we have.
1227 * @param aClippingFrame the frame that is inducing the clipping.
1229 nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
1230 nsDisplayItem* aItem, const nsRect& aRect);
1231 nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
1232 nsDisplayList* aList, const nsRect& aRect);
1233 #ifdef NS_BUILD_REFCNT_LOGGING
1234 virtual ~nsDisplayClip();
1235 #endif
1237 virtual Type GetType() { return TYPE_CLIP; }
1238 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
1239 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
1240 const nsRect& aDirtyRect);
1241 virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
1242 nsRegion* aVisibleRegion);
1243 virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
1244 NS_DISPLAY_DECL_NAME("Clip")
1246 nsRect GetClipRect() { return mClip; }
1247 void SetClipRect(const nsRect& aRect) { mClip = aRect; }
1248 nsIFrame* GetClippingFrame() { return mClippingFrame; }
1250 virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
1251 nsDisplayItem* aItem);
1253 private:
1254 // The frame that is responsible for the clipping. This may be different
1255 // from mFrame because mFrame represents the content that is being
1256 // clipped, and for example may be used to obtain the z-index of the
1257 // content.
1258 nsIFrame* mClippingFrame;
1259 nsRect mClip;
1262 #ifdef MOZ_SVG
1264 * A display item to paint a stacking context with effects
1265 * set by the stacking context root frame's style.
1267 class nsDisplaySVGEffects : public nsDisplayWrapList {
1268 public:
1269 nsDisplaySVGEffects(nsIFrame* aFrame, nsDisplayList* aList);
1270 #ifdef NS_BUILD_REFCNT_LOGGING
1271 virtual ~nsDisplaySVGEffects();
1272 #endif
1274 virtual Type GetType() { return TYPE_SVG_EFFECTS; }
1275 virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
1276 virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
1277 HitTestState* aState);
1278 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
1279 return mBounds + aBuilder->ToReferenceFrame(mEffectsFrame);
1281 virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
1282 const nsRect& aDirtyRect);
1283 virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
1284 nsRegion* aVisibleRegion);
1285 virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
1286 NS_DISPLAY_DECL_NAME("SVGEffects")
1288 nsIFrame* GetEffectsFrame() { return mEffectsFrame; }
1290 private:
1291 nsIFrame* mEffectsFrame;
1292 // relative to mEffectsFrame
1293 nsRect mBounds;
1295 #endif
1297 /* A display item that applies a transformation to all of its descendent
1298 * elements. This wrapper should only be used if there is a transform applied
1299 * to the root element.
1300 * INVARIANT: The wrapped frame is transformed.
1301 * INVARIANT: The wrapped frame is non-null.
1303 class nsDisplayTransform: public nsDisplayItem
1305 public:
1306 /* Constructor accepts a display list, empties it, and wraps it up. It also
1307 * ferries the underlying frame to the nsDisplayItem constructor.
1309 nsDisplayTransform(nsIFrame *aFrame, nsDisplayList *aList) :
1310 nsDisplayItem(aFrame), mStoredList(aFrame, aList)
1312 MOZ_COUNT_CTOR(nsDisplayTransform);
1315 #ifdef NS_BUILD_REFCNT_LOGGING
1316 virtual ~nsDisplayTransform()
1318 MOZ_COUNT_DTOR(nsDisplayTransform);
1320 #endif
1322 NS_DISPLAY_DECL_NAME("nsDisplayTransform");
1324 virtual Type GetType()
1326 return TYPE_TRANSFORM;
1329 virtual nsIFrame* HitTest(nsDisplayListBuilder *aBuilder, nsPoint aPt,
1330 HitTestState *aState);
1331 virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder);
1332 virtual PRBool IsOpaque(nsDisplayListBuilder *aBuilder);
1333 virtual PRBool IsUniform(nsDisplayListBuilder *aBuilder);
1334 virtual void Paint(nsDisplayListBuilder *aBuilder,
1335 nsIRenderingContext *aCtx,
1336 const nsRect &aDirtyRect);
1337 virtual PRBool OptimizeVisibility(nsDisplayListBuilder *aBuilder,
1338 nsRegion *aVisibleRegion);
1339 virtual PRBool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem);
1342 * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
1343 * space) and returns the smallest rectangle (in aFrame's coordinate space)
1344 * containing the transformed image of that rectangle. That is, it takes
1345 * the four corners of the rectangle, transforms them according to the
1346 * matrix associated with the specified frame, then returns the smallest
1347 * rectangle containing the four transformed points.
1349 * @param untransformedBounds The rectangle (in app units) to transform.
1350 * @param aFrame The frame whose transformation should be applied. This
1351 * function raises an assertion if aFrame is null or doesn't have a
1352 * transform applied to it.
1353 * @param aOrigin The origin of the transform relative to aFrame's local
1354 * coordinate space.
1355 * @param aBoundsOverride (optional) Rather than using the frame's computed
1356 * bounding rect as frame bounds, use this rectangle instead. Pass
1357 * nsnull (or nothing at all) to use the default.
1359 static nsRect TransformRect(const nsRect &aUntransformedBounds,
1360 const nsIFrame* aFrame,
1361 const nsPoint &aOrigin,
1362 const nsRect* aBoundsOverride = nsnull);
1364 /* UntransformRect is like TransformRect, except that it inverts the
1365 * transform.
1367 static nsRect UntransformRect(const nsRect &aUntransformedBounds,
1368 const nsIFrame* aFrame,
1369 const nsPoint &aOrigin);
1372 * Returns the bounds of a frame as defined for transforms. If
1373 * UNIFIED_CONTINUATIONS is not defined, this is simply the frame's bounding
1374 * rectangle, translated to the origin. Otherwise, returns the smallest
1375 * rectangle containing a frame and all of its continuations. For example,
1376 * if there is a <span> element with several continuations split over
1377 * several lines, this function will return the rectangle containing all of
1378 * those continuations. This rectangle is relative to the origin of the
1379 * frame's local coordinate space.
1381 * @param aFrame The frame to get the bounding rect for.
1382 * @return The frame's bounding rect, as described above.
1384 static nsRect GetFrameBoundsForTransform(const nsIFrame* aFrame);
1387 * Given a frame with the -moz-transform property, returns the
1388 * transformation matrix for that frame.
1390 * @param aFrame The frame to get the matrix from.
1391 * @param aOrigin Relative to which point this transform should be applied.
1392 * @param aScaleFactor The number of app units per graphics unit.
1393 * @param aBoundsOverride [optional] If this is nsnull (the default), the
1394 * computation will use the value of GetFrameBoundsForTransform(aFrame)
1395 * for the frame's bounding rectangle. Otherwise, it will use the
1396 * value of aBoundsOverride. This is mostly for internal use and in
1397 * most cases you will not need to specify a value.
1399 static gfxMatrix GetResultingTransformMatrix(const nsIFrame* aFrame,
1400 const nsPoint& aOrigin,
1401 float aFactor,
1402 const nsRect* aBoundsOverride = nsnull);
1404 private:
1405 nsDisplayWrapList mStoredList;
1408 #endif /*NSDISPLAYLIST_H_*/