layout/base/nsDisplayList.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * vim: set ts=2 sw=2 et tw=78:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 6 */
michael@0 7
michael@0 8 /*
michael@0 9 * structures that represent things to be painted (ordered in z-order),
michael@0 10 * used during painting and hit testing
michael@0 11 */
michael@0 12
michael@0 13 #ifndef NSDISPLAYLIST_H_
michael@0 14 #define NSDISPLAYLIST_H_
michael@0 15
michael@0 16 #include "mozilla/Attributes.h"
michael@0 17 #include "nsCOMPtr.h"
michael@0 18 #include "nsIFrame.h"
michael@0 19 #include "nsPoint.h"
michael@0 20 #include "nsRect.h"
michael@0 21 #include "nsCaret.h"
michael@0 22 #include "plarena.h"
michael@0 23 #include "nsRegion.h"
michael@0 24 #include "FrameLayerBuilder.h"
michael@0 25 #include "nsLayoutUtils.h"
michael@0 26 #include "nsDisplayListInvalidation.h"
michael@0 27 #include "DisplayListClipState.h"
michael@0 28
michael@0 29 #include <stdint.h>
michael@0 30
michael@0 31 #include <stdlib.h>
michael@0 32 #include <algorithm>
michael@0 33
michael@0 34 class nsIContent;
michael@0 35 class nsRenderingContext;
michael@0 36 class nsDisplayTableItem;
michael@0 37 class nsISelection;
michael@0 38 class nsDisplayLayerEventRegions;
michael@0 39
michael@0 40 namespace mozilla {
michael@0 41 namespace layers {
michael@0 42 class Layer;
michael@0 43 class ImageLayer;
michael@0 44 class ImageContainer;
michael@0 45 } //namepsace
michael@0 46 } //namepsace
michael@0 47
michael@0 48 /*
michael@0 49 * An nsIFrame can have many different visual parts. For example an image frame
michael@0 50 * can have a background, border, and outline, the image itself, and a
michael@0 51 * translucent selection overlay. In general these parts can be drawn at
michael@0 52 * discontiguous z-levels; see CSS2.1 appendix E:
michael@0 53 * http://www.w3.org/TR/CSS21/zindex.html
michael@0 54 *
michael@0 55 * We construct a display list for a frame tree that contains one item
michael@0 56 * for each visual part. The display list is itself a tree since some items
michael@0 57 * are containers for other items; however, its structure does not match
michael@0 58 * the structure of its source frame tree. The display list items are sorted
michael@0 59 * by z-order. A display list can be used to paint the frames, to determine
michael@0 60 * which frame is the target of a mouse event, and to determine what areas
michael@0 61 * need to be repainted when scrolling. The display lists built for each task
michael@0 62 * may be different for efficiency; in particular some frames need special
michael@0 63 * display list items only for event handling, and do not create these items
michael@0 64 * when the display list will be used for painting (the common case). For
michael@0 65 * example, when painting we avoid creating nsDisplayBackground items for
michael@0 66 * frames that don't display a visible background, but for event handling
michael@0 67 * we need those backgrounds because they are not transparent to events.
michael@0 68 *
michael@0 69 * We could avoid constructing an explicit display list by traversing the
michael@0 70 * frame tree multiple times in clever ways. However, reifying the display list
michael@0 71 * reduces code complexity and reduces the number of times each frame must be
michael@0 72 * traversed to one, which seems to be good for performance. It also means
michael@0 73 * we can share code for painting, event handling and scroll analysis.
michael@0 74 *
michael@0 75 * Display lists are short-lived; content and frame trees cannot change
michael@0 76 * between a display list being created and destroyed. Display lists should
michael@0 77 * not be created during reflow because the frame tree may be in an
michael@0 78 * inconsistent state (e.g., a frame's stored overflow-area may not include
michael@0 79 * the bounds of all its children). However, it should be fine to create
michael@0 80 * a display list while a reflow is pending, before it starts.
michael@0 81 *
michael@0 82 * A display list covers the "extended" frame tree; the display list for a frame
michael@0 83 * tree containing FRAME/IFRAME elements can include frames from the subdocuments.
michael@0 84 *
michael@0 85 * Display item's coordinates are relative to their nearest reference frame ancestor.
michael@0 86 * Both the display root and any frame with a transform act as a reference frame
michael@0 87 * for their frame subtrees.
michael@0 88 */
michael@0 89
michael@0 90 // All types are defined in nsDisplayItemTypes.h
michael@0 91 #ifdef MOZ_DUMP_PAINTING
michael@0 92 #define NS_DISPLAY_DECL_NAME(n, e) \
michael@0 93 virtual const char* Name() { return n; } \
michael@0 94 virtual Type GetType() { return e; }
michael@0 95 #else
michael@0 96 #define NS_DISPLAY_DECL_NAME(n, e) \
michael@0 97 virtual Type GetType() { return e; }
michael@0 98 #endif
michael@0 99
michael@0 100 /**
michael@0 101 * This manages a display list and is passed as a parameter to
michael@0 102 * nsIFrame::BuildDisplayList.
michael@0 103 * It contains the parameters that don't change from frame to frame and manages
michael@0 104 * the display list memory using a PLArena. It also establishes the reference
michael@0 105 * coordinate system for all display list items. Some of the parameters are
michael@0 106 * available from the prescontext/presshell, but we copy them into the builder
michael@0 107 * for faster/more convenient access.
michael@0 108 */
michael@0 109 class nsDisplayListBuilder {
michael@0 110 public:
michael@0 111 typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
michael@0 112 typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
michael@0 113 typedef mozilla::DisplayItemClip DisplayItemClip;
michael@0 114 typedef mozilla::DisplayListClipState DisplayListClipState;
michael@0 115 typedef nsIWidget::ThemeGeometry ThemeGeometry;
michael@0 116 typedef mozilla::layers::Layer Layer;
michael@0 117 typedef mozilla::layers::FrameMetrics::ViewID ViewID;
michael@0 118
michael@0 119 /**
michael@0 120 * @param aReferenceFrame the frame at the root of the subtree; its origin
michael@0 121 * is the origin of the reference coordinate system for this display list
michael@0 122 * @param aIsForEvents true if we're creating this list in order to
michael@0 123 * determine which frame is under the mouse position
michael@0 124 * @param aBuildCaret whether or not we should include the caret in any
michael@0 125 * display lists that we make.
michael@0 126 */
michael@0 127 enum Mode {
michael@0 128 PAINTING,
michael@0 129 EVENT_DELIVERY,
michael@0 130 PLUGIN_GEOMETRY,
michael@0 131 IMAGE_VISIBILITY,
michael@0 132 OTHER
michael@0 133 };
michael@0 134 nsDisplayListBuilder(nsIFrame* aReferenceFrame, Mode aMode, bool aBuildCaret);
michael@0 135 ~nsDisplayListBuilder();
michael@0 136
michael@0 137 void SetWillComputePluginGeometry(bool aWillComputePluginGeometry)
michael@0 138 {
michael@0 139 mWillComputePluginGeometry = aWillComputePluginGeometry;
michael@0 140 }
michael@0 141 void SetForPluginGeometry()
michael@0 142 {
michael@0 143 NS_ASSERTION(mMode == PAINTING, "Can only switch from PAINTING to PLUGIN_GEOMETRY");
michael@0 144 NS_ASSERTION(mWillComputePluginGeometry, "Should have signalled this in advance");
michael@0 145 mMode = PLUGIN_GEOMETRY;
michael@0 146 }
michael@0 147
michael@0 148 /**
michael@0 149 * @return true if the display is being built in order to determine which
michael@0 150 * frame is under the mouse position.
michael@0 151 */
michael@0 152 bool IsForEventDelivery() { return mMode == EVENT_DELIVERY; }
michael@0 153 /**
michael@0 154 * Be careful with this. The display list will be built in PAINTING mode
michael@0 155 * first and then switched to PLUGIN_GEOMETRY before a second call to
michael@0 156 * ComputeVisibility.
michael@0 157 * @return true if the display list is being built to compute geometry
michael@0 158 * for plugins.
michael@0 159 */
michael@0 160 bool IsForPluginGeometry() { return mMode == PLUGIN_GEOMETRY; }
michael@0 161 /**
michael@0 162 * @return true if the display list is being built for painting.
michael@0 163 */
michael@0 164 bool IsForPainting() { return mMode == PAINTING; }
michael@0 165 /**
michael@0 166 * @return true if the display list is being built for determining image
michael@0 167 * visibility.
michael@0 168 */
michael@0 169 bool IsForImageVisibility() { return mMode == IMAGE_VISIBILITY; }
michael@0 170 bool WillComputePluginGeometry() { return mWillComputePluginGeometry; }
michael@0 171 /**
michael@0 172 * @return true if "painting is suppressed" during page load and we
michael@0 173 * should paint only the background of the document.
michael@0 174 */
michael@0 175 bool IsBackgroundOnly() {
michael@0 176 NS_ASSERTION(mPresShellStates.Length() > 0,
michael@0 177 "don't call this if we're not in a presshell");
michael@0 178 return CurrentPresShellState()->mIsBackgroundOnly;
michael@0 179 }
michael@0 180 /**
michael@0 181 * @return true if the currently active BuildDisplayList call is being
michael@0 182 * applied to a frame at the root of a pseudo stacking context. A pseudo
michael@0 183 * stacking context is either a real stacking context or basically what
michael@0 184 * CSS2.1 appendix E refers to with "treat the element as if it created
michael@0 185 * a new stacking context
michael@0 186 */
michael@0 187 bool IsAtRootOfPseudoStackingContext() { return mIsAtRootOfPseudoStackingContext; }
michael@0 188
michael@0 189 /**
michael@0 190 * @return the selection that painting should be restricted to (or nullptr
michael@0 191 * in the normal unrestricted case)
michael@0 192 */
michael@0 193 nsISelection* GetBoundingSelection() { return mBoundingSelection; }
michael@0 194
michael@0 195 /**
michael@0 196 * @return the root of given frame's (sub)tree, whose origin
michael@0 197 * establishes the coordinate system for the child display items.
michael@0 198 */
michael@0 199 const nsIFrame* FindReferenceFrameFor(const nsIFrame *aFrame)
michael@0 200 {
michael@0 201 if (aFrame == mCachedOffsetFrame) {
michael@0 202 return mCachedReferenceFrame;
michael@0 203 }
michael@0 204 for (const nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f))
michael@0 205 {
michael@0 206 if (f == mReferenceFrame || f->IsTransformed()) {
michael@0 207 mCachedOffsetFrame = aFrame;
michael@0 208 mCachedReferenceFrame = f;
michael@0 209 mCachedOffset = aFrame->GetOffsetToCrossDoc(f);
michael@0 210 return f;
michael@0 211 }
michael@0 212 }
michael@0 213 mCachedOffsetFrame = aFrame;
michael@0 214 mCachedReferenceFrame = mReferenceFrame;
michael@0 215 mCachedOffset = aFrame->GetOffsetToCrossDoc(mReferenceFrame);
michael@0 216 return mReferenceFrame;
michael@0 217 }
michael@0 218
michael@0 219 /**
michael@0 220 * @return the root of the display list's frame (sub)tree, whose origin
michael@0 221 * establishes the coordinate system for the display list
michael@0 222 */
michael@0 223 nsIFrame* RootReferenceFrame()
michael@0 224 {
michael@0 225 return mReferenceFrame;
michael@0 226 }
michael@0 227
michael@0 228 /**
michael@0 229 * @return a point pt such that adding pt to a coordinate relative to aFrame
michael@0 230 * makes it relative to ReferenceFrame(), i.e., returns
michael@0 231 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
michael@0 232 * the appunits of aFrame. It may be optimized to be faster than
michael@0 233 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()) (but currently isn't).
michael@0 234 */
michael@0 235 const nsPoint& ToReferenceFrame(const nsIFrame* aFrame) {
michael@0 236 if (aFrame != mCachedOffsetFrame) {
michael@0 237 FindReferenceFrameFor(aFrame);
michael@0 238 }
michael@0 239 return mCachedOffset;
michael@0 240 }
michael@0 241 /**
michael@0 242 * When building the display list, the scrollframe aFrame will be "ignored"
michael@0 243 * for the purposes of clipping, and its scrollbars will be hidden. We use
michael@0 244 * this to allow RenderOffscreen to render a whole document without beign
michael@0 245 * clipped by the viewport or drawing the viewport scrollbars.
michael@0 246 */
michael@0 247 void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
michael@0 248 /**
michael@0 249 * Get the scrollframe to ignore, if any.
michael@0 250 */
michael@0 251 nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
michael@0 252 /**
michael@0 253 * Get the ViewID of the nearest scrolling ancestor frame.
michael@0 254 */
michael@0 255 ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; }
michael@0 256 /**
michael@0 257 * Calling this setter makes us include all out-of-flow descendant
michael@0 258 * frames in the display list, wherever they may be positioned (even
michael@0 259 * outside the dirty rects).
michael@0 260 */
michael@0 261 void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
michael@0 262 bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
michael@0 263 /**
michael@0 264 * Calling this setter makes us exclude all leaf frames that aren't
michael@0 265 * selected.
michael@0 266 */
michael@0 267 void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
michael@0 268 bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
michael@0 269 /**
michael@0 270 * Calling this setter makes us compute accurate visible regions at the cost
michael@0 271 * of performance if regions get very complex.
michael@0 272 */
michael@0 273 void SetAccurateVisibleRegions() { mAccurateVisibleRegions = true; }
michael@0 274 bool GetAccurateVisibleRegions() { return mAccurateVisibleRegions; }
michael@0 275 /**
michael@0 276 * Allows callers to selectively override the regular paint suppression checks,
michael@0 277 * so that methods like GetFrameForPoint work when painting is suppressed.
michael@0 278 */
michael@0 279 void IgnorePaintSuppression() { mIgnoreSuppression = true; }
michael@0 280 /**
michael@0 281 * @return Returns if this builder will ignore paint suppression.
michael@0 282 */
michael@0 283 bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; }
michael@0 284 /**
michael@0 285 * @return Returns if this builder had to ignore painting suppression on some
michael@0 286 * document when building the display list.
michael@0 287 */
michael@0 288 bool GetHadToIgnorePaintSuppression() { return mHadToIgnoreSuppression; }
michael@0 289 /**
michael@0 290 * Call this if we're doing normal painting to the window.
michael@0 291 */
michael@0 292 void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
michael@0 293 bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
michael@0 294 /**
michael@0 295 * Call this to prevent descending into subdocuments.
michael@0 296 */
michael@0 297 void SetDescendIntoSubdocuments(bool aDescend) { mDescendIntoSubdocuments = aDescend; }
michael@0 298 bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; }
michael@0 299
michael@0 300 /**
michael@0 301 * Returns true if merging and flattening of display lists should be
michael@0 302 * performed while computing visibility.
michael@0 303 */
michael@0 304 bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening; }
michael@0 305 void SetAllowMergingAndFlattening(bool aAllow) { mAllowMergingAndFlattening = aAllow; }
michael@0 306
michael@0 307 nsDisplayLayerEventRegions* GetLayerEventRegions() { return mLayerEventRegions; }
michael@0 308 void SetLayerEventRegions(nsDisplayLayerEventRegions* aItem)
michael@0 309 {
michael@0 310 mLayerEventRegions = aItem;
michael@0 311 }
michael@0 312 bool IsBuildingLayerEventRegions()
michael@0 313 {
michael@0 314 // Disable for now.
michael@0 315 return false;
michael@0 316 // return mMode == PAINTING;
michael@0 317 }
michael@0 318
michael@0 319 bool GetAncestorHasTouchEventHandler() { return mAncestorHasTouchEventHandler; }
michael@0 320 void SetAncestorHasTouchEventHandler(bool aValue)
michael@0 321 {
michael@0 322 mAncestorHasTouchEventHandler = aValue;
michael@0 323 }
michael@0 324
michael@0 325 bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; }
michael@0 326 void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = true; }
michael@0 327
michael@0 328 bool SetIsCompositingCheap(bool aCompositingCheap) {
michael@0 329 bool temp = mIsCompositingCheap;
michael@0 330 mIsCompositingCheap = aCompositingCheap;
michael@0 331 return temp;
michael@0 332 }
michael@0 333 bool IsCompositingCheap() const { return mIsCompositingCheap; }
michael@0 334 /**
michael@0 335 * Display the caret if needed.
michael@0 336 */
michael@0 337 void DisplayCaret(nsIFrame* aFrame, const nsRect& aDirtyRect,
michael@0 338 nsDisplayList* aList) {
michael@0 339 nsIFrame* frame = GetCaretFrame();
michael@0 340 if (aFrame == frame) {
michael@0 341 frame->DisplayCaret(this, aDirtyRect, aList);
michael@0 342 }
michael@0 343 }
michael@0 344 /**
michael@0 345 * Get the frame that the caret is supposed to draw in.
michael@0 346 * If the caret is currently invisible, this will be null.
michael@0 347 */
michael@0 348 nsIFrame* GetCaretFrame() {
michael@0 349 return CurrentPresShellState()->mCaretFrame;
michael@0 350 }
michael@0 351 /**
michael@0 352 * Get the caret associated with the current presshell.
michael@0 353 */
michael@0 354 nsCaret* GetCaret();
michael@0 355 /**
michael@0 356 * Notify the display list builder that we're entering a presshell.
michael@0 357 * aReferenceFrame should be a frame in the new presshell and aDirtyRect
michael@0 358 * should be the current dirty rect in aReferenceFrame's coordinate space.
michael@0 359 */
michael@0 360 void EnterPresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect);
michael@0 361 /**
michael@0 362 * For print-preview documents, we sometimes need to build display items for
michael@0 363 * the same frames multiple times in the same presentation, with different
michael@0 364 * clipping. Between each such batch of items, call
michael@0 365 * ResetMarkedFramesForDisplayList to make sure that the results of
michael@0 366 * MarkFramesForDisplayList do not carry over between batches.
michael@0 367 */
michael@0 368 void ResetMarkedFramesForDisplayList();
michael@0 369 /**
michael@0 370 * Notify the display list builder that we're leaving a presshell.
michael@0 371 */
michael@0 372 void LeavePresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect);
michael@0 373
michael@0 374 /**
michael@0 375 * Returns true if we're currently building a display list that's
michael@0 376 * directly or indirectly under an nsDisplayTransform.
michael@0 377 */
michael@0 378 bool IsInTransform() const { return mInTransform; }
michael@0 379 /**
michael@0 380 * Indicate whether or not we're directly or indirectly under and
michael@0 381 * nsDisplayTransform or SVG foreignObject.
michael@0 382 */
michael@0 383 void SetInTransform(bool aInTransform) { mInTransform = aInTransform; }
michael@0 384
michael@0 385 /**
michael@0 386 * Returns true if we're currently building display items that are in
michael@0 387 * true fixed position subtree.
michael@0 388 */
michael@0 389 bool IsInFixedPos() const { return mInFixedPos; }
michael@0 390
michael@0 391 /**
michael@0 392 * @return true if images have been set to decode synchronously.
michael@0 393 */
michael@0 394 bool ShouldSyncDecodeImages() { return mSyncDecodeImages; }
michael@0 395
michael@0 396 /**
michael@0 397 * Indicates whether we should synchronously decode images. If true, we decode
michael@0 398 * and draw whatever image data has been loaded. If false, we just draw
michael@0 399 * whatever has already been decoded.
michael@0 400 */
michael@0 401 void SetSyncDecodeImages(bool aSyncDecodeImages) {
michael@0 402 mSyncDecodeImages = aSyncDecodeImages;
michael@0 403 }
michael@0 404
michael@0 405 /**
michael@0 406 * Helper method to generate background painting flags based on the
michael@0 407 * information available in the display list builder. Currently only
michael@0 408 * accounts for mSyncDecodeImages.
michael@0 409 */
michael@0 410 uint32_t GetBackgroundPaintFlags();
michael@0 411
michael@0 412 /**
michael@0 413 * Subtracts aRegion from *aVisibleRegion. We avoid letting
michael@0 414 * aVisibleRegion become overcomplex by simplifying it if necessary ---
michael@0 415 * unless mAccurateVisibleRegions is set, in which case we let it
michael@0 416 * get arbitrarily complex.
michael@0 417 */
michael@0 418 void SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
michael@0 419 const nsRegion& aRegion);
michael@0 420
michael@0 421 /**
michael@0 422 * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
michael@0 423 * (which is relative to aDirtyFrame). If the frames have placeholders
michael@0 424 * that might not be displayed, we mark the placeholders and their ancestors
michael@0 425 * to ensure that display list construction descends into them
michael@0 426 * anyway. nsDisplayListBuilder will take care of unmarking them when it is
michael@0 427 * destroyed.
michael@0 428 */
michael@0 429 void MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
michael@0 430 const nsFrameList& aFrames,
michael@0 431 const nsRect& aDirtyRect);
michael@0 432 /**
michael@0 433 * Mark all child frames that Preserve3D() as needing display.
michael@0 434 * Because these frames include transforms set on their parent, dirty rects
michael@0 435 * for intermediate frames may be empty, yet child frames could still be visible.
michael@0 436 */
michael@0 437 void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, const nsRect& aDirtyRect);
michael@0 438
michael@0 439 /**
michael@0 440 * Get the area of the final transparent region.
michael@0 441 */
michael@0 442 const nsRegion* GetFinalTransparentRegion() { return mFinalTransparentRegion; }
michael@0 443 /**
michael@0 444 * Record the area of the final transparent region after all visibility
michael@0 445 * calculations were performed.
michael@0 446 */
michael@0 447 void SetFinalTransparentRegion(const nsRegion& aFinalTransparentRegion)
michael@0 448 {
michael@0 449 mFinalTransparentRegion = &aFinalTransparentRegion;
michael@0 450 }
michael@0 451
michael@0 452 const nsTArray<ThemeGeometry>& GetThemeGeometries() { return mThemeGeometries; }
michael@0 453
michael@0 454 /**
michael@0 455 * Returns true if we need to descend into this frame when building
michael@0 456 * the display list, even though it doesn't intersect the dirty
michael@0 457 * rect, because it may have out-of-flows that do so.
michael@0 458 */
michael@0 459 bool ShouldDescendIntoFrame(nsIFrame* aFrame) const {
michael@0 460 return
michael@0 461 (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
michael@0 462 GetIncludeAllOutOfFlows();
michael@0 463 }
michael@0 464
michael@0 465 /**
michael@0 466 * Notifies the builder that a particular themed widget exists
michael@0 467 * at the given rectangle within the currently built display list.
michael@0 468 * For certain appearance values (currently only
michael@0 469 * NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR, NS_THEME_TOOLBAR and
michael@0 470 * NS_THEME_WINDOW_TITLEBAR) this gets called during every display list
michael@0 471 * construction, for every themed widget of the right type within the
michael@0 472 * display list, except for themed widgets which are transformed or have
michael@0 473 * effects applied to them (e.g. CSS opacity or filters).
michael@0 474 *
michael@0 475 * @param aWidgetType the -moz-appearance value for the themed widget
michael@0 476 * @param aRect the device-pixel rect relative to the widget's displayRoot
michael@0 477 * for the themed widget
michael@0 478 */
michael@0 479 void RegisterThemeGeometry(uint8_t aWidgetType,
michael@0 480 const nsIntRect& aRect) {
michael@0 481 if (mIsPaintingToWindow && mPresShellStates.Length() == 1) {
michael@0 482 ThemeGeometry geometry(aWidgetType, aRect);
michael@0 483 mThemeGeometries.AppendElement(geometry);
michael@0 484 }
michael@0 485 }
michael@0 486
michael@0 487 /**
michael@0 488 * Allocate memory in our arena. It will only be freed when this display list
michael@0 489 * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
michael@0 490 * destructors are called as soon as the item is no longer used.
michael@0 491 */
michael@0 492 void* Allocate(size_t aSize);
michael@0 493
michael@0 494 /**
michael@0 495 * Allocate a new DisplayListClip in the arena. Will be cleaned up
michael@0 496 * automatically when the arena goes away.
michael@0 497 */
michael@0 498 const DisplayItemClip* AllocateDisplayItemClip(const DisplayItemClip& aOriginal);
michael@0 499
michael@0 500 /**
michael@0 501 * Transfer off main thread animations to the layer. May be called
michael@0 502 * with aBuilder and aItem both null, but only if the caller has
michael@0 503 * already checked that off main thread animations should be sent to
michael@0 504 * the layer. When they are both null, the animations are added to
michael@0 505 * the layer as pending animations.
michael@0 506 */
michael@0 507 static void AddAnimationsAndTransitionsToLayer(Layer* aLayer,
michael@0 508 nsDisplayListBuilder* aBuilder,
michael@0 509 nsDisplayItem* aItem,
michael@0 510 nsIFrame* aFrame,
michael@0 511 nsCSSProperty aProperty);
michael@0 512 /**
michael@0 513 * A helper class to temporarily set the value of
michael@0 514 * mIsAtRootOfPseudoStackingContext, and temporarily
michael@0 515 * update mCachedOffsetFrame/mCachedOffset from a frame to its child.
michael@0 516 * Also saves and restores mClipState.
michael@0 517 */
michael@0 518 class AutoBuildingDisplayList;
michael@0 519 friend class AutoBuildingDisplayList;
michael@0 520 class AutoBuildingDisplayList {
michael@0 521 public:
michael@0 522 AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, bool aIsRoot)
michael@0 523 : mBuilder(aBuilder),
michael@0 524 mPrevCachedOffsetFrame(aBuilder->mCachedOffsetFrame),
michael@0 525 mPrevCachedReferenceFrame(aBuilder->mCachedReferenceFrame),
michael@0 526 mPrevLayerEventRegions(aBuilder->mLayerEventRegions),
michael@0 527 mPrevCachedOffset(aBuilder->mCachedOffset),
michael@0 528 mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext),
michael@0 529 mPrevAncestorHasTouchEventHandler(aBuilder->mAncestorHasTouchEventHandler)
michael@0 530 {
michael@0 531 aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
michael@0 532 }
michael@0 533 AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder,
michael@0 534 nsIFrame* aForChild, bool aIsRoot)
michael@0 535 : mBuilder(aBuilder),
michael@0 536 mPrevCachedOffsetFrame(aBuilder->mCachedOffsetFrame),
michael@0 537 mPrevCachedReferenceFrame(aBuilder->mCachedReferenceFrame),
michael@0 538 mPrevLayerEventRegions(aBuilder->mLayerEventRegions),
michael@0 539 mPrevCachedOffset(aBuilder->mCachedOffset),
michael@0 540 mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext),
michael@0 541 mPrevAncestorHasTouchEventHandler(aBuilder->mAncestorHasTouchEventHandler)
michael@0 542 {
michael@0 543 if (aForChild->IsTransformed()) {
michael@0 544 aBuilder->mCachedOffset = nsPoint();
michael@0 545 aBuilder->mCachedReferenceFrame = aForChild;
michael@0 546 } else if (mPrevCachedOffsetFrame == aForChild->GetParent()) {
michael@0 547 aBuilder->mCachedOffset += aForChild->GetPosition();
michael@0 548 } else {
michael@0 549 aBuilder->mCachedOffset = aBuilder->ToReferenceFrame(aForChild);
michael@0 550 }
michael@0 551 aBuilder->mCachedOffsetFrame = aForChild;
michael@0 552 aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
michael@0 553 }
michael@0 554 ~AutoBuildingDisplayList() {
michael@0 555 mBuilder->mCachedOffsetFrame = mPrevCachedOffsetFrame;
michael@0 556 mBuilder->mCachedReferenceFrame = mPrevCachedReferenceFrame;
michael@0 557 mBuilder->mLayerEventRegions = mPrevLayerEventRegions;
michael@0 558 mBuilder->mCachedOffset = mPrevCachedOffset;
michael@0 559 mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext;
michael@0 560 mBuilder->mAncestorHasTouchEventHandler = mPrevAncestorHasTouchEventHandler;
michael@0 561 }
michael@0 562 private:
michael@0 563 nsDisplayListBuilder* mBuilder;
michael@0 564 const nsIFrame* mPrevCachedOffsetFrame;
michael@0 565 const nsIFrame* mPrevCachedReferenceFrame;
michael@0 566 nsDisplayLayerEventRegions* mPrevLayerEventRegions;
michael@0 567 nsPoint mPrevCachedOffset;
michael@0 568 bool mPrevIsAtRootOfPseudoStackingContext;
michael@0 569 bool mPrevAncestorHasTouchEventHandler;
michael@0 570 };
michael@0 571
michael@0 572 /**
michael@0 573 * A helper class to temporarily set the value of mInTransform.
michael@0 574 */
michael@0 575 class AutoInTransformSetter;
michael@0 576 friend class AutoInTransformSetter;
michael@0 577 class AutoInTransformSetter {
michael@0 578 public:
michael@0 579 AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
michael@0 580 : mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
michael@0 581 aBuilder->mInTransform = aInTransform;
michael@0 582 }
michael@0 583 ~AutoInTransformSetter() {
michael@0 584 mBuilder->mInTransform = mOldValue;
michael@0 585 }
michael@0 586 private:
michael@0 587 nsDisplayListBuilder* mBuilder;
michael@0 588 bool mOldValue;
michael@0 589 };
michael@0 590
michael@0 591 /**
michael@0 592 * A helper class to temporarily set the value of mInFixedPos.
michael@0 593 */
michael@0 594 class AutoInFixedPosSetter;
michael@0 595 friend class AutoInFixedPosSetter;
michael@0 596 class AutoInFixedPosSetter {
michael@0 597 public:
michael@0 598 AutoInFixedPosSetter(nsDisplayListBuilder* aBuilder, bool aInFixedPos)
michael@0 599 : mBuilder(aBuilder), mOldValue(aBuilder->mInFixedPos) {
michael@0 600 aBuilder->mInFixedPos = aInFixedPos;
michael@0 601 }
michael@0 602 ~AutoInFixedPosSetter() {
michael@0 603 mBuilder->mInFixedPos = mOldValue;
michael@0 604 }
michael@0 605 private:
michael@0 606 nsDisplayListBuilder* mBuilder;
michael@0 607 bool mOldValue;
michael@0 608 };
michael@0 609
michael@0 610 /**
michael@0 611 * A helper class to temporarily set the value of mCurrentScrollParentId.
michael@0 612 */
michael@0 613 class AutoCurrentScrollParentIdSetter;
michael@0 614 friend class AutoCurrentScrollParentIdSetter;
michael@0 615 class AutoCurrentScrollParentIdSetter {
michael@0 616 public:
michael@0 617 AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollId)
michael@0 618 : mBuilder(aBuilder), mOldValue(aBuilder->mCurrentScrollParentId) {
michael@0 619 aBuilder->mCurrentScrollParentId = aScrollId;
michael@0 620 }
michael@0 621 ~AutoCurrentScrollParentIdSetter() {
michael@0 622 mBuilder->mCurrentScrollParentId = mOldValue;
michael@0 623 }
michael@0 624 private:
michael@0 625 nsDisplayListBuilder* mBuilder;
michael@0 626 ViewID mOldValue;
michael@0 627 };
michael@0 628
michael@0 629 // Helpers for tables
michael@0 630 nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
michael@0 631 void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
michael@0 632
michael@0 633 struct OutOfFlowDisplayData {
michael@0 634 OutOfFlowDisplayData(const DisplayItemClip& aContainingBlockClip,
michael@0 635 const nsRect &aDirtyRect)
michael@0 636 : mContainingBlockClip(aContainingBlockClip)
michael@0 637 , mDirtyRect(aDirtyRect)
michael@0 638 {}
michael@0 639 OutOfFlowDisplayData(const nsRect &aDirtyRect)
michael@0 640 : mDirtyRect(aDirtyRect)
michael@0 641 {}
michael@0 642 DisplayItemClip mContainingBlockClip;
michael@0 643 nsRect mDirtyRect;
michael@0 644 };
michael@0 645 static void DestroyOutOfFlowDisplayData(void* aPropertyValue)
michael@0 646 {
michael@0 647 delete static_cast<OutOfFlowDisplayData*>(aPropertyValue);
michael@0 648 }
michael@0 649
michael@0 650 NS_DECLARE_FRAME_PROPERTY(OutOfFlowDisplayDataProperty, DestroyOutOfFlowDisplayData)
michael@0 651 NS_DECLARE_FRAME_PROPERTY(Preserve3DDirtyRectProperty, nsIFrame::DestroyRect)
michael@0 652
michael@0 653 nsPresContext* CurrentPresContext() {
michael@0 654 return CurrentPresShellState()->mPresShell->GetPresContext();
michael@0 655 }
michael@0 656
michael@0 657 /**
michael@0 658 * Accumulates the bounds of box frames that have moz-appearance
michael@0 659 * -moz-win-exclude-glass style. Used in setting glass margins on
michael@0 660 * Windows.
michael@0 661 */
michael@0 662 void AddExcludedGlassRegion(nsRect &bounds) {
michael@0 663 mExcludedGlassRegion.Or(mExcludedGlassRegion, bounds);
michael@0 664 }
michael@0 665 const nsRegion& GetExcludedGlassRegion() {
michael@0 666 return mExcludedGlassRegion;
michael@0 667 }
michael@0 668 void SetGlassDisplayItem(nsDisplayItem* aItem) {
michael@0 669 if (mGlassDisplayItem) {
michael@0 670 // Web pages or extensions could trigger this by using
michael@0 671 // -moz-appearance:win-borderless-glass etc on their own elements.
michael@0 672 // Keep the first one, since that will be the background of the root
michael@0 673 // window
michael@0 674 NS_WARNING("Multiple glass backgrounds found?");
michael@0 675 } else {
michael@0 676 mGlassDisplayItem = aItem;
michael@0 677 }
michael@0 678 }
michael@0 679 bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem) {
michael@0 680 return aItem == mGlassDisplayItem;
michael@0 681 }
michael@0 682
michael@0 683 void SetContainsPluginItem() { mContainsPluginItem = true; }
michael@0 684 bool ContainsPluginItem() { return mContainsPluginItem; }
michael@0 685
michael@0 686 /**
michael@0 687 * mContainsBlendMode is true if we processed a display item that
michael@0 688 * has a blend mode attached. We do this so we can insert a
michael@0 689 * nsDisplayBlendContainer in the parent stacking context.
michael@0 690 */
michael@0 691 void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; }
michael@0 692 bool ContainsBlendMode() const { return mContainsBlendMode; }
michael@0 693
michael@0 694 DisplayListClipState& ClipState() { return mClipState; }
michael@0 695
michael@0 696 private:
michael@0 697 void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
michael@0 698 const nsRect& aDirtyRect);
michael@0 699
michael@0 700 struct PresShellState {
michael@0 701 nsIPresShell* mPresShell;
michael@0 702 nsIFrame* mCaretFrame;
michael@0 703 uint32_t mFirstFrameMarkedForDisplay;
michael@0 704 bool mIsBackgroundOnly;
michael@0 705 };
michael@0 706 PresShellState* CurrentPresShellState() {
michael@0 707 NS_ASSERTION(mPresShellStates.Length() > 0,
michael@0 708 "Someone forgot to enter a presshell");
michael@0 709 return &mPresShellStates[mPresShellStates.Length() - 1];
michael@0 710 }
michael@0 711
michael@0 712 nsIFrame* mReferenceFrame;
michael@0 713 nsIFrame* mIgnoreScrollFrame;
michael@0 714 nsDisplayLayerEventRegions* mLayerEventRegions;
michael@0 715 PLArenaPool mPool;
michael@0 716 nsCOMPtr<nsISelection> mBoundingSelection;
michael@0 717 nsAutoTArray<PresShellState,8> mPresShellStates;
michael@0 718 nsAutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
michael@0 719 nsAutoTArray<ThemeGeometry,2> mThemeGeometries;
michael@0 720 nsDisplayTableItem* mCurrentTableItem;
michael@0 721 DisplayListClipState mClipState;
michael@0 722 const nsRegion* mFinalTransparentRegion;
michael@0 723 // When mCachedOffsetFrame is non-null, mCachedOffset is the offset from
michael@0 724 // mCachedOffsetFrame to mReferenceFrame.
michael@0 725 const nsIFrame* mCachedOffsetFrame;
michael@0 726 const nsIFrame* mCachedReferenceFrame;
michael@0 727 nsPoint mCachedOffset;
michael@0 728 nsRegion mExcludedGlassRegion;
michael@0 729 // The display item for the Windows window glass background, if any
michael@0 730 nsDisplayItem* mGlassDisplayItem;
michael@0 731 nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;
michael@0 732 Mode mMode;
michael@0 733 ViewID mCurrentScrollParentId;
michael@0 734 bool mBuildCaret;
michael@0 735 bool mIgnoreSuppression;
michael@0 736 bool mHadToIgnoreSuppression;
michael@0 737 bool mIsAtRootOfPseudoStackingContext;
michael@0 738 bool mIncludeAllOutOfFlows;
michael@0 739 bool mDescendIntoSubdocuments;
michael@0 740 bool mSelectedFramesOnly;
michael@0 741 bool mAccurateVisibleRegions;
michael@0 742 bool mAllowMergingAndFlattening;
michael@0 743 bool mWillComputePluginGeometry;
michael@0 744 // True when we're building a display list that's directly or indirectly
michael@0 745 // under an nsDisplayTransform
michael@0 746 bool mInTransform;
michael@0 747 bool mInFixedPos;
michael@0 748 bool mSyncDecodeImages;
michael@0 749 bool mIsPaintingToWindow;
michael@0 750 bool mIsCompositingCheap;
michael@0 751 bool mContainsPluginItem;
michael@0 752 bool mContainsBlendMode;
michael@0 753 bool mAncestorHasTouchEventHandler;
michael@0 754 // True when the first async-scrollable scroll frame for which we build a
michael@0 755 // display list has a display port. An async-scrollable scroll frame is one
michael@0 756 // which WantsAsyncScroll().
michael@0 757 bool mHaveScrollableDisplayPort;
michael@0 758 };
michael@0 759
michael@0 760 class nsDisplayItem;
michael@0 761 class nsDisplayList;
michael@0 762 /**
michael@0 763 * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
michael@0 764 * nsDisplayItemLink holds the link. The lists are linked from lowest to
michael@0 765 * highest in z-order.
michael@0 766 */
michael@0 767 class nsDisplayItemLink {
michael@0 768 // This is never instantiated directly, so no need to count constructors and
michael@0 769 // destructors.
michael@0 770 protected:
michael@0 771 nsDisplayItemLink() : mAbove(nullptr) {}
michael@0 772 nsDisplayItem* mAbove;
michael@0 773
michael@0 774 friend class nsDisplayList;
michael@0 775 };
michael@0 776
michael@0 777 /**
michael@0 778 * This is the unit of rendering and event testing. Each instance of this
michael@0 779 * class represents an entity that can be drawn on the screen, e.g., a
michael@0 780 * frame's CSS background, or a frame's text string.
michael@0 781 *
michael@0 782 * nsDisplayListItems can be containers --- i.e., they can perform hit testing
michael@0 783 * and painting by recursively traversing a list of child items.
michael@0 784 *
michael@0 785 * These are arena-allocated during display list construction. A typical
michael@0 786 * subclass would just have a frame pointer, so its object would be just three
michael@0 787 * pointers (vtable, next-item, frame).
michael@0 788 *
michael@0 789 * Display items belong to a list at all times (except temporarily as they
michael@0 790 * move from one list to another).
michael@0 791 */
michael@0 792 class nsDisplayItem : public nsDisplayItemLink {
michael@0 793 public:
michael@0 794 typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
michael@0 795 typedef mozilla::DisplayItemClip DisplayItemClip;
michael@0 796 typedef mozilla::layers::FrameMetrics::ViewID ViewID;
michael@0 797 typedef mozilla::layers::Layer Layer;
michael@0 798 typedef mozilla::layers::LayerManager LayerManager;
michael@0 799 typedef mozilla::LayerState LayerState;
michael@0 800
michael@0 801 // This is never instantiated directly (it has pure virtual methods), so no
michael@0 802 // need to count constructors and destructors.
michael@0 803 nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
michael@0 804 : mFrame(aFrame)
michael@0 805 , mClip(aBuilder->ClipState().GetCurrentCombinedClip(aBuilder))
michael@0 806 , mInFixedPos(aBuilder->IsInFixedPos())
michael@0 807 #ifdef MOZ_DUMP_PAINTING
michael@0 808 , mPainted(false)
michael@0 809 #endif
michael@0 810 {
michael@0 811 mReferenceFrame = aBuilder->FindReferenceFrameFor(aFrame);
michael@0 812 mToReferenceFrame = aBuilder->ToReferenceFrame(aFrame);
michael@0 813 }
michael@0 814 nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 815 const nsIFrame* aReferenceFrame,
michael@0 816 const nsPoint& aToReferenceFrame)
michael@0 817 : mFrame(aFrame)
michael@0 818 , mClip(aBuilder->ClipState().GetCurrentCombinedClip(aBuilder))
michael@0 819 , mReferenceFrame(aReferenceFrame)
michael@0 820 , mToReferenceFrame(aToReferenceFrame)
michael@0 821 , mInFixedPos(aBuilder->IsInFixedPos())
michael@0 822 #ifdef MOZ_DUMP_PAINTING
michael@0 823 , mPainted(false)
michael@0 824 #endif
michael@0 825 {
michael@0 826 }
michael@0 827 /**
michael@0 828 * This constructor is only used in rare cases when we need to construct
michael@0 829 * temporary items.
michael@0 830 */
michael@0 831 nsDisplayItem(nsIFrame* aFrame)
michael@0 832 : mFrame(aFrame)
michael@0 833 , mClip(nullptr)
michael@0 834 , mReferenceFrame(nullptr)
michael@0 835 , mInFixedPos(false)
michael@0 836 #ifdef MOZ_DUMP_PAINTING
michael@0 837 , mPainted(false)
michael@0 838 #endif
michael@0 839 {
michael@0 840 }
michael@0 841 virtual ~nsDisplayItem() {}
michael@0 842
michael@0 843 void* operator new(size_t aSize,
michael@0 844 nsDisplayListBuilder* aBuilder) CPP_THROW_NEW {
michael@0 845 return aBuilder->Allocate(aSize);
michael@0 846 }
michael@0 847
michael@0 848 // Contains all the type integers for each display list item type
michael@0 849 #include "nsDisplayItemTypes.h"
michael@0 850
michael@0 851 struct HitTestState {
michael@0 852 typedef nsTArray<ViewID> ShadowArray;
michael@0 853
michael@0 854 HitTestState(ShadowArray* aShadows = nullptr)
michael@0 855 : mShadows(aShadows) {
michael@0 856 }
michael@0 857
michael@0 858 ~HitTestState() {
michael@0 859 NS_ASSERTION(mItemBuffer.Length() == 0,
michael@0 860 "mItemBuffer should have been cleared");
michael@0 861 }
michael@0 862
michael@0 863 nsAutoTArray<nsDisplayItem*, 100> mItemBuffer;
michael@0 864
michael@0 865 // It is sometimes useful to hit test for frames that are not in this
michael@0 866 // process. Display items may append IDs into this array if it is
michael@0 867 // non-null.
michael@0 868 ShadowArray* mShadows;
michael@0 869 };
michael@0 870
michael@0 871 /**
michael@0 872 * Some consecutive items should be rendered together as a unit, e.g.,
michael@0 873 * outlines for the same element. For this, we need a way for items to
michael@0 874 * identify their type. We use the type for other purposes too.
michael@0 875 */
michael@0 876 virtual Type GetType() = 0;
michael@0 877 /**
michael@0 878 * Pairing this with the GetUnderlyingFrame() pointer gives a key that
michael@0 879 * uniquely identifies this display item in the display item tree.
michael@0 880 * XXX check ScrollLayerWrapper/nsOptionEventGrabberWrapper/nsXULEventRedirectorWrapper
michael@0 881 */
michael@0 882 virtual uint32_t GetPerFrameKey() { return uint32_t(GetType()); }
michael@0 883 /**
michael@0 884 * This is called after we've constructed a display list for event handling.
michael@0 885 * When this is called, we've already ensured that aRect intersects the
michael@0 886 * item's bounds and that clipping has been taking into account.
michael@0 887 *
michael@0 888 * @param aRect the point or rect being tested, relative to the reference
michael@0 889 * frame. If the width and height are both 1 app unit, it indicates we're
michael@0 890 * hit testing a point, not a rect.
michael@0 891 * @param aState must point to a HitTestState. If you don't have one,
michael@0 892 * just create one with the default constructor and pass it in.
michael@0 893 * @param aOutFrames each item appends the frame(s) in this display item that
michael@0 894 * the rect is considered over (if any) to aOutFrames.
michael@0 895 */
michael@0 896 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 897 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {}
michael@0 898 /**
michael@0 899 * @return the frame that this display item is based on. This is used to sort
michael@0 900 * items by z-index and content order and for some other uses. Never
michael@0 901 * returns null.
michael@0 902 */
michael@0 903 inline nsIFrame* Frame() const { return mFrame; }
michael@0 904 /**
michael@0 905 * Compute the used z-index of our frame; returns zero for elements to which
michael@0 906 * z-index does not apply, and for z-index:auto.
michael@0 907 * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex.
michael@0 908 */
michael@0 909 virtual int32_t ZIndex() const;
michael@0 910 /**
michael@0 911 * The default bounds is the frame border rect.
michael@0 912 * @param aSnap *aSnap is set to true if the returned rect will be
michael@0 913 * snapped to nearest device pixel edges during actual drawing.
michael@0 914 * It might be set to false and snap anyway, so code computing the set of
michael@0 915 * pixels affected by this display item needs to round outwards to pixel
michael@0 916 * boundaries when *aSnap is set to false.
michael@0 917 * This does not take the item's clipping into account.
michael@0 918 * @return a rectangle relative to aBuilder->ReferenceFrame() that
michael@0 919 * contains the area drawn by this display item
michael@0 920 */
michael@0 921 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
michael@0 922 {
michael@0 923 *aSnap = false;
michael@0 924 return nsRect(ToReferenceFrame(), Frame()->GetSize());
michael@0 925 }
michael@0 926 /**
michael@0 927 * Returns the result of GetBounds intersected with the item's clip.
michael@0 928 * The intersection is approximate since rounded corners are not taking into
michael@0 929 * account.
michael@0 930 */
michael@0 931 nsRect GetClippedBounds(nsDisplayListBuilder* aBuilder);
michael@0 932 nsRect GetBorderRect() {
michael@0 933 return nsRect(ToReferenceFrame(), Frame()->GetSize());
michael@0 934 }
michael@0 935 nsRect GetPaddingRect() {
michael@0 936 return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
michael@0 937 }
michael@0 938 nsRect GetContentRect() {
michael@0 939 return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
michael@0 940 }
michael@0 941
michael@0 942 /**
michael@0 943 * Checks if the frame(s) owning this display item have been marked as invalid,
michael@0 944 * and needing repainting.
michael@0 945 */
michael@0 946 virtual bool IsInvalid(nsRect& aRect) {
michael@0 947 bool result = mFrame ? mFrame->IsInvalid(aRect) : false;
michael@0 948 aRect += ToReferenceFrame();
michael@0 949 return result;
michael@0 950 }
michael@0 951
michael@0 952 /**
michael@0 953 * Creates and initializes an nsDisplayItemGeometry object that retains the current
michael@0 954 * areas covered by this display item. These need to retain enough information
michael@0 955 * such that they can be compared against a future nsDisplayItem of the same type,
michael@0 956 * and determine if repainting needs to happen.
michael@0 957 *
michael@0 958 * Subclasses wishing to store more information need to override both this
michael@0 959 * and ComputeInvalidationRegion, as well as implementing an nsDisplayItemGeometry
michael@0 960 * subclass.
michael@0 961 *
michael@0 962 * The default implementation tracks both the display item bounds, and the frame's
michael@0 963 * border rect.
michael@0 964 */
michael@0 965 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
michael@0 966 {
michael@0 967 return new nsDisplayItemGenericGeometry(this, aBuilder);
michael@0 968 }
michael@0 969
michael@0 970 /**
michael@0 971 * Compares an nsDisplayItemGeometry object from a previous paint against the
michael@0 972 * current item. Computes if the geometry of the item has changed, and the
michael@0 973 * invalidation area required for correct repainting.
michael@0 974 *
michael@0 975 * The existing geometry will have been created from a display item with a
michael@0 976 * matching GetPerFrameKey()/mFrame pair to the current item.
michael@0 977 *
michael@0 978 * The default implementation compares the display item bounds, and the frame's
michael@0 979 * border rect, and invalidates the entire bounds if either rect changes.
michael@0 980 *
michael@0 981 * @param aGeometry The geometry of the matching display item from the
michael@0 982 * previous paint.
michael@0 983 * @param aInvalidRegion Output param, the region to invalidate, or
michael@0 984 * unchanged if none.
michael@0 985 */
michael@0 986 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 987 const nsDisplayItemGeometry* aGeometry,
michael@0 988 nsRegion* aInvalidRegion)
michael@0 989 {
michael@0 990 const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
michael@0 991 bool snap;
michael@0 992 if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
michael@0 993 !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
michael@0 994 aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
michael@0 995 }
michael@0 996 }
michael@0 997
michael@0 998 /**
michael@0 999 * An alternative default implementation of ComputeInvalidationRegion,
michael@0 1000 * that instead invalidates only the changed area between the two items.
michael@0 1001 */
michael@0 1002 void ComputeInvalidationRegionDifference(nsDisplayListBuilder* aBuilder,
michael@0 1003 const nsDisplayItemBoundsGeometry* aGeometry,
michael@0 1004 nsRegion* aInvalidRegion)
michael@0 1005 {
michael@0 1006 bool snap;
michael@0 1007 nsRect bounds = GetBounds(aBuilder, &snap);
michael@0 1008
michael@0 1009 if (!aGeometry->mBounds.IsEqualInterior(bounds)) {
michael@0 1010 nscoord radii[8];
michael@0 1011 if (aGeometry->mHasRoundedCorners ||
michael@0 1012 Frame()->GetBorderRadii(radii)) {
michael@0 1013 aInvalidRegion->Or(aGeometry->mBounds, bounds);
michael@0 1014 } else {
michael@0 1015 aInvalidRegion->Xor(aGeometry->mBounds, bounds);
michael@0 1016 }
michael@0 1017 }
michael@0 1018 }
michael@0 1019
michael@0 1020 /**
michael@0 1021 * For display items types that just draw a background we use this function
michael@0 1022 * to do any invalidation that might be needed if we are asked to sync decode
michael@0 1023 * images.
michael@0 1024 */
michael@0 1025 void AddInvalidRegionForSyncDecodeBackgroundImages(
michael@0 1026 nsDisplayListBuilder* aBuilder,
michael@0 1027 const nsDisplayItemGeometry* aGeometry,
michael@0 1028 nsRegion* aInvalidRegion);
michael@0 1029
michael@0 1030 /**
michael@0 1031 * Called when the area rendered by this display item has changed (been
michael@0 1032 * invalidated or changed geometry) since the last paint. This includes
michael@0 1033 * when the display item was not rendered at all in the last paint.
michael@0 1034 * It does NOT get called when a display item was being rendered and no
michael@0 1035 * longer is, because generally that means there is no display item to
michael@0 1036 * call this method on.
michael@0 1037 */
michael@0 1038 virtual void NotifyRenderingChanged() {}
michael@0 1039
michael@0 1040 /**
michael@0 1041 * @param aSnap set to true if the edges of the rectangles of the opaque
michael@0 1042 * region would be snapped to device pixels when drawing
michael@0 1043 * @return a region of the item that is opaque --- that is, every pixel
michael@0 1044 * that is visible (according to ComputeVisibility) is painted with an opaque
michael@0 1045 * color. This is useful for determining when one piece
michael@0 1046 * of content completely obscures another so that we can do occlusion
michael@0 1047 * culling.
michael@0 1048 * This does not take clipping into account.
michael@0 1049 */
michael@0 1050 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 1051 bool* aSnap)
michael@0 1052 {
michael@0 1053 *aSnap = false;
michael@0 1054 return nsRegion();
michael@0 1055 }
michael@0 1056 /**
michael@0 1057 * If this returns true, then aColor is set to the uniform color
michael@0 1058 * @return true if the item is guaranteed to paint every pixel in its
michael@0 1059 * bounds with the same (possibly translucent) color
michael@0 1060 */
michael@0 1061 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) { return false; }
michael@0 1062 /**
michael@0 1063 * @return false if the painting performed by the item is invariant
michael@0 1064 * when the item's underlying frame is moved relative to aFrame.
michael@0 1065 * In other words, if you render the item at locations P and P', the rendering
michael@0 1066 * only differs by the translation.
michael@0 1067 * It return true for all wrapped lists.
michael@0 1068 */
michael@0 1069 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
michael@0 1070 nsIFrame* aFrame)
michael@0 1071 { return false; }
michael@0 1072 /**
michael@0 1073 * @return true if the contents of this item are rendered fixed relative
michael@0 1074 * to the nearest viewport.
michael@0 1075 */
michael@0 1076 virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
michael@0 1077 { return false; }
michael@0 1078
michael@0 1079 /**
michael@0 1080 * Returns true if all layers that can be active should be forced to be
michael@0 1081 * active. Requires setting the pref layers.force-active=true.
michael@0 1082 */
michael@0 1083 static bool ForceActiveLayers();
michael@0 1084
michael@0 1085 /**
michael@0 1086 * Returns the maximum number of layers that should be created
michael@0 1087 * or -1 for no limit. Requires setting the pref layers.max-acitve.
michael@0 1088 */
michael@0 1089 static int32_t MaxActiveLayers();
michael@0 1090
michael@0 1091 /**
michael@0 1092 * @return LAYER_NONE if BuildLayer will return null. In this case
michael@0 1093 * there is no layer for the item, and Paint should be called instead
michael@0 1094 * to paint the content using Thebes.
michael@0 1095 * Return LAYER_INACTIVE if there is a layer --- BuildLayer will
michael@0 1096 * not return null (unless there's an error) --- but the layer contents
michael@0 1097 * are not changing frequently. In this case it makes sense to composite
michael@0 1098 * the layer into a ThebesLayer with other content, so we don't have to
michael@0 1099 * recomposite it every time we paint.
michael@0 1100 * Note: GetLayerState is only allowed to return LAYER_INACTIVE if all
michael@0 1101 * descendant display items returned LAYER_INACTIVE or LAYER_NONE. Also,
michael@0 1102 * all descendant display item frames must have an active scrolled root
michael@0 1103 * that's either the same as this item's frame's active scrolled root, or
michael@0 1104 * a descendant of this item's frame. This ensures that the entire
michael@0 1105 * set of display items can be collapsed onto a single ThebesLayer.
michael@0 1106 * Return LAYER_ACTIVE if the layer is active, that is, its contents are
michael@0 1107 * changing frequently. In this case it makes sense to keep the layer
michael@0 1108 * as a separate buffer in VRAM and composite it into the destination
michael@0 1109 * every time we paint.
michael@0 1110 *
michael@0 1111 * Users of GetLayerState should check ForceActiveLayers() and if it returns
michael@0 1112 * true, change a returned value of LAYER_INACTIVE to LAYER_ACTIVE.
michael@0 1113 */
michael@0 1114 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 1115 LayerManager* aManager,
michael@0 1116 const ContainerLayerParameters& aParameters)
michael@0 1117 { return mozilla::LAYER_NONE; }
michael@0 1118 /**
michael@0 1119 * Return true to indicate the layer should be constructed even if it's
michael@0 1120 * completely invisible.
michael@0 1121 */
michael@0 1122 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder)
michael@0 1123 { return false; }
michael@0 1124 /**
michael@0 1125 * Actually paint this item to some rendering context.
michael@0 1126 * Content outside mVisibleRect need not be painted.
michael@0 1127 * aCtx must be set up as for nsDisplayList::Paint.
michael@0 1128 */
michael@0 1129 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) {}
michael@0 1130
michael@0 1131 #ifdef MOZ_DUMP_PAINTING
michael@0 1132 /**
michael@0 1133 * Mark this display item as being painted via FrameLayerBuilder::DrawThebesLayer.
michael@0 1134 */
michael@0 1135 bool Painted() { return mPainted; }
michael@0 1136
michael@0 1137 /**
michael@0 1138 * Check if this display item has been painted.
michael@0 1139 */
michael@0 1140 void SetPainted() { mPainted = true; }
michael@0 1141 #endif
michael@0 1142
michael@0 1143 /**
michael@0 1144 * Get the layer drawn by this display item. Call this only if
michael@0 1145 * GetLayerState() returns something other than LAYER_NONE.
michael@0 1146 * If GetLayerState returned LAYER_NONE then Paint will be called
michael@0 1147 * instead.
michael@0 1148 * This is called while aManager is in the construction phase.
michael@0 1149 *
michael@0 1150 * The caller (nsDisplayList) is responsible for setting the visible
michael@0 1151 * region of the layer.
michael@0 1152 *
michael@0 1153 * @param aContainerParameters should be passed to
michael@0 1154 * FrameLayerBuilder::BuildContainerLayerFor if a ContainerLayer is
michael@0 1155 * constructed.
michael@0 1156 */
michael@0 1157 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 1158 LayerManager* aManager,
michael@0 1159 const ContainerLayerParameters& aContainerParameters)
michael@0 1160 { return nullptr; }
michael@0 1161
michael@0 1162 /**
michael@0 1163 * On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
michael@0 1164 * which may be visible. If the display item opaquely covers an area, it
michael@0 1165 * can remove that area from aVisibleRegion before returning.
michael@0 1166 * nsDisplayList::ComputeVisibility automatically subtracts the region
michael@0 1167 * returned by GetOpaqueRegion, and automatically removes items whose bounds
michael@0 1168 * do not intersect the visible area, so implementations of
michael@0 1169 * nsDisplayItem::ComputeVisibility do not need to do these things.
michael@0 1170 * nsDisplayList::ComputeVisibility will already have set mVisibleRect on
michael@0 1171 * this item to the intersection of *aVisibleRegion and this item's bounds.
michael@0 1172 * We rely on that, so this should only be called by
michael@0 1173 * nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility.
michael@0 1174 * aAllowVisibleRegionExpansion is a rect where we are allowed to
michael@0 1175 * expand the visible region and is only used for making sure the
michael@0 1176 * background behind a plugin is visible.
michael@0 1177 * This method needs to be idempotent.
michael@0 1178 *
michael@0 1179 * @return true if the item is visible, false if no part of the item
michael@0 1180 * is visible.
michael@0 1181 */
michael@0 1182 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 1183 nsRegion* aVisibleRegion,
michael@0 1184 const nsRect& aAllowVisibleRegionExpansion)
michael@0 1185 { return !mVisibleRect.IsEmpty(); }
michael@0 1186
michael@0 1187 /**
michael@0 1188 * Try to merge with the other item (which is below us in the display
michael@0 1189 * list). This gets used by nsDisplayClip to coalesce clipping operations
michael@0 1190 * (optimization), by nsDisplayOpacity to merge rendering for the same
michael@0 1191 * content element into a single opacity group (correctness), and will be
michael@0 1192 * used by nsDisplayOutline to merge multiple outlines for the same element
michael@0 1193 * (also for correctness).
michael@0 1194 * @return true if the merge was successful and the other item should be deleted
michael@0 1195 */
michael@0 1196 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
michael@0 1197 return false;
michael@0 1198 }
michael@0 1199
michael@0 1200 /**
michael@0 1201 * Appends the underlying frames of all display items that have been
michael@0 1202 * merged into this one (excluding this item's own underlying frame)
michael@0 1203 * to aFrames.
michael@0 1204 */
michael@0 1205 virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) {}
michael@0 1206
michael@0 1207 /**
michael@0 1208 * During the visibility computation and after TryMerge, display lists may
michael@0 1209 * return true here to flatten themselves away, removing them. This
michael@0 1210 * flattening is distinctly different from FlattenTo, which occurs before
michael@0 1211 * items are merged together.
michael@0 1212 */
michael@0 1213 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
michael@0 1214 return false;
michael@0 1215 }
michael@0 1216
michael@0 1217 /**
michael@0 1218 * If this has a child list where the children are in the same coordinate
michael@0 1219 * system as this item (i.e., they have the same reference frame),
michael@0 1220 * return the list.
michael@0 1221 */
michael@0 1222 virtual nsDisplayList* GetSameCoordinateSystemChildren() { return nullptr; }
michael@0 1223 virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) {}
michael@0 1224
michael@0 1225 /**
michael@0 1226 * If this has a child list, return it, even if the children are in
michael@0 1227 * a different coordinate system to this item.
michael@0 1228 */
michael@0 1229 virtual nsDisplayList* GetChildren() { return nullptr; }
michael@0 1230
michael@0 1231 /**
michael@0 1232 * Returns the visible rect. Should only be called after ComputeVisibility
michael@0 1233 * has happened.
michael@0 1234 */
michael@0 1235 const nsRect& GetVisibleRect() { return mVisibleRect; }
michael@0 1236
michael@0 1237 /**
michael@0 1238 * Stores the given opacity value to be applied when drawing. Returns
michael@0 1239 * false if this isn't supported for this display item.
michael@0 1240 */
michael@0 1241 virtual bool ApplyOpacity(nsDisplayListBuilder* aBuilder,
michael@0 1242 float aOpacity,
michael@0 1243 const DisplayItemClip* aClip) {
michael@0 1244 return false;
michael@0 1245 }
michael@0 1246
michael@0 1247 #ifdef MOZ_DUMP_PAINTING
michael@0 1248 /**
michael@0 1249 * For debugging and stuff
michael@0 1250 */
michael@0 1251 virtual const char* Name() = 0;
michael@0 1252
michael@0 1253 virtual void WriteDebugInfo(nsACString& aTo) {}
michael@0 1254 #endif
michael@0 1255
michael@0 1256 nsDisplayItem* GetAbove() { return mAbove; }
michael@0 1257
michael@0 1258 /**
michael@0 1259 * Like ComputeVisibility, but does the work that nsDisplayList
michael@0 1260 * does per-item:
michael@0 1261 * -- Intersects GetBounds with aVisibleRegion and puts the result
michael@0 1262 * in mVisibleRect
michael@0 1263 * -- Subtracts bounds from aVisibleRegion if the item is opaque
michael@0 1264 */
michael@0 1265 bool RecomputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 1266 nsRegion* aVisibleRegion);
michael@0 1267
michael@0 1268 /**
michael@0 1269 * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
michael@0 1270 */
michael@0 1271 const nsPoint& ToReferenceFrame() const {
michael@0 1272 NS_ASSERTION(mFrame, "No frame?");
michael@0 1273 return mToReferenceFrame;
michael@0 1274 }
michael@0 1275 /**
michael@0 1276 * @return the root of the display list's frame (sub)tree, whose origin
michael@0 1277 * establishes the coordinate system for the display list
michael@0 1278 */
michael@0 1279 const nsIFrame* ReferenceFrame() const { return mReferenceFrame; }
michael@0 1280
michael@0 1281 /**
michael@0 1282 * Returns the reference frame for display item children of this item.
michael@0 1283 */
michael@0 1284 virtual const nsIFrame* ReferenceFrameForChildren() const { return mReferenceFrame; }
michael@0 1285
michael@0 1286 /**
michael@0 1287 * Checks if this display item (or any children) contains content that might
michael@0 1288 * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
michael@0 1289 * bounds of the area that needs component alpha, or an empty rect if nothing
michael@0 1290 * in the item does.
michael@0 1291 */
michael@0 1292 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) { return nsRect(); }
michael@0 1293
michael@0 1294 /**
michael@0 1295 * Disable usage of component alpha. Currently only relevant for items that have text.
michael@0 1296 */
michael@0 1297 virtual void DisableComponentAlpha() {}
michael@0 1298
michael@0 1299 /**
michael@0 1300 * Check if we can add async animations to the layer for this display item.
michael@0 1301 */
michael@0 1302 virtual bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
michael@0 1303 return false;
michael@0 1304 }
michael@0 1305
michael@0 1306 virtual bool SupportsOptimizingToImage() { return false; }
michael@0 1307
michael@0 1308 const DisplayItemClip& GetClip()
michael@0 1309 {
michael@0 1310 return mClip ? *mClip : DisplayItemClip::NoClip();
michael@0 1311 }
michael@0 1312 void SetClip(nsDisplayListBuilder* aBuilder, const DisplayItemClip& aClip)
michael@0 1313 {
michael@0 1314 if (!aClip.HasClip()) {
michael@0 1315 mClip = nullptr;
michael@0 1316 return;
michael@0 1317 }
michael@0 1318 mClip = aBuilder->AllocateDisplayItemClip(aClip);
michael@0 1319 }
michael@0 1320
michael@0 1321 void IntersectClip(nsDisplayListBuilder* aBuilder, const DisplayItemClip& aClip)
michael@0 1322 {
michael@0 1323 if (mClip) {
michael@0 1324 DisplayItemClip temp = *mClip;
michael@0 1325 temp.IntersectWith(aClip);
michael@0 1326 SetClip(aBuilder, temp);
michael@0 1327 } else {
michael@0 1328 SetClip(aBuilder, aClip);
michael@0 1329 }
michael@0 1330 }
michael@0 1331
michael@0 1332 // If we return false here it means that if this item creates a layer then
michael@0 1333 // ProcessDisplayItems will not set the visible region on the layer. The item
michael@0 1334 // should set the visible region, usually in BuildContainerLayer.
michael@0 1335 virtual bool SetVisibleRegionOnLayer() { return true; }
michael@0 1336
michael@0 1337 bool IsInFixedPos() { return mInFixedPos; }
michael@0 1338
michael@0 1339 protected:
michael@0 1340 friend class nsDisplayList;
michael@0 1341
michael@0 1342 nsDisplayItem() { mAbove = nullptr; }
michael@0 1343
michael@0 1344 nsIFrame* mFrame;
michael@0 1345 const DisplayItemClip* mClip;
michael@0 1346 // Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
michael@0 1347 const nsIFrame* mReferenceFrame;
michael@0 1348 // Result of ToReferenceFrame(mFrame), if mFrame is non-null
michael@0 1349 nsPoint mToReferenceFrame;
michael@0 1350 // This is the rectangle that needs to be painted.
michael@0 1351 // nsDisplayList::ComputeVisibility sets this to the visible region
michael@0 1352 // of the item by intersecting the current visible region with the bounds
michael@0 1353 // of the item. Paint implementations can use this to limit their drawing.
michael@0 1354 // Guaranteed to be contained in GetBounds().
michael@0 1355 nsRect mVisibleRect;
michael@0 1356 bool mInFixedPos;
michael@0 1357 #ifdef MOZ_DUMP_PAINTING
michael@0 1358 // True if this frame has been painted.
michael@0 1359 bool mPainted;
michael@0 1360 #endif
michael@0 1361 };
michael@0 1362
michael@0 1363 /**
michael@0 1364 * Manages a singly-linked list of display list items.
michael@0 1365 *
michael@0 1366 * mSentinel is the sentinel list value, the first value in the null-terminated
michael@0 1367 * linked list of items. mTop is the last item in the list (whose 'above'
michael@0 1368 * pointer is null). This class has no virtual methods. So list objects are just
michael@0 1369 * two pointers.
michael@0 1370 *
michael@0 1371 * Stepping upward through this list is very fast. Stepping downward is very
michael@0 1372 * slow so we don't support it. The methods that need to step downward
michael@0 1373 * (HitTest(), ComputeVisibility()) internally build a temporary array of all
michael@0 1374 * the items while they do the downward traversal, so overall they're still
michael@0 1375 * linear time. We have optimized for efficient AppendToTop() of both
michael@0 1376 * items and lists, with minimal codesize. AppendToBottom() is efficient too.
michael@0 1377 */
michael@0 1378 class nsDisplayList {
michael@0 1379 public:
michael@0 1380 typedef mozilla::layers::Layer Layer;
michael@0 1381 typedef mozilla::layers::LayerManager LayerManager;
michael@0 1382 typedef mozilla::layers::ThebesLayer ThebesLayer;
michael@0 1383
michael@0 1384 /**
michael@0 1385 * Create an empty list.
michael@0 1386 */
michael@0 1387 nsDisplayList() :
michael@0 1388 mIsOpaque(false)
michael@0 1389 {
michael@0 1390 mTop = &mSentinel;
michael@0 1391 mSentinel.mAbove = nullptr;
michael@0 1392 #if defined(DEBUG) || defined(MOZ_DUMP_PAINTING)
michael@0 1393 mDidComputeVisibility = false;
michael@0 1394 #endif
michael@0 1395 }
michael@0 1396 ~nsDisplayList() {
michael@0 1397 if (mSentinel.mAbove) {
michael@0 1398 NS_WARNING("Nonempty list left over?");
michael@0 1399 }
michael@0 1400 DeleteAll();
michael@0 1401 }
michael@0 1402
michael@0 1403 /**
michael@0 1404 * Append an item to the top of the list. The item must not currently
michael@0 1405 * be in a list and cannot be null.
michael@0 1406 */
michael@0 1407 void AppendToTop(nsDisplayItem* aItem) {
michael@0 1408 NS_ASSERTION(aItem, "No item to append!");
michael@0 1409 NS_ASSERTION(!aItem->mAbove, "Already in a list!");
michael@0 1410 mTop->mAbove = aItem;
michael@0 1411 mTop = aItem;
michael@0 1412 }
michael@0 1413
michael@0 1414 /**
michael@0 1415 * Append a new item to the top of the list. If the item is null we return
michael@0 1416 * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToTop(new ...);
michael@0 1417 */
michael@0 1418 void AppendNewToTop(nsDisplayItem* aItem) {
michael@0 1419 if (aItem) {
michael@0 1420 AppendToTop(aItem);
michael@0 1421 }
michael@0 1422 }
michael@0 1423
michael@0 1424 /**
michael@0 1425 * Append a new item to the bottom of the list. If the item is null we return
michael@0 1426 * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToBottom(new ...);
michael@0 1427 */
michael@0 1428 void AppendNewToBottom(nsDisplayItem* aItem) {
michael@0 1429 if (aItem) {
michael@0 1430 AppendToBottom(aItem);
michael@0 1431 }
michael@0 1432 }
michael@0 1433
michael@0 1434 /**
michael@0 1435 * Append a new item to the bottom of the list. The item must be non-null
michael@0 1436 * and not already in a list.
michael@0 1437 */
michael@0 1438 void AppendToBottom(nsDisplayItem* aItem) {
michael@0 1439 NS_ASSERTION(aItem, "No item to append!");
michael@0 1440 NS_ASSERTION(!aItem->mAbove, "Already in a list!");
michael@0 1441 aItem->mAbove = mSentinel.mAbove;
michael@0 1442 mSentinel.mAbove = aItem;
michael@0 1443 if (mTop == &mSentinel) {
michael@0 1444 mTop = aItem;
michael@0 1445 }
michael@0 1446 }
michael@0 1447
michael@0 1448 /**
michael@0 1449 * Removes all items from aList and appends them to the top of this list
michael@0 1450 */
michael@0 1451 void AppendToTop(nsDisplayList* aList) {
michael@0 1452 if (aList->mSentinel.mAbove) {
michael@0 1453 mTop->mAbove = aList->mSentinel.mAbove;
michael@0 1454 mTop = aList->mTop;
michael@0 1455 aList->mTop = &aList->mSentinel;
michael@0 1456 aList->mSentinel.mAbove = nullptr;
michael@0 1457 }
michael@0 1458 }
michael@0 1459
michael@0 1460 /**
michael@0 1461 * Removes all items from aList and prepends them to the bottom of this list
michael@0 1462 */
michael@0 1463 void AppendToBottom(nsDisplayList* aList) {
michael@0 1464 if (aList->mSentinel.mAbove) {
michael@0 1465 aList->mTop->mAbove = mSentinel.mAbove;
michael@0 1466 mSentinel.mAbove = aList->mSentinel.mAbove;
michael@0 1467 if (mTop == &mSentinel) {
michael@0 1468 mTop = aList->mTop;
michael@0 1469 }
michael@0 1470
michael@0 1471 aList->mTop = &aList->mSentinel;
michael@0 1472 aList->mSentinel.mAbove = nullptr;
michael@0 1473 }
michael@0 1474 }
michael@0 1475
michael@0 1476 /**
michael@0 1477 * Remove an item from the bottom of the list and return it.
michael@0 1478 */
michael@0 1479 nsDisplayItem* RemoveBottom();
michael@0 1480
michael@0 1481 /**
michael@0 1482 * Remove all items from the list and call their destructors.
michael@0 1483 */
michael@0 1484 void DeleteAll();
michael@0 1485
michael@0 1486 /**
michael@0 1487 * @return the item at the top of the list, or null if the list is empty
michael@0 1488 */
michael@0 1489 nsDisplayItem* GetTop() const {
michael@0 1490 return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nullptr;
michael@0 1491 }
michael@0 1492 /**
michael@0 1493 * @return the item at the bottom of the list, or null if the list is empty
michael@0 1494 */
michael@0 1495 nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
michael@0 1496 bool IsEmpty() const { return mTop == &mSentinel; }
michael@0 1497
michael@0 1498 /**
michael@0 1499 * This is *linear time*!
michael@0 1500 * @return the number of items in the list
michael@0 1501 */
michael@0 1502 uint32_t Count() const;
michael@0 1503 /**
michael@0 1504 * Stable sort the list by the z-order of GetUnderlyingFrame() on
michael@0 1505 * each item. 'auto' is counted as zero. Content order is used as the
michael@0 1506 * secondary order.
michael@0 1507 * @param aCommonAncestor a common ancestor of all the content elements
michael@0 1508 * associated with the display items, for speeding up tree order
michael@0 1509 * checks, or nullptr if not known; it's only a hint, if it is not an
michael@0 1510 * ancestor of some elements, then we lose performance but not correctness
michael@0 1511 */
michael@0 1512 void SortByZOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
michael@0 1513 /**
michael@0 1514 * Stable sort the list by the tree order of the content of
michael@0 1515 * GetUnderlyingFrame() on each item. z-index is ignored.
michael@0 1516 * @param aCommonAncestor a common ancestor of all the content elements
michael@0 1517 * associated with the display items, for speeding up tree order
michael@0 1518 * checks, or nullptr if not known; it's only a hint, if it is not an
michael@0 1519 * ancestor of some elements, then we lose performance but not correctness
michael@0 1520 */
michael@0 1521 void SortByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
michael@0 1522
michael@0 1523 /**
michael@0 1524 * Generic stable sort. Take care, because some of the items might be nsDisplayLists
michael@0 1525 * themselves.
michael@0 1526 * aCmp(item1, item2) should return true if item1 <= item2. We sort the items
michael@0 1527 * into increasing order.
michael@0 1528 */
michael@0 1529 typedef bool (* SortLEQ)(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
michael@0 1530 void* aClosure);
michael@0 1531 void Sort(nsDisplayListBuilder* aBuilder, SortLEQ aCmp, void* aClosure);
michael@0 1532
michael@0 1533 /**
michael@0 1534 * Compute visiblity for the items in the list.
michael@0 1535 * We put this logic here so it can be shared by top-level
michael@0 1536 * painting and also display items that maintain child lists.
michael@0 1537 * This is also a good place to put ComputeVisibility-related logic
michael@0 1538 * that must be applied to every display item. In particular, this
michael@0 1539 * sets mVisibleRect on each display item.
michael@0 1540 * This sets mIsOpaque if the entire visible area of this list has
michael@0 1541 * been removed from aVisibleRegion when we return.
michael@0 1542 * This does not remove any items from the list, so we can recompute
michael@0 1543 * visiblity with different regions later (see
michael@0 1544 * FrameLayerBuilder::DrawThebesLayer).
michael@0 1545 * This method needs to be idempotent.
michael@0 1546 *
michael@0 1547 * @param aVisibleRegion the area that is visible, relative to the
michael@0 1548 * reference frame; on return, this contains the area visible under the list.
michael@0 1549 * I.e., opaque contents of this list are subtracted from aVisibleRegion.
michael@0 1550 * @param aListVisibleBounds must be equal to the bounds of the intersection
michael@0 1551 * of aVisibleRegion and GetBounds() for this list.
michael@0 1552 * @param aDisplayPortFrame If the item for which this list corresponds is
michael@0 1553 * within a displayport, the scroll frame for which that display port
michael@0 1554 * applies. For root scroll frames, you can pass the the root frame instead.
michael@0 1555 * @return true if any item in the list is visible.
michael@0 1556 */
michael@0 1557 bool ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
michael@0 1558 nsRegion* aVisibleRegion,
michael@0 1559 const nsRect& aListVisibleBounds,
michael@0 1560 const nsRect& aAllowVisibleRegionExpansion,
michael@0 1561 nsIFrame* aDisplayPortFrame = nullptr);
michael@0 1562
michael@0 1563 /**
michael@0 1564 * As ComputeVisibilityForSublist, but computes visibility for a root
michael@0 1565 * list (a list that does not belong to an nsDisplayItem).
michael@0 1566 * This method needs to be idempotent.
michael@0 1567 *
michael@0 1568 * @param aVisibleRegion the area that is visible
michael@0 1569 * @param aDisplayPortFrame The root scroll frame, if a displayport is set
michael@0 1570 */
michael@0 1571 bool ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
michael@0 1572 nsRegion* aVisibleRegion,
michael@0 1573 nsIFrame* aDisplayPortFrame = nullptr);
michael@0 1574
michael@0 1575 /**
michael@0 1576 * Returns true if the visible region output from ComputeVisiblity was
michael@0 1577 * empty, i.e. everything visible in this list is opaque.
michael@0 1578 */
michael@0 1579 bool IsOpaque() const {
michael@0 1580 NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility");
michael@0 1581 return mIsOpaque;
michael@0 1582 }
michael@0 1583
michael@0 1584 /**
michael@0 1585 * Returns true if during ComputeVisibility any display item
michael@0 1586 * set the surface to be transparent.
michael@0 1587 */
michael@0 1588 bool NeedsTransparentSurface() const {
michael@0 1589 NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility");
michael@0 1590 return mForceTransparentSurface;
michael@0 1591 }
michael@0 1592 /**
michael@0 1593 * Paint the list to the rendering context. We assume that (0,0) in aCtx
michael@0 1594 * corresponds to the origin of the reference frame. For best results,
michael@0 1595 * aCtx's current transform should make (0,0) pixel-aligned. The
michael@0 1596 * rectangle in aDirtyRect is painted, which *must* be contained in the
michael@0 1597 * dirty rect used to construct the display list.
michael@0 1598 *
michael@0 1599 * If aFlags contains PAINT_USE_WIDGET_LAYERS and
michael@0 1600 * ShouldUseWidgetLayerManager() is set, then we will paint using
michael@0 1601 * the reference frame's widget's layer manager (and ctx may be null),
michael@0 1602 * otherwise we will use a temporary BasicLayerManager and ctx must
michael@0 1603 * not be null.
michael@0 1604 *
michael@0 1605 * If PAINT_FLUSH_LAYERS is set, we'll force a completely new layer
michael@0 1606 * tree to be created for this paint *and* the next paint.
michael@0 1607 *
michael@0 1608 * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
michael@0 1609 * layer manager has already had BeginTransaction() called on it and
michael@0 1610 * we should not call it again.
michael@0 1611 *
michael@0 1612 * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode
michael@0 1613 * to avoid short cut optimizations.
michael@0 1614 *
michael@0 1615 * ComputeVisibility must be called before Paint.
michael@0 1616 *
michael@0 1617 * This must only be called on the root display list of the display list
michael@0 1618 * tree.
michael@0 1619 */
michael@0 1620 enum {
michael@0 1621 PAINT_DEFAULT = 0,
michael@0 1622 PAINT_USE_WIDGET_LAYERS = 0x01,
michael@0 1623 PAINT_FLUSH_LAYERS = 0x02,
michael@0 1624 PAINT_EXISTING_TRANSACTION = 0x04,
michael@0 1625 PAINT_NO_COMPOSITE = 0x08,
michael@0 1626 PAINT_COMPRESSED = 0x10
michael@0 1627 };
michael@0 1628 void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
michael@0 1629 uint32_t aFlags) const;
michael@0 1630 /**
michael@0 1631 * Like PaintRoot, but used for internal display sublists.
michael@0 1632 * aForFrame is the frame that the list is associated with.
michael@0 1633 */
michael@0 1634 void PaintForFrame(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
michael@0 1635 nsIFrame* aForFrame, uint32_t aFlags) const;
michael@0 1636 /**
michael@0 1637 * Get the bounds. Takes the union of the bounds of all children.
michael@0 1638 */
michael@0 1639 nsRect GetBounds(nsDisplayListBuilder* aBuilder) const;
michael@0 1640 /**
michael@0 1641 * Find the topmost display item that returns a non-null frame, and return
michael@0 1642 * the frame.
michael@0 1643 */
michael@0 1644 void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 1645 nsDisplayItem::HitTestState* aState,
michael@0 1646 nsTArray<nsIFrame*> *aOutFrames) const;
michael@0 1647
michael@0 1648 #if defined(DEBUG) || defined(MOZ_DUMP_PAINTING)
michael@0 1649 bool DidComputeVisibility() const { return mDidComputeVisibility; }
michael@0 1650 #endif
michael@0 1651
michael@0 1652 nsRect GetVisibleRect() const { return mVisibleRect; }
michael@0 1653
michael@0 1654 private:
michael@0 1655 // This class is only used on stack, so we don't have to worry about leaking
michael@0 1656 // it. Don't let us be heap-allocated!
michael@0 1657 void* operator new(size_t sz) CPP_THROW_NEW;
michael@0 1658
michael@0 1659 // Utility function used to massage the list during ComputeVisibility.
michael@0 1660 void FlattenTo(nsTArray<nsDisplayItem*>* aElements);
michael@0 1661
michael@0 1662 nsDisplayItemLink mSentinel;
michael@0 1663 nsDisplayItemLink* mTop;
michael@0 1664
michael@0 1665 // This is set by ComputeVisibility
michael@0 1666 nsRect mVisibleRect;
michael@0 1667 // This is set to true by ComputeVisibility if the final visible region
michael@0 1668 // is empty (i.e. everything that was visible is covered by some
michael@0 1669 // opaque content in this list).
michael@0 1670 bool mIsOpaque;
michael@0 1671 // This is set to true by ComputeVisibility if any display item in this
michael@0 1672 // list needs to force the surface containing this list to be transparent.
michael@0 1673 bool mForceTransparentSurface;
michael@0 1674 #if defined(DEBUG) || defined(MOZ_DUMP_PAINTING)
michael@0 1675 bool mDidComputeVisibility;
michael@0 1676 #endif
michael@0 1677 };
michael@0 1678
michael@0 1679 /**
michael@0 1680 * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
michael@0 1681 * will put any generated items onto the appropriate list given here. It's
michael@0 1682 * basically just a collection with one list for each separate stacking layer.
michael@0 1683 * The lists themselves are external to this object and thus can be shared
michael@0 1684 * with others. Some of the list pointers may even refer to the same list.
michael@0 1685 */
michael@0 1686 class nsDisplayListSet {
michael@0 1687 public:
michael@0 1688 /**
michael@0 1689 * @return a list where one should place the border and/or background for
michael@0 1690 * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
michael@0 1691 */
michael@0 1692 nsDisplayList* BorderBackground() const { return mBorderBackground; }
michael@0 1693 /**
michael@0 1694 * @return a list where one should place the borders and/or backgrounds for
michael@0 1695 * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
michael@0 1696 */
michael@0 1697 nsDisplayList* BlockBorderBackgrounds() const { return mBlockBorderBackgrounds; }
michael@0 1698 /**
michael@0 1699 * @return a list where one should place descendant floats (step 5 of
michael@0 1700 * CSS 2.1 appendix E)
michael@0 1701 */
michael@0 1702 nsDisplayList* Floats() const { return mFloats; }
michael@0 1703 /**
michael@0 1704 * @return a list where one should place the (pseudo) stacking contexts
michael@0 1705 * for descendants of this frame (everything from steps 3, 7 and 8
michael@0 1706 * of CSS 2.1 appendix E)
michael@0 1707 */
michael@0 1708 nsDisplayList* PositionedDescendants() const { return mPositioned; }
michael@0 1709 /**
michael@0 1710 * @return a list where one should place the outlines
michael@0 1711 * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
michael@0 1712 */
michael@0 1713 nsDisplayList* Outlines() const { return mOutlines; }
michael@0 1714 /**
michael@0 1715 * @return a list where one should place all other content
michael@0 1716 */
michael@0 1717 nsDisplayList* Content() const { return mContent; }
michael@0 1718
michael@0 1719 nsDisplayListSet(nsDisplayList* aBorderBackground,
michael@0 1720 nsDisplayList* aBlockBorderBackgrounds,
michael@0 1721 nsDisplayList* aFloats,
michael@0 1722 nsDisplayList* aContent,
michael@0 1723 nsDisplayList* aPositionedDescendants,
michael@0 1724 nsDisplayList* aOutlines) :
michael@0 1725 mBorderBackground(aBorderBackground),
michael@0 1726 mBlockBorderBackgrounds(aBlockBorderBackgrounds),
michael@0 1727 mFloats(aFloats),
michael@0 1728 mContent(aContent),
michael@0 1729 mPositioned(aPositionedDescendants),
michael@0 1730 mOutlines(aOutlines) {
michael@0 1731 }
michael@0 1732
michael@0 1733 /**
michael@0 1734 * A copy constructor that lets the caller override the BorderBackground
michael@0 1735 * list.
michael@0 1736 */
michael@0 1737 nsDisplayListSet(const nsDisplayListSet& aLists,
michael@0 1738 nsDisplayList* aBorderBackground) :
michael@0 1739 mBorderBackground(aBorderBackground),
michael@0 1740 mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),
michael@0 1741 mFloats(aLists.Floats()),
michael@0 1742 mContent(aLists.Content()),
michael@0 1743 mPositioned(aLists.PositionedDescendants()),
michael@0 1744 mOutlines(aLists.Outlines()) {
michael@0 1745 }
michael@0 1746
michael@0 1747 /**
michael@0 1748 * Move all display items in our lists to top of the corresponding lists in the
michael@0 1749 * destination.
michael@0 1750 */
michael@0 1751 void MoveTo(const nsDisplayListSet& aDestination) const;
michael@0 1752
michael@0 1753 private:
michael@0 1754 // This class is only used on stack, so we don't have to worry about leaking
michael@0 1755 // it. Don't let us be heap-allocated!
michael@0 1756 void* operator new(size_t sz) CPP_THROW_NEW;
michael@0 1757
michael@0 1758 protected:
michael@0 1759 nsDisplayList* mBorderBackground;
michael@0 1760 nsDisplayList* mBlockBorderBackgrounds;
michael@0 1761 nsDisplayList* mFloats;
michael@0 1762 nsDisplayList* mContent;
michael@0 1763 nsDisplayList* mPositioned;
michael@0 1764 nsDisplayList* mOutlines;
michael@0 1765 };
michael@0 1766
michael@0 1767 /**
michael@0 1768 * A specialization of nsDisplayListSet where the lists are actually internal
michael@0 1769 * to the object, and all distinct.
michael@0 1770 */
michael@0 1771 struct nsDisplayListCollection : public nsDisplayListSet {
michael@0 1772 nsDisplayListCollection() :
michael@0 1773 nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4],
michael@0 1774 &mLists[5]) {}
michael@0 1775 nsDisplayListCollection(nsDisplayList* aBorderBackground) :
michael@0 1776 nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4],
michael@0 1777 &mLists[5]) {}
michael@0 1778
michael@0 1779 /**
michael@0 1780 * Sort all lists by content order.
michael@0 1781 */
michael@0 1782 void SortAllByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor) {
michael@0 1783 for (int32_t i = 0; i < 6; ++i) {
michael@0 1784 mLists[i].SortByContentOrder(aBuilder, aCommonAncestor);
michael@0 1785 }
michael@0 1786 }
michael@0 1787
michael@0 1788 private:
michael@0 1789 // This class is only used on stack, so we don't have to worry about leaking
michael@0 1790 // it. Don't let us be heap-allocated!
michael@0 1791 void* operator new(size_t sz) CPP_THROW_NEW;
michael@0 1792
michael@0 1793 nsDisplayList mLists[6];
michael@0 1794 };
michael@0 1795
michael@0 1796
michael@0 1797 class nsDisplayImageContainer : public nsDisplayItem {
michael@0 1798 public:
michael@0 1799 typedef mozilla::layers::ImageContainer ImageContainer;
michael@0 1800 typedef mozilla::layers::ImageLayer ImageLayer;
michael@0 1801
michael@0 1802 nsDisplayImageContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
michael@0 1803 : nsDisplayItem(aBuilder, aFrame)
michael@0 1804 {}
michael@0 1805
michael@0 1806 virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
michael@0 1807 nsDisplayListBuilder* aBuilder) = 0;
michael@0 1808 virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) = 0;
michael@0 1809
michael@0 1810 virtual bool SupportsOptimizingToImage() MOZ_OVERRIDE { return true; }
michael@0 1811 };
michael@0 1812
michael@0 1813 /**
michael@0 1814 * Use this class to implement not-very-frequently-used display items
michael@0 1815 * that are not opaque, do not receive events, and are bounded by a frame's
michael@0 1816 * border-rect.
michael@0 1817 *
michael@0 1818 * This should not be used for display items which are created frequently,
michael@0 1819 * because each item is one or two pointers bigger than an item from a
michael@0 1820 * custom display item class could be, and fractionally slower. However it does
michael@0 1821 * save code size. We use this for infrequently-used item types.
michael@0 1822 */
michael@0 1823 class nsDisplayGeneric : public nsDisplayItem {
michael@0 1824 public:
michael@0 1825 typedef void (* PaintCallback)(nsIFrame* aFrame, nsRenderingContext* aCtx,
michael@0 1826 const nsRect& aDirtyRect, nsPoint aFramePt);
michael@0 1827
michael@0 1828 nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 1829 PaintCallback aPaint, const char* aName, Type aType)
michael@0 1830 : nsDisplayItem(aBuilder, aFrame), mPaint(aPaint)
michael@0 1831 #ifdef MOZ_DUMP_PAINTING
michael@0 1832 , mName(aName)
michael@0 1833 #endif
michael@0 1834 , mType(aType)
michael@0 1835 {
michael@0 1836 MOZ_COUNT_CTOR(nsDisplayGeneric);
michael@0 1837 }
michael@0 1838 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 1839 virtual ~nsDisplayGeneric() {
michael@0 1840 MOZ_COUNT_DTOR(nsDisplayGeneric);
michael@0 1841 }
michael@0 1842 #endif
michael@0 1843
michael@0 1844 virtual void Paint(nsDisplayListBuilder* aBuilder,
michael@0 1845 nsRenderingContext* aCtx) MOZ_OVERRIDE {
michael@0 1846 mPaint(mFrame, aCtx, mVisibleRect, ToReferenceFrame());
michael@0 1847 }
michael@0 1848 NS_DISPLAY_DECL_NAME(mName, mType)
michael@0 1849
michael@0 1850 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE {
michael@0 1851 if (mType == nsDisplayItem::TYPE_HEADER_FOOTER) {
michael@0 1852 bool snap;
michael@0 1853 return GetBounds(aBuilder, &snap);
michael@0 1854 }
michael@0 1855 return nsRect();
michael@0 1856 }
michael@0 1857
michael@0 1858 protected:
michael@0 1859 PaintCallback mPaint;
michael@0 1860 #ifdef MOZ_DUMP_PAINTING
michael@0 1861 const char* mName;
michael@0 1862 #endif
michael@0 1863 Type mType;
michael@0 1864 };
michael@0 1865
michael@0 1866 /**
michael@0 1867 * Generic display item that can contain overflow. Use this in lieu of
michael@0 1868 * nsDisplayGeneric if you have a frame that should use the visual overflow
michael@0 1869 * rect of its frame when drawing items, instead of the frame's bounds.
michael@0 1870 */
michael@0 1871 class nsDisplayGenericOverflow : public nsDisplayGeneric {
michael@0 1872 public:
michael@0 1873 nsDisplayGenericOverflow(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 1874 PaintCallback aPaint, const char* aName, Type aType)
michael@0 1875 : nsDisplayGeneric(aBuilder, aFrame, aPaint, aName, aType)
michael@0 1876 {
michael@0 1877 MOZ_COUNT_CTOR(nsDisplayGenericOverflow);
michael@0 1878 }
michael@0 1879 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 1880 virtual ~nsDisplayGenericOverflow() {
michael@0 1881 MOZ_COUNT_DTOR(nsDisplayGenericOverflow);
michael@0 1882 }
michael@0 1883 #endif
michael@0 1884
michael@0 1885 /**
michael@0 1886 * Returns the frame's visual overflow rect instead of the frame's bounds.
michael@0 1887 */
michael@0 1888 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
michael@0 1889 bool* aSnap) MOZ_OVERRIDE
michael@0 1890 {
michael@0 1891 *aSnap = false;
michael@0 1892 return Frame()->GetVisualOverflowRect() + ToReferenceFrame();
michael@0 1893 }
michael@0 1894 };
michael@0 1895
michael@0 1896 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
michael@0 1897 /**
michael@0 1898 * This class implements painting of reflow counts. Ideally, we would simply
michael@0 1899 * make all the frame names be those returned by nsFrame::GetFrameName
michael@0 1900 * (except that tosses in the content tag name!) and support only one color
michael@0 1901 * and eliminate this class altogether in favor of nsDisplayGeneric, but for
michael@0 1902 * the time being we can't pass args to a PaintCallback, so just have a
michael@0 1903 * separate class to do the right thing. Sadly, this alsmo means we need to
michael@0 1904 * hack all leaf frame classes to handle this.
michael@0 1905 *
michael@0 1906 * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
michael@0 1907 * here... I could switch it all to nscolor, but why bother?
michael@0 1908 */
michael@0 1909 class nsDisplayReflowCount : public nsDisplayItem {
michael@0 1910 public:
michael@0 1911 nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 1912 const char* aFrameName,
michael@0 1913 uint32_t aColor = 0)
michael@0 1914 : nsDisplayItem(aBuilder, aFrame),
michael@0 1915 mFrameName(aFrameName),
michael@0 1916 mColor(aColor)
michael@0 1917 {
michael@0 1918 MOZ_COUNT_CTOR(nsDisplayReflowCount);
michael@0 1919 }
michael@0 1920 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 1921 virtual ~nsDisplayReflowCount() {
michael@0 1922 MOZ_COUNT_DTOR(nsDisplayReflowCount);
michael@0 1923 }
michael@0 1924 #endif
michael@0 1925
michael@0 1926 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE {
michael@0 1927 mFrame->PresContext()->PresShell()->PaintCount(mFrameName, aCtx,
michael@0 1928 mFrame->PresContext(),
michael@0 1929 mFrame, ToReferenceFrame(),
michael@0 1930 mColor);
michael@0 1931 }
michael@0 1932 NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT)
michael@0 1933 protected:
michael@0 1934 const char* mFrameName;
michael@0 1935 nscolor mColor;
michael@0 1936 };
michael@0 1937
michael@0 1938 #define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
michael@0 1939 PR_BEGIN_MACRO \
michael@0 1940 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
michael@0 1941 PresContext()->PresShell()->IsPaintingFrameCounts()) { \
michael@0 1942 aLists.Outlines()->AppendNewToTop( \
michael@0 1943 new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name)); \
michael@0 1944 } \
michael@0 1945 PR_END_MACRO
michael@0 1946
michael@0 1947 #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
michael@0 1948 PR_BEGIN_MACRO \
michael@0 1949 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
michael@0 1950 PresContext()->PresShell()->IsPaintingFrameCounts()) { \
michael@0 1951 aLists.Outlines()->AppendNewToTop( \
michael@0 1952 new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name, _color)); \
michael@0 1953 } \
michael@0 1954 PR_END_MACRO
michael@0 1955
michael@0 1956 /*
michael@0 1957 Macro to be used for classes that don't actually implement BuildDisplayList
michael@0 1958 */
michael@0 1959 #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
michael@0 1960 void BuildDisplayList(nsDisplayListBuilder* aBuilder, \
michael@0 1961 const nsRect& aDirtyRect, \
michael@0 1962 const nsDisplayListSet& aLists) { \
michael@0 1963 DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
michael@0 1964 _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
michael@0 1965 }
michael@0 1966
michael@0 1967 #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
michael@0 1968
michael@0 1969 #define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
michael@0 1970 #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
michael@0 1971 #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
michael@0 1972
michael@0 1973 #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
michael@0 1974
michael@0 1975 class nsDisplayCaret : public nsDisplayItem {
michael@0 1976 public:
michael@0 1977 nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame,
michael@0 1978 nsCaret *aCaret)
michael@0 1979 : nsDisplayItem(aBuilder, aCaretFrame), mCaret(aCaret) {
michael@0 1980 MOZ_COUNT_CTOR(nsDisplayCaret);
michael@0 1981 }
michael@0 1982 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 1983 virtual ~nsDisplayCaret() {
michael@0 1984 MOZ_COUNT_DTOR(nsDisplayCaret);
michael@0 1985 }
michael@0 1986 #endif
michael@0 1987
michael@0 1988 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE {
michael@0 1989 *aSnap = false;
michael@0 1990 // The caret returns a rect in the coordinates of mFrame.
michael@0 1991 return mCaret->GetCaretRect() + ToReferenceFrame();
michael@0 1992 }
michael@0 1993 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 1994 NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
michael@0 1995 protected:
michael@0 1996 nsRefPtr<nsCaret> mCaret;
michael@0 1997 };
michael@0 1998
michael@0 1999 /**
michael@0 2000 * The standard display item to paint the CSS borders of a frame.
michael@0 2001 */
michael@0 2002 class nsDisplayBorder : public nsDisplayItem {
michael@0 2003 public:
michael@0 2004 nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
michael@0 2005 nsDisplayItem(aBuilder, aFrame)
michael@0 2006 {
michael@0 2007 MOZ_COUNT_CTOR(nsDisplayBorder);
michael@0 2008 }
michael@0 2009 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2010 virtual ~nsDisplayBorder() {
michael@0 2011 MOZ_COUNT_DTOR(nsDisplayBorder);
michael@0 2012 }
michael@0 2013 #endif
michael@0 2014
michael@0 2015 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2016 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 2017 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2018 nsRegion* aVisibleRegion,
michael@0 2019 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2020 NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
michael@0 2021
michael@0 2022 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 2023
michael@0 2024 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 2025 const nsDisplayItemGeometry* aGeometry,
michael@0 2026 nsRegion* aInvalidRegion) MOZ_OVERRIDE;
michael@0 2027
michael@0 2028 protected:
michael@0 2029 nsRect CalculateBounds(const nsStyleBorder& aStyleBorder);
michael@0 2030 };
michael@0 2031
michael@0 2032 /**
michael@0 2033 * A simple display item that just renders a solid color across the
michael@0 2034 * specified bounds. For canvas frames (in the CSS sense) we split off the
michael@0 2035 * drawing of the background color into this class (from nsDisplayBackground
michael@0 2036 * via nsDisplayCanvasBackground). This is done so that we can always draw a
michael@0 2037 * background color to avoid ugly flashes of white when we can't draw a full
michael@0 2038 * frame tree (ie when a page is loading). The bounds can differ from the
michael@0 2039 * frame's bounds -- this is needed when a frame/iframe is loading and there
michael@0 2040 * is not yet a frame tree to go in the frame/iframe so we use the subdoc
michael@0 2041 * frame of the parent document as a standin.
michael@0 2042 */
michael@0 2043 class nsDisplaySolidColor : public nsDisplayItem {
michael@0 2044 public:
michael@0 2045 nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2046 const nsRect& aBounds, nscolor aColor)
michael@0 2047 : nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor)
michael@0 2048 {
michael@0 2049 NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!");
michael@0 2050 MOZ_COUNT_CTOR(nsDisplaySolidColor);
michael@0 2051 }
michael@0 2052 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2053 virtual ~nsDisplaySolidColor() {
michael@0 2054 MOZ_COUNT_DTOR(nsDisplaySolidColor);
michael@0 2055 }
michael@0 2056 #endif
michael@0 2057
michael@0 2058 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2059
michael@0 2060 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 2061 bool* aSnap) MOZ_OVERRIDE {
michael@0 2062 *aSnap = false;
michael@0 2063 nsRegion result;
michael@0 2064 if (NS_GET_A(mColor) == 255) {
michael@0 2065 result = GetBounds(aBuilder, aSnap);
michael@0 2066 }
michael@0 2067 return result;
michael@0 2068 }
michael@0 2069
michael@0 2070 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE
michael@0 2071 {
michael@0 2072 *aColor = mColor;
michael@0 2073 return true;
michael@0 2074 }
michael@0 2075
michael@0 2076 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 2077
michael@0 2078 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
michael@0 2079 {
michael@0 2080 return new nsDisplaySolidColorGeometry(this, aBuilder, mColor);
michael@0 2081 }
michael@0 2082
michael@0 2083 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 2084 const nsDisplayItemGeometry* aGeometry,
michael@0 2085 nsRegion* aInvalidRegion) MOZ_OVERRIDE
michael@0 2086 {
michael@0 2087 const nsDisplaySolidColorGeometry* geometry =
michael@0 2088 static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
michael@0 2089 if (mColor != geometry->mColor) {
michael@0 2090 bool dummy;
michael@0 2091 aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
michael@0 2092 return;
michael@0 2093 }
michael@0 2094 ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
michael@0 2095 }
michael@0 2096
michael@0 2097 #ifdef MOZ_DUMP_PAINTING
michael@0 2098 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE;
michael@0 2099 #endif
michael@0 2100
michael@0 2101 NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
michael@0 2102
michael@0 2103 private:
michael@0 2104 nsRect mBounds;
michael@0 2105 nscolor mColor;
michael@0 2106 };
michael@0 2107
michael@0 2108 /**
michael@0 2109 * A display item to paint one background-image for a frame. Each background
michael@0 2110 * image layer gets its own nsDisplayBackgroundImage.
michael@0 2111 */
michael@0 2112 class nsDisplayBackgroundImage : public nsDisplayImageContainer {
michael@0 2113 public:
michael@0 2114 /**
michael@0 2115 * aLayer signifies which background layer this item represents.
michael@0 2116 * aIsThemed should be the value of aFrame->IsThemed.
michael@0 2117 * aBackgroundStyle should be the result of
michael@0 2118 * nsCSSRendering::FindBackground, or null if FindBackground returned false.
michael@0 2119 */
michael@0 2120 nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2121 uint32_t aLayer,
michael@0 2122 const nsStyleBackground* aBackgroundStyle);
michael@0 2123 virtual ~nsDisplayBackgroundImage();
michael@0 2124
michael@0 2125 // This will create and append new items for all the layers of the
michael@0 2126 // background. Returns whether we appended a themed background.
michael@0 2127 static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
michael@0 2128 nsIFrame* aFrame,
michael@0 2129 nsDisplayList* aList);
michael@0 2130
michael@0 2131 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 2132 LayerManager* aManager,
michael@0 2133 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
michael@0 2134
michael@0 2135 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 2136 LayerManager* aManager,
michael@0 2137 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 2138
michael@0 2139 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 2140 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
michael@0 2141 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2142 nsRegion* aVisibleRegion,
michael@0 2143 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2144 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 2145 bool* aSnap) MOZ_OVERRIDE;
michael@0 2146 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
michael@0 2147 nsIFrame* aFrame) MOZ_OVERRIDE;
michael@0 2148 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
michael@0 2149 /**
michael@0 2150 * GetBounds() returns the background painting area.
michael@0 2151 */
michael@0 2152 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2153 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 2154 virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE;
michael@0 2155 NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
michael@0 2156
michael@0 2157 /**
michael@0 2158 * Return the background positioning area.
michael@0 2159 * (GetBounds() returns the background painting area.)
michael@0 2160 * Can be called only when mBackgroundStyle is non-null.
michael@0 2161 */
michael@0 2162 nsRect GetPositioningArea();
michael@0 2163
michael@0 2164 /**
michael@0 2165 * Returns true if existing rendered pixels of this display item may need
michael@0 2166 * to be redrawn if the positioning area size changes but its position does
michael@0 2167 * not.
michael@0 2168 * If false, only the changed painting area needs to be redrawn when the
michael@0 2169 * positioning area size changes but its position does not.
michael@0 2170 */
michael@0 2171 bool RenderingMightDependOnPositioningAreaSizeChange();
michael@0 2172
michael@0 2173 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
michael@0 2174 {
michael@0 2175 return new nsDisplayBackgroundGeometry(this, aBuilder);
michael@0 2176 }
michael@0 2177
michael@0 2178 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 2179 const nsDisplayItemGeometry* aGeometry,
michael@0 2180 nsRegion* aInvalidRegion) MOZ_OVERRIDE;
michael@0 2181
michael@0 2182 virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
michael@0 2183 nsDisplayListBuilder *aBuilder) MOZ_OVERRIDE;
michael@0 2184 virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) MOZ_OVERRIDE;
michael@0 2185
michael@0 2186 static nsRegion GetInsideClipRegion(nsDisplayItem* aItem, nsPresContext* aPresContext, uint8_t aClip,
michael@0 2187 const nsRect& aRect, bool* aSnap);
michael@0 2188
michael@0 2189 protected:
michael@0 2190 typedef class mozilla::layers::ImageContainer ImageContainer;
michael@0 2191 typedef class mozilla::layers::ImageLayer ImageLayer;
michael@0 2192
michael@0 2193 bool TryOptimizeToImageLayer(LayerManager* aManager, nsDisplayListBuilder* aBuilder);
michael@0 2194 bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
michael@0 2195 const nsRect& aClipRect,
michael@0 2196 gfxRect* aDestRect);
michael@0 2197 nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder);
michael@0 2198
michael@0 2199 void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
michael@0 2200 const nsRect& aBounds, nsRect* aClipRect);
michael@0 2201
michael@0 2202 // Cache the result of nsCSSRendering::FindBackground. Always null if
michael@0 2203 // mIsThemed is true or if FindBackground returned false.
michael@0 2204 const nsStyleBackground* mBackgroundStyle;
michael@0 2205 /* If this background can be a simple image layer, we store the format here. */
michael@0 2206 nsRefPtr<ImageContainer> mImageContainer;
michael@0 2207 gfxRect mDestRect;
michael@0 2208 /* Bounds of this display item */
michael@0 2209 nsRect mBounds;
michael@0 2210 uint32_t mLayer;
michael@0 2211 };
michael@0 2212
michael@0 2213
michael@0 2214 /**
michael@0 2215 * A display item to paint the native theme background for a frame.
michael@0 2216 */
michael@0 2217 class nsDisplayThemedBackground : public nsDisplayItem {
michael@0 2218 public:
michael@0 2219 nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
michael@0 2220 virtual ~nsDisplayThemedBackground();
michael@0 2221
michael@0 2222 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 2223 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
michael@0 2224 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 2225 bool* aSnap) MOZ_OVERRIDE;
michael@0 2226 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
michael@0 2227 /**
michael@0 2228 * GetBounds() returns the background painting area.
michael@0 2229 */
michael@0 2230 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2231 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 2232 NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND)
michael@0 2233
michael@0 2234 /**
michael@0 2235 * Return the background positioning area.
michael@0 2236 * (GetBounds() returns the background painting area.)
michael@0 2237 * Can be called only when mBackgroundStyle is non-null.
michael@0 2238 */
michael@0 2239 nsRect GetPositioningArea();
michael@0 2240
michael@0 2241 /**
michael@0 2242 * Return whether our frame's document does not have the state
michael@0 2243 * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
michael@0 2244 */
michael@0 2245 bool IsWindowActive();
michael@0 2246
michael@0 2247 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
michael@0 2248 {
michael@0 2249 return new nsDisplayThemedBackgroundGeometry(this, aBuilder);
michael@0 2250 }
michael@0 2251
michael@0 2252 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 2253 const nsDisplayItemGeometry* aGeometry,
michael@0 2254 nsRegion* aInvalidRegion) MOZ_OVERRIDE;
michael@0 2255
michael@0 2256 #ifdef MOZ_DUMP_PAINTING
michael@0 2257 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE;
michael@0 2258 #endif
michael@0 2259 protected:
michael@0 2260 nsRect GetBoundsInternal();
michael@0 2261
michael@0 2262 void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
michael@0 2263 const nsRect& aBounds, nsRect* aClipRect);
michael@0 2264
michael@0 2265 nsRect mBounds;
michael@0 2266 nsITheme::Transparency mThemeTransparency;
michael@0 2267 uint8_t mAppearance;
michael@0 2268 };
michael@0 2269
michael@0 2270 class nsDisplayBackgroundColor : public nsDisplayItem
michael@0 2271 {
michael@0 2272 public:
michael@0 2273 nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2274 const nsStyleBackground* aBackgroundStyle,
michael@0 2275 nscolor aColor)
michael@0 2276 : nsDisplayItem(aBuilder, aFrame)
michael@0 2277 , mBackgroundStyle(aBackgroundStyle)
michael@0 2278 , mColor(aColor)
michael@0 2279 { }
michael@0 2280
michael@0 2281 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 2282
michael@0 2283 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 2284 bool* aSnap) MOZ_OVERRIDE;
michael@0 2285 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
michael@0 2286 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 2287 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
michael@0 2288
michael@0 2289 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
michael@0 2290 {
michael@0 2291 *aSnap = true;
michael@0 2292 return nsRect(ToReferenceFrame(), Frame()->GetSize());
michael@0 2293 }
michael@0 2294
michael@0 2295 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
michael@0 2296 {
michael@0 2297 return new nsDisplayItemBoundsGeometry(this, aBuilder);
michael@0 2298 }
michael@0 2299
michael@0 2300 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 2301 const nsDisplayItemGeometry* aGeometry,
michael@0 2302 nsRegion* aInvalidRegion) MOZ_OVERRIDE
michael@0 2303 {
michael@0 2304 const nsDisplayItemBoundsGeometry* geometry = static_cast<const nsDisplayItemBoundsGeometry*>(aGeometry);
michael@0 2305 ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
michael@0 2306 }
michael@0 2307
michael@0 2308 NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
michael@0 2309 #ifdef MOZ_DUMP_PAINTING
michael@0 2310 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE;
michael@0 2311 #endif
michael@0 2312
michael@0 2313 protected:
michael@0 2314 const nsStyleBackground* mBackgroundStyle;
michael@0 2315 nscolor mColor;
michael@0 2316 };
michael@0 2317
michael@0 2318 /**
michael@0 2319 * The standard display item to paint the outer CSS box-shadows of a frame.
michael@0 2320 */
michael@0 2321 class nsDisplayBoxShadowOuter : public nsDisplayItem {
michael@0 2322 public:
michael@0 2323 nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
michael@0 2324 : nsDisplayItem(aBuilder, aFrame)
michael@0 2325 , mOpacity(1.0) {
michael@0 2326 MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
michael@0 2327 mBounds = GetBoundsInternal();
michael@0 2328 }
michael@0 2329 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2330 virtual ~nsDisplayBoxShadowOuter() {
michael@0 2331 MOZ_COUNT_DTOR(nsDisplayBoxShadowOuter);
michael@0 2332 }
michael@0 2333 #endif
michael@0 2334
michael@0 2335 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 2336 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2337 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2338 nsRegion* aVisibleRegion,
michael@0 2339 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2340 NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
michael@0 2341
michael@0 2342 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 2343 const nsDisplayItemGeometry* aGeometry,
michael@0 2344 nsRegion* aInvalidRegion) MOZ_OVERRIDE;
michael@0 2345
michael@0 2346 virtual bool ApplyOpacity(nsDisplayListBuilder* aBuilder,
michael@0 2347 float aOpacity,
michael@0 2348 const DisplayItemClip* aClip) MOZ_OVERRIDE
michael@0 2349 {
michael@0 2350 mOpacity = aOpacity;
michael@0 2351 if (aClip) {
michael@0 2352 IntersectClip(aBuilder, *aClip);
michael@0 2353 }
michael@0 2354 return true;
michael@0 2355 }
michael@0 2356
michael@0 2357 nsRect GetBoundsInternal();
michael@0 2358
michael@0 2359 private:
michael@0 2360 nsRegion mVisibleRegion;
michael@0 2361 nsRect mBounds;
michael@0 2362 float mOpacity;
michael@0 2363 };
michael@0 2364
michael@0 2365 /**
michael@0 2366 * The standard display item to paint the inner CSS box-shadows of a frame.
michael@0 2367 */
michael@0 2368 class nsDisplayBoxShadowInner : public nsDisplayItem {
michael@0 2369 public:
michael@0 2370 nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
michael@0 2371 : nsDisplayItem(aBuilder, aFrame) {
michael@0 2372 MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
michael@0 2373 }
michael@0 2374 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2375 virtual ~nsDisplayBoxShadowInner() {
michael@0 2376 MOZ_COUNT_DTOR(nsDisplayBoxShadowInner);
michael@0 2377 }
michael@0 2378 #endif
michael@0 2379
michael@0 2380 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 2381 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2382 nsRegion* aVisibleRegion,
michael@0 2383 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2384 NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
michael@0 2385
michael@0 2386 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
michael@0 2387 {
michael@0 2388 return new nsDisplayBoxShadowInnerGeometry(this, aBuilder);
michael@0 2389 }
michael@0 2390
michael@0 2391 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 2392 const nsDisplayItemGeometry* aGeometry,
michael@0 2393 nsRegion* aInvalidRegion) MOZ_OVERRIDE
michael@0 2394 {
michael@0 2395 const nsDisplayBoxShadowInnerGeometry* geometry = static_cast<const nsDisplayBoxShadowInnerGeometry*>(aGeometry);
michael@0 2396 if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) {
michael@0 2397 // nsDisplayBoxShadowInner is based around the padding rect, but it can
michael@0 2398 // touch pixels outside of this. We should invalidate the entire bounds.
michael@0 2399 bool snap;
michael@0 2400 aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
michael@0 2401 }
michael@0 2402 }
michael@0 2403
michael@0 2404 private:
michael@0 2405 nsRegion mVisibleRegion;
michael@0 2406 };
michael@0 2407
michael@0 2408 /**
michael@0 2409 * The standard display item to paint the CSS outline of a frame.
michael@0 2410 */
michael@0 2411 class nsDisplayOutline : public nsDisplayItem {
michael@0 2412 public:
michael@0 2413 nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
michael@0 2414 nsDisplayItem(aBuilder, aFrame) {
michael@0 2415 MOZ_COUNT_CTOR(nsDisplayOutline);
michael@0 2416 }
michael@0 2417 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2418 virtual ~nsDisplayOutline() {
michael@0 2419 MOZ_COUNT_DTOR(nsDisplayOutline);
michael@0 2420 }
michael@0 2421 #endif
michael@0 2422
michael@0 2423 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2424 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 2425 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2426 nsRegion* aVisibleRegion,
michael@0 2427 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2428 NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
michael@0 2429 };
michael@0 2430
michael@0 2431 /**
michael@0 2432 * A class that lets you receive events within the frame bounds but never paints.
michael@0 2433 */
michael@0 2434 class nsDisplayEventReceiver : public nsDisplayItem {
michael@0 2435 public:
michael@0 2436 nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
michael@0 2437 : nsDisplayItem(aBuilder, aFrame) {
michael@0 2438 MOZ_COUNT_CTOR(nsDisplayEventReceiver);
michael@0 2439 }
michael@0 2440 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2441 virtual ~nsDisplayEventReceiver() {
michael@0 2442 MOZ_COUNT_DTOR(nsDisplayEventReceiver);
michael@0 2443 }
michael@0 2444 #endif
michael@0 2445
michael@0 2446 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 2447 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
michael@0 2448 NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER)
michael@0 2449 };
michael@0 2450
michael@0 2451 /**
michael@0 2452 * A display item that tracks event-sensitive regions which will be set
michael@0 2453 * on the ContainerLayer that eventually contains this item.
michael@0 2454 *
michael@0 2455 * One of these is created for each stacking context and pseudo-stacking-context.
michael@0 2456 * It accumulates regions for event targets contributed by the border-boxes of
michael@0 2457 * frames in its (pseudo) stacking context. A nsDisplayLayerEventRegions
michael@0 2458 * eventually contributes its regions to the ThebesLayer it is placed in by
michael@0 2459 * FrameLayerBuilder. (We don't create a display item for every frame that
michael@0 2460 * could be an event target (i.e. almost all frames), because that would be
michael@0 2461 * high overhead.)
michael@0 2462 *
michael@0 2463 * We always make leaf layers other than ThebesLayers transparent to events.
michael@0 2464 * For example, an event targeting a canvas or video will actually target the
michael@0 2465 * background of that element, which is logically in the ThebesLayer behind the
michael@0 2466 * CanvasFrame or ImageFrame. We only need to create a
michael@0 2467 * nsDisplayLayerEventRegions when an element's background could be in front
michael@0 2468 * of a lower z-order element with its own layer.
michael@0 2469 */
michael@0 2470 class nsDisplayLayerEventRegions MOZ_FINAL : public nsDisplayItem {
michael@0 2471 public:
michael@0 2472 nsDisplayLayerEventRegions(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
michael@0 2473 : nsDisplayItem(aBuilder, aFrame)
michael@0 2474 {
michael@0 2475 MOZ_COUNT_CTOR(nsDisplayEventReceiver);
michael@0 2476 AddFrame(aBuilder, aFrame);
michael@0 2477 }
michael@0 2478 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2479 virtual ~nsDisplayLayerEventRegions() {
michael@0 2480 MOZ_COUNT_DTOR(nsDisplayEventReceiver);
michael@0 2481 }
michael@0 2482 #endif
michael@0 2483 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
michael@0 2484 {
michael@0 2485 *aSnap = false;
michael@0 2486 return mHitRegion.GetBounds().Union(mMaybeHitRegion.GetBounds());
michael@0 2487 }
michael@0 2488
michael@0 2489 NS_DISPLAY_DECL_NAME("LayerEventRegions", TYPE_LAYER_EVENT_REGIONS)
michael@0 2490
michael@0 2491 // Indicate that aFrame's border-box contributes to the event regions for
michael@0 2492 // this layer. aFrame must have the same reference frame as mFrame.
michael@0 2493 void AddFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
michael@0 2494
michael@0 2495 const nsRegion& HitRegion() { return mHitRegion; }
michael@0 2496 const nsRegion& MaybeHitRegion() { return mMaybeHitRegion; }
michael@0 2497 const nsRegion& DispatchToContentHitRegion() { return mDispatchToContentHitRegion; }
michael@0 2498
michael@0 2499 private:
michael@0 2500 // Relative to aFrame's reference frame.
michael@0 2501 // These are the points that are definitely in the hit region.
michael@0 2502 nsRegion mHitRegion;
michael@0 2503 // These are points that may or may not be in the hit region. Only main-thread
michael@0 2504 // event handling can tell for sure (e.g. because complex shapes are present).
michael@0 2505 nsRegion mMaybeHitRegion;
michael@0 2506 // These are points that need to be dispatched to the content thread for
michael@0 2507 // resolution. Always contained in the union of mHitRegion and mMaybeHitRegion.
michael@0 2508 nsRegion mDispatchToContentHitRegion;
michael@0 2509 };
michael@0 2510
michael@0 2511 /**
michael@0 2512 * A class that lets you wrap a display list as a display item.
michael@0 2513 *
michael@0 2514 * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
michael@0 2515 * list has many items, it's not clear which one has the 'underlying frame'.
michael@0 2516 * Thus we force the creator to specify what the underlying frame is. The
michael@0 2517 * underlying frame should be the root of a stacking context, because sorting
michael@0 2518 * a list containing this item will not get at the children.
michael@0 2519 *
michael@0 2520 * In some cases (e.g., clipping) we want to wrap a list but we don't have a
michael@0 2521 * particular underlying frame that is a stacking context root. In that case
michael@0 2522 * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
michael@0 2523 * detect and handle this case.
michael@0 2524 */
michael@0 2525 class nsDisplayWrapList : public nsDisplayItem {
michael@0 2526 // This is never instantiated directly, so no need to count constructors and
michael@0 2527 // destructors.
michael@0 2528
michael@0 2529 public:
michael@0 2530 /**
michael@0 2531 * Takes all the items from aList and puts them in our list.
michael@0 2532 */
michael@0 2533 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2534 nsDisplayList* aList);
michael@0 2535 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2536 nsDisplayItem* aItem);
michael@0 2537 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2538 nsDisplayItem* aItem, const nsIFrame* aReferenceFrame, const nsPoint& aToReferenceFrame);
michael@0 2539 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
michael@0 2540 : nsDisplayItem(aBuilder, aFrame), mOverrideZIndex(0) {}
michael@0 2541 virtual ~nsDisplayWrapList();
michael@0 2542 /**
michael@0 2543 * Call this if the wrapped list is changed.
michael@0 2544 */
michael@0 2545 virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
michael@0 2546 {
michael@0 2547 mBounds = mList.GetBounds(aBuilder);
michael@0 2548 }
michael@0 2549 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 2550 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
michael@0 2551 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2552 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 2553 bool* aSnap) MOZ_OVERRIDE;
michael@0 2554 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
michael@0 2555 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
michael@0 2556 nsIFrame* aFrame) MOZ_OVERRIDE;
michael@0 2557 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 2558 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2559 nsRegion* aVisibleRegion,
michael@0 2560 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2561 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE {
michael@0 2562 NS_WARNING("This list should already have been flattened!!!");
michael@0 2563 return false;
michael@0 2564 }
michael@0 2565 virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) MOZ_OVERRIDE
michael@0 2566 {
michael@0 2567 aFrames->AppendElements(mMergedFrames);
michael@0 2568 }
michael@0 2569 virtual bool IsInvalid(nsRect& aRect) MOZ_OVERRIDE
michael@0 2570 {
michael@0 2571 if (mFrame->IsInvalid(aRect) && aRect.IsEmpty()) {
michael@0 2572 return true;
michael@0 2573 }
michael@0 2574 nsRect temp;
michael@0 2575 for (uint32_t i = 0; i < mMergedFrames.Length(); i++) {
michael@0 2576 if (mMergedFrames[i]->IsInvalid(temp) && temp.IsEmpty()) {
michael@0 2577 aRect.SetEmpty();
michael@0 2578 return true;
michael@0 2579 }
michael@0 2580 aRect = aRect.Union(temp);
michael@0 2581 }
michael@0 2582 aRect += ToReferenceFrame();
michael@0 2583 return !aRect.IsEmpty();
michael@0 2584 }
michael@0 2585 NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
michael@0 2586
michael@0 2587 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 2588
michael@0 2589 virtual nsDisplayList* GetSameCoordinateSystemChildren() MOZ_OVERRIDE
michael@0 2590 {
michael@0 2591 NS_ASSERTION(mList.IsEmpty() || !ReferenceFrame() ||
michael@0 2592 !mList.GetBottom()->ReferenceFrame() ||
michael@0 2593 mList.GetBottom()->ReferenceFrame() == ReferenceFrame(),
michael@0 2594 "Children must have same reference frame");
michael@0 2595 return &mList;
michael@0 2596 }
michael@0 2597 virtual nsDisplayList* GetChildren() MOZ_OVERRIDE { return &mList; }
michael@0 2598
michael@0 2599 virtual int32_t ZIndex() const MOZ_OVERRIDE
michael@0 2600 {
michael@0 2601 return (mOverrideZIndex > 0) ? mOverrideZIndex : nsDisplayItem::ZIndex();
michael@0 2602 }
michael@0 2603
michael@0 2604 void SetOverrideZIndex(int32_t aZIndex)
michael@0 2605 {
michael@0 2606 mOverrideZIndex = aZIndex;
michael@0 2607 }
michael@0 2608
michael@0 2609 /**
michael@0 2610 * This creates a copy of this item, but wrapping aItem instead of
michael@0 2611 * our existing list. Only gets called if this item returned nullptr
michael@0 2612 * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
michael@0 2613 * GetUnderlyingFrame().
michael@0 2614 */
michael@0 2615 virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
michael@0 2616 nsDisplayItem* aItem) {
michael@0 2617 NS_NOTREACHED("We never returned nullptr for GetUnderlyingFrame!");
michael@0 2618 return nullptr;
michael@0 2619 }
michael@0 2620
michael@0 2621 protected:
michael@0 2622 nsDisplayWrapList() {}
michael@0 2623
michael@0 2624 void MergeFrom(nsDisplayWrapList* aOther)
michael@0 2625 {
michael@0 2626 mList.AppendToBottom(&aOther->mList);
michael@0 2627 mBounds.UnionRect(mBounds, aOther->mBounds);
michael@0 2628 }
michael@0 2629 void MergeFromTrackingMergedFrames(nsDisplayWrapList* aOther)
michael@0 2630 {
michael@0 2631 MergeFrom(aOther);
michael@0 2632 mMergedFrames.AppendElement(aOther->mFrame);
michael@0 2633 mMergedFrames.MoveElementsFrom(aOther->mMergedFrames);
michael@0 2634 }
michael@0 2635
michael@0 2636 nsDisplayList mList;
michael@0 2637 // The frames from items that have been merged into this item, excluding
michael@0 2638 // this item's own frame.
michael@0 2639 nsTArray<nsIFrame*> mMergedFrames;
michael@0 2640 nsRect mBounds;
michael@0 2641 // Overrides the ZIndex of our frame if > 0.
michael@0 2642 int32_t mOverrideZIndex;
michael@0 2643 };
michael@0 2644
michael@0 2645 /**
michael@0 2646 * We call WrapDisplayList on the in-flow lists: BorderBackground(),
michael@0 2647 * BlockBorderBackgrounds() and Content().
michael@0 2648 * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
michael@0 2649 * and Floats(). This is done to support special wrapping processing for frames
michael@0 2650 * that may not be in-flow descendants of the current frame.
michael@0 2651 */
michael@0 2652 class nsDisplayWrapper {
michael@0 2653 public:
michael@0 2654 // This is never instantiated directly (it has pure virtual methods), so no
michael@0 2655 // need to count constructors and destructors.
michael@0 2656
michael@0 2657 virtual bool WrapBorderBackground() { return true; }
michael@0 2658 virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
michael@0 2659 nsIFrame* aFrame, nsDisplayList* aList) = 0;
michael@0 2660 virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
michael@0 2661 nsDisplayItem* aItem) = 0;
michael@0 2662
michael@0 2663 nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2664 const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
michael@0 2665 nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2666 const nsDisplayListSet& aLists);
michael@0 2667 protected:
michael@0 2668 nsDisplayWrapper() {}
michael@0 2669 };
michael@0 2670
michael@0 2671 /**
michael@0 2672 * The standard display item to paint a stacking context with translucency
michael@0 2673 * set by the stacking context root frame's 'opacity' style.
michael@0 2674 */
michael@0 2675 class nsDisplayOpacity : public nsDisplayWrapList {
michael@0 2676 public:
michael@0 2677 nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2678 nsDisplayList* aList);
michael@0 2679 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2680 virtual ~nsDisplayOpacity();
michael@0 2681 #endif
michael@0 2682
michael@0 2683 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 2684 bool* aSnap) MOZ_OVERRIDE;
michael@0 2685 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 2686 LayerManager* aManager,
michael@0 2687 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 2688 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 2689 LayerManager* aManager,
michael@0 2690 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
michael@0 2691 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2692 nsRegion* aVisibleRegion,
michael@0 2693 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2694 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
michael@0 2695 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 2696 const nsDisplayItemGeometry* aGeometry,
michael@0 2697 nsRegion* aInvalidRegion) MOZ_OVERRIDE
michael@0 2698 {
michael@0 2699 // We don't need to compute an invalidation region since we have LayerTreeInvalidation
michael@0 2700 }
michael@0 2701 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 2702 bool NeedsActiveLayer();
michael@0 2703 NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
michael@0 2704 #ifdef MOZ_DUMP_PAINTING
michael@0 2705 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE;
michael@0 2706 #endif
michael@0 2707
michael@0 2708 bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 2709 };
michael@0 2710
michael@0 2711 class nsDisplayMixBlendMode : public nsDisplayWrapList {
michael@0 2712 public:
michael@0 2713 nsDisplayMixBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2714 nsDisplayList* aList, uint32_t aFlags = 0);
michael@0 2715 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2716 virtual ~nsDisplayMixBlendMode();
michael@0 2717 #endif
michael@0 2718
michael@0 2719 nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 2720 bool* aSnap) MOZ_OVERRIDE;
michael@0 2721
michael@0 2722 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 2723 LayerManager* aManager,
michael@0 2724 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 2725 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 2726 const nsDisplayItemGeometry* aGeometry,
michael@0 2727 nsRegion* aInvalidRegion) MOZ_OVERRIDE
michael@0 2728 {
michael@0 2729 // We don't need to compute an invalidation region since we have LayerTreeInvalidation
michael@0 2730 }
michael@0 2731 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 2732 LayerManager* aManager,
michael@0 2733 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
michael@0 2734 {
michael@0 2735 return mozilla::LAYER_INACTIVE;
michael@0 2736 }
michael@0 2737 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2738 nsRegion* aVisibleRegion,
michael@0 2739 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2740 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
michael@0 2741 NS_DISPLAY_DECL_NAME("MixBlendMode", TYPE_MIX_BLEND_MODE)
michael@0 2742 };
michael@0 2743
michael@0 2744 class nsDisplayBlendContainer : public nsDisplayWrapList {
michael@0 2745 public:
michael@0 2746 nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2747 nsDisplayList* aList, uint32_t aFlags = 0);
michael@0 2748 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2749 virtual ~nsDisplayBlendContainer();
michael@0 2750 #endif
michael@0 2751
michael@0 2752 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 2753 LayerManager* aManager,
michael@0 2754 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 2755 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 2756 LayerManager* aManager,
michael@0 2757 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
michael@0 2758 {
michael@0 2759 return mozilla::LAYER_INACTIVE;
michael@0 2760 }
michael@0 2761 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
michael@0 2762 NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
michael@0 2763 };
michael@0 2764
michael@0 2765 /**
michael@0 2766 * A display item that has no purpose but to ensure its contents get
michael@0 2767 * their own layer.
michael@0 2768 */
michael@0 2769 class nsDisplayOwnLayer : public nsDisplayWrapList {
michael@0 2770 public:
michael@0 2771
michael@0 2772 /**
michael@0 2773 * nsDisplayOwnLayer constructor flags
michael@0 2774 */
michael@0 2775 enum {
michael@0 2776 GENERATE_SUBDOC_INVALIDATIONS = 0x01,
michael@0 2777 VERTICAL_SCROLLBAR = 0x02,
michael@0 2778 HORIZONTAL_SCROLLBAR = 0x04,
michael@0 2779 GENERATE_SCROLLABLE_LAYER = 0x08
michael@0 2780 };
michael@0 2781
michael@0 2782 /**
michael@0 2783 * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
michael@0 2784 * Add UserData to the created ContainerLayer, so that invalidations
michael@0 2785 * for this layer are send to our nsPresContext.
michael@0 2786 * GENERATE_SCROLLABLE_LAYER : only valid on nsDisplaySubDocument (and
michael@0 2787 * subclasses), indicates this layer is to be a scrollable layer, so call
michael@0 2788 * RecordFrameMetrics, etc.
michael@0 2789 * @param aScrollTarget when VERTICAL_SCROLLBAR or HORIZONTAL_SCROLLBAR
michael@0 2790 * is set in the flags, this parameter should be the ViewID of the
michael@0 2791 * scrollable content this scrollbar is for.
michael@0 2792 */
michael@0 2793 nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2794 nsDisplayList* aList, uint32_t aFlags = 0,
michael@0 2795 ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID);
michael@0 2796 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2797 virtual ~nsDisplayOwnLayer();
michael@0 2798 #endif
michael@0 2799
michael@0 2800 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 2801 LayerManager* aManager,
michael@0 2802 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 2803 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 2804 LayerManager* aManager,
michael@0 2805 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
michael@0 2806 {
michael@0 2807 return mozilla::LAYER_ACTIVE_FORCE;
michael@0 2808 }
michael@0 2809 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE
michael@0 2810 {
michael@0 2811 // Don't allow merging, each sublist must have its own layer
michael@0 2812 return false;
michael@0 2813 }
michael@0 2814 uint32_t GetFlags() { return mFlags; }
michael@0 2815 NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
michael@0 2816 protected:
michael@0 2817 uint32_t mFlags;
michael@0 2818 ViewID mScrollTarget;
michael@0 2819 };
michael@0 2820
michael@0 2821 /**
michael@0 2822 * A display item for subdocuments. This is more or less the same as nsDisplayOwnLayer,
michael@0 2823 * except that it always populates the FrameMetrics instance on the ContainerLayer it
michael@0 2824 * builds.
michael@0 2825 */
michael@0 2826 class nsDisplaySubDocument : public nsDisplayOwnLayer {
michael@0 2827 public:
michael@0 2828 nsDisplaySubDocument(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2829 nsDisplayList* aList, uint32_t aFlags);
michael@0 2830 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2831 virtual ~nsDisplaySubDocument();
michael@0 2832 #endif
michael@0 2833
michael@0 2834 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 2835 LayerManager* aManager,
michael@0 2836 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 2837
michael@0 2838 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2839
michael@0 2840 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2841 nsRegion* aVisibleRegion,
michael@0 2842 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2843
michael@0 2844 virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return !(mFlags & GENERATE_SCROLLABLE_LAYER); }
michael@0 2845
michael@0 2846 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 2847
michael@0 2848 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2849
michael@0 2850 NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT)
michael@0 2851 protected:
michael@0 2852 ViewID mScrollParentId;
michael@0 2853 };
michael@0 2854
michael@0 2855 /**
michael@0 2856 * A display item for subdocuments to capture the resolution from the presShell
michael@0 2857 * and ensure that it gets applied to all the right elements. This item creates
michael@0 2858 * a container layer.
michael@0 2859 */
michael@0 2860 class nsDisplayResolution : public nsDisplaySubDocument {
michael@0 2861 public:
michael@0 2862 nsDisplayResolution(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2863 nsDisplayList* aList, uint32_t aFlags);
michael@0 2864 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2865 virtual ~nsDisplayResolution();
michael@0 2866 #endif
michael@0 2867
michael@0 2868 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 2869 LayerManager* aManager,
michael@0 2870 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 2871 NS_DISPLAY_DECL_NAME("Resolution", TYPE_RESOLUTION)
michael@0 2872 };
michael@0 2873
michael@0 2874 /**
michael@0 2875 * A display item used to represent sticky position elements. The contents
michael@0 2876 * gets its own layer and creates a stacking context, and the layer will have
michael@0 2877 * position-related metadata set on it.
michael@0 2878 */
michael@0 2879 class nsDisplayStickyPosition : public nsDisplayOwnLayer {
michael@0 2880 public:
michael@0 2881 nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 2882 nsDisplayList* aList);
michael@0 2883 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2884 virtual ~nsDisplayStickyPosition();
michael@0 2885 #endif
michael@0 2886
michael@0 2887 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 2888 LayerManager* aManager,
michael@0 2889 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 2890 NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION)
michael@0 2891 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 2892 LayerManager* aManager,
michael@0 2893 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
michael@0 2894 {
michael@0 2895 return mozilla::LAYER_ACTIVE;
michael@0 2896 }
michael@0 2897 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
michael@0 2898 };
michael@0 2899
michael@0 2900 /**
michael@0 2901 * This potentially creates a layer for the given list of items, whose
michael@0 2902 * visibility is determined by the displayport for the given frame instead of
michael@0 2903 * what is passed in to ComputeVisibility.
michael@0 2904 *
michael@0 2905 * Here in content, we can use this to render more content than is actually
michael@0 2906 * visible. Then, the compositing process can manipulate the generated layer
michael@0 2907 * through transformations so that asynchronous scrolling can be implemented.
michael@0 2908 *
michael@0 2909 * Note that setting the displayport will not change any hit testing! The
michael@0 2910 * content process will know nothing about what the user is actually seeing,
michael@0 2911 * so it can only do hit testing for what is supposed to be the visible region.
michael@0 2912 *
michael@0 2913 * It is possible for scroll boxes to have content that can be both above and
michael@0 2914 * below content outside of the scroll box. We cannot create layers for these
michael@0 2915 * cases. This is accomplished by wrapping display items with
michael@0 2916 * nsDisplayScrollLayers. nsDisplayScrollLayers with the same scroll frame will
michael@0 2917 * be merged together. If more than one nsDisplayScrollLayer exists after
michael@0 2918 * merging, all nsDisplayScrollLayers will be flattened out so that no new
michael@0 2919 * layer is created at all.
michael@0 2920 */
michael@0 2921 class nsDisplayScrollLayer : public nsDisplayWrapList
michael@0 2922 {
michael@0 2923 public:
michael@0 2924 /**
michael@0 2925 * @param aScrolledFrame This will determine what the displayport is. It should be
michael@0 2926 * the root content frame of the scrolled area. Note
michael@0 2927 * that nsDisplayScrollLayer will expect for
michael@0 2928 * ScrollLayerCount to be defined on aScrolledFrame.
michael@0 2929 * @param aScrollFrame The viewport frame you see this content through.
michael@0 2930 */
michael@0 2931 nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
michael@0 2932 nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
michael@0 2933 nsIFrame* aScrollFrame);
michael@0 2934 nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
michael@0 2935 nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
michael@0 2936 nsIFrame* aScrollFrame);
michael@0 2937 nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
michael@0 2938 nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
michael@0 2939 nsIFrame* aScrollFrame);
michael@0 2940 NS_DISPLAY_DECL_NAME("ScrollLayer", TYPE_SCROLL_LAYER)
michael@0 2941
michael@0 2942 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 2943 virtual ~nsDisplayScrollLayer();
michael@0 2944 #endif
michael@0 2945
michael@0 2946 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 2947
michael@0 2948 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 2949 LayerManager* aManager,
michael@0 2950 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 2951
michael@0 2952 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 2953
michael@0 2954 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 2955 bool* aSnap) MOZ_OVERRIDE {
michael@0 2956 *aSnap = false;
michael@0 2957 return nsRegion();
michael@0 2958 }
michael@0 2959
michael@0 2960 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 2961 nsRegion* aVisibleRegion,
michael@0 2962 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 2963
michael@0 2964 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 2965 LayerManager* aManager,
michael@0 2966 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
michael@0 2967
michael@0 2968 virtual bool TryMerge(nsDisplayListBuilder* aBuilder,
michael@0 2969 nsDisplayItem* aItem) MOZ_OVERRIDE;
michael@0 2970
michael@0 2971 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 2972
michael@0 2973 // Get the number of nsDisplayScrollLayers for a scroll frame. Note that this
michael@0 2974 // number does not include nsDisplayScrollInfoLayers. If this number is not 1
michael@0 2975 // after merging, all the nsDisplayScrollLayers should flatten away.
michael@0 2976 intptr_t GetScrollLayerCount();
michael@0 2977
michael@0 2978 virtual nsIFrame* GetScrollFrame() { return mScrollFrame; }
michael@0 2979 virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; }
michael@0 2980
michael@0 2981 virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return false; }
michael@0 2982
michael@0 2983 #ifdef MOZ_DUMP_PAINTING
michael@0 2984 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE;
michael@0 2985 #endif
michael@0 2986
michael@0 2987 protected:
michael@0 2988 nsIFrame* mScrollFrame;
michael@0 2989 nsIFrame* mScrolledFrame;
michael@0 2990 ViewID mScrollParentId;
michael@0 2991 };
michael@0 2992
michael@0 2993 /**
michael@0 2994 * Like nsDisplayScrollLayer, but only has metadata on the scroll frame. This
michael@0 2995 * creates a layer that has no Thebes child layer, but still allows the
michael@0 2996 * compositor process to know of the scroll frame's existence.
michael@0 2997 *
michael@0 2998 * After visibility computation, nsDisplayScrollInfoLayers should only exist if
michael@0 2999 * nsDisplayScrollLayers were all flattened away.
michael@0 3000 *
michael@0 3001 * Important!! Add info layers to the bottom of the list so they are only
michael@0 3002 * considered after the others have flattened out!
michael@0 3003 */
michael@0 3004 class nsDisplayScrollInfoLayer : public nsDisplayScrollLayer
michael@0 3005 {
michael@0 3006 public:
michael@0 3007 nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder,
michael@0 3008 nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame);
michael@0 3009 NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER)
michael@0 3010
michael@0 3011 virtual ~nsDisplayScrollInfoLayer();
michael@0 3012
michael@0 3013 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 3014
michael@0 3015 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 3016 LayerManager* aManager,
michael@0 3017 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
michael@0 3018 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
michael@0 3019 { return true; }
michael@0 3020 virtual bool TryMerge(nsDisplayListBuilder* aBuilder,
michael@0 3021 nsDisplayItem* aItem) MOZ_OVERRIDE;
michael@0 3022
michael@0 3023 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 3024 };
michael@0 3025
michael@0 3026 /**
michael@0 3027 * nsDisplayZoom is used for subdocuments that have a different full zoom than
michael@0 3028 * their parent documents. This item creates a container layer.
michael@0 3029 */
michael@0 3030 class nsDisplayZoom : public nsDisplaySubDocument {
michael@0 3031 public:
michael@0 3032 /**
michael@0 3033 * @param aFrame is the root frame of the subdocument.
michael@0 3034 * @param aList contains the display items for the subdocument.
michael@0 3035 * @param aAPD is the app units per dev pixel ratio of the subdocument.
michael@0 3036 * @param aParentAPD is the app units per dev pixel ratio of the parent
michael@0 3037 * document.
michael@0 3038 * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
michael@0 3039 * Add UserData to the created ContainerLayer, so that invalidations
michael@0 3040 * for this layer are send to our nsPresContext.
michael@0 3041 */
michael@0 3042 nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 3043 nsDisplayList* aList,
michael@0 3044 int32_t aAPD, int32_t aParentAPD,
michael@0 3045 uint32_t aFlags = 0);
michael@0 3046 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 3047 virtual ~nsDisplayZoom();
michael@0 3048 #endif
michael@0 3049
michael@0 3050 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 3051 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
michael@0 3052 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 3053 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
michael@0 3054 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 3055 nsRegion* aVisibleRegion,
michael@0 3056 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 3057 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 3058 LayerManager* aManager,
michael@0 3059 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
michael@0 3060 {
michael@0 3061 return mozilla::LAYER_ACTIVE;
michael@0 3062 }
michael@0 3063 NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM)
michael@0 3064
michael@0 3065 // Get the app units per dev pixel ratio of the child document.
michael@0 3066 int32_t GetChildAppUnitsPerDevPixel() { return mAPD; }
michael@0 3067 // Get the app units per dev pixel ratio of the parent document.
michael@0 3068 int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD; }
michael@0 3069
michael@0 3070 private:
michael@0 3071 int32_t mAPD, mParentAPD;
michael@0 3072 };
michael@0 3073
michael@0 3074 /**
michael@0 3075 * A display item to paint a stacking context with effects
michael@0 3076 * set by the stacking context root frame's style.
michael@0 3077 */
michael@0 3078 class nsDisplaySVGEffects : public nsDisplayWrapList {
michael@0 3079 public:
michael@0 3080 nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
michael@0 3081 nsDisplayList* aList);
michael@0 3082 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 3083 virtual ~nsDisplaySVGEffects();
michael@0 3084 #endif
michael@0 3085
michael@0 3086 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 3087 bool* aSnap) MOZ_OVERRIDE;
michael@0 3088 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 3089 HitTestState* aState,
michael@0 3090 nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
michael@0 3091 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
michael@0 3092 bool* aSnap) MOZ_OVERRIDE {
michael@0 3093 *aSnap = false;
michael@0 3094 return mEffectsBounds + ToReferenceFrame();
michael@0 3095 }
michael@0 3096 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 3097 nsRegion* aVisibleRegion,
michael@0 3098 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 3099 virtual bool TryMerge(nsDisplayListBuilder* aBuilder,
michael@0 3100 nsDisplayItem* aItem) MOZ_OVERRIDE;
michael@0 3101 NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS)
michael@0 3102
michael@0 3103 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 3104 LayerManager* aManager,
michael@0 3105 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
michael@0 3106
michael@0 3107 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 3108 LayerManager* aManager,
michael@0 3109 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 3110
michael@0 3111 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 3112 const nsDisplayItemGeometry* aGeometry,
michael@0 3113 nsRegion* aInvalidRegion) MOZ_OVERRIDE
michael@0 3114 {
michael@0 3115 // We don't need to compute an invalidation region since we have LayerTreeInvalidation
michael@0 3116 }
michael@0 3117
michael@0 3118 void PaintAsLayer(nsDisplayListBuilder* aBuilder,
michael@0 3119 nsRenderingContext* aCtx,
michael@0 3120 LayerManager* aManager);
michael@0 3121
michael@0 3122 #ifdef MOZ_DUMP_PAINTING
michael@0 3123 void PrintEffects(nsACString& aTo);
michael@0 3124 #endif
michael@0 3125
michael@0 3126 private:
michael@0 3127 // relative to mFrame
michael@0 3128 nsRect mEffectsBounds;
michael@0 3129 };
michael@0 3130
michael@0 3131 /* A display item that applies a transformation to all of its descendant
michael@0 3132 * elements. This wrapper should only be used if there is a transform applied
michael@0 3133 * to the root element.
michael@0 3134 *
michael@0 3135 * The reason that a "bounds" rect is involved in transform calculations is
michael@0 3136 * because CSS-transforms allow percentage values for the x and y components
michael@0 3137 * of <translation-value>s, where percentages are percentages of the element's
michael@0 3138 * border box.
michael@0 3139 *
michael@0 3140 * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
michael@0 3141 * function.
michael@0 3142 * INVARIANT: The wrapped frame is non-null.
michael@0 3143 */
michael@0 3144 class nsDisplayTransform: public nsDisplayItem
michael@0 3145 {
michael@0 3146 public:
michael@0 3147 /**
michael@0 3148 * Returns a matrix (in pixels) for the current frame. The matrix should be relative to
michael@0 3149 * the current frame's coordinate space.
michael@0 3150 *
michael@0 3151 * @param aFrame The frame to compute the transform for.
michael@0 3152 * @param aAppUnitsPerPixel The number of app units per graphics unit.
michael@0 3153 */
michael@0 3154 typedef gfx3DMatrix (* ComputeTransformFunction)(nsIFrame* aFrame, float aAppUnitsPerPixel);
michael@0 3155
michael@0 3156 /* Constructor accepts a display list, empties it, and wraps it up. It also
michael@0 3157 * ferries the underlying frame to the nsDisplayItem constructor.
michael@0 3158 */
michael@0 3159 nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
michael@0 3160 nsDisplayList *aList, uint32_t aIndex = 0);
michael@0 3161 nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
michael@0 3162 nsDisplayItem *aItem, uint32_t aIndex = 0);
michael@0 3163 nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
michael@0 3164 nsDisplayList *aList, ComputeTransformFunction aTransformGetter, uint32_t aIndex = 0);
michael@0 3165
michael@0 3166 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 3167 virtual ~nsDisplayTransform()
michael@0 3168 {
michael@0 3169 MOZ_COUNT_DTOR(nsDisplayTransform);
michael@0 3170 }
michael@0 3171 #endif
michael@0 3172
michael@0 3173 NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM)
michael@0 3174
michael@0 3175 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
michael@0 3176 {
michael@0 3177 if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty())
michael@0 3178 return nsRect();
michael@0 3179 bool snap;
michael@0 3180 return GetBounds(aBuilder, &snap);
michael@0 3181 }
michael@0 3182
michael@0 3183 virtual nsDisplayList* GetChildren() MOZ_OVERRIDE { return mStoredList.GetChildren(); }
michael@0 3184
michael@0 3185 virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
michael@0 3186 HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
michael@0 3187 virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 3188 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
michael@0 3189 bool* aSnap) MOZ_OVERRIDE;
michael@0 3190 virtual bool IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor) MOZ_OVERRIDE;
michael@0 3191 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 3192 LayerManager* aManager,
michael@0 3193 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
michael@0 3194 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 3195 LayerManager* aManager,
michael@0 3196 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
michael@0 3197 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 3198 virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder,
michael@0 3199 nsRegion *aVisibleRegion,
michael@0 3200 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 3201 virtual bool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem) MOZ_OVERRIDE;
michael@0 3202
michael@0 3203 virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); }
michael@0 3204
michael@0 3205 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
michael@0 3206 const nsDisplayItemGeometry* aGeometry,
michael@0 3207 nsRegion* aInvalidRegion) MOZ_OVERRIDE
michael@0 3208 {
michael@0 3209 // We don't need to compute an invalidation region since we have LayerTreeInvalidation
michael@0 3210 }
michael@0 3211
michael@0 3212 virtual const nsIFrame* ReferenceFrameForChildren() const MOZ_OVERRIDE {
michael@0 3213 // If we were created using a transform-getter, then we don't
michael@0 3214 // belong to a transformed frame, and aren't a reference frame
michael@0 3215 // for our children.
michael@0 3216 if (!mTransformGetter) {
michael@0 3217 return mFrame;
michael@0 3218 }
michael@0 3219 return nsDisplayItem::ReferenceFrameForChildren();
michael@0 3220 }
michael@0 3221
michael@0 3222 enum {
michael@0 3223 INDEX_MAX = UINT32_MAX >> nsDisplayItem::TYPE_BITS
michael@0 3224 };
michael@0 3225
michael@0 3226 const gfx3DMatrix& GetTransform();
michael@0 3227
michael@0 3228 float GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint);
michael@0 3229
michael@0 3230 /**
michael@0 3231 * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
michael@0 3232 * space) and returns the smallest rectangle (in aFrame's coordinate space)
michael@0 3233 * containing the transformed image of that rectangle. That is, it takes
michael@0 3234 * the four corners of the rectangle, transforms them according to the
michael@0 3235 * matrix associated with the specified frame, then returns the smallest
michael@0 3236 * rectangle containing the four transformed points.
michael@0 3237 *
michael@0 3238 * @param untransformedBounds The rectangle (in app units) to transform.
michael@0 3239 * @param aFrame The frame whose transformation should be applied. This
michael@0 3240 * function raises an assertion if aFrame is null or doesn't have a
michael@0 3241 * transform applied to it.
michael@0 3242 * @param aOrigin The origin of the transform relative to aFrame's local
michael@0 3243 * coordinate space.
michael@0 3244 * @param aBoundsOverride (optional) Rather than using the frame's computed
michael@0 3245 * bounding rect as frame bounds, use this rectangle instead. Pass
michael@0 3246 * nullptr (or nothing at all) to use the default.
michael@0 3247 */
michael@0 3248 static nsRect TransformRect(const nsRect &aUntransformedBounds,
michael@0 3249 const nsIFrame* aFrame,
michael@0 3250 const nsPoint &aOrigin,
michael@0 3251 const nsRect* aBoundsOverride = nullptr);
michael@0 3252
michael@0 3253 static nsRect TransformRectOut(const nsRect &aUntransformedBounds,
michael@0 3254 const nsIFrame* aFrame,
michael@0 3255 const nsPoint &aOrigin,
michael@0 3256 const nsRect* aBoundsOverride = nullptr);
michael@0 3257
michael@0 3258 /* UntransformRect is like TransformRect, except that it inverts the
michael@0 3259 * transform.
michael@0 3260 */
michael@0 3261 static bool UntransformRect(const nsRect &aTransformedBounds,
michael@0 3262 const nsRect &aChildBounds,
michael@0 3263 const nsIFrame* aFrame,
michael@0 3264 const nsPoint &aOrigin,
michael@0 3265 nsRect *aOutRect);
michael@0 3266
michael@0 3267 bool UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
michael@0 3268 nsRect* aOutRect);
michael@0 3269
michael@0 3270 static gfxPoint3D GetDeltaToTransformOrigin(const nsIFrame* aFrame,
michael@0 3271 float aAppUnitsPerPixel,
michael@0 3272 const nsRect* aBoundsOverride);
michael@0 3273
michael@0 3274 static gfxPoint3D GetDeltaToPerspectiveOrigin(const nsIFrame* aFrame,
michael@0 3275 float aAppUnitsPerPixel);
michael@0 3276
michael@0 3277 /**
michael@0 3278 * Returns the bounds of a frame as defined for resolving percentage
michael@0 3279 * <translation-value>s in CSS transforms. If
michael@0 3280 * UNIFIED_CONTINUATIONS is not defined, this is simply the frame's bounding
michael@0 3281 * rectangle, translated to the origin. Otherwise, returns the smallest
michael@0 3282 * rectangle containing a frame and all of its continuations. For example,
michael@0 3283 * if there is a <span> element with several continuations split over
michael@0 3284 * several lines, this function will return the rectangle containing all of
michael@0 3285 * those continuations. This rectangle is relative to the origin of the
michael@0 3286 * frame's local coordinate space.
michael@0 3287 *
michael@0 3288 * @param aFrame The frame to get the bounding rect for.
michael@0 3289 * @return The frame's bounding rect, as described above.
michael@0 3290 */
michael@0 3291 static nsRect GetFrameBoundsForTransform(const nsIFrame* aFrame);
michael@0 3292
michael@0 3293 struct FrameTransformProperties
michael@0 3294 {
michael@0 3295 FrameTransformProperties(const nsIFrame* aFrame,
michael@0 3296 float aAppUnitsPerPixel,
michael@0 3297 const nsRect* aBoundsOverride);
michael@0 3298 FrameTransformProperties(nsCSSValueSharedList* aTransformList,
michael@0 3299 const gfxPoint3D& aToTransformOrigin,
michael@0 3300 const gfxPoint3D& aToPerspectiveOrigin,
michael@0 3301 nscoord aChildPerspective)
michael@0 3302 : mFrame(nullptr)
michael@0 3303 , mTransformList(aTransformList)
michael@0 3304 , mToTransformOrigin(aToTransformOrigin)
michael@0 3305 , mToPerspectiveOrigin(aToPerspectiveOrigin)
michael@0 3306 , mChildPerspective(aChildPerspective)
michael@0 3307 {}
michael@0 3308
michael@0 3309 const nsIFrame* mFrame;
michael@0 3310 nsRefPtr<nsCSSValueSharedList> mTransformList;
michael@0 3311 const gfxPoint3D mToTransformOrigin;
michael@0 3312 const gfxPoint3D mToPerspectiveOrigin;
michael@0 3313 nscoord mChildPerspective;
michael@0 3314 };
michael@0 3315
michael@0 3316 /**
michael@0 3317 * Given a frame with the -moz-transform property or an SVG transform,
michael@0 3318 * returns the transformation matrix for that frame.
michael@0 3319 *
michael@0 3320 * @param aFrame The frame to get the matrix from.
michael@0 3321 * @param aOrigin Relative to which point this transform should be applied.
michael@0 3322 * @param aAppUnitsPerPixel The number of app units per graphics unit.
michael@0 3323 * @param aBoundsOverride [optional] If this is nullptr (the default), the
michael@0 3324 * computation will use the value of GetFrameBoundsForTransform(aFrame)
michael@0 3325 * for the frame's bounding rectangle. Otherwise, it will use the
michael@0 3326 * value of aBoundsOverride. This is mostly for internal use and in
michael@0 3327 * most cases you will not need to specify a value.
michael@0 3328 */
michael@0 3329 static gfx3DMatrix GetResultingTransformMatrix(const nsIFrame* aFrame,
michael@0 3330 const nsPoint& aOrigin,
michael@0 3331 float aAppUnitsPerPixel,
michael@0 3332 const nsRect* aBoundsOverride = nullptr,
michael@0 3333 nsIFrame** aOutAncestor = nullptr);
michael@0 3334 static gfx3DMatrix GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
michael@0 3335 const nsPoint& aOrigin,
michael@0 3336 float aAppUnitsPerPixel,
michael@0 3337 const nsRect* aBoundsOverride = nullptr,
michael@0 3338 nsIFrame** aOutAncestor = nullptr);
michael@0 3339 /**
michael@0 3340 * Return true when we should try to prerender the entire contents of the
michael@0 3341 * transformed frame even when it's not completely visible (yet).
michael@0 3342 */
michael@0 3343 static bool ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
michael@0 3344 nsIFrame* aFrame,
michael@0 3345 bool aLogAnimations = false);
michael@0 3346 bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
michael@0 3347
michael@0 3348 virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return false; }
michael@0 3349
michael@0 3350 private:
michael@0 3351 static gfx3DMatrix GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
michael@0 3352 const nsPoint& aOrigin,
michael@0 3353 float aAppUnitsPerPixel,
michael@0 3354 const nsRect* aBoundsOverride,
michael@0 3355 nsIFrame** aOutAncestor);
michael@0 3356
michael@0 3357 nsDisplayWrapList mStoredList;
michael@0 3358 gfx3DMatrix mTransform;
michael@0 3359 ComputeTransformFunction mTransformGetter;
michael@0 3360 uint32_t mIndex;
michael@0 3361 };
michael@0 3362
michael@0 3363 /**
michael@0 3364 * This class adds basic support for limiting the rendering to the part inside
michael@0 3365 * the specified edges. It's a base class for the display item classes that
michael@0 3366 * does the actual work. The two members, mLeftEdge and mRightEdge, are
michael@0 3367 * relative to the edges of the frame's scrollable overflow rectangle and is
michael@0 3368 * the amount to suppress on each side.
michael@0 3369 *
michael@0 3370 * Setting none, both or only one edge is allowed.
michael@0 3371 * The values must be non-negative.
michael@0 3372 * The default value for both edges is zero, which means everything is painted.
michael@0 3373 */
michael@0 3374 class nsCharClipDisplayItem : public nsDisplayItem {
michael@0 3375 public:
michael@0 3376 nsCharClipDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
michael@0 3377 : nsDisplayItem(aBuilder, aFrame), mLeftEdge(0), mRightEdge(0) {}
michael@0 3378
michael@0 3379 nsCharClipDisplayItem(nsIFrame* aFrame)
michael@0 3380 : nsDisplayItem(aFrame) {}
michael@0 3381
michael@0 3382 struct ClipEdges {
michael@0 3383 ClipEdges(const nsDisplayItem& aItem,
michael@0 3384 nscoord aLeftEdge, nscoord aRightEdge) {
michael@0 3385 nsRect r = aItem.Frame()->GetScrollableOverflowRect() +
michael@0 3386 aItem.ToReferenceFrame();
michael@0 3387 mX = aLeftEdge > 0 ? r.x + aLeftEdge : nscoord_MIN;
michael@0 3388 mXMost = aRightEdge > 0 ? std::max(r.XMost() - aRightEdge, mX) : nscoord_MAX;
michael@0 3389 }
michael@0 3390 void Intersect(nscoord* aX, nscoord* aWidth) const {
michael@0 3391 nscoord xmost1 = *aX + *aWidth;
michael@0 3392 *aX = std::max(*aX, mX);
michael@0 3393 *aWidth = std::max(std::min(xmost1, mXMost) - *aX, 0);
michael@0 3394 }
michael@0 3395 nscoord mX;
michael@0 3396 nscoord mXMost;
michael@0 3397 };
michael@0 3398
michael@0 3399 ClipEdges Edges() const { return ClipEdges(*this, mLeftEdge, mRightEdge); }
michael@0 3400
michael@0 3401 static nsCharClipDisplayItem* CheckCast(nsDisplayItem* aItem) {
michael@0 3402 nsDisplayItem::Type t = aItem->GetType();
michael@0 3403 return (t == nsDisplayItem::TYPE_TEXT ||
michael@0 3404 t == nsDisplayItem::TYPE_TEXT_DECORATION ||
michael@0 3405 t == nsDisplayItem::TYPE_TEXT_SHADOW)
michael@0 3406 ? static_cast<nsCharClipDisplayItem*>(aItem) : nullptr;
michael@0 3407 }
michael@0 3408
michael@0 3409 nscoord mLeftEdge; // length from the left side
michael@0 3410 nscoord mRightEdge; // length from the right side
michael@0 3411 };
michael@0 3412
michael@0 3413 #endif /*NSDISPLAYLIST_H_*/

mercurial