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 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef nsLayoutUtils_h__ |
michael@0 | 7 | #define nsLayoutUtils_h__ |
michael@0 | 8 | |
michael@0 | 9 | #include "mozilla/MemoryReporting.h" |
michael@0 | 10 | #include "nsChangeHint.h" |
michael@0 | 11 | #include "nsAutoPtr.h" |
michael@0 | 12 | #include "nsFrameList.h" |
michael@0 | 13 | #include "mozilla/layout/FrameChildList.h" |
michael@0 | 14 | #include "nsThreadUtils.h" |
michael@0 | 15 | #include "nsIPrincipal.h" |
michael@0 | 16 | #include "GraphicsFilter.h" |
michael@0 | 17 | #include "nsCSSPseudoElements.h" |
michael@0 | 18 | #include "FrameMetrics.h" |
michael@0 | 19 | #include "gfx3DMatrix.h" |
michael@0 | 20 | #include "nsIWidget.h" |
michael@0 | 21 | #include "nsCSSProperty.h" |
michael@0 | 22 | #include "nsStyleCoord.h" |
michael@0 | 23 | #include "nsStyleConsts.h" |
michael@0 | 24 | #include "nsGkAtoms.h" |
michael@0 | 25 | #include "nsRuleNode.h" |
michael@0 | 26 | #include "imgIContainer.h" |
michael@0 | 27 | #include "mozilla/gfx/2D.h" |
michael@0 | 28 | #include "Units.h" |
michael@0 | 29 | |
michael@0 | 30 | #include <limits> |
michael@0 | 31 | #include <algorithm> |
michael@0 | 32 | |
michael@0 | 33 | class nsIFormControlFrame; |
michael@0 | 34 | class nsPresContext; |
michael@0 | 35 | class nsIContent; |
michael@0 | 36 | class nsIAtom; |
michael@0 | 37 | class nsIScrollableFrame; |
michael@0 | 38 | class nsIDOMEvent; |
michael@0 | 39 | class nsRegion; |
michael@0 | 40 | class nsDisplayListBuilder; |
michael@0 | 41 | class nsDisplayItem; |
michael@0 | 42 | class nsFontMetrics; |
michael@0 | 43 | class nsFontFaceList; |
michael@0 | 44 | class nsIImageLoadingContent; |
michael@0 | 45 | class nsStyleContext; |
michael@0 | 46 | class nsBlockFrame; |
michael@0 | 47 | class gfxASurface; |
michael@0 | 48 | class gfxDrawable; |
michael@0 | 49 | class nsView; |
michael@0 | 50 | class nsIFrame; |
michael@0 | 51 | class nsStyleCoord; |
michael@0 | 52 | class nsStyleCorners; |
michael@0 | 53 | class gfxContext; |
michael@0 | 54 | class nsPIDOMWindow; |
michael@0 | 55 | class imgIRequest; |
michael@0 | 56 | class nsIDocument; |
michael@0 | 57 | class gfxPoint; |
michael@0 | 58 | struct nsStyleFont; |
michael@0 | 59 | struct nsStyleImageOrientation; |
michael@0 | 60 | struct nsOverflowAreas; |
michael@0 | 61 | |
michael@0 | 62 | namespace mozilla { |
michael@0 | 63 | class SVGImageContext; |
michael@0 | 64 | struct IntrinsicSize; |
michael@0 | 65 | struct ContainerLayerParameters; |
michael@0 | 66 | namespace dom { |
michael@0 | 67 | class DOMRectList; |
michael@0 | 68 | class Element; |
michael@0 | 69 | class HTMLImageElement; |
michael@0 | 70 | class HTMLCanvasElement; |
michael@0 | 71 | class HTMLVideoElement; |
michael@0 | 72 | } // namespace dom |
michael@0 | 73 | namespace layers { |
michael@0 | 74 | class Layer; |
michael@0 | 75 | } |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | namespace mozilla { |
michael@0 | 79 | |
michael@0 | 80 | struct DisplayPortPropertyData { |
michael@0 | 81 | DisplayPortPropertyData(const nsRect& aRect, uint32_t aPriority) |
michael@0 | 82 | : mRect(aRect) |
michael@0 | 83 | , mPriority(aPriority) |
michael@0 | 84 | {} |
michael@0 | 85 | nsRect mRect; |
michael@0 | 86 | uint32_t mPriority; |
michael@0 | 87 | }; |
michael@0 | 88 | |
michael@0 | 89 | struct DisplayPortMarginsPropertyData { |
michael@0 | 90 | DisplayPortMarginsPropertyData(const LayerMargin& aMargins, |
michael@0 | 91 | uint32_t aAlignmentX, uint32_t aAlignmentY, |
michael@0 | 92 | uint32_t aPriority) |
michael@0 | 93 | : mMargins(aMargins) |
michael@0 | 94 | , mAlignmentX(aAlignmentX) |
michael@0 | 95 | , mAlignmentY(aAlignmentY) |
michael@0 | 96 | , mPriority(aPriority) |
michael@0 | 97 | {} |
michael@0 | 98 | LayerMargin mMargins; |
michael@0 | 99 | uint32_t mAlignmentX; |
michael@0 | 100 | uint32_t mAlignmentY; |
michael@0 | 101 | uint32_t mPriority; |
michael@0 | 102 | }; |
michael@0 | 103 | |
michael@0 | 104 | template <class AnimationsOrTransitions> |
michael@0 | 105 | extern AnimationsOrTransitions* HasAnimationOrTransition(nsIContent* aContent, |
michael@0 | 106 | nsIAtom* aAnimationProperty, |
michael@0 | 107 | nsCSSProperty aProperty); |
michael@0 | 108 | |
michael@0 | 109 | } // namespace mozilla |
michael@0 | 110 | |
michael@0 | 111 | /** |
michael@0 | 112 | * nsLayoutUtils is a namespace class used for various helper |
michael@0 | 113 | * functions that are useful in multiple places in layout. The goal |
michael@0 | 114 | * is not to define multiple copies of the same static helper. |
michael@0 | 115 | */ |
michael@0 | 116 | class nsLayoutUtils |
michael@0 | 117 | { |
michael@0 | 118 | typedef ::GraphicsFilter GraphicsFilter; |
michael@0 | 119 | typedef mozilla::dom::DOMRectList DOMRectList; |
michael@0 | 120 | typedef mozilla::layers::Layer Layer; |
michael@0 | 121 | typedef mozilla::ContainerLayerParameters ContainerLayerParameters; |
michael@0 | 122 | typedef mozilla::gfx::SourceSurface SourceSurface; |
michael@0 | 123 | typedef mozilla::gfx::DrawTarget DrawTarget; |
michael@0 | 124 | typedef mozilla::gfx::Rect Rect; |
michael@0 | 125 | |
michael@0 | 126 | public: |
michael@0 | 127 | typedef mozilla::layers::FrameMetrics FrameMetrics; |
michael@0 | 128 | typedef FrameMetrics::ViewID ViewID; |
michael@0 | 129 | typedef mozilla::CSSPoint CSSPoint; |
michael@0 | 130 | typedef mozilla::CSSSize CSSSize; |
michael@0 | 131 | typedef mozilla::LayerMargin LayerMargin; |
michael@0 | 132 | |
michael@0 | 133 | /** |
michael@0 | 134 | * Finds previously assigned ViewID for the given content element, if any. |
michael@0 | 135 | * Returns whether a ViewID was previously assigned. |
michael@0 | 136 | */ |
michael@0 | 137 | static bool FindIDFor(const nsIContent* aContent, ViewID* aOutViewId); |
michael@0 | 138 | |
michael@0 | 139 | /** |
michael@0 | 140 | * Finds previously assigned or generates a unique ViewID for the given |
michael@0 | 141 | * content element. |
michael@0 | 142 | */ |
michael@0 | 143 | static ViewID FindOrCreateIDFor(nsIContent* aContent); |
michael@0 | 144 | |
michael@0 | 145 | /** |
michael@0 | 146 | * Find content for given ID. |
michael@0 | 147 | */ |
michael@0 | 148 | static nsIContent* FindContentFor(ViewID aId); |
michael@0 | 149 | |
michael@0 | 150 | /** |
michael@0 | 151 | * Find the scrollable frame for a given ID. |
michael@0 | 152 | */ |
michael@0 | 153 | static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId); |
michael@0 | 154 | |
michael@0 | 155 | /** |
michael@0 | 156 | * Get display port for the given element. |
michael@0 | 157 | */ |
michael@0 | 158 | static bool GetDisplayPort(nsIContent* aContent, nsRect *aResult = nullptr); |
michael@0 | 159 | |
michael@0 | 160 | MOZ_BEGIN_NESTED_ENUM_CLASS(RepaintMode, uint8_t) |
michael@0 | 161 | Repaint, |
michael@0 | 162 | DoNotRepaint |
michael@0 | 163 | MOZ_END_NESTED_ENUM_CLASS(RepaintMode) |
michael@0 | 164 | |
michael@0 | 165 | /** |
michael@0 | 166 | * Set the display port margins for a content element to be used with a |
michael@0 | 167 | * display port base (see SetDisplayPortBase()). |
michael@0 | 168 | * See also nsIDOMWindowUtils.setDisplayPortMargins. |
michael@0 | 169 | * @param aContent the content element for which to set the margins |
michael@0 | 170 | * @param aPresShell the pres shell for the document containing the element |
michael@0 | 171 | * @param aMargins the margins to set |
michael@0 | 172 | * @param aAlignmentX, alignmentY the amount of pixels to which to align the |
michael@0 | 173 | * displayport built by combining the base |
michael@0 | 174 | * rect with the margins, in either direction |
michael@0 | 175 | * @param aPriority a priority value to determine which margins take effect |
michael@0 | 176 | * when multiple callers specify margins |
michael@0 | 177 | * @param aRepaintMode whether to schedule a paint after setting the margins |
michael@0 | 178 | */ |
michael@0 | 179 | static void SetDisplayPortMargins(nsIContent* aContent, |
michael@0 | 180 | nsIPresShell* aPresShell, |
michael@0 | 181 | const LayerMargin& aMargins, |
michael@0 | 182 | uint32_t aAlignmentX, |
michael@0 | 183 | uint32_t aAlignmentY, |
michael@0 | 184 | uint32_t aPriority = 0, |
michael@0 | 185 | RepaintMode aRepaintMode = RepaintMode::Repaint); |
michael@0 | 186 | |
michael@0 | 187 | /** |
michael@0 | 188 | * Set the display port base rect for given element to be used with display |
michael@0 | 189 | * port margins. |
michael@0 | 190 | * SetDisplayPortBaseIfNotSet is like SetDisplayPortBase except it only sets |
michael@0 | 191 | * the display port base to aBase if no display port base is currently set. |
michael@0 | 192 | */ |
michael@0 | 193 | static void SetDisplayPortBase(nsIContent* aContent, const nsRect& aBase); |
michael@0 | 194 | static void SetDisplayPortBaseIfNotSet(nsIContent* aContent, const nsRect& aBase); |
michael@0 | 195 | |
michael@0 | 196 | /** |
michael@0 | 197 | * Get the critical display port for the given element. |
michael@0 | 198 | */ |
michael@0 | 199 | static bool GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult = nullptr); |
michael@0 | 200 | |
michael@0 | 201 | /** |
michael@0 | 202 | * Use heuristics to figure out the child list that |
michael@0 | 203 | * aChildFrame is currently in. |
michael@0 | 204 | */ |
michael@0 | 205 | static mozilla::layout::FrameChildListID GetChildListNameFor(nsIFrame* aChildFrame); |
michael@0 | 206 | |
michael@0 | 207 | /** |
michael@0 | 208 | * GetBeforeFrame returns the outermost :before frame of the given frame, if |
michael@0 | 209 | * one exists. This is typically O(1). The frame passed in must be |
michael@0 | 210 | * the first-in-flow. |
michael@0 | 211 | * |
michael@0 | 212 | * @param aFrame the frame whose :before is wanted |
michael@0 | 213 | * @return the :before frame or nullptr if there isn't one |
michael@0 | 214 | */ |
michael@0 | 215 | static nsIFrame* GetBeforeFrame(nsIFrame* aFrame); |
michael@0 | 216 | |
michael@0 | 217 | /** |
michael@0 | 218 | * GetAfterFrame returns the outermost :after frame of the given frame, if one |
michael@0 | 219 | * exists. This will walk the in-flow chain to the last-in-flow if |
michael@0 | 220 | * needed. This function is typically O(N) in the number of child |
michael@0 | 221 | * frames, following in-flows, etc. |
michael@0 | 222 | * |
michael@0 | 223 | * @param aFrame the frame whose :after is wanted |
michael@0 | 224 | * @return the :after frame or nullptr if there isn't one |
michael@0 | 225 | */ |
michael@0 | 226 | static nsIFrame* GetAfterFrame(nsIFrame* aFrame); |
michael@0 | 227 | |
michael@0 | 228 | /** |
michael@0 | 229 | * Given a frame, search up the frame tree until we find an |
michael@0 | 230 | * ancestor that (or the frame itself) is of type aFrameType, if any. |
michael@0 | 231 | * |
michael@0 | 232 | * @param aFrame the frame to start at |
michael@0 | 233 | * @param aFrameType the frame type to look for |
michael@0 | 234 | * @return a frame of the given type or nullptr if no |
michael@0 | 235 | * such ancestor exists |
michael@0 | 236 | */ |
michael@0 | 237 | static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame, nsIAtom* aFrameType); |
michael@0 | 238 | |
michael@0 | 239 | /** |
michael@0 | 240 | * Given a frame, search up the frame tree until we find an |
michael@0 | 241 | * ancestor that (or the frame itself) is a "Page" frame, if any. |
michael@0 | 242 | * |
michael@0 | 243 | * @param aFrame the frame to start at |
michael@0 | 244 | * @return a frame of type nsGkAtoms::pageFrame or nullptr if no |
michael@0 | 245 | * such ancestor exists |
michael@0 | 246 | */ |
michael@0 | 247 | static nsIFrame* GetPageFrame(nsIFrame* aFrame) |
michael@0 | 248 | { |
michael@0 | 249 | return GetClosestFrameOfType(aFrame, nsGkAtoms::pageFrame); |
michael@0 | 250 | } |
michael@0 | 251 | |
michael@0 | 252 | /** |
michael@0 | 253 | * Given a frame which is the primary frame for an element, |
michael@0 | 254 | * return the frame that has the non-psuedoelement style context for |
michael@0 | 255 | * the content. |
michael@0 | 256 | * This is aPrimaryFrame itself except for tableOuter frames. |
michael@0 | 257 | */ |
michael@0 | 258 | static nsIFrame* GetStyleFrame(nsIFrame* aPrimaryFrame); |
michael@0 | 259 | |
michael@0 | 260 | /** |
michael@0 | 261 | * Given a content node, |
michael@0 | 262 | * return the frame that has the non-psuedoelement style context for |
michael@0 | 263 | * the content. May return null. |
michael@0 | 264 | * This is aContent->GetPrimaryFrame() except for tableOuter frames. |
michael@0 | 265 | */ |
michael@0 | 266 | static nsIFrame* GetStyleFrame(const nsIContent* aContent); |
michael@0 | 267 | |
michael@0 | 268 | /** |
michael@0 | 269 | * IsGeneratedContentFor returns true if aFrame is the outermost |
michael@0 | 270 | * frame for generated content of type aPseudoElement for aContent. |
michael@0 | 271 | * aFrame *might not* have the aPseudoElement pseudo-style! For example |
michael@0 | 272 | * it might be a table outer frame and the inner table frame might |
michael@0 | 273 | * have the pseudo-style. |
michael@0 | 274 | * |
michael@0 | 275 | * @param aContent the content node we're looking at. If this is |
michael@0 | 276 | * null, then we just assume that aFrame has the right content |
michael@0 | 277 | * pointer. |
michael@0 | 278 | * @param aFrame the frame we're looking at |
michael@0 | 279 | * @param aPseudoElement the pseudo type we're interested in |
michael@0 | 280 | * @return whether aFrame is the generated aPseudoElement frame for aContent |
michael@0 | 281 | */ |
michael@0 | 282 | static bool IsGeneratedContentFor(nsIContent* aContent, nsIFrame* aFrame, |
michael@0 | 283 | nsIAtom* aPseudoElement); |
michael@0 | 284 | |
michael@0 | 285 | #ifdef DEBUG |
michael@0 | 286 | // TODO: remove, see bug 598468. |
michael@0 | 287 | static bool gPreventAssertInCompareTreePosition; |
michael@0 | 288 | #endif // DEBUG |
michael@0 | 289 | |
michael@0 | 290 | /** |
michael@0 | 291 | * CompareTreePosition determines whether aContent1 comes before or |
michael@0 | 292 | * after aContent2 in a preorder traversal of the content tree. |
michael@0 | 293 | * |
michael@0 | 294 | * @param aCommonAncestor either null, or a common ancestor of |
michael@0 | 295 | * aContent1 and aContent2. Actually this is |
michael@0 | 296 | * only a hint; if it's not an ancestor of |
michael@0 | 297 | * aContent1 or aContent2, this function will |
michael@0 | 298 | * still work, but it will be slower than |
michael@0 | 299 | * normal. |
michael@0 | 300 | * @return < 0 if aContent1 is before aContent2 |
michael@0 | 301 | * > 0 if aContent1 is after aContent2, |
michael@0 | 302 | * 0 otherwise (meaning they're the same, or they're in |
michael@0 | 303 | * different documents) |
michael@0 | 304 | */ |
michael@0 | 305 | static int32_t CompareTreePosition(nsIContent* aContent1, |
michael@0 | 306 | nsIContent* aContent2, |
michael@0 | 307 | const nsIContent* aCommonAncestor = nullptr) |
michael@0 | 308 | { |
michael@0 | 309 | return DoCompareTreePosition(aContent1, aContent2, -1, 1, aCommonAncestor); |
michael@0 | 310 | } |
michael@0 | 311 | |
michael@0 | 312 | /* |
michael@0 | 313 | * More generic version of |CompareTreePosition|. |aIf1Ancestor| |
michael@0 | 314 | * gives the value to return when 1 is an ancestor of 2, and likewise |
michael@0 | 315 | * for |aIf2Ancestor|. Passing (-1, 1) gives preorder traversal |
michael@0 | 316 | * order, and (1, -1) gives postorder traversal order. |
michael@0 | 317 | */ |
michael@0 | 318 | static int32_t DoCompareTreePosition(nsIContent* aContent1, |
michael@0 | 319 | nsIContent* aContent2, |
michael@0 | 320 | int32_t aIf1Ancestor, |
michael@0 | 321 | int32_t aIf2Ancestor, |
michael@0 | 322 | const nsIContent* aCommonAncestor = nullptr); |
michael@0 | 323 | |
michael@0 | 324 | /** |
michael@0 | 325 | * CompareTreePosition determines whether aFrame1 comes before or |
michael@0 | 326 | * after aFrame2 in a preorder traversal of the frame tree, where out |
michael@0 | 327 | * of flow frames are treated as children of their placeholders. This is |
michael@0 | 328 | * basically the same ordering as DoCompareTreePosition(nsIContent*) except |
michael@0 | 329 | * that it handles anonymous content properly and there are subtleties with |
michael@0 | 330 | * continuations. |
michael@0 | 331 | * |
michael@0 | 332 | * @param aCommonAncestor either null, or a common ancestor of |
michael@0 | 333 | * aContent1 and aContent2. Actually this is |
michael@0 | 334 | * only a hint; if it's not an ancestor of |
michael@0 | 335 | * aContent1 or aContent2, this function will |
michael@0 | 336 | * still work, but it will be slower than |
michael@0 | 337 | * normal. |
michael@0 | 338 | * @return < 0 if aContent1 is before aContent2 |
michael@0 | 339 | * > 0 if aContent1 is after aContent2, |
michael@0 | 340 | * 0 otherwise (meaning they're the same, or they're in |
michael@0 | 341 | * different frame trees) |
michael@0 | 342 | */ |
michael@0 | 343 | static int32_t CompareTreePosition(nsIFrame* aFrame1, |
michael@0 | 344 | nsIFrame* aFrame2, |
michael@0 | 345 | nsIFrame* aCommonAncestor = nullptr) |
michael@0 | 346 | { |
michael@0 | 347 | return DoCompareTreePosition(aFrame1, aFrame2, -1, 1, aCommonAncestor); |
michael@0 | 348 | } |
michael@0 | 349 | |
michael@0 | 350 | static int32_t CompareTreePosition(nsIFrame* aFrame1, |
michael@0 | 351 | nsIFrame* aFrame2, |
michael@0 | 352 | nsTArray<nsIFrame*>& aFrame2Ancestors, |
michael@0 | 353 | nsIFrame* aCommonAncestor = nullptr) |
michael@0 | 354 | { |
michael@0 | 355 | return DoCompareTreePosition(aFrame1, aFrame2, aFrame2Ancestors, |
michael@0 | 356 | -1, 1, aCommonAncestor); |
michael@0 | 357 | } |
michael@0 | 358 | |
michael@0 | 359 | /* |
michael@0 | 360 | * More generic version of |CompareTreePosition|. |aIf1Ancestor| |
michael@0 | 361 | * gives the value to return when 1 is an ancestor of 2, and likewise |
michael@0 | 362 | * for |aIf2Ancestor|. Passing (-1, 1) gives preorder traversal |
michael@0 | 363 | * order, and (1, -1) gives postorder traversal order. |
michael@0 | 364 | */ |
michael@0 | 365 | static int32_t DoCompareTreePosition(nsIFrame* aFrame1, |
michael@0 | 366 | nsIFrame* aFrame2, |
michael@0 | 367 | int32_t aIf1Ancestor, |
michael@0 | 368 | int32_t aIf2Ancestor, |
michael@0 | 369 | nsIFrame* aCommonAncestor = nullptr); |
michael@0 | 370 | |
michael@0 | 371 | static nsIFrame* FillAncestors(nsIFrame* aFrame, |
michael@0 | 372 | nsIFrame* aStopAtAncestor, |
michael@0 | 373 | nsTArray<nsIFrame*>* aAncestors); |
michael@0 | 374 | |
michael@0 | 375 | static int32_t DoCompareTreePosition(nsIFrame* aFrame1, |
michael@0 | 376 | nsIFrame* aFrame2, |
michael@0 | 377 | nsTArray<nsIFrame*>& aFrame2Ancestors, |
michael@0 | 378 | int32_t aIf1Ancestor, |
michael@0 | 379 | int32_t aIf2Ancestor, |
michael@0 | 380 | nsIFrame* aCommonAncestor); |
michael@0 | 381 | |
michael@0 | 382 | /** |
michael@0 | 383 | * LastContinuationWithChild gets the last continuation in aFrame's chain |
michael@0 | 384 | * that has a child, or the first continuation if the frame has no children. |
michael@0 | 385 | */ |
michael@0 | 386 | static nsIFrame* LastContinuationWithChild(nsIFrame* aFrame); |
michael@0 | 387 | |
michael@0 | 388 | /** |
michael@0 | 389 | * GetLastSibling simply finds the last sibling of aFrame, or returns nullptr if |
michael@0 | 390 | * aFrame is null. |
michael@0 | 391 | */ |
michael@0 | 392 | static nsIFrame* GetLastSibling(nsIFrame* aFrame); |
michael@0 | 393 | |
michael@0 | 394 | /** |
michael@0 | 395 | * FindSiblingViewFor locates the child of aParentView that aFrame's |
michael@0 | 396 | * view should be inserted 'above' (i.e., before in sibling view |
michael@0 | 397 | * order). This is the first child view of aParentView whose |
michael@0 | 398 | * corresponding content is before aFrame's content (view siblings |
michael@0 | 399 | * are in reverse content order). |
michael@0 | 400 | */ |
michael@0 | 401 | static nsView* FindSiblingViewFor(nsView* aParentView, nsIFrame* aFrame); |
michael@0 | 402 | |
michael@0 | 403 | /** |
michael@0 | 404 | * Get the parent of aFrame. If aFrame is the root frame for a document, |
michael@0 | 405 | * and the document has a parent document in the same view hierarchy, then |
michael@0 | 406 | * we try to return the subdocumentframe in the parent document. |
michael@0 | 407 | * @param aExtraOffset [in/out] if non-null, then as we cross documents |
michael@0 | 408 | * an extra offset may be required and it will be added to aCrossDocOffset. |
michael@0 | 409 | * Be careful dealing with this extra offset as it is in app units of the |
michael@0 | 410 | * parent document, which may have a different app units per dev pixel ratio |
michael@0 | 411 | * than the child document. |
michael@0 | 412 | */ |
michael@0 | 413 | static nsIFrame* GetCrossDocParentFrame(const nsIFrame* aFrame, |
michael@0 | 414 | nsPoint* aCrossDocOffset = nullptr); |
michael@0 | 415 | |
michael@0 | 416 | /** |
michael@0 | 417 | * IsProperAncestorFrame checks whether aAncestorFrame is an ancestor |
michael@0 | 418 | * of aFrame and not equal to aFrame. |
michael@0 | 419 | * @param aCommonAncestor nullptr, or a common ancestor of aFrame and |
michael@0 | 420 | * aAncestorFrame. If non-null, this can bound the search and speed up |
michael@0 | 421 | * the function |
michael@0 | 422 | */ |
michael@0 | 423 | static bool IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame, |
michael@0 | 424 | nsIFrame* aCommonAncestor = nullptr); |
michael@0 | 425 | |
michael@0 | 426 | /** |
michael@0 | 427 | * Like IsProperAncestorFrame, but looks across document boundaries. |
michael@0 | 428 | * |
michael@0 | 429 | * Just like IsAncestorFrameCrossDoc, except that it returns false when |
michael@0 | 430 | * aFrame == aAncestorFrame. |
michael@0 | 431 | */ |
michael@0 | 432 | static bool IsProperAncestorFrameCrossDoc(nsIFrame* aAncestorFrame, nsIFrame* aFrame, |
michael@0 | 433 | nsIFrame* aCommonAncestor = nullptr); |
michael@0 | 434 | |
michael@0 | 435 | /** |
michael@0 | 436 | * IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor |
michael@0 | 437 | * of aFrame or equal to aFrame, looking across document boundaries. |
michael@0 | 438 | * @param aCommonAncestor nullptr, or a common ancestor of aFrame and |
michael@0 | 439 | * aAncestorFrame. If non-null, this can bound the search and speed up |
michael@0 | 440 | * the function. |
michael@0 | 441 | * |
michael@0 | 442 | * Just like IsProperAncestorFrameCrossDoc, except that it returns true when |
michael@0 | 443 | * aFrame == aAncestorFrame. |
michael@0 | 444 | */ |
michael@0 | 445 | static bool IsAncestorFrameCrossDoc(const nsIFrame* aAncestorFrame, const nsIFrame* aFrame, |
michael@0 | 446 | const nsIFrame* aCommonAncestor = nullptr); |
michael@0 | 447 | |
michael@0 | 448 | /** |
michael@0 | 449 | * Sets the fixed-pos metadata properties on aLayer. |
michael@0 | 450 | * aAnchorRect is the basic anchor rectangle. If aFixedPosFrame is not a viewport |
michael@0 | 451 | * frame, then we pick a corner of aAnchorRect to as the anchor point for the |
michael@0 | 452 | * fixed-pos layer (i.e. the point to remain stable during zooming), based |
michael@0 | 453 | * on which of the fixed-pos frame's CSS absolute positioning offset |
michael@0 | 454 | * properties (top, left, right, bottom) are auto. aAnchorRect is in the |
michael@0 | 455 | * coordinate space of aLayer's container layer (i.e. relative to the reference |
michael@0 | 456 | * frame of the display item which is building aLayer's container layer). |
michael@0 | 457 | */ |
michael@0 | 458 | static void SetFixedPositionLayerData(Layer* aLayer, const nsIFrame* aViewportFrame, |
michael@0 | 459 | const nsRect& aAnchorRect, |
michael@0 | 460 | const nsIFrame* aFixedPosFrame, |
michael@0 | 461 | nsPresContext* aPresContext, |
michael@0 | 462 | const ContainerLayerParameters& aContainerParameters); |
michael@0 | 463 | |
michael@0 | 464 | /** |
michael@0 | 465 | * Return true if aPresContext's viewport has a displayport. |
michael@0 | 466 | * Fills in aDisplayPort with the displayport rectangle if non-null. |
michael@0 | 467 | */ |
michael@0 | 468 | static bool ViewportHasDisplayPort(nsPresContext* aPresContext, |
michael@0 | 469 | nsRect* aDisplayPort = nullptr); |
michael@0 | 470 | |
michael@0 | 471 | /** |
michael@0 | 472 | * Return true if aFrame is a fixed-pos frame and is a child of a viewport |
michael@0 | 473 | * which has a displayport. These frames get special treatment from the compositor. |
michael@0 | 474 | * aDisplayPort, if non-null, is set to the display port rectangle (relative to |
michael@0 | 475 | * the viewport). |
michael@0 | 476 | */ |
michael@0 | 477 | static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame, |
michael@0 | 478 | nsRect* aDisplayPort = nullptr); |
michael@0 | 479 | |
michael@0 | 480 | /** |
michael@0 | 481 | * Finds the nearest ancestor frame to aItem that is considered to have (or |
michael@0 | 482 | * will have) "animated geometry". For example the scrolled frames of |
michael@0 | 483 | * scrollframes which are actively being scrolled fall into this category. |
michael@0 | 484 | * Frames with certain CSS properties that are being animated (e.g. |
michael@0 | 485 | * 'left'/'top' etc) are also placed in this category. |
michael@0 | 486 | * Frames with different active geometry roots are in different ThebesLayers, |
michael@0 | 487 | * so that we can animate the geometry root by changing its transform (either |
michael@0 | 488 | * on the main thread or in the compositor). |
michael@0 | 489 | * The animated geometry root is required to be a descendant (or equal to) |
michael@0 | 490 | * aItem's ReferenceFrame(), which means that we will fall back to |
michael@0 | 491 | * returning aItem->ReferenceFrame() when we can't find another animated |
michael@0 | 492 | * geometry root. |
michael@0 | 493 | */ |
michael@0 | 494 | static nsIFrame* GetAnimatedGeometryRootFor(nsDisplayItem* aItem, |
michael@0 | 495 | nsDisplayListBuilder* aBuilder); |
michael@0 | 496 | |
michael@0 | 497 | /** |
michael@0 | 498 | * GetScrollableFrameFor returns the scrollable frame for a scrolled frame |
michael@0 | 499 | */ |
michael@0 | 500 | static nsIScrollableFrame* GetScrollableFrameFor(const nsIFrame *aScrolledFrame); |
michael@0 | 501 | |
michael@0 | 502 | /** |
michael@0 | 503 | * GetNearestScrollableFrameForDirection locates the first ancestor of |
michael@0 | 504 | * aFrame (or aFrame itself) that is scrollable with overflow:scroll or |
michael@0 | 505 | * overflow:auto in the given direction and where either the scrollbar for |
michael@0 | 506 | * that direction is visible or the frame can be scrolled by some |
michael@0 | 507 | * positive amount in that direction. |
michael@0 | 508 | * The search extends across document boundaries. |
michael@0 | 509 | * |
michael@0 | 510 | * @param aFrame the frame to start with |
michael@0 | 511 | * @param aDirection Whether it's for horizontal or vertical scrolling. |
michael@0 | 512 | * @return the nearest scrollable frame or nullptr if not found |
michael@0 | 513 | */ |
michael@0 | 514 | enum Direction { eHorizontal, eVertical }; |
michael@0 | 515 | static nsIScrollableFrame* GetNearestScrollableFrameForDirection(nsIFrame* aFrame, |
michael@0 | 516 | Direction aDirection); |
michael@0 | 517 | |
michael@0 | 518 | enum { |
michael@0 | 519 | SCROLLABLE_SAME_DOC = 0x01, |
michael@0 | 520 | SCROLLABLE_INCLUDE_HIDDEN = 0x02 |
michael@0 | 521 | }; |
michael@0 | 522 | /** |
michael@0 | 523 | * GetNearestScrollableFrame locates the first ancestor of aFrame |
michael@0 | 524 | * (or aFrame itself) that is scrollable with overflow:scroll or |
michael@0 | 525 | * overflow:auto in some direction. |
michael@0 | 526 | * |
michael@0 | 527 | * @param aFrame the frame to start with |
michael@0 | 528 | * @param aFlags if SCROLLABLE_SAME_DOC is set, do not search across |
michael@0 | 529 | * document boundaries. If SCROLLABLE_INCLUDE_HIDDEN is set, include |
michael@0 | 530 | * frames scrollable with overflow:hidden. |
michael@0 | 531 | * @return the nearest scrollable frame or nullptr if not found |
michael@0 | 532 | */ |
michael@0 | 533 | static nsIScrollableFrame* GetNearestScrollableFrame(nsIFrame* aFrame, |
michael@0 | 534 | uint32_t aFlags = 0); |
michael@0 | 535 | |
michael@0 | 536 | /** |
michael@0 | 537 | * GetScrolledRect returns the range of allowable scroll offsets |
michael@0 | 538 | * for aScrolledFrame, assuming the scrollable overflow area is |
michael@0 | 539 | * aScrolledFrameOverflowArea and the scrollport size is aScrollPortSize. |
michael@0 | 540 | * aDirection is either NS_STYLE_DIRECTION_LTR or NS_STYLE_DIRECTION_RTL. |
michael@0 | 541 | */ |
michael@0 | 542 | static nsRect GetScrolledRect(nsIFrame* aScrolledFrame, |
michael@0 | 543 | const nsRect& aScrolledFrameOverflowArea, |
michael@0 | 544 | const nsSize& aScrollPortSize, |
michael@0 | 545 | uint8_t aDirection); |
michael@0 | 546 | |
michael@0 | 547 | /** |
michael@0 | 548 | * HasPseudoStyle returns true if aContent (whose primary style |
michael@0 | 549 | * context is aStyleContext) has the aPseudoElement pseudo-style |
michael@0 | 550 | * attached to it; returns false otherwise. |
michael@0 | 551 | * |
michael@0 | 552 | * @param aContent the content node we're looking at |
michael@0 | 553 | * @param aStyleContext aContent's style context |
michael@0 | 554 | * @param aPseudoElement the id of the pseudo style we care about |
michael@0 | 555 | * @param aPresContext the presentation context |
michael@0 | 556 | * @return whether aContent has aPseudoElement style attached to it |
michael@0 | 557 | */ |
michael@0 | 558 | static bool HasPseudoStyle(nsIContent* aContent, |
michael@0 | 559 | nsStyleContext* aStyleContext, |
michael@0 | 560 | nsCSSPseudoElements::Type aPseudoElement, |
michael@0 | 561 | nsPresContext* aPresContext); |
michael@0 | 562 | |
michael@0 | 563 | /** |
michael@0 | 564 | * If this frame is a placeholder for a float, then return the float, |
michael@0 | 565 | * otherwise return nullptr. aPlaceholder must be a placeholder frame. |
michael@0 | 566 | */ |
michael@0 | 567 | static nsIFrame* GetFloatFromPlaceholder(nsIFrame* aPlaceholder); |
michael@0 | 568 | |
michael@0 | 569 | // Combine aNewBreakType with aOrigBreakType, but limit the break types |
michael@0 | 570 | // to NS_STYLE_CLEAR_LEFT, RIGHT, LEFT_AND_RIGHT. |
michael@0 | 571 | static uint8_t CombineBreakType(uint8_t aOrigBreakType, uint8_t aNewBreakType); |
michael@0 | 572 | |
michael@0 | 573 | /** |
michael@0 | 574 | * Get the coordinates of a given DOM mouse event, relative to a given |
michael@0 | 575 | * frame. Works only for DOM events generated by WidgetGUIEvents. |
michael@0 | 576 | * @param aDOMEvent the event |
michael@0 | 577 | * @param aFrame the frame to make coordinates relative to |
michael@0 | 578 | * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if |
michael@0 | 579 | * for some reason the coordinates for the mouse are not known (e.g., |
michael@0 | 580 | * the event is not a GUI event). |
michael@0 | 581 | */ |
michael@0 | 582 | static nsPoint GetDOMEventCoordinatesRelativeTo(nsIDOMEvent* aDOMEvent, |
michael@0 | 583 | nsIFrame* aFrame); |
michael@0 | 584 | |
michael@0 | 585 | /** |
michael@0 | 586 | * Get the coordinates of a given native mouse event, relative to a given |
michael@0 | 587 | * frame. |
michael@0 | 588 | * @param aEvent the event |
michael@0 | 589 | * @param aFrame the frame to make coordinates relative to |
michael@0 | 590 | * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if |
michael@0 | 591 | * for some reason the coordinates for the mouse are not known (e.g., |
michael@0 | 592 | * the event is not a GUI event). |
michael@0 | 593 | */ |
michael@0 | 594 | static nsPoint GetEventCoordinatesRelativeTo( |
michael@0 | 595 | const mozilla::WidgetEvent* aEvent, |
michael@0 | 596 | nsIFrame* aFrame); |
michael@0 | 597 | |
michael@0 | 598 | /** |
michael@0 | 599 | * Get the coordinates of a given point relative to an event and a |
michael@0 | 600 | * given frame. |
michael@0 | 601 | * @param aEvent the event |
michael@0 | 602 | * @param aPoint the point to get the coordinates relative to |
michael@0 | 603 | * @param aFrame the frame to make coordinates relative to |
michael@0 | 604 | * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if |
michael@0 | 605 | * for some reason the coordinates for the mouse are not known (e.g., |
michael@0 | 606 | * the event is not a GUI event). |
michael@0 | 607 | */ |
michael@0 | 608 | static nsPoint GetEventCoordinatesRelativeTo( |
michael@0 | 609 | const mozilla::WidgetEvent* aEvent, |
michael@0 | 610 | const nsIntPoint aPoint, |
michael@0 | 611 | nsIFrame* aFrame); |
michael@0 | 612 | |
michael@0 | 613 | /** |
michael@0 | 614 | * Get the coordinates of a given point relative to a widget and a |
michael@0 | 615 | * given frame. |
michael@0 | 616 | * @param aWidget the event src widget |
michael@0 | 617 | * @param aPoint the point to get the coordinates relative to |
michael@0 | 618 | * @param aFrame the frame to make coordinates relative to |
michael@0 | 619 | * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if |
michael@0 | 620 | * for some reason the coordinates for the mouse are not known (e.g., |
michael@0 | 621 | * the event is not a GUI event). |
michael@0 | 622 | */ |
michael@0 | 623 | static nsPoint GetEventCoordinatesRelativeTo(nsIWidget* aWidget, |
michael@0 | 624 | const nsIntPoint aPoint, |
michael@0 | 625 | nsIFrame* aFrame); |
michael@0 | 626 | |
michael@0 | 627 | /** |
michael@0 | 628 | * Get the popup frame of a given native mouse event. |
michael@0 | 629 | * @param aPresContext only check popups within aPresContext or a descendant |
michael@0 | 630 | * @param aEvent the event. |
michael@0 | 631 | * @return Null, if there is no popup frame at the point, otherwise, |
michael@0 | 632 | * returns top-most popup frame at the point. |
michael@0 | 633 | */ |
michael@0 | 634 | static nsIFrame* GetPopupFrameForEventCoordinates( |
michael@0 | 635 | nsPresContext* aPresContext, |
michael@0 | 636 | const mozilla::WidgetEvent* aEvent); |
michael@0 | 637 | |
michael@0 | 638 | /** |
michael@0 | 639 | * Translate from widget coordinates to the view's coordinates |
michael@0 | 640 | * @param aPresContext the PresContext for the view |
michael@0 | 641 | * @param aWidget the widget |
michael@0 | 642 | * @param aPt the point relative to the widget |
michael@0 | 643 | * @param aView view to which returned coordinates are relative |
michael@0 | 644 | * @return the point in the view's coordinates |
michael@0 | 645 | */ |
michael@0 | 646 | static nsPoint TranslateWidgetToView(nsPresContext* aPresContext, |
michael@0 | 647 | nsIWidget* aWidget, nsIntPoint aPt, |
michael@0 | 648 | nsView* aView); |
michael@0 | 649 | |
michael@0 | 650 | /** |
michael@0 | 651 | * Given a matrix and a point, let T be the transformation matrix translating points |
michael@0 | 652 | * in the coordinate space with origin aOrigin to the coordinate space used by the |
michael@0 | 653 | * matrix. If M is the stored matrix, this function returns (T-1)MT, the matrix |
michael@0 | 654 | * that's equivalent to aMatrix but in the coordinate space that treats aOrigin |
michael@0 | 655 | * as the origin. |
michael@0 | 656 | * |
michael@0 | 657 | * @param aOrigin The origin to translate to. |
michael@0 | 658 | * @param aMatrix The matrix to change the basis of. |
michael@0 | 659 | * @return A matrix equivalent to aMatrix, but operating in the coordinate system with |
michael@0 | 660 | * origin aOrigin. |
michael@0 | 661 | */ |
michael@0 | 662 | static gfx3DMatrix ChangeMatrixBasis(const gfxPoint3D &aOrigin, const gfx3DMatrix &aMatrix); |
michael@0 | 663 | |
michael@0 | 664 | /** |
michael@0 | 665 | * Find IDs corresponding to a scrollable content element in the child process. |
michael@0 | 666 | * In correspondence with the shadow layer tree, you can use this to perform a |
michael@0 | 667 | * hit test that corresponds to a specific shadow layer that you can then perform |
michael@0 | 668 | * transformations on to do parent-side scrolling. |
michael@0 | 669 | * |
michael@0 | 670 | * @param aFrame The root frame of a stack context |
michael@0 | 671 | * @param aTarget The rect to hit test relative to the frame origin |
michael@0 | 672 | * @param aOutIDs All found IDs are added here |
michael@0 | 673 | * @param aIgnoreRootScrollFrame a boolean to control if the display list |
michael@0 | 674 | * builder should ignore the root scroll frame |
michael@0 | 675 | */ |
michael@0 | 676 | static nsresult GetRemoteContentIds(nsIFrame* aFrame, |
michael@0 | 677 | const nsRect& aTarget, |
michael@0 | 678 | nsTArray<ViewID> &aOutIDs, |
michael@0 | 679 | bool aIgnoreRootScrollFrame); |
michael@0 | 680 | |
michael@0 | 681 | enum FrameForPointFlags { |
michael@0 | 682 | /** |
michael@0 | 683 | * When set, paint suppression is ignored, so we'll return non-root page |
michael@0 | 684 | * elements even if paint suppression is stopping them from painting. |
michael@0 | 685 | */ |
michael@0 | 686 | IGNORE_PAINT_SUPPRESSION = 0x01, |
michael@0 | 687 | /** |
michael@0 | 688 | * When set, clipping due to the root scroll frame (and any other viewport- |
michael@0 | 689 | * related clipping) is ignored. |
michael@0 | 690 | */ |
michael@0 | 691 | IGNORE_ROOT_SCROLL_FRAME = 0x02, |
michael@0 | 692 | /** |
michael@0 | 693 | * When set, return only content in the same document as aFrame. |
michael@0 | 694 | */ |
michael@0 | 695 | IGNORE_CROSS_DOC = 0x04 |
michael@0 | 696 | }; |
michael@0 | 697 | |
michael@0 | 698 | /** |
michael@0 | 699 | * Given aFrame, the root frame of a stacking context, find its descendant |
michael@0 | 700 | * frame under the point aPt that receives a mouse event at that location, |
michael@0 | 701 | * or nullptr if there is no such frame. |
michael@0 | 702 | * @param aPt the point, relative to the frame origin |
michael@0 | 703 | * @param aFlags some combination of FrameForPointFlags |
michael@0 | 704 | */ |
michael@0 | 705 | static nsIFrame* GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt, |
michael@0 | 706 | uint32_t aFlags = 0); |
michael@0 | 707 | |
michael@0 | 708 | /** |
michael@0 | 709 | * Given aFrame, the root frame of a stacking context, find all descendant |
michael@0 | 710 | * frames under the area of a rectangle that receives a mouse event, |
michael@0 | 711 | * or nullptr if there is no such frame. |
michael@0 | 712 | * @param aRect the rect, relative to the frame origin |
michael@0 | 713 | * @param aOutFrames an array to add all the frames found |
michael@0 | 714 | * @param aFlags some combination of FrameForPointFlags |
michael@0 | 715 | */ |
michael@0 | 716 | static nsresult GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect, |
michael@0 | 717 | nsTArray<nsIFrame*> &aOutFrames, |
michael@0 | 718 | uint32_t aFlags = 0); |
michael@0 | 719 | |
michael@0 | 720 | /** |
michael@0 | 721 | * Transform aRect relative to aFrame up to the coordinate system of |
michael@0 | 722 | * aAncestor. Computes the bounding-box of the true quadrilateral. |
michael@0 | 723 | * Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if |
michael@0 | 724 | * we only need to use a 2d transform that PreservesAxisAlignedRectangles(). |
michael@0 | 725 | */ |
michael@0 | 726 | static nsRect TransformFrameRectToAncestor(nsIFrame* aFrame, |
michael@0 | 727 | const nsRect& aRect, |
michael@0 | 728 | const nsIFrame* aAncestor, |
michael@0 | 729 | bool* aPreservesAxisAlignedRectangles = nullptr); |
michael@0 | 730 | |
michael@0 | 731 | |
michael@0 | 732 | /** |
michael@0 | 733 | * Gets the transform for aFrame relative to aAncestor. Pass null for aAncestor |
michael@0 | 734 | * to go up to the root frame. |
michael@0 | 735 | */ |
michael@0 | 736 | static gfx3DMatrix GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor); |
michael@0 | 737 | |
michael@0 | 738 | /** |
michael@0 | 739 | * Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into |
michael@0 | 740 | * account all relevant transformations on the frames up to (but excluding) |
michael@0 | 741 | * their nearest common ancestor. |
michael@0 | 742 | * If we encounter a transform that we need to invert but which is |
michael@0 | 743 | * non-invertible, we return NONINVERTIBLE_TRANSFORM. If the frames have |
michael@0 | 744 | * no common ancestor, we return NO_COMMON_ANCESTOR. |
michael@0 | 745 | * If this returns TRANSFORM_SUCCEEDED, the points in aPoints are transformed |
michael@0 | 746 | * in-place, otherwise they are untouched. |
michael@0 | 747 | */ |
michael@0 | 748 | enum TransformResult { |
michael@0 | 749 | TRANSFORM_SUCCEEDED, |
michael@0 | 750 | NO_COMMON_ANCESTOR, |
michael@0 | 751 | NONINVERTIBLE_TRANSFORM |
michael@0 | 752 | }; |
michael@0 | 753 | static TransformResult TransformPoints(nsIFrame* aFromFrame, nsIFrame* aToFrame, |
michael@0 | 754 | uint32_t aPointCount, CSSPoint* aPoints); |
michael@0 | 755 | |
michael@0 | 756 | /** |
michael@0 | 757 | * Return true if a "layer transform" could be computed for aFrame, |
michael@0 | 758 | * and optionally return the computed transform. The returned |
michael@0 | 759 | * transform is what would be set on the layer currently if a layers |
michael@0 | 760 | * transaction were opened at the time this helper is called. |
michael@0 | 761 | */ |
michael@0 | 762 | static bool GetLayerTransformForFrame(nsIFrame* aFrame, |
michael@0 | 763 | gfx3DMatrix* aTransform); |
michael@0 | 764 | |
michael@0 | 765 | /** |
michael@0 | 766 | * Given a point in the global coordinate space, returns that point expressed |
michael@0 | 767 | * in the coordinate system of aFrame. This effectively inverts all transforms |
michael@0 | 768 | * between this point and the root frame. |
michael@0 | 769 | * |
michael@0 | 770 | * @param aFrame The frame that acts as the coordinate space container. |
michael@0 | 771 | * @param aPoint The point, in the global space, to get in the frame-local space. |
michael@0 | 772 | * @return aPoint, expressed in aFrame's canonical coordinate space. |
michael@0 | 773 | */ |
michael@0 | 774 | static nsPoint TransformRootPointToFrame(nsIFrame* aFrame, |
michael@0 | 775 | const nsPoint &aPoint) |
michael@0 | 776 | { |
michael@0 | 777 | return TransformAncestorPointToFrame(aFrame, aPoint, nullptr); |
michael@0 | 778 | } |
michael@0 | 779 | |
michael@0 | 780 | /** |
michael@0 | 781 | * Transform aPoint relative to aAncestor down to the coordinate system of |
michael@0 | 782 | * aFrame. |
michael@0 | 783 | */ |
michael@0 | 784 | static nsPoint TransformAncestorPointToFrame(nsIFrame* aFrame, |
michael@0 | 785 | const nsPoint& aPoint, |
michael@0 | 786 | nsIFrame* aAncestor); |
michael@0 | 787 | |
michael@0 | 788 | /** |
michael@0 | 789 | * Helper function that, given a rectangle and a matrix, returns the smallest |
michael@0 | 790 | * rectangle containing the image of the source rectangle. |
michael@0 | 791 | * |
michael@0 | 792 | * @param aBounds The rectangle to transform. |
michael@0 | 793 | * @param aMatrix The matrix to transform it with. |
michael@0 | 794 | * @param aFactor The number of app units per graphics unit. |
michael@0 | 795 | * @return The smallest rect that contains the image of aBounds. |
michael@0 | 796 | */ |
michael@0 | 797 | static nsRect MatrixTransformRect(const nsRect &aBounds, |
michael@0 | 798 | const gfx3DMatrix &aMatrix, float aFactor); |
michael@0 | 799 | |
michael@0 | 800 | /** |
michael@0 | 801 | * Helper function that, given a rectangle and a matrix, returns the smallest |
michael@0 | 802 | * rectangle containing the image of the source rectangle rounded out to the nearest |
michael@0 | 803 | * pixel value. |
michael@0 | 804 | * |
michael@0 | 805 | * @param aBounds The rectangle to transform. |
michael@0 | 806 | * @param aMatrix The matrix to transform it with. |
michael@0 | 807 | * @param aFactor The number of app units per graphics unit. |
michael@0 | 808 | * @return The smallest rect that contains the image of aBounds. |
michael@0 | 809 | */ |
michael@0 | 810 | static nsRect MatrixTransformRectOut(const nsRect &aBounds, |
michael@0 | 811 | const gfx3DMatrix &aMatrix, float aFactor); |
michael@0 | 812 | /** |
michael@0 | 813 | * Helper function that, given a point and a matrix, returns the image |
michael@0 | 814 | * of that point under the matrix transform. |
michael@0 | 815 | * |
michael@0 | 816 | * @param aPoint The point to transform. |
michael@0 | 817 | * @param aMatrix The matrix to transform it with. |
michael@0 | 818 | * @param aFactor The number of app units per graphics unit. |
michael@0 | 819 | * @return The image of the point under the transform. |
michael@0 | 820 | */ |
michael@0 | 821 | static nsPoint MatrixTransformPoint(const nsPoint &aPoint, |
michael@0 | 822 | const gfx3DMatrix &aMatrix, float aFactor); |
michael@0 | 823 | |
michael@0 | 824 | /** |
michael@0 | 825 | * Given a graphics rectangle in graphics space, return a rectangle in |
michael@0 | 826 | * app space that contains the graphics rectangle, rounding out as necessary. |
michael@0 | 827 | * |
michael@0 | 828 | * @param aRect The graphics rect to round outward. |
michael@0 | 829 | * @param aFactor The number of app units per graphics unit. |
michael@0 | 830 | * @return The smallest rectangle in app space that contains aRect. |
michael@0 | 831 | */ |
michael@0 | 832 | static nsRect RoundGfxRectToAppRect(const Rect &aRect, float aFactor); |
michael@0 | 833 | |
michael@0 | 834 | /** |
michael@0 | 835 | * Given a graphics rectangle in graphics space, return a rectangle in |
michael@0 | 836 | * app space that contains the graphics rectangle, rounding out as necessary. |
michael@0 | 837 | * |
michael@0 | 838 | * @param aRect The graphics rect to round outward. |
michael@0 | 839 | * @param aFactor The number of app units per graphics unit. |
michael@0 | 840 | * @return The smallest rectangle in app space that contains aRect. |
michael@0 | 841 | */ |
michael@0 | 842 | static nsRect RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor); |
michael@0 | 843 | |
michael@0 | 844 | /** |
michael@0 | 845 | * Returns a subrectangle of aContainedRect that is entirely inside the rounded |
michael@0 | 846 | * rect. Complex cases are handled conservatively by returning a smaller |
michael@0 | 847 | * rect than necessary. |
michael@0 | 848 | */ |
michael@0 | 849 | static nsRegion RoundedRectIntersectRect(const nsRect& aRoundedRect, |
michael@0 | 850 | const nscoord aRadii[8], |
michael@0 | 851 | const nsRect& aContainedRect); |
michael@0 | 852 | |
michael@0 | 853 | /** |
michael@0 | 854 | * Return whether any part of aTestRect is inside of the rounded |
michael@0 | 855 | * rectangle formed by aBounds and aRadii (which are indexed by the |
michael@0 | 856 | * NS_CORNER_* constants in nsStyleConsts.h). This is precise. |
michael@0 | 857 | */ |
michael@0 | 858 | static bool RoundedRectIntersectsRect(const nsRect& aRoundedRect, |
michael@0 | 859 | const nscoord aRadii[8], |
michael@0 | 860 | const nsRect& aTestRect); |
michael@0 | 861 | |
michael@0 | 862 | enum { |
michael@0 | 863 | PAINT_IN_TRANSFORM = 0x01, |
michael@0 | 864 | PAINT_SYNC_DECODE_IMAGES = 0x02, |
michael@0 | 865 | PAINT_WIDGET_LAYERS = 0x04, |
michael@0 | 866 | PAINT_IGNORE_SUPPRESSION = 0x08, |
michael@0 | 867 | PAINT_DOCUMENT_RELATIVE = 0x10, |
michael@0 | 868 | PAINT_HIDE_CARET = 0x20, |
michael@0 | 869 | PAINT_ALL_CONTINUATIONS = 0x40, |
michael@0 | 870 | PAINT_TO_WINDOW = 0x80, |
michael@0 | 871 | PAINT_EXISTING_TRANSACTION = 0x100, |
michael@0 | 872 | PAINT_NO_COMPOSITE = 0x200, |
michael@0 | 873 | PAINT_COMPRESSED = 0x400 |
michael@0 | 874 | }; |
michael@0 | 875 | |
michael@0 | 876 | /** |
michael@0 | 877 | * Given aFrame, the root frame of a stacking context, paint it and its |
michael@0 | 878 | * descendants to aRenderingContext. |
michael@0 | 879 | * @param aRenderingContext a rendering context translated so that (0,0) |
michael@0 | 880 | * is the origin of aFrame; for best results, (0,0) should transform |
michael@0 | 881 | * to pixel-aligned coordinates. This can be null, in which case |
michael@0 | 882 | * aFrame must be a "display root" (root frame for a root document, |
michael@0 | 883 | * or the root of a popup) with an associated widget and we draw using |
michael@0 | 884 | * the layer manager for the frame's widget. |
michael@0 | 885 | * @param aDirtyRegion the region that must be painted, in the coordinates |
michael@0 | 886 | * of aFrame |
michael@0 | 887 | * @param aBackstop paint the dirty area with this color before drawing |
michael@0 | 888 | * the actual content; pass NS_RGBA(0,0,0,0) to draw no background |
michael@0 | 889 | * @param aFlags if PAINT_IN_TRANSFORM is set, then we assume |
michael@0 | 890 | * this is inside a transform or SVG foreignObject. If |
michael@0 | 891 | * PAINT_SYNC_DECODE_IMAGES is set, we force synchronous decode on all |
michael@0 | 892 | * images. If PAINT_WIDGET_LAYERS is set, aFrame must be a display root, |
michael@0 | 893 | * and we will use the frame's widget's layer manager to paint |
michael@0 | 894 | * even if aRenderingContext is non-null. This is useful if you want |
michael@0 | 895 | * to force rendering to use the widget's layer manager for testing |
michael@0 | 896 | * or speed. PAINT_WIDGET_LAYERS must be set if aRenderingContext is null. |
michael@0 | 897 | * If PAINT_DOCUMENT_RELATIVE is used, the visible region is interpreted |
michael@0 | 898 | * as being relative to the document. (Normally it's relative to the CSS |
michael@0 | 899 | * viewport.) PAINT_TO_WINDOW sets painting to window to true on the display |
michael@0 | 900 | * list builder even if we can't tell that we are painting to the window. |
michael@0 | 901 | * If PAINT_EXISTING_TRANSACTION is set, then BeginTransaction() has already |
michael@0 | 902 | * been called on aFrame's widget's layer manager and should not be |
michael@0 | 903 | * called again. |
michael@0 | 904 | * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode |
michael@0 | 905 | * to avoid short cut optimizations. |
michael@0 | 906 | * |
michael@0 | 907 | * So there are three possible behaviours: |
michael@0 | 908 | * 1) PAINT_WIDGET_LAYERS is set and aRenderingContext is null; we paint |
michael@0 | 909 | * by calling BeginTransaction on the widget's layer manager |
michael@0 | 910 | * 2) PAINT_WIDGET_LAYERS is set and aRenderingContext is non-null; we |
michael@0 | 911 | * paint by calling BeginTransactionWithTarget on the widget's layer |
michael@0 | 912 | * maanger |
michael@0 | 913 | * 3) PAINT_WIDGET_LAYERS is not set and aRenderingContext is non-null; |
michael@0 | 914 | * we paint by construct a BasicLayerManager and calling |
michael@0 | 915 | * BeginTransactionWithTarget on it. This is desirable if we're doing |
michael@0 | 916 | * something like drawWindow in a mode where what gets rendered doesn't |
michael@0 | 917 | * necessarily correspond to what's visible in the window; we don't |
michael@0 | 918 | * want to mess up the widget's layer tree. |
michael@0 | 919 | */ |
michael@0 | 920 | static nsresult PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFrame, |
michael@0 | 921 | const nsRegion& aDirtyRegion, nscolor aBackstop, |
michael@0 | 922 | uint32_t aFlags = 0); |
michael@0 | 923 | |
michael@0 | 924 | /** |
michael@0 | 925 | * Uses a binary search for find where the cursor falls in the line of text |
michael@0 | 926 | * It also keeps track of the part of the string that has already been measured |
michael@0 | 927 | * so it doesn't have to keep measuring the same text over and over |
michael@0 | 928 | * |
michael@0 | 929 | * @param "aBaseWidth" contains the width in twips of the portion |
michael@0 | 930 | * of the text that has already been measured, and aBaseInx contains |
michael@0 | 931 | * the index of the text that has already been measured. |
michael@0 | 932 | * |
michael@0 | 933 | * @param aTextWidth returns the (in twips) the length of the text that falls |
michael@0 | 934 | * before the cursor aIndex contains the index of the text where the cursor falls |
michael@0 | 935 | */ |
michael@0 | 936 | static bool |
michael@0 | 937 | BinarySearchForPosition(nsRenderingContext* acx, |
michael@0 | 938 | const char16_t* aText, |
michael@0 | 939 | int32_t aBaseWidth, |
michael@0 | 940 | int32_t aBaseInx, |
michael@0 | 941 | int32_t aStartInx, |
michael@0 | 942 | int32_t aEndInx, |
michael@0 | 943 | int32_t aCursorPos, |
michael@0 | 944 | int32_t& aIndex, |
michael@0 | 945 | int32_t& aTextWidth); |
michael@0 | 946 | |
michael@0 | 947 | class BoxCallback { |
michael@0 | 948 | public: |
michael@0 | 949 | virtual void AddBox(nsIFrame* aFrame) = 0; |
michael@0 | 950 | }; |
michael@0 | 951 | /** |
michael@0 | 952 | * Collect all CSS boxes associated with aFrame and its |
michael@0 | 953 | * continuations, "drilling down" through outer table frames and |
michael@0 | 954 | * some anonymous blocks since they're not real CSS boxes. |
michael@0 | 955 | * If aFrame is null, no boxes are returned. |
michael@0 | 956 | * SVG frames return a single box, themselves. |
michael@0 | 957 | */ |
michael@0 | 958 | static void GetAllInFlowBoxes(nsIFrame* aFrame, BoxCallback* aCallback); |
michael@0 | 959 | |
michael@0 | 960 | /** |
michael@0 | 961 | * Find the first frame descendant of aFrame (including aFrame) which is |
michael@0 | 962 | * not an anonymous frame that getBoxQuads/getClientRects should ignore. |
michael@0 | 963 | */ |
michael@0 | 964 | static nsIFrame* GetFirstNonAnonymousFrame(nsIFrame* aFrame); |
michael@0 | 965 | |
michael@0 | 966 | class RectCallback { |
michael@0 | 967 | public: |
michael@0 | 968 | virtual void AddRect(const nsRect& aRect) = 0; |
michael@0 | 969 | }; |
michael@0 | 970 | |
michael@0 | 971 | struct RectAccumulator : public RectCallback { |
michael@0 | 972 | nsRect mResultRect; |
michael@0 | 973 | nsRect mFirstRect; |
michael@0 | 974 | bool mSeenFirstRect; |
michael@0 | 975 | |
michael@0 | 976 | RectAccumulator(); |
michael@0 | 977 | |
michael@0 | 978 | virtual void AddRect(const nsRect& aRect); |
michael@0 | 979 | }; |
michael@0 | 980 | |
michael@0 | 981 | struct RectListBuilder : public RectCallback { |
michael@0 | 982 | DOMRectList* mRectList; |
michael@0 | 983 | |
michael@0 | 984 | RectListBuilder(DOMRectList* aList); |
michael@0 | 985 | virtual void AddRect(const nsRect& aRect); |
michael@0 | 986 | }; |
michael@0 | 987 | |
michael@0 | 988 | static nsIFrame* GetContainingBlockForClientRect(nsIFrame* aFrame); |
michael@0 | 989 | |
michael@0 | 990 | enum { |
michael@0 | 991 | RECTS_ACCOUNT_FOR_TRANSFORMS = 0x01, |
michael@0 | 992 | // Two bits for specifying which box type to use. |
michael@0 | 993 | // With neither bit set (default), use the border box. |
michael@0 | 994 | RECTS_USE_CONTENT_BOX = 0x02, |
michael@0 | 995 | RECTS_USE_PADDING_BOX = 0x04, |
michael@0 | 996 | RECTS_USE_MARGIN_BOX = 0x06, // both bits set |
michael@0 | 997 | RECTS_WHICH_BOX_MASK = 0x06 // bitmask for these two bits |
michael@0 | 998 | }; |
michael@0 | 999 | /** |
michael@0 | 1000 | * Collect all CSS boxes (content, padding, border, or margin) associated |
michael@0 | 1001 | * with aFrame and its continuations, "drilling down" through outer table |
michael@0 | 1002 | * frames and some anonymous blocks since they're not real CSS boxes. |
michael@0 | 1003 | * The boxes are positioned relative to aRelativeTo (taking scrolling |
michael@0 | 1004 | * into account) and passed to the callback in frame-tree order. |
michael@0 | 1005 | * If aFrame is null, no boxes are returned. |
michael@0 | 1006 | * For SVG frames, returns one rectangle, the bounding box. |
michael@0 | 1007 | * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting |
michael@0 | 1008 | * the boxes into aRelativeTo coordinates, transforms (including CSS |
michael@0 | 1009 | * and SVG transforms) are taken into account. |
michael@0 | 1010 | * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX, |
michael@0 | 1011 | * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used. |
michael@0 | 1012 | * Otherwise (by default), the border box is used. |
michael@0 | 1013 | */ |
michael@0 | 1014 | static void GetAllInFlowRects(nsIFrame* aFrame, nsIFrame* aRelativeTo, |
michael@0 | 1015 | RectCallback* aCallback, uint32_t aFlags = 0); |
michael@0 | 1016 | |
michael@0 | 1017 | /** |
michael@0 | 1018 | * Computes the union of all rects returned by GetAllInFlowRects. If |
michael@0 | 1019 | * the union is empty, returns the first rect. |
michael@0 | 1020 | * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting |
michael@0 | 1021 | * the boxes into aRelativeTo coordinates, transforms (including CSS |
michael@0 | 1022 | * and SVG transforms) are taken into account. |
michael@0 | 1023 | * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX, |
michael@0 | 1024 | * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used. |
michael@0 | 1025 | * Otherwise (by default), the border box is used. |
michael@0 | 1026 | */ |
michael@0 | 1027 | static nsRect GetAllInFlowRectsUnion(nsIFrame* aFrame, nsIFrame* aRelativeTo, |
michael@0 | 1028 | uint32_t aFlags = 0); |
michael@0 | 1029 | |
michael@0 | 1030 | enum { |
michael@0 | 1031 | EXCLUDE_BLUR_SHADOWS = 0x01 |
michael@0 | 1032 | }; |
michael@0 | 1033 | /** |
michael@0 | 1034 | * Takes a text-shadow array from the style properties of a given nsIFrame and |
michael@0 | 1035 | * computes the union of those shadows along with the given initial rect. |
michael@0 | 1036 | * If there are no shadows, the initial rect is returned. |
michael@0 | 1037 | */ |
michael@0 | 1038 | static nsRect GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect, |
michael@0 | 1039 | nsIFrame* aFrame, |
michael@0 | 1040 | uint32_t aFlags = 0); |
michael@0 | 1041 | |
michael@0 | 1042 | /** |
michael@0 | 1043 | * Get the font metrics corresponding to the frame's style data. |
michael@0 | 1044 | * @param aFrame the frame |
michael@0 | 1045 | * @param aFontMetrics the font metrics result |
michael@0 | 1046 | * @param aSizeInflation number to multiply font size by |
michael@0 | 1047 | * @return success or failure code |
michael@0 | 1048 | */ |
michael@0 | 1049 | static nsresult GetFontMetricsForFrame(const nsIFrame* aFrame, |
michael@0 | 1050 | nsFontMetrics** aFontMetrics, |
michael@0 | 1051 | float aSizeInflation = 1.0f); |
michael@0 | 1052 | |
michael@0 | 1053 | /** |
michael@0 | 1054 | * Get the font metrics corresponding to the given style data. |
michael@0 | 1055 | * @param aStyleContext the style data |
michael@0 | 1056 | * @param aFontMetrics the font metrics result |
michael@0 | 1057 | * @param aSizeInflation number to multiply font size by |
michael@0 | 1058 | * @return success or failure code |
michael@0 | 1059 | */ |
michael@0 | 1060 | static nsresult GetFontMetricsForStyleContext(nsStyleContext* aStyleContext, |
michael@0 | 1061 | nsFontMetrics** aFontMetrics, |
michael@0 | 1062 | float aSizeInflation = 1.0f); |
michael@0 | 1063 | |
michael@0 | 1064 | /** |
michael@0 | 1065 | * Find the immediate child of aParent whose frame subtree contains |
michael@0 | 1066 | * aDescendantFrame. Returns null if aDescendantFrame is not a descendant |
michael@0 | 1067 | * of aParent. |
michael@0 | 1068 | */ |
michael@0 | 1069 | static nsIFrame* FindChildContainingDescendant(nsIFrame* aParent, nsIFrame* aDescendantFrame); |
michael@0 | 1070 | |
michael@0 | 1071 | /** |
michael@0 | 1072 | * Find the nearest ancestor that's a block |
michael@0 | 1073 | */ |
michael@0 | 1074 | static nsBlockFrame* FindNearestBlockAncestor(nsIFrame* aFrame); |
michael@0 | 1075 | |
michael@0 | 1076 | /** |
michael@0 | 1077 | * Find the nearest ancestor that's not for generated content. Will return |
michael@0 | 1078 | * aFrame if aFrame is not for generated content. |
michael@0 | 1079 | */ |
michael@0 | 1080 | static nsIFrame* GetNonGeneratedAncestor(nsIFrame* aFrame); |
michael@0 | 1081 | |
michael@0 | 1082 | /** |
michael@0 | 1083 | * Cast aFrame to an nsBlockFrame* or return null if it's not |
michael@0 | 1084 | * an nsBlockFrame. |
michael@0 | 1085 | */ |
michael@0 | 1086 | static nsBlockFrame* GetAsBlock(nsIFrame* aFrame); |
michael@0 | 1087 | |
michael@0 | 1088 | /* |
michael@0 | 1089 | * Whether the frame is an nsBlockFrame which is not a wrapper block. |
michael@0 | 1090 | */ |
michael@0 | 1091 | static bool IsNonWrapperBlock(nsIFrame* aFrame); |
michael@0 | 1092 | |
michael@0 | 1093 | /** |
michael@0 | 1094 | * If aFrame is an out of flow frame, return its placeholder, otherwise |
michael@0 | 1095 | * return its parent. |
michael@0 | 1096 | */ |
michael@0 | 1097 | static nsIFrame* GetParentOrPlaceholderFor(nsIFrame* aFrame); |
michael@0 | 1098 | |
michael@0 | 1099 | /** |
michael@0 | 1100 | * If aFrame is an out of flow frame, return its placeholder, otherwise |
michael@0 | 1101 | * return its (possibly cross-doc) parent. |
michael@0 | 1102 | */ |
michael@0 | 1103 | static nsIFrame* GetParentOrPlaceholderForCrossDoc(nsIFrame* aFrame); |
michael@0 | 1104 | |
michael@0 | 1105 | /** |
michael@0 | 1106 | * Get a frame's next-in-flow, or, if it doesn't have one, its |
michael@0 | 1107 | * block-in-inline-split sibling. |
michael@0 | 1108 | */ |
michael@0 | 1109 | static nsIFrame* |
michael@0 | 1110 | GetNextContinuationOrIBSplitSibling(nsIFrame *aFrame); |
michael@0 | 1111 | |
michael@0 | 1112 | /** |
michael@0 | 1113 | * Get the first frame in the continuation-plus-ib-split-sibling chain |
michael@0 | 1114 | * containing aFrame. |
michael@0 | 1115 | */ |
michael@0 | 1116 | static nsIFrame* |
michael@0 | 1117 | FirstContinuationOrIBSplitSibling(nsIFrame *aFrame); |
michael@0 | 1118 | |
michael@0 | 1119 | /** |
michael@0 | 1120 | * Is FirstContinuationOrIBSplitSibling(aFrame) going to return |
michael@0 | 1121 | * aFrame? |
michael@0 | 1122 | */ |
michael@0 | 1123 | static bool |
michael@0 | 1124 | IsFirstContinuationOrIBSplitSibling(nsIFrame *aFrame); |
michael@0 | 1125 | |
michael@0 | 1126 | /** |
michael@0 | 1127 | * Check whether aFrame is a part of the scrollbar or scrollcorner of |
michael@0 | 1128 | * the root content. |
michael@0 | 1129 | * @param aFrame the checking frame |
michael@0 | 1130 | * @return if TRUE, the frame is a part of the scrollbar or scrollcorner of |
michael@0 | 1131 | * the root content. |
michael@0 | 1132 | */ |
michael@0 | 1133 | static bool IsViewportScrollbarFrame(nsIFrame* aFrame); |
michael@0 | 1134 | |
michael@0 | 1135 | /** |
michael@0 | 1136 | * Get the contribution of aFrame to its containing block's intrinsic |
michael@0 | 1137 | * width. This considers the child's intrinsic width, its 'width', |
michael@0 | 1138 | * 'min-width', and 'max-width' properties, and its padding, border, |
michael@0 | 1139 | * and margin. |
michael@0 | 1140 | */ |
michael@0 | 1141 | enum IntrinsicWidthType { MIN_WIDTH, PREF_WIDTH }; |
michael@0 | 1142 | enum { |
michael@0 | 1143 | IGNORE_PADDING = 0x01 |
michael@0 | 1144 | }; |
michael@0 | 1145 | static nscoord IntrinsicForContainer(nsRenderingContext* aRenderingContext, |
michael@0 | 1146 | nsIFrame* aFrame, |
michael@0 | 1147 | IntrinsicWidthType aType, |
michael@0 | 1148 | uint32_t aFlags = 0); |
michael@0 | 1149 | |
michael@0 | 1150 | /* |
michael@0 | 1151 | * Convert nsStyleCoord to nscoord when percentages depend on the |
michael@0 | 1152 | * containing block size. |
michael@0 | 1153 | * @param aPercentBasis The width or height of the containing block |
michael@0 | 1154 | * (whichever the client wants to use for resolving percentages). |
michael@0 | 1155 | */ |
michael@0 | 1156 | static nscoord ComputeCBDependentValue(nscoord aPercentBasis, |
michael@0 | 1157 | const nsStyleCoord& aCoord); |
michael@0 | 1158 | |
michael@0 | 1159 | /* |
michael@0 | 1160 | * Convert nsStyleCoord to nscoord when percentages depend on the |
michael@0 | 1161 | * containing block width, and enumerated values are for width, |
michael@0 | 1162 | * min-width, or max-width. Returns the content-box width value based |
michael@0 | 1163 | * on aContentEdgeToBoxSizing and aBoxSizingToMarginEdge (which are |
michael@0 | 1164 | * also used for the enumerated values for width. This function does |
michael@0 | 1165 | * not handle 'auto'. It ensures that the result is nonnegative. |
michael@0 | 1166 | * |
michael@0 | 1167 | * @param aRenderingContext Rendering context for font measurement/metrics. |
michael@0 | 1168 | * @param aFrame Frame whose (min-/max-/)width is being computed |
michael@0 | 1169 | * @param aContainingBlockWidth Width of aFrame's containing block. |
michael@0 | 1170 | * @param aContentEdgeToBoxSizing The sum of any left/right padding and |
michael@0 | 1171 | * border that goes inside the rect chosen by box-sizing. |
michael@0 | 1172 | * @param aBoxSizingToMarginEdge The sum of any left/right padding, border, |
michael@0 | 1173 | * and margin that goes outside the rect chosen by box-sizing. |
michael@0 | 1174 | * @param aCoord The width value to compute. |
michael@0 | 1175 | */ |
michael@0 | 1176 | static nscoord ComputeWidthValue( |
michael@0 | 1177 | nsRenderingContext* aRenderingContext, |
michael@0 | 1178 | nsIFrame* aFrame, |
michael@0 | 1179 | nscoord aContainingBlockWidth, |
michael@0 | 1180 | nscoord aContentEdgeToBoxSizing, |
michael@0 | 1181 | nscoord aBoxSizingToMarginEdge, |
michael@0 | 1182 | const nsStyleCoord& aCoord); |
michael@0 | 1183 | |
michael@0 | 1184 | /* |
michael@0 | 1185 | * Convert nsStyleCoord to nscoord when percentages depend on the |
michael@0 | 1186 | * containing block height. |
michael@0 | 1187 | */ |
michael@0 | 1188 | static nscoord ComputeHeightDependentValue( |
michael@0 | 1189 | nscoord aContainingBlockHeight, |
michael@0 | 1190 | const nsStyleCoord& aCoord); |
michael@0 | 1191 | |
michael@0 | 1192 | /* |
michael@0 | 1193 | * Likewise, but for 'height', 'min-height', or 'max-height'. |
michael@0 | 1194 | */ |
michael@0 | 1195 | static nscoord ComputeHeightValue(nscoord aContainingBlockHeight, |
michael@0 | 1196 | nscoord aContentEdgeToBoxSizingBoxEdge, |
michael@0 | 1197 | const nsStyleCoord& aCoord) |
michael@0 | 1198 | { |
michael@0 | 1199 | MOZ_ASSERT(aContainingBlockHeight != nscoord_MAX || !aCoord.HasPercent(), |
michael@0 | 1200 | "caller must deal with %% of unconstrained height"); |
michael@0 | 1201 | MOZ_ASSERT(aCoord.IsCoordPercentCalcUnit()); |
michael@0 | 1202 | |
michael@0 | 1203 | nscoord result = |
michael@0 | 1204 | nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockHeight); |
michael@0 | 1205 | // Clamp calc(), and the subtraction for box-sizing. |
michael@0 | 1206 | return std::max(0, result - aContentEdgeToBoxSizingBoxEdge); |
michael@0 | 1207 | } |
michael@0 | 1208 | |
michael@0 | 1209 | static bool IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight) |
michael@0 | 1210 | { |
michael@0 | 1211 | nsStyleUnit unit = aCoord.GetUnit(); |
michael@0 | 1212 | return unit == eStyleUnit_Auto || // only for 'height' |
michael@0 | 1213 | unit == eStyleUnit_None || // only for 'max-height' |
michael@0 | 1214 | (aCBHeight == nscoord_MAX && aCoord.HasPercent()); |
michael@0 | 1215 | } |
michael@0 | 1216 | |
michael@0 | 1217 | static bool IsPaddingZero(const nsStyleCoord &aCoord) |
michael@0 | 1218 | { |
michael@0 | 1219 | return (aCoord.GetUnit() == eStyleUnit_Coord && |
michael@0 | 1220 | aCoord.GetCoordValue() == 0) || |
michael@0 | 1221 | (aCoord.GetUnit() == eStyleUnit_Percent && |
michael@0 | 1222 | aCoord.GetPercentValue() == 0.0f) || |
michael@0 | 1223 | (aCoord.IsCalcUnit() && |
michael@0 | 1224 | // clamp negative calc() to 0 |
michael@0 | 1225 | nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) <= 0 && |
michael@0 | 1226 | nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) <= 0); |
michael@0 | 1227 | } |
michael@0 | 1228 | |
michael@0 | 1229 | static bool IsMarginZero(const nsStyleCoord &aCoord) |
michael@0 | 1230 | { |
michael@0 | 1231 | return (aCoord.GetUnit() == eStyleUnit_Coord && |
michael@0 | 1232 | aCoord.GetCoordValue() == 0) || |
michael@0 | 1233 | (aCoord.GetUnit() == eStyleUnit_Percent && |
michael@0 | 1234 | aCoord.GetPercentValue() == 0.0f) || |
michael@0 | 1235 | (aCoord.IsCalcUnit() && |
michael@0 | 1236 | nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) == 0 && |
michael@0 | 1237 | nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) == 0); |
michael@0 | 1238 | } |
michael@0 | 1239 | |
michael@0 | 1240 | static void MarkDescendantsDirty(nsIFrame *aSubtreeRoot); |
michael@0 | 1241 | |
michael@0 | 1242 | /* |
michael@0 | 1243 | * Calculate the used values for 'width' and 'height' for a replaced element. |
michael@0 | 1244 | * |
michael@0 | 1245 | * http://www.w3.org/TR/CSS21/visudet.html#min-max-widths |
michael@0 | 1246 | */ |
michael@0 | 1247 | static nsSize ComputeSizeWithIntrinsicDimensions( |
michael@0 | 1248 | nsRenderingContext* aRenderingContext, nsIFrame* aFrame, |
michael@0 | 1249 | const mozilla::IntrinsicSize& aIntrinsicSize, |
michael@0 | 1250 | nsSize aIntrinsicRatio, nsSize aCBSize, |
michael@0 | 1251 | nsSize aMargin, nsSize aBorder, nsSize aPadding); |
michael@0 | 1252 | |
michael@0 | 1253 | /* |
michael@0 | 1254 | * Calculate the used values for 'width' and 'height' when width |
michael@0 | 1255 | * and height are 'auto'. The tentWidth and tentHeight arguments should be |
michael@0 | 1256 | * the result of applying the rules for computing intrinsic sizes and ratios. |
michael@0 | 1257 | * as specified by CSS 2.1 sections 10.3.2 and 10.6.2 |
michael@0 | 1258 | */ |
michael@0 | 1259 | static nsSize ComputeAutoSizeWithIntrinsicDimensions(nscoord minWidth, nscoord minHeight, |
michael@0 | 1260 | nscoord maxWidth, nscoord maxHeight, |
michael@0 | 1261 | nscoord tentWidth, nscoord tentHeight); |
michael@0 | 1262 | |
michael@0 | 1263 | // Implement nsIFrame::GetPrefWidth in terms of nsIFrame::AddInlinePrefWidth |
michael@0 | 1264 | static nscoord PrefWidthFromInline(nsIFrame* aFrame, |
michael@0 | 1265 | nsRenderingContext* aRenderingContext); |
michael@0 | 1266 | |
michael@0 | 1267 | // Implement nsIFrame::GetMinWidth in terms of nsIFrame::AddInlineMinWidth |
michael@0 | 1268 | static nscoord MinWidthFromInline(nsIFrame* aFrame, |
michael@0 | 1269 | nsRenderingContext* aRenderingContext); |
michael@0 | 1270 | |
michael@0 | 1271 | // Get a suitable foreground color for painting aProperty for aFrame. |
michael@0 | 1272 | static nscolor GetColor(nsIFrame* aFrame, nsCSSProperty aProperty); |
michael@0 | 1273 | |
michael@0 | 1274 | // Get the native text color if appropriate. If false is returned, callers |
michael@0 | 1275 | // should fallback to the CSS color. |
michael@0 | 1276 | static bool GetNativeTextColor(nsIFrame* aFrame, nscolor& aColor); |
michael@0 | 1277 | |
michael@0 | 1278 | // Get a baseline y position in app units that is snapped to device pixels. |
michael@0 | 1279 | static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext, |
michael@0 | 1280 | nscoord aY, nscoord aAscent); |
michael@0 | 1281 | |
michael@0 | 1282 | static void DrawString(const nsIFrame* aFrame, |
michael@0 | 1283 | nsRenderingContext* aContext, |
michael@0 | 1284 | const char16_t* aString, |
michael@0 | 1285 | int32_t aLength, |
michael@0 | 1286 | nsPoint aPoint, |
michael@0 | 1287 | nsStyleContext* aStyleContext = nullptr); |
michael@0 | 1288 | |
michael@0 | 1289 | static nscoord GetStringWidth(const nsIFrame* aFrame, |
michael@0 | 1290 | nsRenderingContext* aContext, |
michael@0 | 1291 | const char16_t* aString, |
michael@0 | 1292 | int32_t aLength); |
michael@0 | 1293 | |
michael@0 | 1294 | /** |
michael@0 | 1295 | * Helper function for drawing text-shadow. The callback's job |
michael@0 | 1296 | * is to draw whatever needs to be blurred onto the given context. |
michael@0 | 1297 | */ |
michael@0 | 1298 | typedef void (* TextShadowCallback)(nsRenderingContext* aCtx, |
michael@0 | 1299 | nsPoint aShadowOffset, |
michael@0 | 1300 | const nscolor& aShadowColor, |
michael@0 | 1301 | void* aData); |
michael@0 | 1302 | |
michael@0 | 1303 | static void PaintTextShadow(const nsIFrame* aFrame, |
michael@0 | 1304 | nsRenderingContext* aContext, |
michael@0 | 1305 | const nsRect& aTextRect, |
michael@0 | 1306 | const nsRect& aDirtyRect, |
michael@0 | 1307 | const nscolor& aForegroundColor, |
michael@0 | 1308 | TextShadowCallback aCallback, |
michael@0 | 1309 | void* aCallbackData); |
michael@0 | 1310 | |
michael@0 | 1311 | /** |
michael@0 | 1312 | * Gets the baseline to vertically center text from a font within a |
michael@0 | 1313 | * line of specified height. |
michael@0 | 1314 | * |
michael@0 | 1315 | * Returns the baseline position relative to the top of the line. |
michael@0 | 1316 | */ |
michael@0 | 1317 | static nscoord GetCenteredFontBaseline(nsFontMetrics* aFontMetrics, |
michael@0 | 1318 | nscoord aLineHeight); |
michael@0 | 1319 | |
michael@0 | 1320 | /** |
michael@0 | 1321 | * Derive a baseline of |aFrame| (measured from its top border edge) |
michael@0 | 1322 | * from its first in-flow line box (not descending into anything with |
michael@0 | 1323 | * 'overflow' not 'visible', potentially including aFrame itself). |
michael@0 | 1324 | * |
michael@0 | 1325 | * Returns true if a baseline was found (and fills in aResult). |
michael@0 | 1326 | * Otherwise returns false. |
michael@0 | 1327 | */ |
michael@0 | 1328 | static bool GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult); |
michael@0 | 1329 | |
michael@0 | 1330 | /** |
michael@0 | 1331 | * Just like GetFirstLineBaseline, except also returns the top and |
michael@0 | 1332 | * bottom of the line with the baseline. |
michael@0 | 1333 | * |
michael@0 | 1334 | * Returns true if a line was found (and fills in aResult). |
michael@0 | 1335 | * Otherwise returns false. |
michael@0 | 1336 | */ |
michael@0 | 1337 | struct LinePosition { |
michael@0 | 1338 | nscoord mTop, mBaseline, mBottom; |
michael@0 | 1339 | |
michael@0 | 1340 | LinePosition operator+(nscoord aOffset) const { |
michael@0 | 1341 | LinePosition result; |
michael@0 | 1342 | result.mTop = mTop + aOffset; |
michael@0 | 1343 | result.mBaseline = mBaseline + aOffset; |
michael@0 | 1344 | result.mBottom = mBottom + aOffset; |
michael@0 | 1345 | return result; |
michael@0 | 1346 | } |
michael@0 | 1347 | }; |
michael@0 | 1348 | static bool GetFirstLinePosition(const nsIFrame* aFrame, |
michael@0 | 1349 | LinePosition* aResult); |
michael@0 | 1350 | |
michael@0 | 1351 | |
michael@0 | 1352 | /** |
michael@0 | 1353 | * Derive a baseline of |aFrame| (measured from its top border edge) |
michael@0 | 1354 | * from its last in-flow line box (not descending into anything with |
michael@0 | 1355 | * 'overflow' not 'visible', potentially including aFrame itself). |
michael@0 | 1356 | * |
michael@0 | 1357 | * Returns true if a baseline was found (and fills in aResult). |
michael@0 | 1358 | * Otherwise returns false. |
michael@0 | 1359 | */ |
michael@0 | 1360 | static bool GetLastLineBaseline(const nsIFrame* aFrame, nscoord* aResult); |
michael@0 | 1361 | |
michael@0 | 1362 | /** |
michael@0 | 1363 | * Returns a y coordinate relative to this frame's origin that represents |
michael@0 | 1364 | * the logical bottom of the frame or its visible content, whichever is lower. |
michael@0 | 1365 | * Relative positioning is ignored and margins and glyph bounds are not |
michael@0 | 1366 | * considered. |
michael@0 | 1367 | * This value will be >= mRect.height() and <= overflowRect.YMost() unless |
michael@0 | 1368 | * relative positioning is applied. |
michael@0 | 1369 | */ |
michael@0 | 1370 | static nscoord CalculateContentBottom(nsIFrame* aFrame); |
michael@0 | 1371 | |
michael@0 | 1372 | /** |
michael@0 | 1373 | * Gets the closest frame (the frame passed in or one of its parents) that |
michael@0 | 1374 | * qualifies as a "layer"; used in DOM0 methods that depends upon that |
michael@0 | 1375 | * definition. This is the nearest frame that is either positioned or scrolled |
michael@0 | 1376 | * (the child of a scroll frame). |
michael@0 | 1377 | */ |
michael@0 | 1378 | static nsIFrame* GetClosestLayer(nsIFrame* aFrame); |
michael@0 | 1379 | |
michael@0 | 1380 | /** |
michael@0 | 1381 | * Gets the graphics filter for the frame |
michael@0 | 1382 | */ |
michael@0 | 1383 | static GraphicsFilter GetGraphicsFilterForFrame(nsIFrame* aFrame); |
michael@0 | 1384 | |
michael@0 | 1385 | /* N.B. The only difference between variants of the Draw*Image |
michael@0 | 1386 | * functions below is the type of the aImage argument. |
michael@0 | 1387 | */ |
michael@0 | 1388 | |
michael@0 | 1389 | /** |
michael@0 | 1390 | * Draw a background image. The image's dimensions are as specified in aDest; |
michael@0 | 1391 | * the image itself is not consulted to determine a size. |
michael@0 | 1392 | * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering |
michael@0 | 1393 | * @param aRenderingContext Where to draw the image, set up with an |
michael@0 | 1394 | * appropriate scale and transform for drawing in |
michael@0 | 1395 | * app units. |
michael@0 | 1396 | * @param aImage The image. |
michael@0 | 1397 | * @param aImageSize The unscaled size of the image being drawn. |
michael@0 | 1398 | * (This might be the image's size if no scaling |
michael@0 | 1399 | * occurs, or it might be the image's size if |
michael@0 | 1400 | * the image is a vector image being rendered at |
michael@0 | 1401 | * that size.) |
michael@0 | 1402 | * @param aDest The position and scaled area where one copy of |
michael@0 | 1403 | * the image should be drawn. |
michael@0 | 1404 | * @param aFill The area to be filled with copies of the |
michael@0 | 1405 | * image. |
michael@0 | 1406 | * @param aAnchor A point in aFill which we will ensure is |
michael@0 | 1407 | * pixel-aligned in the output. |
michael@0 | 1408 | * @param aDirty Pixels outside this area may be skipped. |
michael@0 | 1409 | * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety |
michael@0 | 1410 | */ |
michael@0 | 1411 | static nsresult DrawBackgroundImage(nsRenderingContext* aRenderingContext, |
michael@0 | 1412 | imgIContainer* aImage, |
michael@0 | 1413 | const nsIntSize& aImageSize, |
michael@0 | 1414 | GraphicsFilter aGraphicsFilter, |
michael@0 | 1415 | const nsRect& aDest, |
michael@0 | 1416 | const nsRect& aFill, |
michael@0 | 1417 | const nsPoint& aAnchor, |
michael@0 | 1418 | const nsRect& aDirty, |
michael@0 | 1419 | uint32_t aImageFlags); |
michael@0 | 1420 | |
michael@0 | 1421 | /** |
michael@0 | 1422 | * Draw an image. |
michael@0 | 1423 | * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering |
michael@0 | 1424 | * @param aRenderingContext Where to draw the image, set up with an |
michael@0 | 1425 | * appropriate scale and transform for drawing in |
michael@0 | 1426 | * app units. |
michael@0 | 1427 | * @param aImage The image. |
michael@0 | 1428 | * @param aDest Where one copy of the image should mapped to. |
michael@0 | 1429 | * @param aFill The area to be filled with copies of the |
michael@0 | 1430 | * image. |
michael@0 | 1431 | * @param aAnchor A point in aFill which we will ensure is |
michael@0 | 1432 | * pixel-aligned in the output. |
michael@0 | 1433 | * @param aDirty Pixels outside this area may be skipped. |
michael@0 | 1434 | * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety |
michael@0 | 1435 | */ |
michael@0 | 1436 | static nsresult DrawImage(nsRenderingContext* aRenderingContext, |
michael@0 | 1437 | imgIContainer* aImage, |
michael@0 | 1438 | GraphicsFilter aGraphicsFilter, |
michael@0 | 1439 | const nsRect& aDest, |
michael@0 | 1440 | const nsRect& aFill, |
michael@0 | 1441 | const nsPoint& aAnchor, |
michael@0 | 1442 | const nsRect& aDirty, |
michael@0 | 1443 | uint32_t aImageFlags); |
michael@0 | 1444 | |
michael@0 | 1445 | /** |
michael@0 | 1446 | * Convert an nsRect to a gfxRect. |
michael@0 | 1447 | */ |
michael@0 | 1448 | static gfxRect RectToGfxRect(const nsRect& aRect, |
michael@0 | 1449 | int32_t aAppUnitsPerDevPixel); |
michael@0 | 1450 | |
michael@0 | 1451 | /** |
michael@0 | 1452 | * Draw a drawable using the pixel snapping algorithm. |
michael@0 | 1453 | * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering |
michael@0 | 1454 | * @param aRenderingContext Where to draw the image, set up with an |
michael@0 | 1455 | * appropriate scale and transform for drawing in |
michael@0 | 1456 | * app units. |
michael@0 | 1457 | * @param aDrawable The drawable we want to draw. |
michael@0 | 1458 | * @param aFilter The graphics filter we should draw with. |
michael@0 | 1459 | * @param aDest Where one copy of the image should mapped to. |
michael@0 | 1460 | * @param aFill The area to be filled with copies of the |
michael@0 | 1461 | * image. |
michael@0 | 1462 | * @param aAnchor A point in aFill which we will ensure is |
michael@0 | 1463 | * pixel-aligned in the output. |
michael@0 | 1464 | * @param aDirty Pixels outside this area may be skipped. |
michael@0 | 1465 | */ |
michael@0 | 1466 | static void DrawPixelSnapped(nsRenderingContext* aRenderingContext, |
michael@0 | 1467 | gfxDrawable* aDrawable, |
michael@0 | 1468 | GraphicsFilter aFilter, |
michael@0 | 1469 | const nsRect& aDest, |
michael@0 | 1470 | const nsRect& aFill, |
michael@0 | 1471 | const nsPoint& aAnchor, |
michael@0 | 1472 | const nsRect& aDirty); |
michael@0 | 1473 | |
michael@0 | 1474 | /** |
michael@0 | 1475 | * Draw a whole image without scaling or tiling. |
michael@0 | 1476 | * |
michael@0 | 1477 | * @param aRenderingContext Where to draw the image, set up with an |
michael@0 | 1478 | * appropriate scale and transform for drawing in |
michael@0 | 1479 | * app units. |
michael@0 | 1480 | * @param aImage The image. |
michael@0 | 1481 | * @param aDest The top-left where the image should be drawn |
michael@0 | 1482 | * @param aDirty If non-null, then pixels outside this area may |
michael@0 | 1483 | * be skipped. |
michael@0 | 1484 | * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety |
michael@0 | 1485 | * @param aSourceArea If non-null, this area is extracted from |
michael@0 | 1486 | * the image and drawn at aDest. It's |
michael@0 | 1487 | * in appunits. For best results it should |
michael@0 | 1488 | * be aligned with image pixels. |
michael@0 | 1489 | */ |
michael@0 | 1490 | static nsresult DrawSingleUnscaledImage(nsRenderingContext* aRenderingContext, |
michael@0 | 1491 | imgIContainer* aImage, |
michael@0 | 1492 | GraphicsFilter aGraphicsFilter, |
michael@0 | 1493 | const nsPoint& aDest, |
michael@0 | 1494 | const nsRect* aDirty, |
michael@0 | 1495 | uint32_t aImageFlags, |
michael@0 | 1496 | const nsRect* aSourceArea = nullptr); |
michael@0 | 1497 | |
michael@0 | 1498 | /** |
michael@0 | 1499 | * Draw a whole image without tiling. |
michael@0 | 1500 | * |
michael@0 | 1501 | * @param aRenderingContext Where to draw the image, set up with an |
michael@0 | 1502 | * appropriate scale and transform for drawing in |
michael@0 | 1503 | * app units. |
michael@0 | 1504 | * @param aImage The image. |
michael@0 | 1505 | * @param aDest The area that the image should fill |
michael@0 | 1506 | * @param aDirty Pixels outside this area may be skipped. |
michael@0 | 1507 | * @param aSVGContext If non-null, SVG-related rendering context |
michael@0 | 1508 | * such as overridden attributes on the image |
michael@0 | 1509 | * document's root <svg> node. Ignored for |
michael@0 | 1510 | * raster images. |
michael@0 | 1511 | * @param aImageFlags Image flags of the imgIContainer::FLAG_* |
michael@0 | 1512 | * variety. |
michael@0 | 1513 | * @param aSourceArea If non-null, this area is extracted from |
michael@0 | 1514 | * the image and drawn in aDest. It's |
michael@0 | 1515 | * in appunits. For best results it should |
michael@0 | 1516 | * be aligned with image pixels. |
michael@0 | 1517 | */ |
michael@0 | 1518 | static nsresult DrawSingleImage(nsRenderingContext* aRenderingContext, |
michael@0 | 1519 | imgIContainer* aImage, |
michael@0 | 1520 | GraphicsFilter aGraphicsFilter, |
michael@0 | 1521 | const nsRect& aDest, |
michael@0 | 1522 | const nsRect& aDirty, |
michael@0 | 1523 | const mozilla::SVGImageContext* aSVGContext, |
michael@0 | 1524 | uint32_t aImageFlags, |
michael@0 | 1525 | const nsRect* aSourceArea = nullptr); |
michael@0 | 1526 | |
michael@0 | 1527 | /** |
michael@0 | 1528 | * Given an imgIContainer, this method attempts to obtain an intrinsic |
michael@0 | 1529 | * px-valued height & width for it. If the imgIContainer has a non-pixel |
michael@0 | 1530 | * value for either height or width, this method tries to generate a pixel |
michael@0 | 1531 | * value for that dimension using the intrinsic ratio (if available). The |
michael@0 | 1532 | * intrinsic ratio will be assigned to aIntrinsicRatio; if there's no |
michael@0 | 1533 | * intrinsic ratio then (0, 0) will be assigned. |
michael@0 | 1534 | * |
michael@0 | 1535 | * This method will always set aGotWidth and aGotHeight to indicate whether |
michael@0 | 1536 | * we were able to successfully obtain (or compute) a value for each |
michael@0 | 1537 | * dimension. |
michael@0 | 1538 | * |
michael@0 | 1539 | * NOTE: This method is similar to ComputeSizeWithIntrinsicDimensions. The |
michael@0 | 1540 | * difference is that this one is simpler and is suited to places where we |
michael@0 | 1541 | * have less information about the frame tree. |
michael@0 | 1542 | */ |
michael@0 | 1543 | static void ComputeSizeForDrawing(imgIContainer* aImage, |
michael@0 | 1544 | nsIntSize& aImageSize, |
michael@0 | 1545 | nsSize& aIntrinsicRatio, |
michael@0 | 1546 | bool& aGotWidth, |
michael@0 | 1547 | bool& aGotHeight); |
michael@0 | 1548 | |
michael@0 | 1549 | /** |
michael@0 | 1550 | * Given a source area of an image (in appunits) and a destination area |
michael@0 | 1551 | * that we want to map that source area too, computes the area that |
michael@0 | 1552 | * would be covered by the whole image. This is useful for passing to |
michael@0 | 1553 | * the aDest parameter of DrawImage, when we want to draw a subimage |
michael@0 | 1554 | * of an overall image. |
michael@0 | 1555 | */ |
michael@0 | 1556 | static nsRect GetWholeImageDestination(const nsIntSize& aWholeImageSize, |
michael@0 | 1557 | const nsRect& aImageSourceArea, |
michael@0 | 1558 | const nsRect& aDestArea); |
michael@0 | 1559 | |
michael@0 | 1560 | /** |
michael@0 | 1561 | * Given an image container and an orientation, returns an image container |
michael@0 | 1562 | * that contains the same image, reoriented appropriately. May return the |
michael@0 | 1563 | * original image container if no changes are needed. |
michael@0 | 1564 | * |
michael@0 | 1565 | * @param aContainer The image container to apply the orientation to. |
michael@0 | 1566 | * @param aOrientation The desired orientation. |
michael@0 | 1567 | */ |
michael@0 | 1568 | static already_AddRefed<imgIContainer> |
michael@0 | 1569 | OrientImage(imgIContainer* aContainer, |
michael@0 | 1570 | const nsStyleImageOrientation& aOrientation); |
michael@0 | 1571 | |
michael@0 | 1572 | /** |
michael@0 | 1573 | * Determine if any corner radius is of nonzero size |
michael@0 | 1574 | * @param aCorners the |nsStyleCorners| object to check |
michael@0 | 1575 | * @return true unless all the coordinates are 0%, 0 or null. |
michael@0 | 1576 | * |
michael@0 | 1577 | * A corner radius with one dimension zero and one nonzero is |
michael@0 | 1578 | * treated as a nonzero-radius corner, even though it will end up |
michael@0 | 1579 | * being rendered like a zero-radius corner. This is because such |
michael@0 | 1580 | * corners are not expected to appear outside of test cases, and it's |
michael@0 | 1581 | * simpler to implement the test this way. |
michael@0 | 1582 | */ |
michael@0 | 1583 | static bool HasNonZeroCorner(const nsStyleCorners& aCorners); |
michael@0 | 1584 | |
michael@0 | 1585 | /** |
michael@0 | 1586 | * Determine if there is any corner radius on corners adjacent to the |
michael@0 | 1587 | * given side. |
michael@0 | 1588 | */ |
michael@0 | 1589 | static bool HasNonZeroCornerOnSide(const nsStyleCorners& aCorners, |
michael@0 | 1590 | mozilla::css::Side aSide); |
michael@0 | 1591 | |
michael@0 | 1592 | /** |
michael@0 | 1593 | * Determine if a widget is likely to require transparency or translucency. |
michael@0 | 1594 | * @param aBackgroundFrame The frame that the background is set on. For |
michael@0 | 1595 | * <window>s, this will be the canvas frame. |
michael@0 | 1596 | * @param aCSSRootFrame The frame that holds CSS properties affecting |
michael@0 | 1597 | * the widget's transparency. For menupopups, |
michael@0 | 1598 | * aBackgroundFrame and aCSSRootFrame will be the |
michael@0 | 1599 | * same. |
michael@0 | 1600 | * @return a value suitable for passing to SetWindowTranslucency |
michael@0 | 1601 | */ |
michael@0 | 1602 | static nsTransparencyMode GetFrameTransparency(nsIFrame* aBackgroundFrame, |
michael@0 | 1603 | nsIFrame* aCSSRootFrame); |
michael@0 | 1604 | |
michael@0 | 1605 | /** |
michael@0 | 1606 | * A frame is a popup if it has its own floating window. Menus, panels |
michael@0 | 1607 | * and combobox dropdowns are popups. |
michael@0 | 1608 | */ |
michael@0 | 1609 | static bool IsPopup(nsIFrame* aFrame); |
michael@0 | 1610 | |
michael@0 | 1611 | /** |
michael@0 | 1612 | * Find the nearest "display root". This is the nearest enclosing |
michael@0 | 1613 | * popup frame or the root prescontext's root frame. |
michael@0 | 1614 | */ |
michael@0 | 1615 | static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame); |
michael@0 | 1616 | |
michael@0 | 1617 | /** |
michael@0 | 1618 | * Get the reference frame that would be used when constructing a |
michael@0 | 1619 | * display item for this frame. (Note, however, that |
michael@0 | 1620 | * nsDisplayTransform use the reference frame appropriate for their |
michael@0 | 1621 | * GetTransformRootFrame(), rather than using their own frame as a |
michael@0 | 1622 | * reference frame.) |
michael@0 | 1623 | * |
michael@0 | 1624 | * This duplicates some of the logic of GetDisplayRootFrame above and |
michael@0 | 1625 | * of nsDisplayListBuilder::FindReferenceFrameFor. |
michael@0 | 1626 | * |
michael@0 | 1627 | * If you have an nsDisplayListBuilder, you should get the reference |
michael@0 | 1628 | * frame from it instead of calling this. |
michael@0 | 1629 | */ |
michael@0 | 1630 | static nsIFrame* GetReferenceFrame(nsIFrame* aFrame); |
michael@0 | 1631 | |
michael@0 | 1632 | /** |
michael@0 | 1633 | * Get the parent of this frame, except if that parent is part of a |
michael@0 | 1634 | * preserve-3d hierarchy, get the parent of the root of the |
michael@0 | 1635 | * preserve-3d hierarchy. |
michael@0 | 1636 | * |
michael@0 | 1637 | * (This is used as the starting point for reference frame computation |
michael@0 | 1638 | * for nsDisplayTransform display items.) |
michael@0 | 1639 | */ |
michael@0 | 1640 | static nsIFrame* GetTransformRootFrame(nsIFrame* aFrame); |
michael@0 | 1641 | |
michael@0 | 1642 | /** |
michael@0 | 1643 | * Get textrun construction flags determined by a given style; in particular |
michael@0 | 1644 | * some combination of: |
michael@0 | 1645 | * -- TEXT_DISABLE_OPTIONAL_LIGATURES if letter-spacing is in use |
michael@0 | 1646 | * -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size |
michael@0 | 1647 | * and prefs indicate we should be optimizing for speed over quality |
michael@0 | 1648 | */ |
michael@0 | 1649 | static uint32_t GetTextRunFlagsForStyle(nsStyleContext* aStyleContext, |
michael@0 | 1650 | const nsStyleFont* aStyleFont, |
michael@0 | 1651 | const nsStyleText* aStyleText, |
michael@0 | 1652 | nscoord aLetterSpacing); |
michael@0 | 1653 | |
michael@0 | 1654 | /** |
michael@0 | 1655 | * Takes two rectangles whose origins must be the same, and computes |
michael@0 | 1656 | * the difference between their union and their intersection as two |
michael@0 | 1657 | * rectangles. (This difference is a superset of the difference |
michael@0 | 1658 | * between the two rectangles.) |
michael@0 | 1659 | */ |
michael@0 | 1660 | static void GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2, |
michael@0 | 1661 | nsRect* aHStrip, nsRect* aVStrip); |
michael@0 | 1662 | |
michael@0 | 1663 | /** |
michael@0 | 1664 | * Get a device context that can be used to get up-to-date device |
michael@0 | 1665 | * dimensions for the given window. For some reason, this is more |
michael@0 | 1666 | * complicated than it ought to be in multi-monitor situations. |
michael@0 | 1667 | */ |
michael@0 | 1668 | static nsDeviceContext* |
michael@0 | 1669 | GetDeviceContextForScreenInfo(nsPIDOMWindow* aWindow); |
michael@0 | 1670 | |
michael@0 | 1671 | /** |
michael@0 | 1672 | * Some frames with 'position: fixed' (nsStylePosition::mDisplay == |
michael@0 | 1673 | * NS_STYLE_POSITION_FIXED) are not really fixed positioned, since |
michael@0 | 1674 | * they're inside an element with -moz-transform. This function says |
michael@0 | 1675 | * whether such an element is a real fixed-pos element. |
michael@0 | 1676 | */ |
michael@0 | 1677 | static bool IsReallyFixedPos(nsIFrame* aFrame); |
michael@0 | 1678 | |
michael@0 | 1679 | /** |
michael@0 | 1680 | * Obtain a gfxASurface from the given DOM element, if possible. |
michael@0 | 1681 | * This obtains the most natural surface from the element; that |
michael@0 | 1682 | * is, the one that can be obtained with the fewest conversions. |
michael@0 | 1683 | * |
michael@0 | 1684 | * The flags below can modify the behaviour of this function. The |
michael@0 | 1685 | * result is returned as a SurfaceFromElementResult struct, also |
michael@0 | 1686 | * defined below. |
michael@0 | 1687 | * |
michael@0 | 1688 | * Currently, this will do: |
michael@0 | 1689 | * - HTML Canvas elements: will return the underlying canvas surface |
michael@0 | 1690 | * - HTML Video elements: will return the current video frame |
michael@0 | 1691 | * - Image elements: will return the image |
michael@0 | 1692 | * |
michael@0 | 1693 | * The above results are modified by the below flags (copying, |
michael@0 | 1694 | * forcing image surface, etc.). |
michael@0 | 1695 | */ |
michael@0 | 1696 | |
michael@0 | 1697 | enum { |
michael@0 | 1698 | /* When creating a new surface, create an image surface */ |
michael@0 | 1699 | SFE_WANT_IMAGE_SURFACE = 1 << 0, |
michael@0 | 1700 | /* Whether to extract the first frame (as opposed to the |
michael@0 | 1701 | current frame) in the case that the element is an image. */ |
michael@0 | 1702 | SFE_WANT_FIRST_FRAME = 1 << 1, |
michael@0 | 1703 | /* Whether we should skip colorspace/gamma conversion */ |
michael@0 | 1704 | SFE_NO_COLORSPACE_CONVERSION = 1 << 2, |
michael@0 | 1705 | /* Specifies that the caller wants unpremultiplied pixel data. |
michael@0 | 1706 | If this is can be done efficiently, the result will be a |
michael@0 | 1707 | DataSourceSurface and mIsPremultiplied with be set to false. */ |
michael@0 | 1708 | SFE_PREFER_NO_PREMULTIPLY_ALPHA = 1 << 3, |
michael@0 | 1709 | /* Whether we should skip getting a surface for vector images and |
michael@0 | 1710 | return a DirectDrawInfo containing an imgIContainer instead. */ |
michael@0 | 1711 | SFE_NO_RASTERIZING_VECTORS = 1 << 4 |
michael@0 | 1712 | }; |
michael@0 | 1713 | |
michael@0 | 1714 | struct DirectDrawInfo { |
michael@0 | 1715 | /* imgIContainer to directly draw to a context */ |
michael@0 | 1716 | nsCOMPtr<imgIContainer> mImgContainer; |
michael@0 | 1717 | /* which frame to draw */ |
michael@0 | 1718 | uint32_t mWhichFrame; |
michael@0 | 1719 | /* imgIContainer flags to use when drawing */ |
michael@0 | 1720 | uint32_t mDrawingFlags; |
michael@0 | 1721 | }; |
michael@0 | 1722 | |
michael@0 | 1723 | struct SurfaceFromElementResult { |
michael@0 | 1724 | SurfaceFromElementResult(); |
michael@0 | 1725 | |
michael@0 | 1726 | /* mSurface will contain the resulting surface, or will be nullptr on error */ |
michael@0 | 1727 | nsRefPtr<gfxASurface> mSurface; |
michael@0 | 1728 | mozilla::RefPtr<SourceSurface> mSourceSurface; |
michael@0 | 1729 | /* Contains info for drawing when there is no mSourceSurface. */ |
michael@0 | 1730 | DirectDrawInfo mDrawInfo; |
michael@0 | 1731 | |
michael@0 | 1732 | /* The size of the surface */ |
michael@0 | 1733 | gfxIntSize mSize; |
michael@0 | 1734 | /* The principal associated with the element whose surface was returned. |
michael@0 | 1735 | If there is a surface, this will never be null. */ |
michael@0 | 1736 | nsCOMPtr<nsIPrincipal> mPrincipal; |
michael@0 | 1737 | /* The image request, if the element is an nsIImageLoadingContent */ |
michael@0 | 1738 | nsCOMPtr<imgIRequest> mImageRequest; |
michael@0 | 1739 | /* Whether the element was "write only", that is, the bits should not be exposed to content */ |
michael@0 | 1740 | bool mIsWriteOnly; |
michael@0 | 1741 | /* Whether the element was still loading. Some consumers need to handle |
michael@0 | 1742 | this case specially. */ |
michael@0 | 1743 | bool mIsStillLoading; |
michael@0 | 1744 | /* Whether the element used CORS when loading. */ |
michael@0 | 1745 | bool mCORSUsed; |
michael@0 | 1746 | /* Whether the returned image contains premultiplied pixel data */ |
michael@0 | 1747 | bool mIsPremultiplied; |
michael@0 | 1748 | }; |
michael@0 | 1749 | |
michael@0 | 1750 | static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::Element *aElement, |
michael@0 | 1751 | uint32_t aSurfaceFlags = 0, |
michael@0 | 1752 | DrawTarget *aTarget = nullptr); |
michael@0 | 1753 | static SurfaceFromElementResult SurfaceFromElement(nsIImageLoadingContent *aElement, |
michael@0 | 1754 | uint32_t aSurfaceFlags = 0, |
michael@0 | 1755 | DrawTarget *aTarget = nullptr); |
michael@0 | 1756 | // Need an HTMLImageElement overload, because otherwise the |
michael@0 | 1757 | // nsIImageLoadingContent and mozilla::dom::Element overloads are ambiguous |
michael@0 | 1758 | // for HTMLImageElement. |
michael@0 | 1759 | static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::HTMLImageElement *aElement, |
michael@0 | 1760 | uint32_t aSurfaceFlags = 0, |
michael@0 | 1761 | DrawTarget *aTarget = nullptr); |
michael@0 | 1762 | static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::HTMLCanvasElement *aElement, |
michael@0 | 1763 | uint32_t aSurfaceFlags = 0, |
michael@0 | 1764 | DrawTarget *aTarget = nullptr); |
michael@0 | 1765 | static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::HTMLVideoElement *aElement, |
michael@0 | 1766 | uint32_t aSurfaceFlags = 0, |
michael@0 | 1767 | DrawTarget *aTarget = nullptr); |
michael@0 | 1768 | |
michael@0 | 1769 | /** |
michael@0 | 1770 | * When the document is editable by contenteditable attribute of its root |
michael@0 | 1771 | * content or body content. |
michael@0 | 1772 | * |
michael@0 | 1773 | * Be aware, this returns nullptr if it's in designMode. |
michael@0 | 1774 | * |
michael@0 | 1775 | * For example: |
michael@0 | 1776 | * |
michael@0 | 1777 | * <html contenteditable="true"><body></body></html> |
michael@0 | 1778 | * returns the <html>. |
michael@0 | 1779 | * |
michael@0 | 1780 | * <html><body contenteditable="true"></body></html> |
michael@0 | 1781 | * <body contenteditable="true"></body> |
michael@0 | 1782 | * With these cases, this returns the <body>. |
michael@0 | 1783 | * NOTE: The latter case isn't created normally, however, it can be |
michael@0 | 1784 | * created by script with XHTML. |
michael@0 | 1785 | * |
michael@0 | 1786 | * <body><p contenteditable="true"></p></body> |
michael@0 | 1787 | * returns nullptr because <body> isn't editable. |
michael@0 | 1788 | */ |
michael@0 | 1789 | static nsIContent* |
michael@0 | 1790 | GetEditableRootContentByContentEditable(nsIDocument* aDocument); |
michael@0 | 1791 | |
michael@0 | 1792 | /** |
michael@0 | 1793 | * Returns true if the passed in prescontext needs the dark grey background |
michael@0 | 1794 | * that goes behind the page of a print preview presentation. |
michael@0 | 1795 | */ |
michael@0 | 1796 | static bool NeedsPrintPreviewBackground(nsPresContext* aPresContext); |
michael@0 | 1797 | |
michael@0 | 1798 | /** |
michael@0 | 1799 | * Adds all font faces used in the frame tree starting from aFrame |
michael@0 | 1800 | * to the list aFontFaceList. |
michael@0 | 1801 | */ |
michael@0 | 1802 | static nsresult GetFontFacesForFrames(nsIFrame* aFrame, |
michael@0 | 1803 | nsFontFaceList* aFontFaceList); |
michael@0 | 1804 | |
michael@0 | 1805 | /** |
michael@0 | 1806 | * Adds all font faces used within the specified range of text in aFrame, |
michael@0 | 1807 | * and optionally its continuations, to the list in aFontFaceList. |
michael@0 | 1808 | * Pass 0 and INT32_MAX for aStartOffset and aEndOffset to specify the |
michael@0 | 1809 | * entire text is to be considered. |
michael@0 | 1810 | */ |
michael@0 | 1811 | static nsresult GetFontFacesForText(nsIFrame* aFrame, |
michael@0 | 1812 | int32_t aStartOffset, |
michael@0 | 1813 | int32_t aEndOffset, |
michael@0 | 1814 | bool aFollowContinuations, |
michael@0 | 1815 | nsFontFaceList* aFontFaceList); |
michael@0 | 1816 | |
michael@0 | 1817 | /** |
michael@0 | 1818 | * Walks the frame tree starting at aFrame looking for textRuns. |
michael@0 | 1819 | * If |clear| is true, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag |
michael@0 | 1820 | * on each textRun found (and |aMallocSizeOf| is not used). |
michael@0 | 1821 | * If |clear| is false, adds the storage used for each textRun to the |
michael@0 | 1822 | * total, and sets the TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double- |
michael@0 | 1823 | * accounting. (Runs with this flag already set will be skipped.) |
michael@0 | 1824 | * Expected usage pattern is therefore to call twice: |
michael@0 | 1825 | * (void)SizeOfTextRunsForFrames(rootFrame, nullptr, true); |
michael@0 | 1826 | * total = SizeOfTextRunsForFrames(rootFrame, mallocSizeOf, false); |
michael@0 | 1827 | */ |
michael@0 | 1828 | static size_t SizeOfTextRunsForFrames(nsIFrame* aFrame, |
michael@0 | 1829 | mozilla::MallocSizeOf aMallocSizeOf, |
michael@0 | 1830 | bool clear); |
michael@0 | 1831 | |
michael@0 | 1832 | /** |
michael@0 | 1833 | * Returns true if the content node has animations or transitions that can be |
michael@0 | 1834 | * performed on the compositor. |
michael@0 | 1835 | */ |
michael@0 | 1836 | static bool HasAnimationsForCompositor(nsIContent* aContent, |
michael@0 | 1837 | nsCSSProperty aProperty); |
michael@0 | 1838 | |
michael@0 | 1839 | /** |
michael@0 | 1840 | * Returns true if the content node has animations or transitions for the |
michael@0 | 1841 | * property. |
michael@0 | 1842 | */ |
michael@0 | 1843 | static bool HasAnimations(nsIContent* aContent, nsCSSProperty aProperty); |
michael@0 | 1844 | |
michael@0 | 1845 | /** |
michael@0 | 1846 | * Checks if off-main-thread animations are enabled. |
michael@0 | 1847 | */ |
michael@0 | 1848 | static bool AreAsyncAnimationsEnabled(); |
michael@0 | 1849 | |
michael@0 | 1850 | /** |
michael@0 | 1851 | * Checks if we should warn about animations that can't be async |
michael@0 | 1852 | */ |
michael@0 | 1853 | static bool IsAnimationLoggingEnabled(); |
michael@0 | 1854 | |
michael@0 | 1855 | /** |
michael@0 | 1856 | * Find a suitable scale for an element (aContent) over the course of any |
michael@0 | 1857 | * animations and transitions on the element. |
michael@0 | 1858 | * It will check the maximum and minimum scale during the animations and |
michael@0 | 1859 | * transitions and return a suitable value for performance and quality. |
michael@0 | 1860 | * Will return scale(1,1) if there is no animated scaling. |
michael@0 | 1861 | * Always return positive value. |
michael@0 | 1862 | */ |
michael@0 | 1863 | static gfxSize ComputeSuitableScaleForAnimation(nsIContent* aContent); |
michael@0 | 1864 | |
michael@0 | 1865 | /** |
michael@0 | 1866 | * Checks if we should forcibly use nearest pixel filtering for the |
michael@0 | 1867 | * background. |
michael@0 | 1868 | */ |
michael@0 | 1869 | static bool UseBackgroundNearestFiltering(); |
michael@0 | 1870 | |
michael@0 | 1871 | /** |
michael@0 | 1872 | * Checks whether we want to use the GPU to scale images when |
michael@0 | 1873 | * possible. |
michael@0 | 1874 | */ |
michael@0 | 1875 | static bool GPUImageScalingEnabled(); |
michael@0 | 1876 | |
michael@0 | 1877 | /** |
michael@0 | 1878 | * Checks whether we want to layerize animated images whenever possible. |
michael@0 | 1879 | */ |
michael@0 | 1880 | static bool AnimatedImageLayersEnabled(); |
michael@0 | 1881 | |
michael@0 | 1882 | /** |
michael@0 | 1883 | * Checks if we should enable parsing for CSS Filters. |
michael@0 | 1884 | */ |
michael@0 | 1885 | static bool CSSFiltersEnabled(); |
michael@0 | 1886 | |
michael@0 | 1887 | /** |
michael@0 | 1888 | * Checks whether support for the CSS-wide "unset" value is enabled. |
michael@0 | 1889 | */ |
michael@0 | 1890 | static bool UnsetValueEnabled(); |
michael@0 | 1891 | |
michael@0 | 1892 | /** |
michael@0 | 1893 | * Checks whether support for the CSS text-align (and -moz-text-align-last) |
michael@0 | 1894 | * 'true' value is enabled. |
michael@0 | 1895 | */ |
michael@0 | 1896 | static bool IsTextAlignTrueValueEnabled(); |
michael@0 | 1897 | |
michael@0 | 1898 | /** |
michael@0 | 1899 | * Checks if CSS variables are currently enabled. |
michael@0 | 1900 | */ |
michael@0 | 1901 | static bool CSSVariablesEnabled() |
michael@0 | 1902 | { |
michael@0 | 1903 | return sCSSVariablesEnabled; |
michael@0 | 1904 | } |
michael@0 | 1905 | |
michael@0 | 1906 | static bool InterruptibleReflowEnabled() |
michael@0 | 1907 | { |
michael@0 | 1908 | return sInterruptibleReflowEnabled; |
michael@0 | 1909 | } |
michael@0 | 1910 | |
michael@0 | 1911 | /** |
michael@0 | 1912 | * Unions the overflow areas of the children of aFrame with aOverflowAreas. |
michael@0 | 1913 | * aSkipChildLists specifies any child lists that should be skipped. |
michael@0 | 1914 | * kSelectPopupList and kPopupList are always skipped. |
michael@0 | 1915 | */ |
michael@0 | 1916 | static void UnionChildOverflow(nsIFrame* aFrame, |
michael@0 | 1917 | nsOverflowAreas& aOverflowAreas, |
michael@0 | 1918 | mozilla::layout::FrameChildListIDs aSkipChildLists = |
michael@0 | 1919 | mozilla::layout::FrameChildListIDs()); |
michael@0 | 1920 | |
michael@0 | 1921 | /** |
michael@0 | 1922 | * Return the font size inflation *ratio* for a given frame. This is |
michael@0 | 1923 | * the factor by which font sizes should be inflated; it is never |
michael@0 | 1924 | * smaller than 1. |
michael@0 | 1925 | */ |
michael@0 | 1926 | static float FontSizeInflationFor(const nsIFrame *aFrame); |
michael@0 | 1927 | |
michael@0 | 1928 | /** |
michael@0 | 1929 | * Perform the first half of the computation of FontSizeInflationFor |
michael@0 | 1930 | * (see above). |
michael@0 | 1931 | * This includes determining whether inflation should be performed |
michael@0 | 1932 | * within this container and returning 0 if it should not be. |
michael@0 | 1933 | * |
michael@0 | 1934 | * The result is guaranteed not to vary between line participants |
michael@0 | 1935 | * (inlines, text frames) within a line. |
michael@0 | 1936 | * |
michael@0 | 1937 | * The result should not be used directly since font sizes slightly |
michael@0 | 1938 | * above the minimum should always be adjusted as done by |
michael@0 | 1939 | * FontSizeInflationInner. |
michael@0 | 1940 | */ |
michael@0 | 1941 | static nscoord InflationMinFontSizeFor(const nsIFrame *aFrame); |
michael@0 | 1942 | |
michael@0 | 1943 | /** |
michael@0 | 1944 | * Perform the second half of the computation done by |
michael@0 | 1945 | * FontSizeInflationFor (see above). |
michael@0 | 1946 | * |
michael@0 | 1947 | * aMinFontSize must be the result of one of the |
michael@0 | 1948 | * InflationMinFontSizeFor methods above. |
michael@0 | 1949 | */ |
michael@0 | 1950 | static float FontSizeInflationInner(const nsIFrame *aFrame, |
michael@0 | 1951 | nscoord aMinFontSize); |
michael@0 | 1952 | |
michael@0 | 1953 | static bool FontSizeInflationEnabled(nsPresContext *aPresContext); |
michael@0 | 1954 | |
michael@0 | 1955 | /** |
michael@0 | 1956 | * See comment above "font.size.inflation.maxRatio" in |
michael@0 | 1957 | * modules/libpref/src/init/all.js . |
michael@0 | 1958 | */ |
michael@0 | 1959 | static uint32_t FontSizeInflationMaxRatio() { |
michael@0 | 1960 | return sFontSizeInflationMaxRatio; |
michael@0 | 1961 | } |
michael@0 | 1962 | |
michael@0 | 1963 | /** |
michael@0 | 1964 | * See comment above "font.size.inflation.emPerLine" in |
michael@0 | 1965 | * modules/libpref/src/init/all.js . |
michael@0 | 1966 | */ |
michael@0 | 1967 | static uint32_t FontSizeInflationEmPerLine() { |
michael@0 | 1968 | return sFontSizeInflationEmPerLine; |
michael@0 | 1969 | } |
michael@0 | 1970 | |
michael@0 | 1971 | /** |
michael@0 | 1972 | * See comment above "font.size.inflation.minTwips" in |
michael@0 | 1973 | * modules/libpref/src/init/all.js . |
michael@0 | 1974 | */ |
michael@0 | 1975 | static uint32_t FontSizeInflationMinTwips() { |
michael@0 | 1976 | return sFontSizeInflationMinTwips; |
michael@0 | 1977 | } |
michael@0 | 1978 | |
michael@0 | 1979 | /** |
michael@0 | 1980 | * See comment above "font.size.inflation.lineThreshold" in |
michael@0 | 1981 | * modules/libpref/src/init/all.js . |
michael@0 | 1982 | */ |
michael@0 | 1983 | static uint32_t FontSizeInflationLineThreshold() { |
michael@0 | 1984 | return sFontSizeInflationLineThreshold; |
michael@0 | 1985 | } |
michael@0 | 1986 | |
michael@0 | 1987 | static bool FontSizeInflationForceEnabled() { |
michael@0 | 1988 | return sFontSizeInflationForceEnabled; |
michael@0 | 1989 | } |
michael@0 | 1990 | |
michael@0 | 1991 | static bool FontSizeInflationDisabledInMasterProcess() { |
michael@0 | 1992 | return sFontSizeInflationDisabledInMasterProcess; |
michael@0 | 1993 | } |
michael@0 | 1994 | |
michael@0 | 1995 | /** |
michael@0 | 1996 | * See comment above "font.size.inflation.mappingIntercept" in |
michael@0 | 1997 | * modules/libpref/src/init/all.js . |
michael@0 | 1998 | */ |
michael@0 | 1999 | static int32_t FontSizeInflationMappingIntercept() { |
michael@0 | 2000 | return sFontSizeInflationMappingIntercept; |
michael@0 | 2001 | } |
michael@0 | 2002 | |
michael@0 | 2003 | /** |
michael@0 | 2004 | * Returns true if the nglayout.debug.invalidation pref is set to true. |
michael@0 | 2005 | * Note that sInvalidationDebuggingIsEnabled is declared outside this function to |
michael@0 | 2006 | * allow it to be accessed an manipulated from breakpoint conditions. |
michael@0 | 2007 | */ |
michael@0 | 2008 | static bool InvalidationDebuggingIsEnabled() { |
michael@0 | 2009 | return sInvalidationDebuggingIsEnabled || getenv("MOZ_DUMP_INVALIDATION") != 0; |
michael@0 | 2010 | } |
michael@0 | 2011 | |
michael@0 | 2012 | static void Initialize(); |
michael@0 | 2013 | static void Shutdown(); |
michael@0 | 2014 | |
michael@0 | 2015 | /** |
michael@0 | 2016 | * Register an imgIRequest object with a refresh driver. |
michael@0 | 2017 | * |
michael@0 | 2018 | * @param aPresContext The nsPresContext whose refresh driver we want to |
michael@0 | 2019 | * register with. |
michael@0 | 2020 | * @param aRequest A pointer to the imgIRequest object which the client wants |
michael@0 | 2021 | * to register with the refresh driver. |
michael@0 | 2022 | * @param aRequestRegistered A pointer to a boolean value which indicates |
michael@0 | 2023 | * whether the given image request is registered. If |
michael@0 | 2024 | * *aRequestRegistered is true, then this request will not be |
michael@0 | 2025 | * registered again. If the request is registered by this function, |
michael@0 | 2026 | * then *aRequestRegistered will be set to true upon the completion of |
michael@0 | 2027 | * this function. |
michael@0 | 2028 | * |
michael@0 | 2029 | */ |
michael@0 | 2030 | static void RegisterImageRequest(nsPresContext* aPresContext, |
michael@0 | 2031 | imgIRequest* aRequest, |
michael@0 | 2032 | bool* aRequestRegistered); |
michael@0 | 2033 | |
michael@0 | 2034 | /** |
michael@0 | 2035 | * Register an imgIRequest object with a refresh driver, but only if the |
michael@0 | 2036 | * request is for an image that is animated. |
michael@0 | 2037 | * |
michael@0 | 2038 | * @param aPresContext The nsPresContext whose refresh driver we want to |
michael@0 | 2039 | * register with. |
michael@0 | 2040 | * @param aRequest A pointer to the imgIRequest object which the client wants |
michael@0 | 2041 | * to register with the refresh driver. |
michael@0 | 2042 | * @param aRequestRegistered A pointer to a boolean value which indicates |
michael@0 | 2043 | * whether the given image request is registered. If |
michael@0 | 2044 | * *aRequestRegistered is true, then this request will not be |
michael@0 | 2045 | * registered again. If the request is registered by this function, |
michael@0 | 2046 | * then *aRequestRegistered will be set to true upon the completion of |
michael@0 | 2047 | * this function. |
michael@0 | 2048 | * |
michael@0 | 2049 | */ |
michael@0 | 2050 | static void RegisterImageRequestIfAnimated(nsPresContext* aPresContext, |
michael@0 | 2051 | imgIRequest* aRequest, |
michael@0 | 2052 | bool* aRequestRegistered); |
michael@0 | 2053 | |
michael@0 | 2054 | /** |
michael@0 | 2055 | * Deregister an imgIRequest object from a refresh driver. |
michael@0 | 2056 | * |
michael@0 | 2057 | * @param aPresContext The nsPresContext whose refresh driver we want to |
michael@0 | 2058 | * deregister from. |
michael@0 | 2059 | * @param aRequest A pointer to the imgIRequest object with which the client |
michael@0 | 2060 | * previously registered and now wants to deregister from the refresh |
michael@0 | 2061 | * driver. |
michael@0 | 2062 | * @param aRequestRegistered A pointer to a boolean value which indicates |
michael@0 | 2063 | * whether the given image request is registered. If |
michael@0 | 2064 | * *aRequestRegistered is false, then this request will not be |
michael@0 | 2065 | * deregistered. If the request is deregistered by this function, |
michael@0 | 2066 | * then *aRequestRegistered will be set to false upon the completion of |
michael@0 | 2067 | * this function. |
michael@0 | 2068 | */ |
michael@0 | 2069 | static void DeregisterImageRequest(nsPresContext* aPresContext, |
michael@0 | 2070 | imgIRequest* aRequest, |
michael@0 | 2071 | bool* aRequestRegistered); |
michael@0 | 2072 | |
michael@0 | 2073 | /** |
michael@0 | 2074 | * Shim to nsCSSFrameConstructor::PostRestyleEvent. Exists so that we |
michael@0 | 2075 | * can avoid including nsCSSFrameConstructor.h and all its dependencies |
michael@0 | 2076 | * in content files. |
michael@0 | 2077 | */ |
michael@0 | 2078 | static void PostRestyleEvent(mozilla::dom::Element* aElement, |
michael@0 | 2079 | nsRestyleHint aRestyleHint, |
michael@0 | 2080 | nsChangeHint aMinChangeHint); |
michael@0 | 2081 | |
michael@0 | 2082 | /** |
michael@0 | 2083 | * Updates a pair of x and y distances if a given point is closer to a given |
michael@0 | 2084 | * rectangle than the original distance values. If aPoint is closer to |
michael@0 | 2085 | * aRect than aClosestXDistance and aClosestYDistance indicate, then those |
michael@0 | 2086 | * two variables are updated with the distance between aPoint and aRect, |
michael@0 | 2087 | * and true is returned. If aPoint is not closer, then aClosestXDistance |
michael@0 | 2088 | * and aClosestYDistance are left unchanged, and false is returned. |
michael@0 | 2089 | * |
michael@0 | 2090 | * Distances are measured in the two dimensions separately; a closer x |
michael@0 | 2091 | * distance beats a closer y distance. |
michael@0 | 2092 | */ |
michael@0 | 2093 | template<typename PointType, typename RectType, typename CoordType> |
michael@0 | 2094 | static bool PointIsCloserToRect(PointType aPoint, const RectType& aRect, |
michael@0 | 2095 | CoordType& aClosestXDistance, |
michael@0 | 2096 | CoordType& aClosestYDistance); |
michael@0 | 2097 | /** |
michael@0 | 2098 | * Computes the box shadow rect for the frame, or returns an empty rect if |
michael@0 | 2099 | * there are no shadows. |
michael@0 | 2100 | * |
michael@0 | 2101 | * @param aFrame Frame to compute shadows for. |
michael@0 | 2102 | * @param aFrameSize Size of aFrame (in case it hasn't been set yet). |
michael@0 | 2103 | */ |
michael@0 | 2104 | static nsRect GetBoxShadowRectForFrame(nsIFrame* aFrame, const nsSize& aFrameSize); |
michael@0 | 2105 | |
michael@0 | 2106 | #ifdef DEBUG |
michael@0 | 2107 | /** |
michael@0 | 2108 | * Assert that there are no duplicate continuations of the same frame |
michael@0 | 2109 | * within aFrameList. Optimize the tests by assuming that all frames |
michael@0 | 2110 | * in aFrameList have parent aContainer. |
michael@0 | 2111 | */ |
michael@0 | 2112 | static void |
michael@0 | 2113 | AssertNoDuplicateContinuations(nsIFrame* aContainer, |
michael@0 | 2114 | const nsFrameList& aFrameList); |
michael@0 | 2115 | |
michael@0 | 2116 | /** |
michael@0 | 2117 | * Assert that the frame tree rooted at |aSubtreeRoot| is empty, i.e., |
michael@0 | 2118 | * that it contains no first-in-flows. |
michael@0 | 2119 | */ |
michael@0 | 2120 | static void |
michael@0 | 2121 | AssertTreeOnlyEmptyNextInFlows(nsIFrame *aSubtreeRoot); |
michael@0 | 2122 | #endif |
michael@0 | 2123 | |
michael@0 | 2124 | /** |
michael@0 | 2125 | * Determine if aImageFrame (which is an nsImageFrame, nsImageControlFrame, or |
michael@0 | 2126 | * nsSVGImageFrame) is visible or close to being visible via scrolling and |
michael@0 | 2127 | * update the presshell with this knowledge. |
michael@0 | 2128 | */ |
michael@0 | 2129 | static void |
michael@0 | 2130 | UpdateImageVisibilityForFrame(nsIFrame* aImageFrame); |
michael@0 | 2131 | |
michael@0 | 2132 | /** |
michael@0 | 2133 | * Calculate the compostion size for a frame. See FrameMetrics.h for |
michael@0 | 2134 | * defintion of composition size (or bounds). |
michael@0 | 2135 | */ |
michael@0 | 2136 | static nsSize |
michael@0 | 2137 | CalculateCompositionSizeForFrame(nsIFrame* aFrame); |
michael@0 | 2138 | |
michael@0 | 2139 | /** |
michael@0 | 2140 | * Calculate the composition size for the root scroll frame of the root |
michael@0 | 2141 | * content document. |
michael@0 | 2142 | * @param aFrame A frame in the root content document (or a descendant of it). |
michael@0 | 2143 | * @param aIsRootContentDocRootScrollFrame Whether aFrame is already the root |
michael@0 | 2144 | * scroll frame of the root content document. In this case we just |
michael@0 | 2145 | * use aFrame's own composition size. |
michael@0 | 2146 | * @param aMetrics A partially populated FrameMetrics for aFrame. Must have at |
michael@0 | 2147 | * least mCompositionBounds, mCumulativeResolution, and |
michael@0 | 2148 | * mDevPixelsPerCSSPixel set. |
michael@0 | 2149 | */ |
michael@0 | 2150 | static CSSSize |
michael@0 | 2151 | CalculateRootCompositionSize(nsIFrame* aFrame, |
michael@0 | 2152 | bool aIsRootContentDocRootScrollFrame, |
michael@0 | 2153 | const FrameMetrics& aMetrics); |
michael@0 | 2154 | |
michael@0 | 2155 | /** |
michael@0 | 2156 | * Calculate the scrollable rect for a frame. See FrameMetrics.h for |
michael@0 | 2157 | * defintion of scrollable rect. aScrollableFrame is the scroll frame to calculate |
michael@0 | 2158 | * the scrollable rect for. If it's null then we calculate the scrollable rect |
michael@0 | 2159 | * as the rect of the root frame. |
michael@0 | 2160 | */ |
michael@0 | 2161 | static nsRect |
michael@0 | 2162 | CalculateScrollableRectForFrame(nsIScrollableFrame* aScrollableFrame, nsIFrame* aRootFrame); |
michael@0 | 2163 | |
michael@0 | 2164 | /** |
michael@0 | 2165 | * Calculate the expanded scrollable rect for a frame. See FrameMetrics.h for |
michael@0 | 2166 | * defintion of expanded scrollable rect. |
michael@0 | 2167 | */ |
michael@0 | 2168 | static nsRect |
michael@0 | 2169 | CalculateExpandedScrollableRect(nsIFrame* aFrame); |
michael@0 | 2170 | |
michael@0 | 2171 | /** |
michael@0 | 2172 | * Return whether we want to use APZ for subframes in this process. |
michael@0 | 2173 | * Currently we don't support APZ for the parent process on B2G. |
michael@0 | 2174 | */ |
michael@0 | 2175 | static bool WantSubAPZC(); |
michael@0 | 2176 | |
michael@0 | 2177 | /** |
michael@0 | 2178 | * Get the display port for |aScrollFrame|'s content. If |aScrollFrame| |
michael@0 | 2179 | * WantsAsyncScroll() and we don't have a scrollable displayport yet (as |
michael@0 | 2180 | * tracked by |aBuilder|), calculate and set a display port. Returns true if |
michael@0 | 2181 | * there is (now) a displayport, and if so the displayport is returned in |
michael@0 | 2182 | * |aOutDisplayport|. |
michael@0 | 2183 | * |
michael@0 | 2184 | * Note that a displayport can either be stored as a rect, or as a base |
michael@0 | 2185 | * rect + margins. If it is stored as a base rect + margins, the base rect |
michael@0 | 2186 | * is updated to |aDisplayPortBase|, and the rect assembled from the |
michael@0 | 2187 | * base rect and margins is returned. If this function creates a displayport, |
michael@0 | 2188 | * it computes margins and stores |aDisplayPortBase| as the base rect. |
michael@0 | 2189 | * |
michael@0 | 2190 | * This is intended to be called during display list building. |
michael@0 | 2191 | */ |
michael@0 | 2192 | static bool GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder, |
michael@0 | 2193 | nsIFrame* aScrollFrame, |
michael@0 | 2194 | nsRect aDisplayPortBase, |
michael@0 | 2195 | nsRect* aOutDisplayport); |
michael@0 | 2196 | |
michael@0 | 2197 | private: |
michael@0 | 2198 | static uint32_t sFontSizeInflationEmPerLine; |
michael@0 | 2199 | static uint32_t sFontSizeInflationMinTwips; |
michael@0 | 2200 | static uint32_t sFontSizeInflationLineThreshold; |
michael@0 | 2201 | static int32_t sFontSizeInflationMappingIntercept; |
michael@0 | 2202 | static uint32_t sFontSizeInflationMaxRatio; |
michael@0 | 2203 | static bool sFontSizeInflationForceEnabled; |
michael@0 | 2204 | static bool sFontSizeInflationDisabledInMasterProcess; |
michael@0 | 2205 | static bool sInvalidationDebuggingIsEnabled; |
michael@0 | 2206 | static bool sCSSVariablesEnabled; |
michael@0 | 2207 | static bool sInterruptibleReflowEnabled; |
michael@0 | 2208 | }; |
michael@0 | 2209 | |
michael@0 | 2210 | MOZ_FINISH_NESTED_ENUM_CLASS(nsLayoutUtils::RepaintMode) |
michael@0 | 2211 | |
michael@0 | 2212 | template<typename PointType, typename RectType, typename CoordType> |
michael@0 | 2213 | /* static */ bool |
michael@0 | 2214 | nsLayoutUtils::PointIsCloserToRect(PointType aPoint, const RectType& aRect, |
michael@0 | 2215 | CoordType& aClosestXDistance, |
michael@0 | 2216 | CoordType& aClosestYDistance) |
michael@0 | 2217 | { |
michael@0 | 2218 | CoordType fromLeft = aPoint.x - aRect.x; |
michael@0 | 2219 | CoordType fromRight = aPoint.x - aRect.XMost(); |
michael@0 | 2220 | |
michael@0 | 2221 | CoordType xDistance; |
michael@0 | 2222 | if (fromLeft >= 0 && fromRight <= 0) { |
michael@0 | 2223 | xDistance = 0; |
michael@0 | 2224 | } else { |
michael@0 | 2225 | xDistance = std::min(abs(fromLeft), abs(fromRight)); |
michael@0 | 2226 | } |
michael@0 | 2227 | |
michael@0 | 2228 | if (xDistance <= aClosestXDistance) { |
michael@0 | 2229 | if (xDistance < aClosestXDistance) { |
michael@0 | 2230 | aClosestYDistance = std::numeric_limits<CoordType>::max(); |
michael@0 | 2231 | } |
michael@0 | 2232 | |
michael@0 | 2233 | CoordType fromTop = aPoint.y - aRect.y; |
michael@0 | 2234 | CoordType fromBottom = aPoint.y - aRect.YMost(); |
michael@0 | 2235 | |
michael@0 | 2236 | CoordType yDistance; |
michael@0 | 2237 | if (fromTop >= 0 && fromBottom <= 0) { |
michael@0 | 2238 | yDistance = 0; |
michael@0 | 2239 | } else { |
michael@0 | 2240 | yDistance = std::min(abs(fromTop), abs(fromBottom)); |
michael@0 | 2241 | } |
michael@0 | 2242 | |
michael@0 | 2243 | if (yDistance < aClosestYDistance) { |
michael@0 | 2244 | aClosestXDistance = xDistance; |
michael@0 | 2245 | aClosestYDistance = yDistance; |
michael@0 | 2246 | return true; |
michael@0 | 2247 | } |
michael@0 | 2248 | } |
michael@0 | 2249 | |
michael@0 | 2250 | return false; |
michael@0 | 2251 | } |
michael@0 | 2252 | |
michael@0 | 2253 | namespace mozilla { |
michael@0 | 2254 | namespace layout { |
michael@0 | 2255 | |
michael@0 | 2256 | /** |
michael@0 | 2257 | * An RAII class which will, for the duration of its lifetime, |
michael@0 | 2258 | * **if** the frame given is a container for font size inflation, |
michael@0 | 2259 | * set the current inflation container on the pres context to null |
michael@0 | 2260 | * (and then, in its destructor, restore the old value). |
michael@0 | 2261 | */ |
michael@0 | 2262 | class AutoMaybeDisableFontInflation { |
michael@0 | 2263 | public: |
michael@0 | 2264 | AutoMaybeDisableFontInflation(nsIFrame *aFrame); |
michael@0 | 2265 | |
michael@0 | 2266 | ~AutoMaybeDisableFontInflation(); |
michael@0 | 2267 | private: |
michael@0 | 2268 | nsPresContext *mPresContext; |
michael@0 | 2269 | bool mOldValue; |
michael@0 | 2270 | }; |
michael@0 | 2271 | |
michael@0 | 2272 | } |
michael@0 | 2273 | } |
michael@0 | 2274 | |
michael@0 | 2275 | class nsSetAttrRunnable : public nsRunnable |
michael@0 | 2276 | { |
michael@0 | 2277 | public: |
michael@0 | 2278 | nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName, |
michael@0 | 2279 | const nsAString& aValue); |
michael@0 | 2280 | nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName, |
michael@0 | 2281 | int32_t aValue); |
michael@0 | 2282 | |
michael@0 | 2283 | NS_DECL_NSIRUNNABLE |
michael@0 | 2284 | |
michael@0 | 2285 | nsCOMPtr<nsIContent> mContent; |
michael@0 | 2286 | nsCOMPtr<nsIAtom> mAttrName; |
michael@0 | 2287 | nsAutoString mValue; |
michael@0 | 2288 | }; |
michael@0 | 2289 | |
michael@0 | 2290 | class nsUnsetAttrRunnable : public nsRunnable |
michael@0 | 2291 | { |
michael@0 | 2292 | public: |
michael@0 | 2293 | nsUnsetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName); |
michael@0 | 2294 | |
michael@0 | 2295 | NS_DECL_NSIRUNNABLE |
michael@0 | 2296 | |
michael@0 | 2297 | nsCOMPtr<nsIContent> mContent; |
michael@0 | 2298 | nsCOMPtr<nsIAtom> mAttrName; |
michael@0 | 2299 | }; |
michael@0 | 2300 | |
michael@0 | 2301 | #endif // nsLayoutUtils_h__ |