Thu, 22 Jan 2015 13:21:57 +0100
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_*/ |