nsLayoutUtils.h (147469B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef nsLayoutUtils_h__ 8 #define nsLayoutUtils_h__ 9 10 #include <algorithm> 11 #include <limits> 12 13 #include "LayoutConstants.h" 14 #include "Units.h" 15 #include "gfxPoint.h" 16 #include "mozilla/LayoutStructs.h" 17 #include "mozilla/LookAndFeel.h" 18 #include "mozilla/Maybe.h" 19 #include "mozilla/MemoryReporting.h" 20 #include "mozilla/RelativeTo.h" 21 #include "mozilla/SVGImageContext.h" 22 #include "mozilla/Span.h" 23 #include "mozilla/StaticPrefs_nglayout.h" 24 #include "mozilla/SurfaceFromElementResult.h" 25 #include "mozilla/ToString.h" 26 #include "mozilla/TypedEnumBits.h" 27 #include "mozilla/UniquePtr.h" 28 #include "mozilla/WritingModes.h" 29 #include "mozilla/gfx/2D.h" 30 #include "mozilla/layers/LayersTypes.h" 31 #include "mozilla/layers/ScrollableLayerGuid.h" 32 #include "nsBoundingMetrics.h" 33 #include "nsCSSPropertyIDSet.h" 34 #include "nsFrameList.h" 35 #include "nsPoint.h" 36 #include "nsThreadUtils.h" 37 // If you're thinking of adding a new include here, please try hard to not. 38 // This header file gets included just about everywhere and adding headers here 39 // can dramatically increase avoidable build activity. Try instead: 40 // - using a forward declaration 41 // - putting the include in the .cpp file, if it is only needed by the body 42 // - putting your new functions in some other less-widely-used header 43 44 class gfxContext; 45 class gfxFontEntry; 46 class imgIContainer; 47 class nsFrameList; 48 class nsPresContext; 49 class nsIContent; 50 class nsIPrincipal; 51 class nsIWidget; 52 class nsAtom; 53 class nsRegion; 54 enum nsChangeHint : uint32_t; 55 class nsFontMetrics; 56 class nsFontFaceList; 57 class nsIImageLoadingContent; 58 class nsBlockFrame; 59 class nsContainerFrame; 60 class nsView; 61 class nsIFrame; 62 class nsPIDOMWindowOuter; 63 class imgIRequest; 64 struct nsStyleFont; 65 66 namespace mozilla { 67 class nsDisplayItem; 68 class nsDisplayList; 69 class nsDisplayListBuilder; 70 enum class nsDisplayListBuilderMode : uint8_t; 71 class RetainedDisplayListBuilder; 72 struct AspectRatio; 73 class ComputedStyle; 74 class DisplayPortUtils; 75 class PresShell; 76 enum class PseudoStyleType : uint8_t; 77 class EventListenerManager; 78 enum class LayoutFrameType : uint8_t; 79 struct IntrinsicSize; 80 class ReflowOutput; 81 class WritingMode; 82 class DisplayItemClip; 83 class EffectSet; 84 struct ActiveScrolledRoot; 85 class ScrollContainerFrame; 86 enum class ScrollOrigin : uint8_t; 87 enum class StyleImageOrientation : uint8_t; 88 enum class StyleSystemFont : uint8_t; 89 enum class StyleScrollbarWidth : uint8_t; 90 struct OverflowAreas; 91 namespace dom { 92 class CanvasRenderingContext2D; 93 class DOMRectList; 94 class Document; 95 class Element; 96 class Event; 97 class HTMLImageElement; 98 class HTMLCanvasElement; 99 class HTMLVideoElement; 100 class ImageBitmap; 101 class InspectorFontFace; 102 class OffscreenCanvas; 103 class Selection; 104 class VideoFrame; 105 } // namespace dom 106 namespace gfx { 107 struct RectCornerRadii; 108 enum class ShapedTextFlags : uint16_t; 109 } // namespace gfx 110 namespace image { 111 class ImageIntRegion; 112 struct Resolution; 113 } // namespace image 114 namespace layers { 115 struct FrameMetrics; 116 struct ScrollMetadata; 117 class Image; 118 class StackingContextHelper; 119 class Layer; 120 class WebRenderLayerManager; 121 } // namespace layers 122 namespace widget { 123 enum class TransparencyMode : uint8_t; 124 } 125 } // namespace mozilla 126 127 // Flags to customize the behavior of nsLayoutUtils::DrawString. 128 enum class DrawStringFlags { 129 Default = 0x0, 130 ForceHorizontal = 0x1 // Forces the text to be drawn horizontally. 131 }; 132 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DrawStringFlags) 133 134 namespace mozilla { 135 136 class RectCallback { 137 public: 138 virtual void AddRect(const nsRect& aRect) = 0; 139 }; 140 141 } // namespace mozilla 142 143 /** 144 * nsLayoutUtils is a namespace class used for various helper 145 * functions that are useful in multiple places in layout. The goal 146 * is not to define multiple copies of the same static helper. 147 */ 148 class nsLayoutUtils { 149 typedef mozilla::AspectRatio AspectRatio; 150 typedef mozilla::ComputedStyle ComputedStyle; 151 typedef mozilla::LengthPercentage LengthPercentage; 152 typedef mozilla::LengthPercentageOrAuto LengthPercentageOrAuto; 153 typedef mozilla::dom::DOMRectList DOMRectList; 154 typedef mozilla::layers::StackingContextHelper StackingContextHelper; 155 typedef mozilla::IntrinsicSize IntrinsicSize; 156 typedef mozilla::RelativeTo RelativeTo; 157 typedef mozilla::ScrollOrigin ScrollOrigin; 158 typedef mozilla::ViewportType ViewportType; 159 typedef mozilla::gfx::SourceSurface SourceSurface; 160 typedef mozilla::gfx::sRGBColor sRGBColor; 161 typedef mozilla::gfx::DrawTarget DrawTarget; 162 typedef mozilla::gfx::ExtendMode ExtendMode; 163 typedef mozilla::gfx::SamplingFilter SamplingFilter; 164 typedef mozilla::gfx::Float Float; 165 typedef mozilla::gfx::Point Point; 166 typedef mozilla::gfx::Rect Rect; 167 typedef mozilla::gfx::RectDouble RectDouble; 168 typedef mozilla::gfx::Size Size; 169 typedef mozilla::gfx::Matrix4x4 Matrix4x4; 170 typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged; 171 typedef mozilla::gfx::MatrixScales MatrixScales; 172 typedef mozilla::gfx::MatrixScalesDouble MatrixScalesDouble; 173 typedef mozilla::gfx::RectCornerRadii RectCornerRadii; 174 typedef mozilla::gfx::StrokeOptions StrokeOptions; 175 typedef mozilla::image::ImgDrawResult ImgDrawResult; 176 177 using nsDisplayItem = mozilla::nsDisplayItem; 178 using nsDisplayList = mozilla::nsDisplayList; 179 using nsDisplayListBuilder = mozilla::nsDisplayListBuilder; 180 using nsDisplayListBuilderMode = mozilla::nsDisplayListBuilderMode; 181 using RetainedDisplayListBuilder = mozilla::RetainedDisplayListBuilder; 182 183 public: 184 typedef mozilla::layers::FrameMetrics FrameMetrics; 185 typedef mozilla::layers::ScrollMetadata ScrollMetadata; 186 typedef mozilla::layers::ScrollableLayerGuid::ViewID ViewID; 187 typedef mozilla::CSSPoint CSSPoint; 188 typedef mozilla::CSSSize CSSSize; 189 typedef mozilla::CSSIntSize CSSIntSize; 190 typedef mozilla::CSSRect CSSRect; 191 typedef mozilla::ScreenMargin ScreenMargin; 192 typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize; 193 typedef mozilla::LayoutDeviceRect LayoutDeviceRect; 194 typedef mozilla::PresShell PresShell; 195 typedef mozilla::StyleGeometryBox StyleGeometryBox; 196 typedef mozilla::SVGImageContext SVGImageContext; 197 typedef mozilla::LogicalSize LogicalSize; 198 199 /** 200 * Finds previously assigned ViewID for the given content element, if any. 201 * Returns whether a ViewID was previously assigned. 202 */ 203 static bool FindIDFor(const nsIContent* aContent, ViewID* aOutViewId); 204 205 /** 206 * Finds previously assigned or generates a unique ViewID for the given 207 * content element. 208 */ 209 static ViewID FindOrCreateIDFor(nsIContent* aContent); 210 211 /** 212 * Find content for given ID. 213 */ 214 static nsIContent* FindContentFor(ViewID aId); 215 216 /** 217 * Find the scroll container frame for a given content element. 218 */ 219 static mozilla::ScrollContainerFrame* FindScrollContainerFrameFor( 220 nsIContent* aContent); 221 222 /** 223 * Find the scroll container frame for a given ID. 224 */ 225 static mozilla::ScrollContainerFrame* FindScrollContainerFrameFor(ViewID aId); 226 227 /** 228 * Helper for FindScrollContainerFrameFor(), also used in DisplayPortUtils. 229 * Most clients should use FindScrollContainerFrameFor(). 230 */ 231 static nsIFrame* GetScrollContainerFrameFromContent(nsIContent* aContent); 232 233 /** 234 * Find the ID for a given scroll container frame. 235 */ 236 static ViewID FindIDForScrollContainerFrame( 237 mozilla::ScrollContainerFrame* aScrollContainerFrame); 238 239 /** 240 * Notify the scroll frame with the given scroll id that its scroll offset 241 * is being sent to APZ as part of a paint-skip transaction. 242 * 243 * Normally, this notification happens during painting, after calls to 244 * ComputeScrollMetadata(). During paint-skipping that code is skipped, 245 * but it's still important for the scroll frame to be notified for 246 * correctness of relative scroll updates, so the code that sends the 247 * empty paint-skip transaction needs to call this. 248 */ 249 static void NotifyPaintSkipTransaction(ViewID aScrollId); 250 251 /** 252 * Similar to above NotifyPaintSkipTransaction, but scroll offset is being 253 * sent to APZ in a full transaction. 254 */ 255 static void NotifyApzTransaction(ViewID aScrollId); 256 257 /** 258 * Use heuristics to figure out the child list that 259 * aChildFrame is currently in. 260 */ 261 static mozilla::FrameChildListID GetChildListNameFor(nsIFrame* aChildFrame); 262 263 /** 264 * Returns the ::before pseudo-element for aContent, if any. 265 */ 266 static mozilla::dom::Element* GetBeforePseudo(const nsIContent* aContent); 267 268 /** 269 * Returns the frame corresponding to the ::before pseudo-element for 270 * aContent, if any. 271 */ 272 static nsIFrame* GetBeforeFrame(const nsIContent* aContent); 273 274 /** 275 * Returns the ::after pseudo-element for aContent, if any. 276 */ 277 static mozilla::dom::Element* GetAfterPseudo(const nsIContent* aContent); 278 279 /** 280 * Returns the frame corresponding to the ::after pseudo-element for aContent, 281 * if any. 282 */ 283 static nsIFrame* GetAfterFrame(const nsIContent* aContent); 284 285 /** 286 * Returns the ::marker pseudo-element for aContent, if any. 287 */ 288 static mozilla::dom::Element* GetMarkerPseudo(const nsIContent* aContent); 289 290 /** 291 * Returns the frame corresponding to the ::marker pseudo-element for 292 * aContent, if any. 293 */ 294 static nsIFrame* GetMarkerFrame(const nsIContent* aContent); 295 296 /** 297 * Returns the ::backdrop pseudo-element for aContent, if any. 298 */ 299 static mozilla::dom::Element* GetBackdropPseudo(const nsIContent* aContent); 300 static nsIFrame* GetBackdropFrame(const nsIContent* aContent); 301 302 #ifdef ACCESSIBILITY 303 /** 304 * Set aText to the spoken text for the given ::marker content (aContent) 305 * if it has a frame, or the empty string otherwise. 306 */ 307 static void GetMarkerSpokenText(const nsIContent* aContent, nsAString& aText); 308 #endif 309 310 /** 311 * Given a frame, search up the frame tree until we find an 312 * ancestor that (or the frame itself) is of type aFrameType, if any. 313 * 314 * @param aFrame the frame to start at 315 * @param aFrameType the frame type to look for 316 * @param aStopAt a frame to stop at after we checked it 317 * @return a frame of the given type or nullptr if no such ancestor exists 318 * 319 * Note: prefer the const overload if possible; the non-const wrapper exists 320 * for legacy callers. 321 */ 322 static const nsIFrame* GetClosestFrameOfType( 323 const nsIFrame* aFrame, mozilla::LayoutFrameType aFrameType, 324 const nsIFrame* aStopAt = nullptr); 325 static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame, 326 mozilla::LayoutFrameType aFrameType, 327 const nsIFrame* aStopAt = nullptr); 328 329 /** 330 * Given a frame, search up the frame tree until we find an 331 * ancestor that (or the frame itself) is a "Page" frame, if any. 332 * 333 * @param aFrame the frame to start at 334 * @return a frame of type mozilla::LayoutFrameType::Page or nullptr if no 335 * such ancestor exists 336 */ 337 static nsIFrame* GetPageFrame(nsIFrame* aFrame); 338 static const nsIFrame* GetPageFrame(const nsIFrame* aFrame); 339 340 /** 341 * Given a frame which is the primary frame for an element, 342 * return the frame that has the non-pseudoelement ComputedStyle for 343 * the content. 344 * This is aPrimaryFrame itself except for tableWrapper frames. 345 * 346 * Given a non-null input, this will return null if and only if its 347 * argument is a table wrapper frame that is mid-destruction (and its 348 * table frame has been destroyed). 349 */ 350 static nsIFrame* GetStyleFrame(nsIFrame* aPrimaryFrame); 351 static const nsIFrame* GetStyleFrame(const nsIFrame* aPrimaryFrame); 352 353 /** 354 * Given a content node, 355 * return the frame that has the non-pseudoelement ComputedStyle for 356 * the content. May return null. 357 * This is aContent->GetPrimaryFrame() except for tableWrapper frames. 358 */ 359 static nsIFrame* GetStyleFrame(const nsIContent* aContent); 360 361 /** 362 * Returns the placeholder size for when the scrollbar is unthemed. 363 */ 364 static mozilla::CSSIntCoord UnthemedScrollbarSize( 365 mozilla::StyleScrollbarWidth); 366 367 /** 368 * The inverse of GetStyleFrame. Returns |aStyleFrame| unless it is an inner 369 * table frame, in which case the table wrapper frame is returned. 370 */ 371 static nsIFrame* GetPrimaryFrameFromStyleFrame(nsIFrame* aStyleFrame); 372 static const nsIFrame* GetPrimaryFrameFromStyleFrame( 373 const nsIFrame* aStyleFrame); 374 375 /** 376 * Similar to nsIFrame::IsPrimaryFrame except that this will return true 377 * for the inner table frame rather than for its wrapper frame. 378 */ 379 static bool IsPrimaryStyleFrame(const nsIFrame* aFrame); 380 381 /** 382 * CompareTreePosition determines whether aFrame1 comes before or 383 * after aFrame2 in a preorder traversal of the frame tree, where out 384 * of flow frames are treated as children of their placeholders. This is 385 * basically the same ordering as DoCompareTreePosition(nsIContent*) except 386 * that it handles anonymous content properly and there are subtleties with 387 * continuations. 388 * 389 * @param aCommonAncestor either null, or a common ancestor of 390 * aContent1 and aContent2. Actually this is 391 * only a hint; if it's not an ancestor of 392 * aContent1 or aContent2, this function will 393 * still work, but it will be slower than 394 * normal. 395 * @return < 0 if aContent1 is before aContent2 396 * > 0 if aContent1 is after aContent2, 397 * 0 otherwise (meaning they're the same, or they're in 398 * different frame trees) 399 */ 400 static int32_t CompareTreePosition( 401 const nsIFrame* aFrame1, const nsIFrame* aFrame2, 402 const nsIFrame* aCommonAncestor = nullptr) { 403 return DoCompareTreePosition(aFrame1, aFrame2, aCommonAncestor); 404 } 405 406 static int32_t CompareTreePosition( 407 const nsIFrame* aFrame1, const nsIFrame* aFrame2, 408 const nsTArray<const nsIFrame*>& aFrame2Ancestors, 409 const nsIFrame* aCommonAncestor = nullptr) { 410 return DoCompareTreePosition(aFrame1, aFrame2, aFrame2Ancestors, 411 aCommonAncestor); 412 } 413 414 static const nsIFrame* FillAncestors(const nsIFrame* aFrame, 415 const nsIFrame* aStopAtAncestor, 416 nsTArray<const nsIFrame*>* aAncestors); 417 418 static int32_t DoCompareTreePosition(const nsIFrame* aFrame1, 419 const nsIFrame* aFrame2, 420 const nsIFrame* aCommonAncestor); 421 static int32_t DoCompareTreePosition( 422 const nsIFrame* aFrame1, const nsIFrame* aFrame2, 423 const nsTArray<const nsIFrame*>& aFrame2Ancestors, 424 const nsIFrame* aCommonAncestor); 425 426 /** 427 * LastContinuationWithChild gets the last continuation in aFrame's chain 428 * that has a child, or the first continuation if the frame has no children. 429 */ 430 static nsContainerFrame* LastContinuationWithChild(nsContainerFrame* aFrame); 431 432 /** 433 * GetLastSibling simply finds the last sibling of aFrame, or returns nullptr 434 * if aFrame is null. 435 */ 436 static nsIFrame* GetLastSibling(nsIFrame* aFrame); 437 438 /** 439 * FindSiblingViewFor locates the child of aParentView that aFrame's 440 * view should be inserted 'above' (i.e., before in sibling view 441 * order). This is the first child view of aParentView whose 442 * corresponding content is before aFrame's content (view siblings 443 * are in reverse content order). 444 */ 445 static nsView* FindSiblingViewFor(nsView* aParentView, nsIFrame* aFrame); 446 447 /** 448 * Get the parent of aFrame. If aFrame is the root frame for a document, 449 * and the document has a parent document in the same view hierarchy, then 450 * we try to return the subdocumentframe in the parent document. 451 * @param aCrossDocOffset [in/out] if non-null, then as we cross documents 452 * an extra offset may be required and it will be added to aCrossDocOffset. 453 * Be careful dealing with this extra offset as it is in app units of the 454 * parent document, which may have a different app units per dev pixel ratio 455 * than the child document. 456 * Note that, while this function crosses document boundaries, it (naturally) 457 * cannot cross process boundaries. 458 */ 459 static nsIFrame* GetCrossDocParentFrameInProcess( 460 const nsIFrame* aFrame, nsPoint* aCrossDocOffset = nullptr); 461 462 /** 463 * Does the same thing as GetCrossDocParentFrameInProcess(). 464 * The purpose of having two functions is to more easily track which call 465 * sites have been audited to consider out-of-process iframes (bug 1599913). 466 * Once all call sites have been audited, this function can be removed. 467 */ 468 static nsIFrame* GetCrossDocParentFrame(const nsIFrame* aFrame, 469 nsPoint* aCrossDocOffset = nullptr); 470 471 /** 472 * IsProperAncestorFrame checks whether aAncestorFrame is an ancestor 473 * of aFrame and not equal to aFrame. 474 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and 475 * aAncestorFrame. If non-null, this can bound the search and speed up 476 * the function 477 */ 478 static bool IsProperAncestorFrame(const nsIFrame* aAncestorFrame, 479 const nsIFrame* aFrame, 480 const nsIFrame* aCommonAncestor = nullptr); 481 482 /** 483 * IsProperAncestorFrameConsideringContinuations checks whether aAncestorFrame 484 * or a continuation of it is an ancestor of aFrame and not equal to aFrame. 485 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and 486 * aAncestorFrame. If non-null, this can bound the search and speed up 487 * the function 488 */ 489 static bool IsProperAncestorFrameConsideringContinuations( 490 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame, 491 const nsIFrame* aCommonAncestor = nullptr); 492 493 /** 494 * Like IsProperAncestorFrame, but looks across document boundaries. 495 * 496 * Just like IsAncestorFrameCrossDoc, except that it returns false when 497 * aFrame == aAncestorFrame. 498 * TODO: Once after we fixed bug 1715932, this function should be removed. 499 */ 500 static bool IsProperAncestorFrameCrossDoc( 501 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame, 502 const nsIFrame* aCommonAncestor = nullptr); 503 504 /** 505 * Like IsProperAncestorFrame, but looks across document boundaries. 506 * 507 * Just like IsAncestorFrameCrossDoc, except that it returns false when 508 * aFrame == aAncestorFrame. 509 */ 510 static bool IsProperAncestorFrameCrossDocInProcess( 511 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame, 512 const nsIFrame* aCommonAncestor = nullptr); 513 514 /** 515 * IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor 516 * of aFrame or equal to aFrame, looking across document boundaries. 517 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and 518 * aAncestorFrame. If non-null, this can bound the search and speed up 519 * the function. 520 * 521 * Just like IsProperAncestorFrameCrossDoc, except that it returns true when 522 * aFrame == aAncestorFrame. 523 * 524 * TODO: Bug 1700245, all call sites of this function will be eventually 525 * replaced by IsAncestorFrameCrossDocInProcess. 526 */ 527 static bool IsAncestorFrameCrossDoc( 528 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame, 529 const nsIFrame* aCommonAncestor = nullptr); 530 531 /** 532 * IsAncestorFrameCrossDocInProcess checks whether aAncestorFrame is an 533 * ancestor of aFrame or equal to aFrame, looking across document boundaries 534 * in the same process. 535 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and 536 * aAncestorFrame. If non-null, this can bound the search and speed up 537 * the function. 538 * 539 * Just like IsProperAncestorFrameCrossDoc, except that it returns true when 540 * aFrame == aAncestorFrame. 541 * 542 * NOTE: This function doesn't return true even if |aAncestorFrame| and 543 * |aFrame| is in the same process but they are not directly connected, e.g. 544 * both |aAncestorFrame| and |aFrame| in A domain documents, but there's 545 * another an iframe document domain B, such as A1 -> B1 ->A2 document tree. 546 */ 547 static bool IsAncestorFrameCrossDocInProcess( 548 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame, 549 const nsIFrame* aCommonAncestor = nullptr); 550 551 static mozilla::SideBits GetSideBitsForFixedPositionContent( 552 const nsIFrame* aFixedPosFrame); 553 554 /** 555 * Get the scroll id for the root scrollframe of the presshell of the given 556 * prescontext. Returns NULL_SCROLL_ID if it couldn't be found. 557 */ 558 static ViewID ScrollIdForRootScrollFrame(nsPresContext* aPresContext); 559 560 /** 561 * GetScrollContainerFrameFor returns the scroll container frame for a 562 * scrolled frame. 563 */ 564 static mozilla::ScrollContainerFrame* GetScrollContainerFrameFor( 565 const nsIFrame* aScrolledFrame); 566 567 /** 568 * GetNearestScrollableFrameForDirection locates the first ancestor of 569 * aFrame (or aFrame itself) that is scrollable with overflow:scroll or 570 * overflow:auto in the given direction and where either the scrollbar for 571 * that direction is visible or the frame can be scrolled by some 572 * positive amount in that direction. 573 * The search extends across document boundaries. 574 * 575 * @param aFrame the frame to start with 576 * @param aDirection Whether it's for horizontal or vertical scrolling. 577 * @return the nearest scroll container frame or nullptr if not found 578 */ 579 static mozilla::ScrollContainerFrame* GetNearestScrollableFrameForDirection( 580 nsIFrame* aFrame, mozilla::layers::ScrollDirections aDirections); 581 582 enum { 583 /** 584 * If the SCROLLABLE_SAME_DOC flag is set, then we only walk the frame tree 585 * up to the root frame in the current document. 586 */ 587 SCROLLABLE_SAME_DOC = 0x01, 588 /** 589 * If the SCROLLABLE_INCLUDE_HIDDEN flag is set then we allow 590 * overflow:hidden scrollframes to be returned as scrollable frames. 591 */ 592 SCROLLABLE_INCLUDE_HIDDEN = 0x02, 593 /** 594 * If the SCROLLABLE_ONLY_ASYNC_SCROLLABLE flag is set, then we only 595 * want to match scrollable frames for which WantAsyncScroll() returns 596 * true. 597 */ 598 SCROLLABLE_ONLY_ASYNC_SCROLLABLE = 0x04, 599 /** 600 * If the SCROLLABLE_ALWAYS_MATCH_ROOT flag is set, then we will always 601 * return the root scrollable frame for the root document (in the current 602 * process) if we encounter it, whether or not it is async scrollable or 603 * overflow: hidden. 604 */ 605 SCROLLABLE_ALWAYS_MATCH_ROOT = 0x08, 606 /** 607 * If the SCROLLABLE_FIXEDPOS_FINDS_ROOT flag is set, then for fixed-pos 608 * frames return the root scrollable frame for that document. 609 */ 610 SCROLLABLE_FIXEDPOS_FINDS_ROOT = 0x10, 611 /** 612 * If the SCROLLABLE_STOP_AT_PAGE flag is set, then we stop searching 613 * for scrollable ancestors when seeing a nsPageFrame. This can be used 614 * to avoid finding the viewport scroll frame in Print Preview (which 615 * would be undesirable as a 'position:sticky' container for content). 616 */ 617 SCROLLABLE_STOP_AT_PAGE = 0x20, 618 }; 619 /** 620 * GetNearestScrollContainerFrame locates the first ancestor of aFrame 621 * (or aFrame itself) that is scrollable with overflow:scroll or 622 * overflow:auto in some direction. 623 * 624 * @param aFrame the frame to start with 625 * @param aFlags if SCROLLABLE_SAME_DOC is set, do not search across 626 * document boundaries. If SCROLLABLE_INCLUDE_HIDDEN is set, include 627 * frames scrollable with overflow:hidden. 628 * @return the nearest scroll container frame or nullptr if not found 629 */ 630 static mozilla::ScrollContainerFrame* GetNearestScrollContainerFrame( 631 nsIFrame* aFrame, uint32_t aFlags = 0); 632 633 /** 634 * GetScrolledRect returns the range of allowable scroll offsets 635 * for aScrolledFrame, assuming the scrollable overflow area is 636 * aScrolledFrameOverflowArea and the scrollport size is aScrollPortSize. 637 */ 638 static nsRect GetScrolledRect(nsIFrame* aScrolledFrame, 639 const nsRect& aScrolledFrameOverflowArea, 640 const nsSize& aScrollPortSize, 641 mozilla::StyleDirection); 642 643 /** 644 * HasPseudoStyle returns true if aContent (whose primary style 645 * context is aComputedStyle) has the aPseudoElement pseudo-style 646 * attached to it; returns false otherwise. 647 * 648 * @param aContent the content node we're looking at 649 * @param aComputedStyle aContent's ComputedStyle 650 * @param aPseudoElement the id of the pseudo style we care about 651 * @param aPresContext the presentation context 652 * @return whether aContent has aPseudoElement style attached to it 653 */ 654 static bool HasPseudoStyle(nsIContent* aContent, 655 ComputedStyle* aComputedStyle, 656 mozilla::PseudoStyleType aPseudoElement, 657 nsPresContext* aPresContext); 658 659 /** 660 * If this frame is a placeholder for a float, then return the float, 661 * otherwise return nullptr. aPlaceholder must be a placeholder frame. 662 */ 663 static nsIFrame* GetFloatFromPlaceholder(nsIFrame* aPlaceholder); 664 665 // Combine aOrigClearType with aNewClearType, but limit the clear types 666 // to UsedClear::Left, Right, Both. 667 static mozilla::UsedClear CombineClearType(mozilla::UsedClear aOrigClearType, 668 mozilla::UsedClear aNewClearType); 669 670 /** 671 * Get the coordinates of a given DOM mouse event, relative to a given 672 * frame. Works only for DOM events generated by WidgetGUIEvents. 673 * @param aDOMEvent the event 674 * @param aFrame the frame to make coordinates relative to 675 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if 676 * for some reason the coordinates for the mouse are not known (e.g., 677 * the event is not a GUI event). 678 */ 679 static nsPoint GetDOMEventCoordinatesRelativeTo( 680 mozilla::dom::Event* aDOMEvent, nsIFrame* aFrame); 681 682 /** 683 * Get the coordinates of a given native mouse event, relative to a given 684 * frame. 685 * @param aEvent the event 686 * @param aFrame the frame to make coordinates relative to 687 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if 688 * for some reason the coordinates for the mouse are not known (e.g., 689 * the event is not a GUI event). 690 */ 691 static nsPoint GetEventCoordinatesRelativeTo( 692 const mozilla::WidgetEvent* aEvent, RelativeTo aFrame); 693 694 /** 695 * Get the coordinates of a given point relative to an event and a 696 * given frame. 697 * @param aEvent the event 698 * @param aPoint the point to get the coordinates relative to 699 * @param aFrame the frame to make coordinates relative to 700 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if 701 * for some reason the coordinates for the mouse are not known (e.g., 702 * the event is not a GUI event). 703 */ 704 static nsPoint GetEventCoordinatesRelativeTo( 705 const mozilla::WidgetEvent* aEvent, 706 const mozilla::LayoutDeviceIntPoint& aPoint, RelativeTo aFrame); 707 708 /** 709 * Get the coordinates of a given point relative to a widget and a 710 * given frame. 711 * @param aWidget the event src widget 712 * @param aPoint the point to get the coordinates relative to 713 * @param aFrame the frame to make coordinates relative to 714 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if 715 * for some reason the coordinates for the mouse are not known (e.g., 716 * the event is not a GUI event). 717 */ 718 static nsPoint GetEventCoordinatesRelativeTo( 719 nsIWidget* aWidget, const mozilla::LayoutDeviceIntPoint& aPoint, 720 RelativeTo aFrame); 721 722 /** 723 * Get the popup frame of a given native mouse event. 724 * @param aRootPresContext only check popups within aRootPresContext or a 725 * descendant 726 * @param aEvent the event. 727 * @return Null, if there is no popup frame at the point, otherwise, 728 * returns top-most popup frame at the point. 729 */ 730 static nsIFrame* GetPopupFrameForEventCoordinates( 731 nsPresContext* aRootPresContext, const mozilla::WidgetEvent* aEvent); 732 733 /** 734 * Get the popup frame of a given point relative to a widget. 735 * @param aRootPresContext only check popups within aRootPresContext or a 736 * descendant 737 * @param aEvent the event. 738 * @return Null, if there is no popup frame at the point, otherwise, 739 * returns top-most popup frame at the point. 740 */ 741 enum class GetPopupFrameForPointFlags : uint8_t { 742 OnlyReturnFramesWithWidgets = 0x1, 743 }; 744 static nsMenuPopupFrame* GetPopupFrameForPoint( 745 nsPresContext* aRootPresContext, nsIWidget* aWidget, 746 const mozilla::LayoutDeviceIntPoint& aPoint, 747 GetPopupFrameForPointFlags aFlags = GetPopupFrameForPointFlags(0)); 748 749 /** 750 * Get container and offset if aEvent collapses Selection. 751 * @param aPresShell The PresShell handling aEvent. 752 * @param aEvent The event having coordinates where you want to 753 * collapse Selection. 754 * @param aContainer Returns the container node at the point. 755 * Set nullptr if you don't need this. 756 * @param aOffset Returns offset in the container node at the point. 757 * Set nullptr if you don't need this. 758 */ 759 MOZ_CAN_RUN_SCRIPT 760 static void GetContainerAndOffsetAtEvent(PresShell* aPresShell, 761 const mozilla::WidgetEvent* aEvent, 762 nsIContent** aContainer, 763 int32_t* aOffset); 764 765 static mozilla::LayoutDeviceIntPoint WidgetToWidgetOffset( 766 nsIWidget* aFromWidget, nsIWidget* aToWidget); 767 768 static mozilla::Maybe<nsPoint> FrameToWidgetOffset(const nsIFrame* aFrame, 769 nsIWidget* aWidget); 770 771 enum class FrameForPointOption { 772 /** 773 * When set, paint suppression is ignored, so we'll return non-root page 774 * elements even if paint suppression is stopping them from painting. 775 */ 776 IgnorePaintSuppression = 1, 777 /** 778 * When set, clipping due to the root scroll frame (and any other viewport- 779 * related clipping) is ignored. 780 */ 781 IgnoreRootScrollFrame, 782 /** 783 * When set, return only content in the same document as aFrame. 784 */ 785 IgnoreCrossDoc, 786 /** 787 * When set, return only content that is actually visible. 788 */ 789 OnlyVisible, 790 }; 791 792 struct FrameForPointOptions { 793 using Bits = mozilla::EnumSet<FrameForPointOption>; 794 795 Bits mBits; 796 // If mBits contains OnlyVisible, what is the opacity threshold which we 797 // consider "opaque enough" to clobber stuff underneath. 798 float mVisibleThreshold; 799 800 FrameForPointOptions(Bits aBits, float aVisibleThreshold) 801 : mBits(aBits), mVisibleThreshold(aVisibleThreshold) {}; 802 803 MOZ_IMPLICIT FrameForPointOptions(Bits aBits) 804 : FrameForPointOptions(aBits, 1.0f) {} 805 806 FrameForPointOptions() : FrameForPointOptions(Bits()) {}; 807 }; 808 809 /** 810 * Given aFrame, the root frame of a stacking context, find its descendant 811 * frame under the point aPt that receives a mouse event at that location, 812 * or nullptr if there is no such frame. 813 * @param aPt the point, relative to the frame origin, in either visual 814 * or layout coordinates depending on aRelativeTo.mViewportType 815 */ 816 static nsIFrame* GetFrameForPoint(RelativeTo aRelativeTo, nsPoint aPt, 817 const FrameForPointOptions& = {}); 818 819 /** 820 * Given aFrame, the root frame of a stacking context, find all descendant 821 * frames under the area of a rectangle that receives a mouse event, 822 * or nullptr if there is no such frame. 823 * @param aRect the rect, relative to the frame origin, in either visual 824 * or layout coordinates depending on aRelativeTo.mViewportType 825 * @param aOutFrames an array to add all the frames found 826 */ 827 static nsresult GetFramesForArea(RelativeTo aRelativeTo, const nsRect& aRect, 828 nsTArray<nsIFrame*>& aOutFrames, 829 const FrameForPointOptions& = {}); 830 831 /** 832 * Transform aRect relative to aFrame up to the coordinate system of 833 * aAncestor. Computes the bounding-box of the true quadrilateral. 834 * Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if 835 * we only need to use a 2d transform that PreservesAxisAlignedRectangles(). 836 * The corner positions of aRect are treated as meaningful even if aRect is 837 * empty. 838 * 839 * |aMatrixCache| allows for optimizations in recomputing the same matrix over 840 * and over. The argument can be one of the following values: 841 * 842 * nullptr (the default) - No optimization; the transform matrix is computed 843 * on every call to this function. 844 * 845 * non-null pointer to an empty Maybe<Matrix4x4> - Upon return, the Maybe is 846 * filled with the transform matrix that was computed. This can then be passed 847 * in to subsequent calls with the same source and destination frames to avoid 848 * recomputing the matrix. 849 * 850 * non-null pointer to a non-empty Matrix4x4 - The provided matrix will be 851 * used as the transform matrix and applied to the rect. 852 */ 853 static nsRect TransformFrameRectToAncestor( 854 const nsIFrame* aFrame, const nsRect& aRect, const nsIFrame* aAncestor, 855 bool* aPreservesAxisAlignedRectangles = nullptr, 856 mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr, 857 bool aStopAtStackingContextAndDisplayPortAndOOFFrame = false, 858 nsIFrame** aOutAncestor = nullptr) { 859 return TransformFrameRectToAncestor( 860 aFrame, aRect, RelativeTo{aAncestor}, aPreservesAxisAlignedRectangles, 861 aMatrixCache, aStopAtStackingContextAndDisplayPortAndOOFFrame, 862 aOutAncestor); 863 } 864 static nsRect TransformFrameRectToAncestor( 865 const nsIFrame* aFrame, const nsRect& aRect, RelativeTo aAncestor, 866 bool* aPreservesAxisAlignedRectangles = nullptr, 867 mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr, 868 bool aStopAtStackingContextAndDisplayPortAndOOFFrame = false, 869 nsIFrame** aOutAncestor = nullptr); 870 871 /** 872 * Gets the transform for aFrame relative to aAncestor. Pass null for 873 * aAncestor to go up to the root frame. Including nsIFrame::IN_CSS_UNITS 874 * flag in aFlags will return CSS pixels, by default it returns device 875 * pixels. 876 * More info can be found in nsIFrame::GetTransformMatrix. 877 * 878 * Some notes on the possible combinations of |aFrame.mViewportType| and 879 * |aAncestor.mViewportType|: 880 * 881 * | aFrame. | aAncestor. | Notes 882 * | mViewportType | mViewportType | 883 * ========================================================================== 884 * | Layout | Layout | Commonplace, when both source and target 885 * | | | are inside zoom boundary. 886 * | | | 887 * | | | Could also happen in non-e10s setups 888 * | | | when both source and target are outside 889 * | | | the zoom boundary and the code is 890 * | | | oblivious to the existence of a zoom 891 * | | | boundary. 892 * ========================================================================== 893 * | Layout | Visual | Commonplace, used when hit testing visual 894 * | | | coordinates (e.g. coming from user input 895 * | | | events). We expected to encounter a 896 * | | | zoomed content root during traversal and 897 * | | | apply a layout-to-visual transform. 898 * ========================================================================== 899 * | Visual | Layout | Should never happen, will assert. 900 * ========================================================================== 901 * | Visual | Visual | In e10s setups, should only happen if 902 * | | | aFrame and aAncestor are both the 903 * | | | RCD viewport frame. 904 * | | | 905 * | | | In non-e10s setups, could happen with 906 * | | | different frames if they are both 907 * | | | outside the zoom boundary. 908 * ========================================================================== 909 */ 910 static Matrix4x4Flagged GetTransformToAncestor( 911 RelativeTo aFrame, RelativeTo aAncestor, uint32_t aFlags = 0, 912 nsIFrame** aOutAncestor = nullptr); 913 914 /** 915 * Gets the scale factors of the transform for aFrame relative to the root 916 * frame if this transform can be drawn 2D, or the identity scale factors 917 * otherwise. 918 */ 919 static MatrixScales GetTransformToAncestorScale(const nsIFrame* aFrame); 920 921 /** 922 * Gets the scale factors of the transform for aFrame relative to the root 923 * frame if this transform is 2D, or the identity scale factors otherwise. 924 * If some frame on the path from aFrame to the display root frame may have an 925 * animated scale, returns the identity scale factors. 926 */ 927 static MatrixScales GetTransformToAncestorScaleExcludingAnimated( 928 nsIFrame* aFrame); 929 930 /** 931 * Gets a scale that includes CSS transforms in this process as well as the 932 * transform to ancestor scale passed down from our direct ancestor process 933 * (which includes any enclosing CSS transforms and resolution). Note: this 934 * does not include any resolution in the current process (this is on purpose 935 * because that is what the transform to ancestor field on FrameMetrics needs, 936 * see its definition for explanation as to why). This is the transform to 937 * ancestor scale to set on FrameMetrics. 938 */ 939 static mozilla::ParentLayerToScreenScale2D 940 GetTransformToAncestorScaleCrossProcessForFrameMetrics( 941 const nsIFrame* aFrame); 942 943 /** 944 * Find the nearest common ancestor frame for aFrame1 and aFrame2. The 945 * ancestor frame could be cross-doc. 946 */ 947 static const nsIFrame* FindNearestCommonAncestorFrame( 948 const nsIFrame* aFrame1, const nsIFrame* aFrame2); 949 950 /** 951 * Find the nearest common ancestor frame for aFrame1 and aFrame2, assuming 952 * that they are within the same block. 953 * 954 * Returns null if they are not within the same block. 955 */ 956 static const nsIFrame* FindNearestCommonAncestorFrameWithinBlock( 957 const nsTextFrame* aFrame1, const nsTextFrame* aFrame2); 958 959 /** 960 * Whether author-specified borders / backgrounds disable theming for a given 961 * appearance value. 962 */ 963 static bool AuthorSpecifiedBorderBackgroundDisablesTheming( 964 mozilla::StyleAppearance); 965 966 /** 967 * Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into 968 * account all relevant transformations on the frames up to (but excluding) 969 * their nearest common ancestor. 970 * If we encounter a transform that we need to invert but which is 971 * non-invertible, we return NONINVERTIBLE_TRANSFORM. If the frames have 972 * no common ancestor, we return NO_COMMON_ANCESTOR. 973 * If this returns TRANSFORM_SUCCEEDED, the points in aPoints are transformed 974 * in-place, otherwise they are untouched. 975 */ 976 enum TransformResult { 977 TRANSFORM_SUCCEEDED, 978 NO_COMMON_ANCESTOR, 979 NONINVERTIBLE_TRANSFORM 980 }; 981 static TransformResult TransformPoints(RelativeTo aFromFrame, 982 RelativeTo aToFrame, 983 uint32_t aPointCount, 984 CSSPoint* aPoints); 985 986 /** 987 * Same as above function, but transform points in app units and 988 * handle 1 point per call. 989 */ 990 static TransformResult TransformPoint(RelativeTo aFromFrame, 991 RelativeTo aToFrame, nsPoint& aPoint); 992 993 /** 994 * Transforms a rect from aFromFrame to aToFrame. In app units. 995 * Returns the bounds of the actual rect if the transform requires rotation 996 * or anything complex like that. 997 */ 998 static TransformResult TransformRect(const nsIFrame* aFromFrame, 999 const nsIFrame* aToFrame, nsRect& aRect); 1000 1001 /** 1002 * Converts app units to pixels (with optional snapping) and appends as a 1003 * translation to aTransform. 1004 */ 1005 static void PostTranslate(Matrix4x4& aTransform, const nsPoint& aOrigin, 1006 float aAppUnitsPerPixel, bool aRounded); 1007 1008 /* 1009 * Whether the frame should snap to grid. This will end up being passed 1010 * as the aRounded parameter in PostTranslate above. SVG frames should 1011 * not have their translation rounded. 1012 */ 1013 static bool ShouldSnapToGrid(const nsIFrame* aFrame); 1014 1015 /** 1016 * Get the border-box of aElement's primary frame, transformed it to be 1017 * relative to aFrame. 1018 */ 1019 static nsRect GetRectRelativeToFrame(const mozilla::dom::Element* aElement, 1020 const nsIFrame* aFrame); 1021 1022 /** 1023 * Returns true if aRect with border inflation of size aInflateSize contains 1024 * aPoint. 1025 */ 1026 static bool ContainsPoint(const nsRect& aRect, const nsPoint& aPoint, 1027 nscoord aInflateSize); 1028 1029 /** 1030 * Clamp aRect relative to aFrame to the scroll frames boundary searching from 1031 * aFrame. 1032 */ 1033 static nsRect ClampRectToScrollFrames(nsIFrame* aFrame, const nsRect& aRect); 1034 1035 /** 1036 * Given a point in the global coordinate space, returns that point expressed 1037 * in the coordinate system of aFrame. This effectively inverts all 1038 * transforms between this point and the root frame. 1039 * 1040 * @param aFromType Specifies whether |aPoint| is in layout or visual 1041 * coordinates. 1042 * @param aFrame The frame that acts as the coordinate space container. 1043 * @param aPoint The point, in global layout or visual coordinates (as per 1044 * |aFromType|, to get in the frame-local space. 1045 * @return aPoint, expressed in aFrame's canonical coordinate space. 1046 */ 1047 static nsPoint TransformRootPointToFrame(ViewportType aFromType, 1048 RelativeTo aFrame, 1049 const nsPoint& aPoint) { 1050 return TransformAncestorPointToFrame(aFrame, aPoint, 1051 RelativeTo{nullptr, aFromType}); 1052 } 1053 1054 /** 1055 * Transform aPoint relative to aAncestor down to the coordinate system of 1056 * aFrame. 1057 */ 1058 static nsPoint TransformAncestorPointToFrame(RelativeTo aFrame, 1059 const nsPoint& aPoint, 1060 RelativeTo aAncestor); 1061 1062 static nsPoint TransformFramePointToRoot(ViewportType aToType, 1063 RelativeTo aFromFrame, 1064 const nsPoint& aPoint); 1065 1066 /** 1067 * Helper function that, given a rectangle and a matrix, returns the smallest 1068 * rectangle containing the image of the source rectangle. 1069 * 1070 * @param aBounds The rectangle to transform. 1071 * @param aMatrix The matrix to transform it with. 1072 * @param aFactor The number of app units per graphics unit. 1073 * @return The smallest rect that contains the image of aBounds. 1074 */ 1075 static nsRect MatrixTransformRect(const nsRect& aBounds, 1076 const Matrix4x4& aMatrix, float aFactor); 1077 static nsRect MatrixTransformRect(const nsRect& aBounds, 1078 const Matrix4x4Flagged& aMatrix, 1079 float aFactor); 1080 1081 /** 1082 * Helper function that, given a point and a matrix, returns the image 1083 * of that point under the matrix transform. 1084 * 1085 * @param aPoint The point to transform. 1086 * @param aMatrix The matrix to transform it with. 1087 * @param aFactor The number of app units per graphics unit. 1088 * @return The image of the point under the transform. 1089 */ 1090 static nsPoint MatrixTransformPoint(const nsPoint& aPoint, 1091 const Matrix4x4& aMatrix, float aFactor); 1092 1093 /** 1094 * Given a graphics rectangle in graphics space, return a rectangle in 1095 * app space that contains the graphics rectangle, rounding out as necessary. 1096 * 1097 * @param aRect The graphics rect to round outward. 1098 * @param aFactor The number of app units per graphics unit. 1099 * @return The smallest rectangle in app space that contains aRect. 1100 */ 1101 template <typename T> 1102 static nsRect RoundGfxRectToAppRect(const T& aRect, const float aFactor); 1103 1104 /** 1105 * Like the above but slightly different scale and round behaviour. First 1106 * scales, then constrains to nscoord, then rounds each component (x, y, 1107 * width, height) individually. 1108 * 1109 * @param aRect The graphics rect to round outward. 1110 * @param aFactor The number of app units per graphics unit. 1111 * @return The rounaded rectangle in app space. 1112 */ 1113 template <typename T> 1114 static nsRect ScaleThenRoundGfxRectToAppRect(const T& aRect, 1115 const float aFactor); 1116 1117 /** 1118 * Returns a subrectangle of aContainedRect that is entirely inside the 1119 * rounded rect. Complex cases are handled conservatively by returning a 1120 * smaller rect than necessary. 1121 */ 1122 static nsRegion RoundedRectIntersectRect(const nsRect& aRoundedRect, 1123 const nsRectCornerRadii&, 1124 const nsRect& aContainedRect); 1125 static nsIntRegion RoundedRectIntersectIntRect( 1126 const nsIntRect& aRoundedRect, const RectCornerRadii& aCornerRadii, 1127 const nsIntRect& aContainedRect); 1128 1129 /** 1130 * Return whether any part of aTestRect is inside of the rounded 1131 * rectangle formed by aBounds and aRadii (which are indexed by the 1132 * enum HalfCorner constants in gfx/2d/Types.h). This is precise. 1133 */ 1134 static bool RoundedRectIntersectsRect(const nsRect& aRoundedRect, 1135 const nsRectCornerRadii&, 1136 const nsRect& aTestRect); 1137 1138 enum class PaintFrameFlags : uint32_t { 1139 InTransform = 0x01, 1140 SyncDecodeImages = 0x02, 1141 WidgetLayers = 0x04, 1142 IgnoreSuppression = 0x08, 1143 DocumentRelative = 0x10, 1144 HideCaret = 0x20, 1145 ToWindow = 0x40, 1146 ExistingTransaction = 0x80, 1147 ForWebRender = 0x100, 1148 UseHighQualityScaling = 0x200, 1149 ResetViewportScrolling = 0x400, 1150 CompositeOffscreen = 0x800, 1151 }; 1152 1153 /** 1154 * Given aFrame, the root frame of a stacking context, paint it and its 1155 * descendants to aRenderingContext. 1156 * @param aRenderingContext a rendering context translated so that (0,0) 1157 * is the origin of aFrame; for best results, (0,0) should transform 1158 * to pixel-aligned coordinates. This can be null, in which case 1159 * aFrame must be a "display root" (root frame for a root document, 1160 * or the root of a popup) with an associated widget and we draw using 1161 * the layer manager for the frame's widget. 1162 * @param aDirtyRegion the region that must be painted, in the coordinates 1163 * of aFrame. 1164 * @param aBackstop paint the dirty area with this color before drawing 1165 * the actual content; pass NS_RGBA(0,0,0,0) to draw no background. 1166 * @param aBuilderMode Passed through to the display-list builder. 1167 * @param aFlags if PAINT_IN_TRANSFORM is set, then we assume 1168 * this is inside a transform or SVG foreignObject. If 1169 * PAINT_SYNC_DECODE_IMAGES is set, we force synchronous decode on all 1170 * images. If PAINT_WIDGET_LAYERS is set, aFrame must be a display root, 1171 * and we will use the frame's widget's layer manager to paint 1172 * even if aRenderingContext is non-null. This is useful if you want 1173 * to force rendering to use the widget's layer manager for testing 1174 * or speed. PAINT_WIDGET_LAYERS must be set if aRenderingContext is null. 1175 * If PAINT_DOCUMENT_RELATIVE is used, the visible region is interpreted 1176 * as being relative to the document (normally it's relative to the CSS 1177 * viewport) and the document is painted as if no scrolling has occured. 1178 * Only considered if PresShell::IgnoringViewportScrolling is true. 1179 * If ResetViewportScrolling is used, then the root scroll frame's scroll 1180 * position is set to 0 during painting, so that position:fixed elements 1181 * are drawn in their initial position. 1182 * PAINT_TO_WINDOW sets painting to window to true on the display list 1183 * builder even if we can't tell that we are painting to the window. 1184 * If PAINT_EXISTING_TRANSACTION is set, then BeginTransaction() has already 1185 * been called on aFrame's widget's layer manager and should not be 1186 * called again. 1187 * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to 1188 * compressed mode to avoid short cut optimizations. 1189 * 1190 * So there are three possible behaviours: 1191 * 1) PAINT_WIDGET_LAYERS is set and aRenderingContext is null; we paint 1192 * by calling BeginTransaction on the widget's layer manager. 1193 * 2) PAINT_WIDGET_LAYERS is set and aRenderingContext is non-null; we 1194 * paint by calling BeginTransactionWithTarget on the widget's layer 1195 * manager. 1196 * 3) PAINT_WIDGET_LAYERS is not set and aRenderingContext is non-null; 1197 * we paint by construct a BasicLayerManager and calling 1198 * BeginTransactionWithTarget on it. This is desirable if we're doing 1199 * something like drawWindow in a mode where what gets rendered doesn't 1200 * necessarily correspond to what's visible in the window; we don't 1201 * want to mess up the widget's layer tree. 1202 */ 1203 static void PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame, 1204 const nsRegion& aDirtyRegion, nscolor aBackstop, 1205 nsDisplayListBuilderMode aBuilderMode, 1206 PaintFrameFlags aFlags = PaintFrameFlags(0)); 1207 1208 /** 1209 * Uses a binary search for find where the cursor falls in the line of text 1210 * It also keeps track of the part of the string that has already been 1211 * measured so it doesn't have to keep measuring the same text over and over. 1212 * 1213 * @param "aBaseWidth" contains the width in twips of the portion 1214 * of the text that has already been measured, and aBaseInx contains 1215 * the index of the text that has already been measured. 1216 * 1217 * @param aTextWidth returns (in twips) the length of the text that falls 1218 * before the cursor aIndex contains the index of the text where the cursor 1219 * falls. 1220 */ 1221 static bool BinarySearchForPosition(DrawTarget* aDrawTarget, 1222 nsFontMetrics& aFontMetrics, 1223 const char16_t* aText, int32_t aBaseWidth, 1224 int32_t aBaseInx, int32_t aStartInx, 1225 int32_t aEndInx, int32_t aCursorPos, 1226 int32_t& aIndex, int32_t& aTextWidth); 1227 1228 class BoxCallback { 1229 public: 1230 BoxCallback() = default; 1231 virtual void AddBox(nsIFrame* aFrame) = 0; 1232 bool mIncludeCaptionBoxForTable = true; 1233 // Whether we are in a continuation or ib-split-sibling of the target we're 1234 // measuring. This is useful because if we know we're in the target subtree 1235 // and measuring against it we can avoid finding the common ancestor. 1236 bool mInTargetContinuation = false; 1237 }; 1238 /** 1239 * Collect all CSS boxes associated with aFrame and its 1240 * continuations, "drilling down" through table wrapper frames and 1241 * some anonymous blocks since they're not real CSS boxes. 1242 * If aFrame is null, no boxes are returned. 1243 * SVG frames return a single box, themselves. 1244 */ 1245 static void GetAllInFlowBoxes(nsIFrame* aFrame, BoxCallback* aCallback); 1246 1247 /** 1248 * Like GetAllInFlowBoxes, but doesn't include continuations. 1249 */ 1250 static void AddBoxesForFrame(nsIFrame* aFrame, BoxCallback* aCallback); 1251 1252 /** 1253 * Find the first frame descendant of aFrame (including aFrame) which is 1254 * not an anonymous frame that getBoxQuads/getClientRects should ignore. 1255 */ 1256 static nsIFrame* GetFirstNonAnonymousFrame(nsIFrame* aFrame); 1257 1258 struct RectAccumulator : public mozilla::RectCallback { 1259 nsRect mResultRect; 1260 nsRect mFirstRect; 1261 bool mSeenFirstRect; 1262 1263 RectAccumulator(); 1264 1265 virtual void AddRect(const nsRect& aRect) override; 1266 }; 1267 1268 struct RectListBuilder : public mozilla::RectCallback { 1269 DOMRectList* mRectList; 1270 1271 explicit RectListBuilder(DOMRectList* aList); 1272 virtual void AddRect(const nsRect& aRect) override; 1273 }; 1274 1275 static nsIFrame* GetContainingBlockForClientRect(nsIFrame* aFrame); 1276 1277 /** 1278 * Collect all CSS boxes (content, padding, border, or margin) associated 1279 * with aFrame and its continuations, "drilling down" through table wrapper 1280 * frames and some anonymous blocks since they're not real CSS boxes. 1281 * 1282 * The boxes are positioned relative to aRelativeTo (taking scrolling 1283 * into account) and passed to the callback in frame-tree order. 1284 * If aFrame is null, no boxes are returned. 1285 * 1286 * For SVG frames, returns one rectangle, the bounding box. 1287 * 1288 * If aFlags includes 'AccountForTransforms', then when converting the boxes 1289 * into aRelativeTo coordinates, transforms (including CSS and SVG transforms) 1290 * are taken into account. 1291 * 1292 * If aFlags includes one of 'UseContentBox', 'UsePaddingBox', 'UseMarginBox', 1293 * or 'UseMarginBoxWithAutoResolvedAsZero', the corresponding type of box is 1294 * used. Otherwise (by default), the border box is used. Note that these "Box" 1295 * flags are meant to be mutually exclusive, though we don't enforce that. If 1296 * multiple "Box" flags are used, we'll gracefully just use the first one in 1297 * the order of the enum. 1298 */ 1299 enum class GetAllInFlowRectsFlag : uint8_t { 1300 AccountForTransforms, 1301 UseContentBox, 1302 UsePaddingBox, 1303 UseMarginBox, 1304 // Similar to UseMarginBox, but the 'auto' margins are resolved as zero. 1305 UseMarginBoxWithAutoResolvedAsZero, 1306 }; 1307 using GetAllInFlowRectsFlags = mozilla::EnumSet<GetAllInFlowRectsFlag>; 1308 static void GetAllInFlowRects(nsIFrame* aFrame, const nsIFrame* aRelativeTo, 1309 mozilla::RectCallback* aCallback, 1310 GetAllInFlowRectsFlags aFlags = {}); 1311 1312 static void GetAllInFlowRectsAndTexts( 1313 nsIFrame* aFrame, const nsIFrame* aRelativeTo, 1314 mozilla::RectCallback* aCallback, 1315 mozilla::dom::Sequence<nsString>* aTextList, 1316 GetAllInFlowRectsFlags aFlags = {}); 1317 1318 /** 1319 * Computes the union of all rects returned by GetAllInFlowRects. If 1320 * the union is empty, returns the first rect. 1321 * 1322 * See GetAllInFlowRects() documentation for the meaning of aRelativeTo and 1323 * aFlags. 1324 */ 1325 static nsRect GetAllInFlowRectsUnion(nsIFrame* aFrame, 1326 const nsIFrame* aRelativeTo, 1327 GetAllInFlowRectsFlags aFlags = {}); 1328 1329 enum { EXCLUDE_BLUR_SHADOWS = 0x01 }; 1330 /** 1331 * Takes a text-shadow array from the style properties of a given nsIFrame and 1332 * computes the union of those shadows along with the given initial rect. 1333 * If there are no shadows, the initial rect is returned. 1334 */ 1335 static nsRect GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect, 1336 nsIFrame* aFrame, uint32_t aFlags = 0); 1337 1338 /** 1339 * Computes the destination rect that a given replaced element should render 1340 * into, based on its CSS 'object-fit' and 'object-position' properties. 1341 * 1342 * @param aConstraintRect The constraint rect that we have at our disposal, 1343 * which would e.g. be exactly filled by the image 1344 * if we had "object-fit: fill". 1345 * @param aIntrinsicSize The replaced content's intrinsic size, as reported 1346 * by nsIFrame::GetIntrinsicSize(). 1347 * @param aIntrinsicRatio The replaced content's intrinsic ratio, as reported 1348 * by nsIFrame::GetIntrinsicRatio(). 1349 * @param aStylePos The nsStylePosition struct that contains the 'object-fit' 1350 * and 'object-position' values that we should rely on. 1351 * (This should usually be the nsStylePosition for the 1352 * replaced element in question, but not always. For 1353 * example, a <video>'s poster-image has a dedicated 1354 * anonymous element & child-frame, but we should still use 1355 * the <video>'s 'object-fit' and 'object-position' values.) 1356 * @param aAnchorPoint [out] A point that should be pixel-aligned by functions 1357 * like nsLayoutUtils::DrawImage. See documentation 1358 * in nsCSSRendering.h for ComputeObjectAnchorPoint. 1359 * @return The nsRect into which we should render the replaced content (using 1360 * the same coordinate space as the passed-in aConstraintRect). 1361 */ 1362 static nsRect ComputeObjectDestRect(const nsRect& aConstraintRect, 1363 const IntrinsicSize& aIntrinsicSize, 1364 const AspectRatio& aIntrinsicRatio, 1365 const nsStylePosition* aStylePos, 1366 nsPoint* aAnchorPoint = nullptr); 1367 1368 /** 1369 * Get the font metrics corresponding to the frame's style data. 1370 * @param aFrame the frame 1371 * @param aSizeInflation number to multiply font size by 1372 */ 1373 static already_AddRefed<nsFontMetrics> GetFontMetricsForFrame( 1374 const nsIFrame* aFrame, float aSizeInflation); 1375 1376 static already_AddRefed<nsFontMetrics> GetInflatedFontMetricsForFrame( 1377 const nsIFrame* aFrame) { 1378 return GetFontMetricsForFrame(aFrame, FontSizeInflationFor(aFrame)); 1379 } 1380 1381 /** 1382 * Get the font metrics corresponding to the given style data. 1383 * @param aComputedStyle the style data 1384 * @param aSizeInflation number to multiply font size by 1385 */ 1386 static already_AddRefed<nsFontMetrics> GetFontMetricsForComputedStyle( 1387 const ComputedStyle* aComputedStyle, nsPresContext* aPresContext, 1388 float aSizeInflation = 1.0f, 1389 uint8_t aVariantWidth = NS_FONT_VARIANT_WIDTH_NORMAL); 1390 1391 /** 1392 * Get the font metrics of emphasis marks corresponding to the given 1393 * style data. The result is same as GetFontMetricsForComputedStyle 1394 * except that the font size is scaled down to 50%. 1395 * @param aComputedStyle the style data 1396 * @param aInflation number to multiple font size by 1397 */ 1398 static already_AddRefed<nsFontMetrics> GetFontMetricsOfEmphasisMarks( 1399 ComputedStyle* aComputedStyle, nsPresContext* aPresContext, 1400 float aInflation) { 1401 return GetFontMetricsForComputedStyle(aComputedStyle, aPresContext, 1402 aInflation * 0.5f); 1403 } 1404 1405 /** 1406 * Find the immediate child of aParent whose frame subtree contains 1407 * aDescendantFrame. Returns null if aDescendantFrame is not a descendant 1408 * of aParent. 1409 */ 1410 static nsIFrame* FindChildContainingDescendant(nsIFrame* aParent, 1411 nsIFrame* aDescendantFrame); 1412 1413 /** 1414 * Find the nearest ancestor that's a block 1415 */ 1416 static nsBlockFrame* FindNearestBlockAncestor(nsIFrame* aFrame); 1417 1418 /* 1419 * Whether the frame is an nsBlockFrame which is not a wrapper block. 1420 */ 1421 static bool IsNonWrapperBlock(nsIFrame* aFrame); 1422 1423 /** 1424 * If aFrame is an out of flow frame, return its placeholder, otherwise 1425 * return its parent. 1426 */ 1427 static nsIFrame* GetParentOrPlaceholderFor(const nsIFrame* aFrame); 1428 1429 /** 1430 * If aFrame is an out of flow frame, return its placeholder, otherwise 1431 * return its (possibly cross-doc) parent. 1432 */ 1433 static nsIFrame* GetParentOrPlaceholderForCrossDoc(const nsIFrame* aFrame); 1434 1435 /** 1436 * Returns the frame that would act as the parent of aFrame when 1437 * descending through the frame tree in display list building. 1438 * Usually the same as GetParentOrPlaceholderForCrossDoc, except 1439 * that pushed floats are treated as children of their containing 1440 * block. 1441 */ 1442 static nsIFrame* GetDisplayListParent(nsIFrame* aFrame); 1443 1444 /** 1445 * Get a frame's previous continuation, or, if it doesn't have one, its 1446 * previous block-in-inline-split sibling. 1447 */ 1448 static nsIFrame* GetPrevContinuationOrIBSplitSibling(const nsIFrame* aFrame); 1449 1450 /** 1451 * Get a frame's next continuation, or, if it doesn't have one, its 1452 * block-in-inline-split sibling. 1453 */ 1454 static nsIFrame* GetNextContinuationOrIBSplitSibling(const nsIFrame* aFrame); 1455 1456 /** 1457 * Get the first frame in the continuation-plus-ib-split-sibling chain 1458 * containing aFrame. 1459 */ 1460 static nsIFrame* FirstContinuationOrIBSplitSibling(const nsIFrame* aFrame); 1461 1462 /** 1463 * Get the last frame in the continuation-plus-ib-split-sibling chain 1464 * containing aFrame. 1465 */ 1466 static nsIFrame* LastContinuationOrIBSplitSibling(const nsIFrame* aFrame); 1467 1468 /** 1469 * Is FirstContinuationOrIBSplitSibling(aFrame) going to return 1470 * aFrame? 1471 */ 1472 static bool IsFirstContinuationOrIBSplitSibling(const nsIFrame* aFrame); 1473 1474 /** 1475 * Check whether aFrame is a part of the scrollbar or scrollcorner of 1476 * the root content. 1477 * @param aFrame the checking frame. 1478 * @return true if the frame is a part of the scrollbar or scrollcorner of 1479 * the root content. 1480 */ 1481 static bool IsViewportScrollbarFrame(nsIFrame* aFrame); 1482 1483 /** 1484 * Use only for paddings / widths / heights, since it clamps negative calc() 1485 * to 0. 1486 */ 1487 template <typename LengthPercentageLike> 1488 static mozilla::Maybe<nscoord> GetAbsoluteSize( 1489 const LengthPercentageLike& aSize) { 1490 if (!aSize.ConvertsToLength()) { 1491 return mozilla::Nothing(); 1492 } 1493 return mozilla::Some(std::max(0, aSize.ToLength())); 1494 } 1495 1496 /** 1497 * Get the contribution of aFrame to its containing block's intrinsic 1498 * size for the given physical axis. This considers the child's intrinsic 1499 * width, its 'width', 'min-width', and 'max-width' properties (or 'height' 1500 * variations if that's what matches aAxis) and its padding, border and margin 1501 * in the corresponding dimension. 1502 * @param aPercentageBasis an optional percentage basis (in aFrame's WM). 1503 * If the basis is indefinite in a given axis, pass a size with 1504 * NS_UNCONSTRAINEDSIZE in that component. 1505 * If you pass Nothing() a percentage basis will be calculated from aFrame's 1506 * ancestors' computed size in the relevant axis, if needed. 1507 * @param aMarginBoxMinSizeClamp make the result fit within this margin-box 1508 * size by reducing the *content size* (flooring at zero). This is used for: 1509 * https://drafts.csswg.org/css-grid/#min-size-auto 1510 * @param aSizeOverrides optional override values for size properties, which 1511 * this function will use internally instead of the actual property values. 1512 */ 1513 enum { 1514 IGNORE_PADDING = 0x01, 1515 BAIL_IF_REFLOW_NEEDED = 0x02, // returns NS_INTRINSIC_ISIZE_UNKNOWN if so 1516 }; 1517 static nscoord IntrinsicForAxis( 1518 mozilla::PhysicalAxis aAxis, gfxContext* aRenderingContext, 1519 nsIFrame* aFrame, mozilla::IntrinsicISizeType aType, 1520 const mozilla::Maybe<LogicalSize>& aPercentageBasis = mozilla::Nothing(), 1521 uint32_t aFlags = 0, nscoord aMarginBoxMinSizeClamp = NS_MAXSIZE, 1522 const mozilla::StyleSizeOverrides& aSizeOverrides = {}); 1523 /** 1524 * Calls IntrinsicForAxis with aFrame's parent's inline physical axis. 1525 */ 1526 static nscoord IntrinsicForContainer( 1527 gfxContext* aRenderingContext, nsIFrame* aFrame, 1528 mozilla::IntrinsicISizeType aType, 1529 const mozilla::Maybe<LogicalSize>& aPercentageBasis = mozilla::Nothing(), 1530 uint32_t aFlags = 0, 1531 const mozilla::StyleSizeOverrides& aSizeOverrides = {}); 1532 1533 /** 1534 * Get the definite size contribution of aFrame for the given physical axis. 1535 * This considers the child's 'min-width' property (or 'min-height' if the 1536 * given axis is vertical), and its padding, border, and margin in the 1537 * corresponding dimension. If the 'min-' property is 'auto' (and 'overflow' 1538 * is 'visible') and the corresponding 'width'/'height' is definite it returns 1539 * the "specified size" for: 1540 * https://drafts.csswg.org/css-grid/#min-size-auto 1541 * Note that the "transferred size" is not handled here; use IntrinsicForAxis. 1542 * Note that any percentage in 'width'/'height' makes it count as indefinite. 1543 * If the 'min-' property is 'auto' and 'overflow' is not 'visible', then it 1544 * calculates the result as if the 'min-' computed value is zero. 1545 * Otherwise, return NS_UNCONSTRAINEDSIZE. 1546 * 1547 * @param aPercentageBasis the percentage basis (in aFrame's WM). 1548 * Pass NS_UNCONSTRAINEDSIZE if the basis is indefinite in either/both axes. 1549 * @note this behavior is specific to Grid/Flexbox (currently) so aFrame 1550 * should be a grid/flex item. 1551 */ 1552 static nscoord MinSizeContributionForAxis(mozilla::PhysicalAxis aAxis, 1553 gfxContext* aRC, nsIFrame* aFrame, 1554 mozilla::IntrinsicISizeType aType, 1555 const LogicalSize& aPercentageBasis, 1556 uint32_t aFlags = 0); 1557 1558 /* 1559 * Convert LengthPercentage to nscoord when percentages depend on the 1560 * containing block size. 1561 * @param aPercentBasis The width or height of the containing block 1562 * (whichever the client wants to use for resolving percentages). 1563 */ 1564 static nscoord ComputeCBDependentValue(nscoord aPercentBasis, 1565 const LengthPercentage& aCoord) { 1566 NS_ASSERTION(aPercentBasis != NS_UNCONSTRAINEDSIZE || !aCoord.HasPercent(), 1567 "Have unconstrained percentage basis when percentage " 1568 "resolution needed; this should only result from very " 1569 "large sizes, not attempts at intrinsic size calculation"); 1570 return aCoord.Resolve(aPercentBasis); 1571 } 1572 static nscoord ComputeCBDependentValue(nscoord aPercentBasis, 1573 const LengthPercentageOrAuto& aCoord) { 1574 if (aCoord.IsAuto()) { 1575 return 0; 1576 } 1577 return ComputeCBDependentValue(aPercentBasis, aCoord.AsLengthPercentage()); 1578 } 1579 1580 static nscoord ComputeCBDependentValue(nscoord aPercentBasis, 1581 const AnchorResolvedInset& aInset) { 1582 if (aInset->IsAuto()) { 1583 // Callers are assumed to have handled other cases already. 1584 return 0; 1585 } 1586 NS_ASSERTION(aPercentBasis != NS_UNCONSTRAINEDSIZE || !aInset->HasPercent(), 1587 "Have unconstrained percentage basis when percentage " 1588 "resolution needed; this should only result from very " 1589 "large sizes, not attempts at intrinsic size calculation"); 1590 return aInset->AsLengthPercentage().Resolve(aPercentBasis); 1591 } 1592 1593 static nscoord ComputeCBDependentValue(nscoord aPercentBasis, 1594 const AnchorResolvedMargin& aMargin) { 1595 if (!aMargin->IsLengthPercentage()) { 1596 MOZ_ASSERT(aMargin->IsAuto(), "Didn't resolve anchor functions first?"); 1597 return 0; 1598 } 1599 return ComputeCBDependentValue(aPercentBasis, 1600 aMargin->AsLengthPercentage()); 1601 } 1602 1603 static nscoord ComputeBSizeValue(nscoord aContainingBlockBSize, 1604 nscoord aContentEdgeToBoxSizingBoxEdge, 1605 const LengthPercentage& aCoord) { 1606 MOZ_ASSERT(aContainingBlockBSize != nscoord_MAX || !aCoord.HasPercent(), 1607 "caller must deal with %% of unconstrained block-size"); 1608 1609 nscoord result = aCoord.Resolve(aContainingBlockBSize); 1610 // Clamp calc(), and the subtraction for box-sizing. 1611 return std::max(0, result - aContentEdgeToBoxSizingBoxEdge); 1612 } 1613 1614 // Wrapper for ComputeBSizeValue that also handles 'stretch': 1615 template <typename SizeOrMaxSize> 1616 static nscoord ComputeBSizeValueHandlingStretch( 1617 nscoord aContainingBlockBSize, nscoord aMargin, nscoord aBorderPadding, 1618 nscoord aContentEdgeToBoxSizingBoxEdge, const SizeOrMaxSize& aSize) { 1619 if (aSize.BehavesLikeStretchOnBlockAxis()) { 1620 // Note: we don't need to worry about accounting for "box-sizing" when 1621 // resolving 'stretch' here. This function unconditionally returns a 1622 // content-box size, and the content-box size of a stretched element is 1623 // the same regardless of whether whether the author is conceptually 1624 // asking us to stretch the content box vs. the border-box. 1625 return ComputeStretchContentBoxBSize(aContainingBlockBSize, aMargin, 1626 aBorderPadding); 1627 } 1628 return ComputeBSizeValue(aContainingBlockBSize, 1629 aContentEdgeToBoxSizingBoxEdge, 1630 aSize.AsLengthPercentage()); 1631 } 1632 1633 /** 1634 * Returns the size that an element's box should take on, in order for its 1635 * margin-box to exactly reach a particular larger size (e.g. to fill its 1636 * containing block in a particular axis). The box in question can be either 1637 * the content-box or the border-box, determined by the aBoxSizing param. 1638 * 1639 * This function can be used to resolve the "stretch" size for the child box, 1640 * for example: https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing 1641 * 1642 * The returned value is floored at 0. 1643 * 1644 * There's a version for ISize and BSize; the only difference is that the 1645 * BSize version has an assertion to be sure that we're not inadvertently 1646 * doing arithmetic with the NS_UNCONSTRAINEDSIZE sentinel value in that 1647 * axis. (This sentinel has special meaning as a block-axis size but not as 1648 * an inline-axis size; hence, the assertion only makes sense for block-axis 1649 * sizes.) 1650 * 1651 * TODO(dholbert): Maybe do minor refactors to use this where we resolve 1652 * 'stretch' alignment in various places, if that feels useful? 1653 * 1654 * @param aSizeToFill 1655 * The size that the child's margin-box should fill, in the axis in 1656 * question -- e.g. the containing block size. Assumed to be a constrained 1657 * size; this function doesn't have any special treatment to handle the 1658 * case where this is unconstrained. 1659 * 1660 * @param aMargin 1661 * The sum of the child box's margins in the axis in question (using zero 1662 * for any margins that should be ignored in computing the 'stretch' size; 1663 * see bug 1932993 for one special case where this should happen). 1664 * 1665 * @param aBorderPadding 1666 * The sum of the child box's border and padding in the axis in question. 1667 * 1668 * @param aBoxSizing 1669 * The StyleBoxSizing enum that represents the box that the caller wants to 1670 * resolve a size for. NOTE: it may or may not be appropriate to actually 1671 * pass the true specified 'box-sizing' value for this param; it depends on 1672 * what box the caller is trying to actually resolve. In many cases, we 1673 * internally work with variables that unconditionally represent a 1674 * content-box size, regardless of the 'box-sizing' value; and for those 1675 * cases, it would be appropriate to unconditionally pass 1676 * StyleBoxSizing::Content to this function, or to just use the 1677 * convenience-wrapper that has "ContentBox" in the function name. 1678 */ 1679 static inline nscoord ComputeStretchBSize( 1680 nscoord aSizeToFill, nscoord aMargin, nscoord aBorderPadding, 1681 mozilla::StyleBoxSizing aBoxSizing) { 1682 NS_ASSERTION(aSizeToFill != NS_UNCONSTRAINEDSIZE, 1683 "We don't handle situations with unconstrained " 1684 "aSizeToFill; caller should handle that!"); 1685 nscoord stretchSize = aSizeToFill - aMargin; 1686 if (aBoxSizing == mozilla::StyleBoxSizing::Content) { 1687 stretchSize -= aBorderPadding; 1688 } 1689 return std::max(0, stretchSize); 1690 } 1691 // Convenience wrapper that assumes we're resolving the content-box size: 1692 static inline nscoord ComputeStretchContentBoxBSize(nscoord aSizeToFill, 1693 nscoord aMargin, 1694 nscoord aBorderPadding) { 1695 return ComputeStretchBSize(aSizeToFill, aMargin, aBorderPadding, 1696 mozilla::StyleBoxSizing::Content); 1697 } 1698 // Similar to the above convenience-wrapper, but now for inline-axis. 1699 // TODO(dholbert): would it be useful to add a box-sizing-aware version of 1700 // this API for the inline axis too, like we've got for the block axis? 1701 static inline nscoord ComputeStretchContentBoxISize(nscoord aSizeToFill, 1702 nscoord aMargin, 1703 nscoord aBorderPadding) { 1704 return std::max(0, aSizeToFill - aMargin - aBorderPadding); 1705 } 1706 1707 /** 1708 * The "extremum length" values (see ExtremumLength) that return true from 1709 * 'BehavesLikeInitialValueOnBlockAxis()' were originally aimed at 1710 * inline-size (or width, as it was before logicalization). For now, we return 1711 * true for those here, so that we don't call ComputeBSizeValue with value 1712 * types that it doesn't understand. (See bug 1113216.) 1713 */ 1714 template <typename SizeOrMaxSize> 1715 static bool IsAutoBSize(const SizeOrMaxSize& aCoord, nscoord aCBBSize) { 1716 // Note: percentages and 'stretch' both behave like 'auto' in the block 1717 // axis *if and only if* they're resolved against an unconstrained 1718 // block-size (on their containing block). That's what the second half of 1719 // this condition is handling. 1720 return aCoord.BehavesLikeInitialValueOnBlockAxis() || 1721 (aCBBSize == nscoord_MAX && 1722 (aCoord.HasPercent() || aCoord.BehavesLikeStretchOnBlockAxis())); 1723 } 1724 1725 static bool IsPaddingZero(const LengthPercentage& aLength) { 1726 // clamp negative calc() to 0 1727 return aLength.Resolve(nscoord_MAX) <= 0 && aLength.Resolve(0) <= 0; 1728 } 1729 1730 static void MarkDescendantsDirty(nsIFrame* aSubtreeRoot); 1731 1732 static void MarkIntrinsicISizesDirtyIfDependentOnBSize(nsIFrame* aFrame); 1733 1734 /* 1735 * Calculate the used values for 'width' and 'height' when width 1736 * and height are 'auto'. The tentWidth and tentHeight arguments should be 1737 * the result of applying the rules for computing intrinsic sizes and ratios. 1738 * as specified by CSS 2.1 sections 10.3.2 and 10.6.2 1739 */ 1740 static nsSize ComputeAutoSizeWithIntrinsicDimensions( 1741 nscoord minWidth, nscoord minHeight, nscoord maxWidth, nscoord maxHeight, 1742 nscoord tentWidth, nscoord tentHeight); 1743 1744 // Get a suitable foreground color for painting aColor for aFrame. 1745 static nscolor DarkenColorIfNeeded(nsIFrame* aFrame, nscolor aColor); 1746 1747 // Get a suitable text foreground color for painting aField for aFrame. 1748 // Type of aFrame is made a template parameter because nsIFrame is not 1749 // a complete type in the header. Type-safety is not harmed given that 1750 // DarkenColorIfNeeded requires an nsIFrame pointer. 1751 template <typename Frame, typename T, typename S> 1752 static nscolor GetTextColor(Frame* aFrame, T S::* aField) { 1753 nscolor color = aFrame->GetVisitedDependentColor(aField); 1754 return DarkenColorIfNeeded(aFrame, color); 1755 } 1756 1757 // Get a baseline y position in app units that is snapped to device pixels. 1758 static gfxFloat GetMaybeSnappedBaselineY(nsIFrame* aFrame, 1759 gfxContext* aContext, nscoord aY, 1760 nscoord aAscent); 1761 // Ditto for an x position (for vertical text). Note that for vertical-rl 1762 // writing mode, the ascent value should be negated by the caller. 1763 static gfxFloat GetMaybeSnappedBaselineX(nsIFrame* aFrame, 1764 gfxContext* aContext, nscoord aX, 1765 nscoord aAscent); 1766 1767 static nscoord AppUnitWidthOfString(char16_t aC, nsFontMetrics& aFontMetrics, 1768 DrawTarget* aDrawTarget) { 1769 return AppUnitWidthOfString(&aC, 1, aFontMetrics, aDrawTarget); 1770 } 1771 static nscoord AppUnitWidthOfString(mozilla::Span<const char16_t> aString, 1772 nsFontMetrics& aFontMetrics, 1773 DrawTarget* aDrawTarget) { 1774 return nsLayoutUtils::AppUnitWidthOfString( 1775 aString.Elements(), aString.Length(), aFontMetrics, aDrawTarget); 1776 } 1777 static nscoord AppUnitWidthOfString(const char16_t* aString, uint32_t aLength, 1778 nsFontMetrics& aFontMetrics, 1779 DrawTarget* aDrawTarget); 1780 static nscoord AppUnitWidthOfStringBidi(const nsString& aString, 1781 const nsIFrame* aFrame, 1782 nsFontMetrics& aFontMetrics, 1783 gfxContext& aContext) { 1784 return nsLayoutUtils::AppUnitWidthOfStringBidi( 1785 aString.get(), aString.Length(), aFrame, aFontMetrics, aContext); 1786 } 1787 static nscoord AppUnitWidthOfStringBidi(const char16_t* aString, 1788 uint32_t aLength, 1789 const nsIFrame* aFrame, 1790 nsFontMetrics& aFontMetrics, 1791 gfxContext& aContext); 1792 1793 static bool StringWidthIsGreaterThan(const nsString& aString, 1794 nsFontMetrics& aFontMetrics, 1795 DrawTarget* aDrawTarget, nscoord aWidth); 1796 1797 static nsBoundingMetrics AppUnitBoundsOfString(const char16_t* aString, 1798 uint32_t aLength, 1799 nsFontMetrics& aFontMetrics, 1800 DrawTarget* aDrawTarget); 1801 1802 static void DrawString(const nsIFrame* aFrame, nsFontMetrics& aFontMetrics, 1803 gfxContext* aContext, const char16_t* aString, 1804 int32_t aLength, nsPoint aPoint, 1805 ComputedStyle* aComputedStyle = nullptr, 1806 DrawStringFlags aFlags = DrawStringFlags::Default); 1807 1808 static nsPoint GetBackgroundFirstTilePos(const nsPoint& aDest, 1809 const nsPoint& aFill, 1810 const nsSize& aRepeatSize); 1811 1812 /** 1813 * Supports only LTR or RTL. Bidi (mixed direction) is not supported. 1814 */ 1815 static void DrawUniDirString(const char16_t* aString, uint32_t aLength, 1816 const nsPoint& aPoint, 1817 nsFontMetrics& aFontMetrics, 1818 gfxContext& aContext); 1819 1820 /** 1821 * Helper function for drawing text-shadow. The callback's job 1822 * is to draw whatever needs to be blurred onto the given context. 1823 */ 1824 typedef void (*TextShadowCallback)(gfxContext* aCtx, nsPoint aShadowOffset, 1825 const nscolor& aShadowColor, void* aData); 1826 1827 static void PaintTextShadow(const nsIFrame* aFrame, gfxContext* aContext, 1828 const nsRect& aTextRect, const nsRect& aDirtyRect, 1829 const nscolor& aForegroundColor, 1830 TextShadowCallback aCallback, 1831 void* aCallbackData); 1832 1833 /** 1834 * Gets the baseline to vertically center text from a font within a 1835 * line of specified height. 1836 * aIsInverted: true if the text is inverted relative to the block 1837 * direction, so that the block-dir "ascent" corresponds to font 1838 * descent. (Applies to sideways text in vertical-lr mode.) 1839 * 1840 * Returns the baseline position relative to the top of the line. 1841 */ 1842 static nscoord GetCenteredFontBaseline(nsFontMetrics* aFontMetrics, 1843 nscoord aLineHeight, bool aIsInverted); 1844 1845 /** 1846 * Derive a baseline of |aFrame| (measured from its top border edge) 1847 * from its first in-flow line box (not descending into anything with 1848 * 'overflow' not 'visible', potentially including aFrame itself). 1849 * 1850 * Returns true if a baseline was found (and fills in aResult). 1851 * Otherwise returns false. 1852 */ 1853 static bool GetFirstLineBaseline(mozilla::WritingMode aWritingMode, 1854 const nsIFrame* aFrame, nscoord* aResult); 1855 1856 /** 1857 * Just like GetFirstLineBaseline, except also returns the top and 1858 * bottom of the line with the baseline. 1859 * 1860 * Returns true if a line was found (and fills in aResult). 1861 * Otherwise returns false. 1862 */ 1863 struct LinePosition { 1864 nscoord mBStart{nscoord_MAX}; 1865 nscoord mBaseline{nscoord_MAX}; 1866 nscoord mBEnd{nscoord_MAX}; 1867 1868 LinePosition operator+(nscoord aOffset) const { 1869 LinePosition result; 1870 result.mBStart = mBStart + aOffset; 1871 result.mBaseline = mBaseline + aOffset; 1872 result.mBEnd = mBEnd + aOffset; 1873 return result; 1874 } 1875 }; 1876 static bool GetFirstLinePosition(mozilla::WritingMode aWritingMode, 1877 const nsIFrame* aFrame, 1878 LinePosition* aResult); 1879 1880 /** 1881 * Derive a baseline of |aFrame| (measured from its top border edge) 1882 * from its last in-flow line box (not descending into anything with 1883 * 'overflow' not 'visible', potentially including aFrame itself). 1884 * 1885 * Returns true if a baseline was found (and fills in aResult). 1886 * Otherwise returns false. 1887 */ 1888 static bool GetLastLineBaseline(mozilla::WritingMode aWritingMode, 1889 const nsIFrame* aFrame, nscoord* aResult); 1890 1891 /** 1892 * Returns a block-dir coordinate relative to this frame's origin that 1893 * represents the logical block-end of the frame or its visible content, 1894 * whichever is further from the origin. 1895 * Relative positioning is ignored and margins and glyph bounds are not 1896 * considered. 1897 * This value will be >= mRect.BSize() and <= overflowRect.BEnd() unless 1898 * relative positioning is applied. 1899 */ 1900 static nscoord CalculateContentBEnd(mozilla::WritingMode aWritingMode, 1901 nsIFrame* aFrame); 1902 1903 /** 1904 * Gets the closest frame (the frame passed in or one of its parents) that 1905 * qualifies as a "layer"; used in DOM0 methods that depends upon that 1906 * definition. This is the nearest frame that is either positioned or scrolled 1907 * (the child of a scroll frame). 1908 */ 1909 static nsIFrame* GetClosestLayer(nsIFrame* aFrame); 1910 1911 /** 1912 * Gets the graphics sampling filter for the frame 1913 */ 1914 static SamplingFilter GetSamplingFilterForFrame(nsIFrame* aFrame); 1915 1916 static inline void InitDashPattern(StrokeOptions& aStrokeOptions, 1917 mozilla::StyleBorderStyle aBorderStyle) { 1918 if (aBorderStyle == mozilla::StyleBorderStyle::Dotted) { 1919 static Float dot[] = {1.f, 1.f}; 1920 aStrokeOptions.mDashLength = std::size(dot); 1921 aStrokeOptions.mDashPattern = dot; 1922 } else if (aBorderStyle == mozilla::StyleBorderStyle::Dashed) { 1923 static Float dash[] = {5.f, 5.f}; 1924 aStrokeOptions.mDashLength = std::size(dash); 1925 aStrokeOptions.mDashPattern = dash; 1926 } else { 1927 aStrokeOptions.mDashLength = 0; 1928 aStrokeOptions.mDashPattern = nullptr; 1929 } 1930 } 1931 1932 /** 1933 * Convert an nsRect to a gfxRect. 1934 */ 1935 static gfxRect RectToGfxRect(const nsRect& aRect, 1936 int32_t aAppUnitsPerDevPixel); 1937 1938 static gfxPoint PointToGfxPoint(const nsPoint& aPoint, 1939 int32_t aAppUnitsPerPixel) { 1940 return gfxPoint(gfxFloat(aPoint.x) / aAppUnitsPerPixel, 1941 gfxFloat(aPoint.y) / aAppUnitsPerPixel); 1942 } 1943 1944 /* N.B. The only difference between variants of the Draw*Image 1945 * functions below is the type of the aImage argument. 1946 */ 1947 1948 /** 1949 * Draw a background image. The image's dimensions are as specified in aDest; 1950 * the image itself is not consulted to determine a size. 1951 * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering 1952 * 1953 * @param aContext 1954 * The context to draw to, already set up with an appropriate scale and 1955 * transform for drawing in app units. 1956 * @param aForFrame 1957 * The nsIFrame that we're drawing this image for. 1958 * @param aImage 1959 * The image. 1960 * @param aDest 1961 * The position and scaled area where one copy of the image should be drawn. 1962 * This area represents the image itself in its correct position as defined 1963 * with the background-position css property. 1964 * @param aFill 1965 * The area to be filled with copies of the image. 1966 * @param aRepeatSize 1967 * The distance between the positions of two subsequent repeats of the image. 1968 * Sizes larger than aDest.Size() create gaps between the images. 1969 * @param aAnchor 1970 * A point in aFill which we will ensure is pixel-aligned in the output. 1971 * @param aDirty 1972 * Pixels outside this area may be skipped. 1973 * @param aImageFlags 1974 * Image flags of the imgIContainer::FLAG_* variety. 1975 * @param aExtendMode 1976 * How to extend the image over the dest rect. 1977 */ 1978 static ImgDrawResult DrawBackgroundImage( 1979 gfxContext& aContext, nsIFrame* aForFrame, nsPresContext* aPresContext, 1980 imgIContainer* aImage, SamplingFilter aSamplingFilter, 1981 const nsRect& aDest, const nsRect& aFill, const nsSize& aRepeatSize, 1982 const nsPoint& aAnchor, const nsRect& aDirty, uint32_t aImageFlags, 1983 ExtendMode aExtendMode, float aOpacity); 1984 1985 /** 1986 * Draw an image. 1987 * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering 1988 * @param aRenderingContext Where to draw the image, set up with an 1989 * appropriate scale and transform for drawing in 1990 * app units. 1991 * @param aComputedStyle The ComputedStyle of the nsIFrame (or 1992 * pseudo-element) for which this image is being 1993 * drawn. 1994 * @param aImage The image. 1995 * @param aDest Where one copy of the image should mapped to. 1996 * @param aFill The area to be filled with copies of the 1997 * image. 1998 * @param aAnchor A point in aFill which we will ensure is 1999 * pixel-aligned in the output. 2000 * @param aDirty Pixels outside this area may be skipped. 2001 * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety 2002 */ 2003 static ImgDrawResult DrawImage(gfxContext& aContext, 2004 ComputedStyle* aComputedStyle, 2005 nsPresContext* aPresContext, 2006 imgIContainer* aImage, 2007 const SamplingFilter aSamplingFilter, 2008 const nsRect& aDest, const nsRect& aFill, 2009 const nsPoint& aAnchor, const nsRect& aDirty, 2010 uint32_t aImageFlags, float aOpacity = 1.0); 2011 2012 /** 2013 * Draw a whole image without scaling or tiling. 2014 * 2015 * @param aRenderingContext Where to draw the image, set up with an 2016 * appropriate scale and transform for drawing in 2017 * app units. 2018 * @param aImage The image. 2019 * @param aDest The top-left where the image should be drawn. 2020 * @param aDirty If non-null, then pixels outside this area may 2021 * be skipped. 2022 * @param aSVGContext Optionally provides an SVGImageContext. 2023 * Callers should pass an SVGImageContext with at 2024 * least the viewport size set if aImage may be of 2025 * type imgIContainer::TYPE_VECTOR, or pass 2026 * Nothing() if it is of type 2027 * imgIContainer::TYPE_RASTER (to save cycles 2028 * constructing an SVGImageContext, since this 2029 * argument will be ignored for raster images). 2030 * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety 2031 * @param aSourceArea If non-null, this area is extracted from 2032 * the image and drawn at aDest. It's 2033 * in appunits. For best results it should 2034 * be aligned with image pixels. 2035 */ 2036 static ImgDrawResult DrawSingleUnscaledImage( 2037 gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage, 2038 const SamplingFilter aSamplingFilter, const nsPoint& aDest, 2039 const nsRect* aDirty, const mozilla::SVGImageContext& aSVGContext, 2040 uint32_t aImageFlags, const nsRect* aSourceArea = nullptr); 2041 2042 /** 2043 * Draw a whole image without tiling. 2044 * 2045 * @param aRenderingContext Where to draw the image, set up with an 2046 * appropriate scale and transform for drawing in 2047 * app units. 2048 * @param aImage The image. 2049 * @param aDest The area that the image should fill. 2050 * @param aDirty Pixels outside this area may be skipped. 2051 * @param aSVGContext Optionally provides an SVGImageContext. 2052 * Callers should pass an SVGImageContext with at 2053 * least the viewport size set if aImage may be of 2054 * type imgIContainer::TYPE_VECTOR, or pass 2055 * Nothing() if it is of type 2056 * imgIContainer::TYPE_RASTER (to save cycles 2057 * constructing an SVGImageContext, since this 2058 * argument will be ignored for raster images). 2059 * @param aImageFlags Image flags of the imgIContainer::FLAG_* 2060 * variety. 2061 * @param aAnchor If non-null, a point which we will ensure 2062 * is pixel-aligned in the output. 2063 */ 2064 static ImgDrawResult DrawSingleImage( 2065 gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage, 2066 SamplingFilter aSamplingFilter, const nsRect& aDest, const nsRect& aDirty, 2067 const mozilla::SVGImageContext& aSVGContext, uint32_t aImageFlags, 2068 const nsPoint* aAnchorPoint = nullptr); 2069 2070 /** 2071 * Given an imgIContainer, this method attempts to obtain an intrinsic 2072 * px-valued height & width for it. If the imgIContainer has a non-pixel 2073 * value for either height or width, this method tries to generate a pixel 2074 * value for that dimension using the intrinsic ratio (if available). The 2075 * intrinsic ratio will be assigned to aIntrinsicRatio; if there's no 2076 * intrinsic ratio then (0, 0) will be assigned. 2077 * 2078 * This method will always set aGotWidth and aGotHeight to indicate whether 2079 * we were able to successfully obtain (or compute) a value for each 2080 * dimension. 2081 * 2082 * NOTE: This method is similar to ComputeSizeWithIntrinsicDimensions. The 2083 * difference is that this one is simpler and is suited to places where we 2084 * have less information about the frame tree. 2085 * 2086 * @param aResolution The resolution specified by the author for the image, or 2087 * its intrinsic resolution. 2088 * 2089 * This will affect the intrinsic size size of the image 2090 * (so e.g., if resolution is 2, and the image is 100x100, 2091 * the intrinsic size of the image will be 50x50). 2092 */ 2093 static void ComputeSizeForDrawing(imgIContainer* aImage, 2094 const mozilla::image::Resolution&, 2095 CSSIntSize& aImageSize, 2096 AspectRatio& aIntrinsicRatio, 2097 bool& aGotWidth, bool& aGotHeight); 2098 2099 /** 2100 * Given an imgIContainer, this method attempts to obtain an intrinsic 2101 * px-valued height & width for it. If the imgIContainer has a non-pixel 2102 * value for either height or width, this method tries to generate a pixel 2103 * value for that dimension using the intrinsic ratio (if available). If, 2104 * after trying all these methods, no value is available for one or both 2105 * dimensions, the corresponding dimension of aFallbackSize is used instead. 2106 */ 2107 static CSSIntSize ComputeSizeForDrawingWithFallback( 2108 imgIContainer* aImage, const mozilla::image::Resolution&, 2109 const nsSize& aFallbackSize); 2110 2111 /** 2112 * Given the image container, frame, and dest rect, determine the best fitting 2113 * size to decode the image at, and calculate any necessary SVG parameters. 2114 */ 2115 static mozilla::gfx::IntSize ComputeImageContainerDrawingParameters( 2116 imgIContainer* aImage, nsIFrame* aForFrame, 2117 const LayoutDeviceRect& aDestRect, const LayoutDeviceRect& aFillRect, 2118 const StackingContextHelper& aSc, uint32_t aFlags, 2119 mozilla::SVGImageContext& aSVGContext, 2120 mozilla::Maybe<mozilla::image::ImageIntRegion>& aRegion); 2121 2122 /** 2123 * Given a source area of an image (in appunits) and a destination area 2124 * that we want to map that source area too, computes the area that 2125 * would be covered by the whole image. This is useful for passing to 2126 * the aDest parameter of DrawImage, when we want to draw a subimage 2127 * of an overall image. 2128 */ 2129 static nsRect GetWholeImageDestination(const nsSize& aWholeImageSize, 2130 const nsRect& aImageSourceArea, 2131 const nsRect& aDestArea); 2132 2133 /** 2134 * Given an image container and an orientation, returns an image container 2135 * that contains the same image, reoriented appropriately. May return the 2136 * original image container if no changes are needed. 2137 * 2138 * @param aContainer The image container to apply the orientation to. 2139 * @param aOrientation The desired orientation. 2140 */ 2141 static already_AddRefed<imgIContainer> OrientImage( 2142 imgIContainer* aContainer, 2143 const mozilla::StyleImageOrientation& aOrientation); 2144 2145 /** 2146 * Given an image request, determine if the request uses CORS. 2147 */ 2148 static bool ImageRequestUsesCORS(imgIRequest* aRequest); 2149 2150 /** 2151 * Determine if any corner radius is of nonzero size 2152 * @param aCorners the |BorderRadius| object to check 2153 * @return true unless all the coordinates are 0%, 0 or null. 2154 * 2155 * A corner radius with one dimension zero and one nonzero is 2156 * treated as a nonzero-radius corner, even though it will end up 2157 * being rendered like a zero-radius corner. This is because such 2158 * corners are not expected to appear outside of test cases, and it's 2159 * simpler to implement the test this way. 2160 */ 2161 static bool HasNonZeroCorner(const mozilla::BorderRadius& aCorners); 2162 2163 /** 2164 * Determine if there is any corner radius on corners adjacent to the 2165 * given side. 2166 */ 2167 static bool HasNonZeroCornerOnSide(const mozilla::BorderRadius& aCorners, 2168 mozilla::Side aSide); 2169 2170 /** 2171 * Determine if a widget is likely to require transparency or translucency. 2172 * @param aBackgroundFrame The frame that the background is set on. For 2173 * <window>s, this will be the canvas frame. 2174 * @param aCSSRootFrame The frame that holds CSS properties affecting 2175 * the widget's transparency. For menupopups, 2176 * aBackgroundFrame and aCSSRootFrame will be the 2177 * same. 2178 * @return a value suitable for passing to SetWindowTranslucency. 2179 */ 2180 using TransparencyMode = mozilla::widget::TransparencyMode; 2181 static TransparencyMode GetFrameTransparency(const nsIFrame* aBackgroundFrame, 2182 const nsIFrame* aCSSRootFrame); 2183 2184 /** 2185 * A frame is a popup if it has its own floating window. Menus, panels 2186 * and combobox dropdowns are popups. 2187 */ 2188 static bool IsPopup(const nsIFrame* aFrame); 2189 2190 /** 2191 * Find the nearest "display root". This is the nearest enclosing 2192 * popup frame or the root prescontext's root frame. 2193 */ 2194 static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame); 2195 static const nsIFrame* GetDisplayRootFrame(const nsIFrame* aFrame); 2196 2197 /** 2198 * Get the reference frame that would be used when constructing a 2199 * display item for this frame. Rather than using their own frame 2200 * as a reference frame.) 2201 * 2202 * This duplicates some of the logic of GetDisplayRootFrame above and 2203 * of nsDisplayListBuilder::FindReferenceFrameFor. 2204 * 2205 * If you have an nsDisplayListBuilder, you should get the reference 2206 * frame from it instead of calling this. 2207 */ 2208 static nsIFrame* GetReferenceFrame(nsIFrame* aFrame); 2209 2210 /** 2211 * Get textrun construction flags determined by a given style; in particular 2212 * some combination of: 2213 * -- TEXT_DISABLE_OPTIONAL_LIGATURES if letter-spacing is in use 2214 * -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size 2215 * and prefs indicate we should be optimizing for speed over quality 2216 */ 2217 static mozilla::gfx::ShapedTextFlags GetTextRunFlagsForStyle( 2218 const ComputedStyle*, nsPresContext*, const nsStyleFont*, 2219 const nsStyleText*, nscoord aLetterSpacing); 2220 2221 /** 2222 * Get orientation flags for textrun construction. 2223 */ 2224 static mozilla::gfx::ShapedTextFlags GetTextRunOrientFlagsForStyle( 2225 const ComputedStyle*); 2226 2227 /** 2228 * Takes two rectangles whose origins must be the same, and computes 2229 * the difference between their union and their intersection as two 2230 * rectangles. (This difference is a superset of the difference 2231 * between the two rectangles.) 2232 */ 2233 static void GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2, 2234 nsRect* aHStrip, nsRect* aVStrip); 2235 2236 /** 2237 * Get a device context that can be used to get up-to-date device 2238 * dimensions for the given window. For some reason, this is more 2239 * complicated than it ought to be in multi-monitor situations. 2240 */ 2241 static nsDeviceContext* GetDeviceContextForScreenInfo( 2242 nsPIDOMWindowOuter* aWindow); 2243 2244 /** 2245 * Some frames with 'position: fixed' (nsStyleDisplay::mPosition == 2246 * StylePositionProperty::Fixed) are not really fixed positioned, since 2247 * they're inside a transformed element or other element that establishes a 2248 * fixed-pos containing block). This function says whether such an element is 2249 * a real fixed-pos element. 2250 */ 2251 static bool IsReallyFixedPos(const nsIFrame* aFrame); 2252 2253 /** 2254 * This function says whether `aFrame` would really be a fixed positioned 2255 * frame if the frame was created with StylePositionProperty::Fixed. 2256 * 2257 * It is effectively the same as IsReallyFixedPos, but without asserting the 2258 * position value. Use it only when you know what you're doing, like when 2259 * tearing down the frame tree (where styles may have changed due to 2260 * ::first-line reparenting and rule changes at the same time). 2261 */ 2262 static bool MayBeReallyFixedPos(const nsIFrame* aFrame); 2263 2264 /** 2265 * Returns true if |aFrame| is inside position:fixed subtree. 2266 */ 2267 static bool IsInPositionFixedSubtree(const nsIFrame* aFrame); 2268 2269 /** 2270 * Obtain a SourceSurface from the given DOM element, if possible. 2271 * This obtains the most natural surface from the element; that 2272 * is, the one that can be obtained with the fewest conversions. 2273 * 2274 * The flags below can modify the behaviour of this function. The 2275 * result is returned as a SurfaceFromElementResult struct, also 2276 * defined below. 2277 * 2278 * Currently, this will do: 2279 * - HTML Canvas elements: will return the underlying canvas surface 2280 * - HTML Video elements: will return the current video frame 2281 * - Image elements: will return the image 2282 * 2283 * The above results are modified by the below flags (copying, 2284 * forcing image surface, etc.). 2285 */ 2286 2287 enum { 2288 /* Whether to extract the first frame (as opposed to the 2289 current frame) in the case that the element is an image. */ 2290 SFE_WANT_FIRST_FRAME_IF_IMAGE = 1 << 0, 2291 /* Whether we should skip colorspace/gamma conversion */ 2292 SFE_NO_COLORSPACE_CONVERSION = 1 << 1, 2293 /* Caller handles SFER::mAlphaType = NonPremult */ 2294 SFE_ALLOW_NON_PREMULT = 1 << 2, 2295 /* Whether we should skip getting a surface for vector images and 2296 return a DirectDrawInfo containing an imgIContainer instead. */ 2297 SFE_NO_RASTERIZING_VECTORS = 1 << 3, 2298 /* If image type is vector, the return surface size will same as 2299 element size, not image's intrinsic size. */ 2300 SFE_USE_ELEMENT_SIZE_IF_VECTOR = 1 << 4, 2301 /* Ensure that the returned surface has a size that matches the 2302 * SurfaceFromElementResult::mSize. This is mostly a convenience thing so 2303 * that callers who want this don't have to deal with it themselves. 2304 * The surface might be different for, e.g., a EXIF-scaled raster image, if 2305 * we don't rescale during decode. */ 2306 SFE_EXACT_SIZE_SURFACE = 1 << 6, 2307 /* Use orientation from image */ 2308 SFE_ORIENTATION_FROM_IMAGE = 1 << 7, 2309 /* Caller handles SFER::mCropRect.isSome() */ 2310 SFE_ALLOW_UNCROPPED_UNSCALED = 1 << 8, 2311 }; 2312 2313 // This function can be called on any thread. 2314 static mozilla::SurfaceFromElementResult SurfaceFromOffscreenCanvas( 2315 mozilla::dom::OffscreenCanvas* aOffscreenCanvas, uint32_t aSurfaceFlags, 2316 RefPtr<DrawTarget>& aTarget); 2317 static mozilla::SurfaceFromElementResult SurfaceFromOffscreenCanvas( 2318 mozilla::dom::OffscreenCanvas* aOffscreenCanvas, 2319 uint32_t aSurfaceFlags = 0) { 2320 RefPtr<DrawTarget> target = nullptr; 2321 return SurfaceFromOffscreenCanvas(aOffscreenCanvas, aSurfaceFlags, target); 2322 } 2323 // This function can be called on any thread. 2324 static mozilla::SurfaceFromElementResult SurfaceFromVideoFrame( 2325 mozilla::dom::VideoFrame* aVideoFrame, uint32_t aSurfaceFlags, 2326 RefPtr<DrawTarget>& aTarget); 2327 static mozilla::SurfaceFromElementResult SurfaceFromVideoFrame( 2328 mozilla::dom::VideoFrame* aVideoFrame, uint32_t aSurfaceFlags = 0) { 2329 RefPtr<DrawTarget> target = nullptr; 2330 return SurfaceFromVideoFrame(aVideoFrame, aSurfaceFlags, target); 2331 } 2332 // This function can be called on any thread. 2333 static mozilla::SurfaceFromElementResult SurfaceFromImageBitmap( 2334 mozilla::dom::ImageBitmap* aImageBitmap, uint32_t aSurfaceFlags); 2335 2336 static mozilla::SurfaceFromElementResult SurfaceFromElement( 2337 mozilla::dom::Element* aElement, 2338 const mozilla::Maybe<int32_t>& aResizeWidth, 2339 const mozilla::Maybe<int32_t>& aResizeHeight, uint32_t aSurfaceFlags, 2340 RefPtr<DrawTarget>& aTarget); 2341 static mozilla::SurfaceFromElementResult SurfaceFromElement( 2342 mozilla::dom::Element* aElement, uint32_t aSurfaceFlags = 0) { 2343 RefPtr<DrawTarget> target = nullptr; 2344 return SurfaceFromElement(aElement, mozilla::Nothing(), mozilla::Nothing(), 2345 aSurfaceFlags, target); 2346 } 2347 static mozilla::SurfaceFromElementResult SurfaceFromElement( 2348 mozilla::dom::Element* aElement, uint32_t aSurfaceFlags, 2349 RefPtr<DrawTarget>& aTarget) { 2350 return SurfaceFromElement(aElement, mozilla::Nothing(), mozilla::Nothing(), 2351 aSurfaceFlags, aTarget); 2352 } 2353 static mozilla::SurfaceFromElementResult SurfaceFromElement( 2354 mozilla::dom::Element* aElement, 2355 const mozilla::Maybe<int32_t>& aResizeWidth, 2356 const mozilla::Maybe<int32_t>& aResizeHeight, 2357 uint32_t aSurfaceFlags = 0) { 2358 RefPtr<DrawTarget> target = nullptr; 2359 return SurfaceFromElement(aElement, aResizeWidth, aResizeHeight, 2360 aSurfaceFlags, target); 2361 } 2362 2363 // There are a bunch of callers of SurfaceFromElement. Just mark it as 2364 MOZ_CAN_RUN_SCRIPT_BOUNDARY 2365 static mozilla::SurfaceFromElementResult SurfaceFromElement( 2366 nsIImageLoadingContent* aElement, 2367 const mozilla::Maybe<int32_t>& aResizeWidth, 2368 const mozilla::Maybe<int32_t>& aResizeHeight, uint32_t aSurfaceFlags, 2369 RefPtr<DrawTarget>& aTarget); 2370 // Need an HTMLImageElement overload, because otherwise the 2371 // nsIImageLoadingContent and mozilla::dom::Element overloads are ambiguous 2372 // for HTMLImageElement. 2373 static mozilla::SurfaceFromElementResult SurfaceFromElement( 2374 mozilla::dom::HTMLImageElement* aElement, uint32_t aSurfaceFlags, 2375 RefPtr<DrawTarget>& aTarget); 2376 static mozilla::SurfaceFromElementResult SurfaceFromElement( 2377 mozilla::dom::HTMLCanvasElement* aElement, uint32_t aSurfaceFlags, 2378 RefPtr<DrawTarget>& aTarget); 2379 static mozilla::SurfaceFromElementResult SurfaceFromElement( 2380 mozilla::dom::HTMLCanvasElement* aElement, uint32_t aSurfaceFlags) { 2381 RefPtr<DrawTarget> target = nullptr; 2382 return SurfaceFromElement(aElement, aSurfaceFlags, target); 2383 } 2384 static mozilla::SurfaceFromElementResult SurfaceFromElement( 2385 mozilla::dom::HTMLVideoElement* aElement, uint32_t aSurfaceFlags, 2386 RefPtr<DrawTarget>& aTarget, bool aOptimizeSourceSurface = true); 2387 2388 /** 2389 * When the document is editable by contenteditable attribute of its root 2390 * content or body content. 2391 * 2392 * Be aware, this returns nullptr if it's in designMode. 2393 * 2394 * For example: 2395 * 2396 * <html contenteditable="true"><body></body></html> 2397 * returns the <html>. 2398 * 2399 * <html><body contenteditable="true"></body></html> 2400 * <body contenteditable="true"></body> 2401 * With these cases, this returns the <body>. 2402 * NOTE: The latter case isn't created normally, however, it can be 2403 * created by script with XHTML. 2404 * 2405 * <body><p contenteditable="true"></p></body> 2406 * returns nullptr because <body> isn't editable. 2407 */ 2408 static mozilla::dom::Element* GetEditableRootContentByContentEditable( 2409 mozilla::dom::Document* aDocument); 2410 2411 static void AddExtraBackgroundItems(nsDisplayListBuilder* aBuilder, 2412 nsDisplayList* aList, nsIFrame* aFrame, 2413 const nsRect& aCanvasArea, 2414 const nsRegion& aVisibleRegion, 2415 nscolor aBackstop); 2416 2417 /** 2418 * Returns true if the passed in prescontext needs the dark grey background 2419 * that goes behind the page of a print preview presentation. 2420 */ 2421 static bool NeedsPrintPreviewBackground(nsPresContext* aPresContext); 2422 2423 /** 2424 * Types used by the helpers for InspectorUtils.getUsedFontFaces. 2425 * The API returns an array (UsedFontFaceList) that owns the 2426 * InspectorFontFace instances, but during range traversal we also 2427 * want to maintain a mapping from gfxFontEntry to InspectorFontFace 2428 * records, so use a temporary hashtable for that. 2429 */ 2430 typedef nsTArray<mozilla::UniquePtr<mozilla::dom::InspectorFontFace>> 2431 UsedFontFaceList; 2432 typedef nsTHashMap<nsPtrHashKey<gfxFontEntry>, 2433 mozilla::dom::InspectorFontFace*> 2434 UsedFontFaceTable; 2435 2436 /** 2437 * Adds all font faces used in the frame tree starting from aFrame 2438 * to the list aFontFaceList. 2439 * aMaxRanges: maximum number of text ranges to record for each face. 2440 */ 2441 static nsresult GetFontFacesForFrames(nsIFrame* aFrame, 2442 UsedFontFaceList& aResult, 2443 UsedFontFaceTable& aFontFaces, 2444 uint32_t aMaxRanges, 2445 bool aSkipCollapsedWhitespace); 2446 2447 /** 2448 * Adds all font faces used within the specified range of text in aFrame, 2449 * and optionally its continuations, to the list in aFontFaceList. 2450 * Pass 0 and INT32_MAX for aStartOffset and aEndOffset to specify the 2451 * entire text is to be considered. 2452 * aMaxRanges: maximum number of text ranges to record for each face. 2453 */ 2454 static void GetFontFacesForText(nsIFrame* aFrame, int32_t aStartOffset, 2455 int32_t aEndOffset, bool aFollowContinuations, 2456 UsedFontFaceList& aResult, 2457 UsedFontFaceTable& aFontFaces, 2458 uint32_t aMaxRanges, 2459 bool aSkipCollapsedWhitespace); 2460 2461 /** 2462 * Walks the frame tree starting at aFrame looking for textRuns. 2463 * If |clear| is true, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag 2464 * on each textRun found (and |aMallocSizeOf| is not used). 2465 * If |clear| is false, adds the storage used for each textRun to the 2466 * total, and sets the TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double- 2467 * accounting. (Runs with this flag already set will be skipped.) 2468 * Expected usage pattern is therefore to call twice: 2469 * (void)SizeOfTextRunsForFrames(rootFrame, nullptr, true); 2470 * total = SizeOfTextRunsForFrames(rootFrame, mallocSizeOf, false); 2471 */ 2472 static size_t SizeOfTextRunsForFrames(nsIFrame* aFrame, 2473 mozilla::MallocSizeOf aMallocSizeOf, 2474 bool clear); 2475 2476 /** 2477 * Returns true if |aFrame| has an animation of a property in |aPropertySet| 2478 * regardless of whether any property in the set is overridden by an 2479 * !important rule. 2480 */ 2481 static bool HasAnimationOfPropertySet(const nsIFrame* aFrame, 2482 const nsCSSPropertyIDSet& aPropertySet); 2483 2484 /** 2485 * A variant of the above HasAnimationOfPropertySet that takes an optional 2486 * EffectSet parameter as an optimization to save redundant lookups of the 2487 * EffectSet. 2488 */ 2489 static bool HasAnimationOfPropertySet(const nsIFrame* aFrame, 2490 const nsCSSPropertyIDSet& aPropertySet, 2491 mozilla::EffectSet* aEffectSet); 2492 2493 /** 2494 * A variant of the above HasAnimationOfPropertySet. This is especially for 2495 * tranform-like properties with motion-path. 2496 * For transform-like properties with motion-path, we need to check if 2497 * offset-path has effect. If we don't have any animation on offset-path and 2498 * offset-path is none, there is no effective motion-path, and so we don't 2499 * care other offset-* properties. In this case, this function only checks the 2500 * rest of transform-like properties (i.e. transform/translate/rotate/scale). 2501 */ 2502 static bool HasAnimationOfTransformAndMotionPath(const nsIFrame* aFrame); 2503 2504 /** 2505 * Returns true if |aFrame| has an animation of |aProperty| which is 2506 * not overridden by !important rules. 2507 */ 2508 static bool HasEffectiveAnimation(const nsIFrame* aFrame, 2509 NonCustomCSSPropertyId aProperty); 2510 2511 /** 2512 * Returns true if |aFrame| has an animation where at least one of the 2513 * properties in |aPropertySet| is not overridden by !important rules. 2514 * 2515 * If |aPropertySet| includes transform-like properties (transform, rotate, 2516 * etc.) however, this will return false if any of the transform-like 2517 * properties is overriden by an !important rule since these properties should 2518 * be combined on the compositor. 2519 */ 2520 static bool HasEffectiveAnimation(const nsIFrame* aFrame, 2521 const nsCSSPropertyIDSet& aPropertySet); 2522 2523 /** 2524 * Returns all effective animated CSS properties on |aStyleFrame| and its 2525 * corresponding primary frame (for content that makes this distinction, 2526 * notable display:table content) that can be animated on the compositor. 2527 * 2528 * Properties that can be animated on the compositor but which are overridden 2529 * by !important rules are not returned. 2530 * 2531 * Unlike HasEffectiveAnimation, however, this does not check the set of 2532 * transform-like properties to ensure that if any such properties are 2533 * overridden by !important rules, the other transform-like properties are 2534 * not run on the compositor (see bug 1534884). 2535 */ 2536 static nsCSSPropertyIDSet GetAnimationPropertiesForCompositor( 2537 const nsIFrame* aStyleFrame); 2538 2539 /** 2540 * Checks if off-main-thread animations are enabled. 2541 */ 2542 static bool AreAsyncAnimationsEnabled(); 2543 2544 /** 2545 * Checks if retained display lists are enabled. 2546 */ 2547 static bool AreRetainedDisplayListsEnabled(); 2548 2549 static bool DisplayRootHasRetainedDisplayListBuilder(nsIFrame* aFrame); 2550 2551 static RetainedDisplayListBuilder* GetRetainedDisplayListBuilder( 2552 nsIFrame* aFrame); 2553 2554 /** 2555 * Find a suitable scale for a element (aFrame's content) over the course of 2556 * any animations and transitions of the CSS transform property on the element 2557 * that run on the compositor thread. It will check the maximum and minimum 2558 * scale during the animations and transitions and return a suitable value for 2559 * performance and quality. Will return scale(1,1) if there are no such 2560 * animations. Always returns a positive value. 2561 * @param aVisibleSize is the size of the area we want to paint 2562 * @param aDisplaySize is the size of the display area of the pres context 2563 */ 2564 static MatrixScales ComputeSuitableScaleForAnimation( 2565 const nsIFrame* aFrame, const nsSize& aVisibleSize, 2566 const nsSize& aDisplaySize); 2567 2568 /** 2569 * Unions the overflow areas of the children of aFrame with aOverflowAreas. 2570 * aSkipChildLists specifies any child lists that should be skipped. 2571 * FrameChildListID::Popup is always skipped. 2572 */ 2573 static void UnionChildOverflow( 2574 nsIFrame* aFrame, mozilla::OverflowAreas& aOverflowAreas, 2575 mozilla::FrameChildListIDs aSkipChildLists = {}); 2576 2577 /** 2578 * Return the font size inflation *ratio* for a given frame. This is 2579 * the factor by which font sizes should be inflated; it is never 2580 * smaller than 1. 2581 */ 2582 static float FontSizeInflationFor(const nsIFrame* aFrame); 2583 2584 /** 2585 * Perform the first half of the computation of FontSizeInflationFor 2586 * (see above). 2587 * This includes determining whether inflation should be performed 2588 * within this container and returning 0 if it should not be. 2589 * 2590 * The result is guaranteed not to vary between line participants 2591 * (inlines, text frames) within a line. 2592 * 2593 * The result should not be used directly since font sizes slightly 2594 * above the minimum should always be adjusted as done by 2595 * FontSizeInflationInner. 2596 */ 2597 static nscoord InflationMinFontSizeFor(const nsIFrame* aFrame); 2598 2599 /** 2600 * Perform the second half of the computation done by 2601 * FontSizeInflationFor (see above). 2602 * 2603 * aMinFontSize must be the result of one of the 2604 * InflationMinFontSizeFor methods above. 2605 */ 2606 static float FontSizeInflationInner(const nsIFrame* aFrame, 2607 nscoord aMinFontSize); 2608 2609 static bool FontSizeInflationEnabled(nsPresContext* aPresContext); 2610 2611 /** 2612 * Returns true if the nglayout.debug.invalidation pref is set to true. 2613 */ 2614 static bool InvalidationDebuggingIsEnabled() { 2615 return mozilla::StaticPrefs::nglayout_debug_invalidation() || 2616 getenv("MOZ_DUMP_INVALIDATION") != 0; 2617 } 2618 2619 static void Initialize(); 2620 static void Shutdown(); 2621 2622 /** 2623 * Register an imgIRequest object with a refresh driver. 2624 * 2625 * @param aPresContext The nsPresContext whose refresh driver we want to 2626 * register with. 2627 * @param aRequest A pointer to the imgIRequest object which the client wants 2628 * to register with the refresh driver. 2629 * @param aRequestRegistered A pointer to a boolean value which indicates 2630 * whether the given image request is registered. If 2631 * *aRequestRegistered is true, then this request will not be 2632 * registered again. If the request is registered by this function, 2633 * then *aRequestRegistered will be set to true upon the completion of 2634 * this function. 2635 * 2636 */ 2637 static void RegisterImageRequest(nsPresContext* aPresContext, 2638 imgIRequest* aRequest, 2639 bool* aRequestRegistered); 2640 2641 /** 2642 * Register an imgIRequest object with a refresh driver, but only if the 2643 * request is for an image that is animated. 2644 * 2645 * @param aPresContext The nsPresContext whose refresh driver we want to 2646 * register with. 2647 * @param aRequest A pointer to the imgIRequest object which the client wants 2648 * to register with the refresh driver. 2649 * @param aRequestRegistered A pointer to a boolean value which indicates 2650 * whether the given image request is registered. If 2651 * *aRequestRegistered is true, then this request will not be 2652 * registered again. If the request is registered by this function, 2653 * then *aRequestRegistered will be set to true upon the completion of 2654 * this function. 2655 * 2656 */ 2657 static void RegisterImageRequestIfAnimated(nsPresContext* aPresContext, 2658 imgIRequest* aRequest, 2659 bool* aRequestRegistered); 2660 2661 /** 2662 * Deregister an imgIRequest object from a refresh driver. 2663 * 2664 * @param aPresContext The nsPresContext whose refresh driver we want to 2665 * deregister from. 2666 * @param aRequest A pointer to the imgIRequest object with which the client 2667 * previously registered and now wants to deregister from the refresh 2668 * driver. 2669 * @param aRequestRegistered A pointer to a boolean value which indicates 2670 * whether the given image request is registered. If 2671 * *aRequestRegistered is false, then this request will not be 2672 * deregistered. If the request is deregistered by this function, 2673 * then *aRequestRegistered will be set to false upon the completion of 2674 * this function. 2675 */ 2676 static void DeregisterImageRequest(nsPresContext* aPresContext, 2677 imgIRequest* aRequest, 2678 bool* aRequestRegistered); 2679 2680 /** 2681 * Shim to nsCSSFrameConstructor::PostRestyleEvent. Exists so that we 2682 * can avoid including nsCSSFrameConstructor.h and all its dependencies 2683 * in content files. 2684 */ 2685 static void PostRestyleEvent(mozilla::dom::Element*, mozilla::RestyleHint, 2686 nsChangeHint aMinChangeHint); 2687 2688 /** 2689 * Updates a pair of x and y distances if a given point is closer to a given 2690 * rectangle than the original distance values. If aPoint is closer to 2691 * aRect than aClosestXDistance and aClosestYDistance indicate, then those 2692 * two variables are updated with the distance between aPoint and aRect, 2693 * and true is returned. If aPoint is not closer, then aClosestXDistance 2694 * and aClosestYDistance are left unchanged, and false is returned. 2695 * 2696 * Distances are measured in the two dimensions separately; a closer x 2697 * distance beats a closer y distance. 2698 */ 2699 template <typename PointType, typename RectType, typename CoordType> 2700 static bool PointIsCloserToRect(PointType aPoint, const RectType& aRect, 2701 CoordType& aClosestXDistance, 2702 CoordType& aClosestYDistance); 2703 /** 2704 * Computes the box shadow rect for the frame, or returns an empty rect if 2705 * there are no shadows. 2706 * 2707 * @param aFrame Frame to compute shadows for. 2708 * @param aFrameSize Size of aFrame (in case it hasn't been set yet). 2709 */ 2710 static nsRect GetBoxShadowRectForFrame(nsIFrame* aFrame, 2711 const nsSize& aFrameSize); 2712 2713 #ifdef DEBUG 2714 /** 2715 * Assert that there are no duplicate continuations of the same frame 2716 * within aFrameList. Optimize the tests by assuming that all frames 2717 * in aFrameList have parent aContainer. 2718 */ 2719 static void AssertNoDuplicateContinuations(nsIFrame* aContainer, 2720 const nsFrameList& aFrameList); 2721 2722 /** 2723 * Assert that the frame tree rooted at |aSubtreeRoot| is empty, i.e., 2724 * that it contains no first-in-flows. 2725 */ 2726 static void AssertTreeOnlyEmptyNextInFlows(nsIFrame* aSubtreeRoot); 2727 #endif 2728 2729 /** 2730 * Helper method to transform |aBounds| from aFrame to aAncestorFrame, 2731 * and combine it with |aPreciseTargetDest| if it is axis-aligned, or 2732 * combine it with |aImpreciseTargetDest| if not. The transformed rect is 2733 * clipped to |aClip|; if |aClip| has rounded corners, that also causes 2734 * the imprecise target to be used. 2735 */ 2736 static void TransformToAncestorAndCombineRegions( 2737 const nsRegion& aRegion, nsIFrame* aFrame, const nsIFrame* aAncestorFrame, 2738 nsRegion* aPreciseTargetDest, nsRegion* aImpreciseTargetDest, 2739 mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache, 2740 const mozilla::DisplayItemClip* aClip); 2741 2742 /** 2743 * Populate aOutSize with the size of the content viewer corresponding 2744 * to the given prescontext. Return true if the size was set, false 2745 * otherwise. 2746 */ 2747 enum class SubtractDynamicToolbar { No, Yes }; 2748 static bool GetDocumentViewerSize( 2749 const nsPresContext* aPresContext, LayoutDeviceIntSize& aOutSize, 2750 SubtractDynamicToolbar = SubtractDynamicToolbar::Yes); 2751 2752 /** 2753 * Whether to include the dynamic toolbar area automatically (depending 2754 * whether the root container is scrollable or not) or forcibly in below 2755 * UpdateCompositionBoundsForRCDRSF and CalculateCompositionSizeForFrame 2756 * functions. 2757 */ 2758 enum class IncludeDynamicToolbar { Auto, Force }; 2759 2760 private: 2761 static bool UpdateCompositionBoundsForRCDRSF( 2762 mozilla::ParentLayerRect& aCompBounds, const nsPresContext* aPresContext, 2763 IncludeDynamicToolbar aIncludeDynamicToolbar = 2764 IncludeDynamicToolbar::Auto); 2765 2766 public: 2767 /** 2768 * Calculate the compostion size for a frame. See FrameMetrics.h for 2769 * defintion of composition size (or bounds). 2770 * Note that for the root content document's root scroll frame (RCD-RSF), 2771 * the returned size does not change as the document's resolution changes, 2772 * but for all other frames it does. This means that callers that pass in 2773 * a frame that may or may not be the RCD-RSF (which is most callers), 2774 * are likely to need special-case handling of the RCD-RSF. 2775 */ 2776 static nsSize CalculateCompositionSizeForFrame( 2777 nsIFrame* aFrame, bool aSubtractScrollbars = true, 2778 const nsSize* aOverrideScrollPortSize = nullptr, 2779 IncludeDynamicToolbar aIncludeDynamicToolbar = 2780 IncludeDynamicToolbar::Auto); 2781 2782 /** 2783 * Calculate a size suitable for bounding the size of the composition bounds 2784 * of scroll frames in the current process. This should be at most the 2785 * composition size of the cross-process RCD-RSF, but it may be a tighter 2786 * bounding size. 2787 * @param aFrame A frame in the (in-process) root content document (or a 2788 * descendant of it). 2789 * @param aIsRootContentDocRootScrollFrame Whether aFrame is the root 2790 * scroll frame of the *cross-process* root content document. 2791 * In this case we just use aFrame's own composition size. 2792 * @param aMetrics A partially populated FrameMetrics for aFrame. Must have at 2793 * least mCompositionBounds, mCumulativeResolution, and 2794 * mDevPixelsPerCSSPixel set. 2795 */ 2796 static CSSSize CalculateBoundingCompositionSize( 2797 const nsIFrame* aFrame, bool aIsRootContentDocRootScrollFrame, 2798 const FrameMetrics& aMetrics); 2799 2800 /** 2801 * Calculate the scrollable rect for a frame. See FrameMetrics.h for 2802 * definition of scrollable rect. aScrollContainerFrame is the scroll 2803 * container frame to calculate the scrollable rect for. If it's null then we 2804 * calculate the scrollable rect as the rect of the root frame. 2805 */ 2806 static nsRect CalculateScrollableRectForFrame( 2807 const mozilla::ScrollContainerFrame* aScrollContainerFrame, 2808 const nsIFrame* aRootFrame); 2809 2810 /** 2811 * Calculate the expanded scrollable rect for a frame. See FrameMetrics.h for 2812 * defintion of expanded scrollable rect. 2813 */ 2814 static nsRect CalculateExpandedScrollableRect(nsIFrame* aFrame); 2815 2816 /** 2817 * Returns true if the widget owning the given frame uses asynchronous 2818 * scrolling. 2819 */ 2820 static bool UsesAsyncScrolling(nsIFrame* aFrame); 2821 2822 /** 2823 * Returns true if the widget owning the given frame has builtin APZ support 2824 * enabled. 2825 */ 2826 static bool AsyncPanZoomEnabled(const nsIFrame* aFrame); 2827 2828 /** 2829 * Returns true if aDocument should be allowed to use resolution 2830 * zooming. 2831 */ 2832 static bool AllowZoomingForDocument(const mozilla::dom::Document* aDocument); 2833 2834 /** 2835 * Returns true if we need to disable async scrolling for this particular 2836 * element. Note that this does a partial disabling - the displayport still 2837 * exists but uses a very small margin, and the compositor doesn't apply the 2838 * async transform. However, the content may still be layerized. 2839 */ 2840 static bool ShouldDisableApzForElement(nsIContent* aContent); 2841 2842 /** 2843 * Log a key/value pair as "additional data" (not associated with a paint) 2844 * for APZ testing. 2845 * While the data is not associated with a paint, the APZTestData object 2846 * is still owned by {Client,WebRender}LayerManager, so we need to be passed 2847 * something from which we can derive the layer manager. 2848 * This function takes a display list builder as the object to derive the 2849 * layer manager from, to facilitate logging test data during display list 2850 * building, but other overloads that take other objects could be added if 2851 * desired. 2852 */ 2853 static void LogAdditionalTestData(nsDisplayListBuilder* aBuilder, 2854 const std::string& aKey, 2855 const std::string& aValue); 2856 2857 /** 2858 * Log a key/value pair for APZ testing during a paint. 2859 * @param aManager The data will be written to the APZTestData associated 2860 * with this layer manager. 2861 * @param aScrollId Identifies the scroll frame to which the data pertains. 2862 * @param aKey The key under which to log the data. 2863 * @param aValue The value of the data to be logged. 2864 */ 2865 static void LogTestDataForPaint( 2866 mozilla::layers::WebRenderLayerManager* aManager, ViewID aScrollId, 2867 const std::string& aKey, const std::string& aValue) { 2868 DoLogTestDataForPaint(aManager, aScrollId, aKey, aValue); 2869 } 2870 2871 /** 2872 * A convenience overload of LogTestDataForPaint() that accepts any type 2873 * as the value, and passes it through mozilla::ToString() to obtain a string 2874 * value. The type passed must support streaming to an std::ostream. 2875 */ 2876 template <typename Value> 2877 static void LogTestDataForPaint( 2878 mozilla::layers::WebRenderLayerManager* aManager, ViewID aScrollId, 2879 const std::string& aKey, const Value& aValue) { 2880 DoLogTestDataForPaint(aManager, aScrollId, aKey, mozilla::ToString(aValue)); 2881 } 2882 2883 /** 2884 * Calculate a basic FrameMetrics with enough fields set to perform some 2885 * layout calculations. The fields set are dev-to-css ratio, pres shell 2886 * resolution, cumulative resolution, zoom, composition size, root 2887 * composition size, scroll offset and scrollable rect. 2888 * 2889 * Note that for the RCD-RSF, the scroll offset returned is the layout 2890 * viewport offset; if you need the visual viewport offset, that needs to 2891 * be queried independently via PresShell::GetVisualViewportOffset(). 2892 * 2893 * By contrast, ComputeScrollMetadata() computes all the fields, but requires 2894 * extra inputs and can only be called during frame layer building. 2895 */ 2896 static FrameMetrics CalculateBasicFrameMetrics( 2897 mozilla::ScrollContainerFrame* aScrollContainerFrame); 2898 2899 /** 2900 * Follows the async scrollable ancestor chain of scroll frames to find 2901 * scroll frames that WantAsyncScroll(). This is used when activating scroll 2902 * frames and finding APZCs. 2903 */ 2904 static mozilla::ScrollContainerFrame* GetAsyncScrollableAncestorFrame( 2905 nsIFrame* aTarget); 2906 2907 static void SetBSizeFromFontMetrics( 2908 const nsIFrame* aFrame, mozilla::ReflowOutput& aMetrics, 2909 const mozilla::LogicalMargin& aFramePadding, mozilla::WritingMode aLineWM, 2910 mozilla::WritingMode aFrameWM); 2911 2912 static bool HasDocumentLevelListenersForApzAwareEvents(PresShell* aPresShell); 2913 2914 /** 2915 * Returns true if the given scroll origin is "higher priority" than APZ. 2916 * In general any content programmatic scrolls (e.g. scrollTo calls) are 2917 * higher priority, and take precedence over APZ scrolling. This function 2918 * returns true for those, and returns false for other origins like APZ 2919 * itself, or scroll position updates from the history restore code. 2920 */ 2921 static bool CanScrollOriginClobberApz(ScrollOrigin aScrollOrigin); 2922 2923 static ScrollMetadata ComputeScrollMetadata( 2924 const nsIFrame* aForFrame, const nsIFrame* aScrollFrame, 2925 nsIContent* aContent, const nsIFrame* aItemFrame, 2926 const nsPoint& aOffsetToReferenceFrame, 2927 mozilla::layers::WebRenderLayerManager* aLayerManager, 2928 ViewID aScrollParentId, const nsSize& aScrollPortSize, bool aIsRoot); 2929 2930 /** 2931 * Returns the metadata to put onto the root layer of a layer tree, if one is 2932 * needed. The last argument is a callback function to check if the caller 2933 * already has a metadata for a given scroll id. 2934 */ 2935 static mozilla::Maybe<ScrollMetadata> GetRootMetadata( 2936 nsDisplayListBuilder* aBuilder, 2937 mozilla::layers::WebRenderLayerManager* aLayerManager, 2938 const std::function<bool(ViewID& aScrollId)>& aCallback); 2939 2940 /** 2941 * If the given scroll frame needs an area excluded from its composition 2942 * bounds due to scrollbars, return that area, otherwise return an empty 2943 * margin. 2944 * There is no need to exclude scrollbars in the following cases: 2945 * - If the scroll frame is not the RCD-RSF; in that case, the composition 2946 * bounds is calculated based on the scroll port which already excludes 2947 * the scrollbar area. 2948 * - If the scrollbars are overlay, since then they are drawn on top of the 2949 * scrollable content. 2950 */ 2951 static nsMargin ScrollbarAreaToExcludeFromCompositionBoundsFor( 2952 const nsIFrame* aScrollFrame); 2953 2954 static bool ShouldUseNoFramesSheet(mozilla::dom::Document*); 2955 2956 /** 2957 * Get the text content inside the frame. This methods traverse the 2958 * frame tree and collect the content from text frames. Note that this 2959 * method is similiar to nsContentUtils::GetNodeTextContent, but it at 2960 * least differs from that method in the following things: 2961 * 1. it skips text content inside nodes like style, script, textarea 2962 * which don't generate an in-tree text frame for the text; 2963 * 2. it skips elements with display property set to none; 2964 * 3. it skips out-of-flow elements; 2965 * 4. it includes content inside pseudo elements; 2966 * 5. it may include part of text content of a node if a text frame 2967 * inside is split to different continuations. 2968 */ 2969 static void GetFrameTextContent(nsIFrame* aFrame, nsAString& aResult); 2970 2971 /** 2972 * Same as GetFrameTextContent but appends the result rather than sets it. 2973 */ 2974 static void AppendFrameTextContent(nsIFrame* aFrame, nsAString& aResult); 2975 2976 /** 2977 * Takes a selection, and returns selection's bounding rect which is relative 2978 * to its root frame. 2979 * 2980 * @param aSel Selection to check 2981 */ 2982 static nsRect GetSelectionBoundingRect(const mozilla::dom::Selection* aSel); 2983 2984 /** 2985 * Calculate the bounding rect of |aContent|, relative to the origin 2986 * of the scrolled content of |aRootScrollFrame|. 2987 * Where the element is contained inside a scrollable subframe, the 2988 * bounding rect is clipped to the bounds of the subframe. 2989 * If non-null aOutNearestScrollClip will be filled in with the rect of the 2990 * nearest scroll frame (excluding aRootScrollFrame) that is an ancestor of 2991 * the frame of aContent, if such exists, in the same coords are the returned 2992 * rect. This rect is used to clip the result. 2993 */ 2994 static CSSRect GetBoundingContentRect( 2995 const nsIContent* aContent, 2996 const mozilla::ScrollContainerFrame* aRootScrollContainerFrame, 2997 mozilla::Maybe<CSSRect>* aOutNearestScrollClip = nullptr); 2998 2999 /** 3000 * Similar to GetBoundingContentRect for nsIFrame. 3001 */ 3002 static CSSRect GetBoundingFrameRect( 3003 nsIFrame* aFrame, 3004 const mozilla::ScrollContainerFrame* aRootScrollContainerFrame, 3005 mozilla::Maybe<CSSRect>* aOutNearestScrollClip = nullptr); 3006 3007 /** 3008 * Returns the first ancestor who is a float containing block. 3009 */ 3010 static nsBlockFrame* GetFloatContainingBlock(nsIFrame* aFrame); 3011 3012 /** 3013 * Walks up the frame tree from |aForFrame| up to |aTopFrame|, or to the 3014 * root of the frame tree if |aTopFrame| is nullptr, and returns true if 3015 * a transformed frame is encountered. 3016 */ 3017 static bool IsTransformed(nsIFrame* aForFrame, nsIFrame* aTopFrame = nullptr); 3018 3019 /** 3020 * Walk up from aFrame to the cross-doc root, accumulating all the APZ 3021 * callback transforms on the content elements encountered along the way. 3022 * Return the accumulated value. 3023 * XXX: Note that this does not take into account CSS transforms, nor 3024 * differences in structure between the frame tree and the layer tree (which 3025 * is probably what we *want* to be computing). 3026 */ 3027 static CSSPoint GetCumulativeApzCallbackTransform(nsIFrame* aFrame); 3028 3029 /** 3030 * Compute a rect to pre-render in cases where we want to render more of 3031 * something than what is visible (usually to support async transformation). 3032 * @param aFrame the target frame to be pre-rendered 3033 * @param aDirtyRect the area that's visible in the coordinate system of 3034 * |aFrame|. 3035 * @param aOverflow the total size of the thing we're rendering in the 3036 * coordinate system of |aFrame|. 3037 * @param aPrerenderSize how large of an area we're willing to render in the 3038 * coordinate system of the root frame. 3039 * @return A rectangle that includes |aDirtyRect|, is clamped to |aOverflow|, 3040 * and is no larger than |aPrerenderSize| (unless |aPrerenderSize| is 3041 * smaller than |aDirtyRect|, in which case the returned rect will 3042 * still include |aDirtyRect| and thus be larger than 3043 * |aPrerenderSize|). 3044 */ 3045 static nsRect ComputePartialPrerenderArea(nsIFrame* aFrame, 3046 const nsRect& aDirtyRect, 3047 const nsRect& aOverflow, 3048 const nsSize& aPrerenderSize); 3049 3050 /* 3051 * Checks whether a node is an invisible break. 3052 * If not, returns the first frame on the next line if such a next line 3053 * exists. 3054 * 3055 * @return 3056 * true if the node is an invisible break. aNextLineFrame is returned null 3057 * in this case. 3058 * 3059 * false if the node causes a visible break or if the node is no break. 3060 * 3061 * @param aNextLineFrame 3062 * assigned to first frame on the next line if such a next line exists, null 3063 * otherwise. 3064 */ 3065 static bool IsInvisibleBreak(const nsINode* aNode, 3066 nsIFrame** aNextLineFrame = nullptr); 3067 3068 static nsRect ComputeSVGOriginBox(mozilla::dom::SVGViewportElement*); 3069 3070 // Compute the geometry box for SVG layout. The caller should map the CSS box 3071 // into the proper SVG box. 3072 // |aMayHaveCyclicDependency| is used for stroke-box to avoid the cyclic 3073 // dependency if any of its descendants uses non-scaling-stroke. 3074 enum class MayHaveNonScalingStrokeCyclicDependency : bool { No, Yes }; 3075 static nsRect ComputeSVGReferenceRect( 3076 nsIFrame*, StyleGeometryBox, 3077 MayHaveNonScalingStrokeCyclicDependency = 3078 MayHaveNonScalingStrokeCyclicDependency::No); 3079 3080 // Compute the geometry box for CSS layout. The caller should map the SVG box 3081 // into the proper CSS box. 3082 static nsRect ComputeHTMLReferenceRect(const nsIFrame*, StyleGeometryBox); 3083 3084 static nsRect ComputeClipPathGeometryBox( 3085 nsIFrame*, const mozilla::StyleShapeGeometryBox&); 3086 3087 static nsPoint ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder, 3088 nsIFrame* aFrame); 3089 3090 // Callers are responsible to ensure the user-font-set is up-to-date if 3091 // aUseUserFontSet is true. 3092 static already_AddRefed<nsFontMetrics> GetMetricsFor( 3093 nsPresContext* aPresContext, bool aIsVertical, 3094 const nsStyleFont* aStyleFont, mozilla::Length aFontSize, 3095 bool aUseUserFontSet); 3096 3097 static void ComputeSystemFont(nsFont* aSystemFont, 3098 mozilla::StyleSystemFont aFontID, 3099 const nsFont& aDefaultVariableFont, 3100 const mozilla::dom::Document* aDocument); 3101 3102 static uint32_t ParseFontLanguageOverride(const nsAString& aLangTag); 3103 3104 /** 3105 * Returns true if there are any preferences or overrides that indicate a 3106 * need to handle <meta name="viewport"> tags. 3107 */ 3108 static bool ShouldHandleMetaViewport(const mozilla::dom::Document*); 3109 3110 /** 3111 * Resolve a CSS <length-percentage> value to a definite size. 3112 */ 3113 template <bool clampNegativeResultToZero> 3114 static nscoord ResolveToLength(const LengthPercentage& aLengthPercentage, 3115 nscoord aPercentageBasis) { 3116 nscoord value = (aPercentageBasis == NS_UNCONSTRAINEDSIZE) 3117 ? aLengthPercentage.Resolve(0) 3118 : aLengthPercentage.Resolve(aPercentageBasis); 3119 return clampNegativeResultToZero ? std::max(0, value) : value; 3120 } 3121 3122 /** 3123 * Resolve a column-gap/row-gap to a definite size. 3124 * @note This method resolves 'normal' to zero. 3125 * Callers who want different behavior should handle 'normal' on their own. 3126 */ 3127 static nscoord ResolveGapToLength( 3128 const mozilla::NonNegativeLengthPercentageOrNormal& aGap, 3129 nscoord aPercentageBasis) { 3130 if (aGap.IsNormal()) { 3131 return nscoord(0); 3132 } 3133 return ResolveToLength<true>(aGap.AsLengthPercentage(), aPercentageBasis); 3134 } 3135 3136 /** 3137 * Get the computed style from which the scrollbar style should be 3138 * used for the given scrollbar part frame. 3139 */ 3140 static ComputedStyle* StyleForScrollbar(const nsIFrame* aScrollbarPart); 3141 3142 /** 3143 * Returns true if |aFrame| is scrolled out of view by a scrollable element in 3144 * a cross-process ancestor document. 3145 * Note this function only works for frames in out-of-process iframes. 3146 **/ 3147 static bool FrameRectIsScrolledOutOfViewInCrossProcess( 3148 const nsIFrame* aFrame, const nsRect& aFrameRect); 3149 3150 /** 3151 * Similar to above FrameIsScrolledOutViewInCrossProcess but returns true even 3152 * if |aFrame| is not fully scrolled out of view and its visible area width or 3153 * height is smaller than |aMargin|. 3154 **/ 3155 static bool FrameIsMostlyScrolledOutOfViewInCrossProcess( 3156 const nsIFrame* aFrame, nscoord aMargin); 3157 3158 /** 3159 * Expand the height of |aSize| to the size of `vh` units. 3160 * 3161 * With dynamic toolbar(s) the height for `vh` units is greater than the 3162 * ICB height, we need to expand it in some places. 3163 **/ 3164 static nsSize ExpandHeightForViewportUnits(nsPresContext* aPresContext, 3165 const nsSize& aSize); 3166 3167 static CSSSize ExpandHeightForDynamicToolbar( 3168 const nsPresContext* aPresContext, const CSSSize& aSize); 3169 static nsSize ExpandHeightForDynamicToolbar(const nsPresContext* aPresContext, 3170 const nsSize& aSize); 3171 3172 /** 3173 * Returns the nsIFrame which clips overflow regions of the given |aFrame|. 3174 * Note CSS clip or clip-path isn't accounted for. 3175 **/ 3176 static nsIFrame* GetNearestOverflowClipFrame(nsIFrame* aFrame); 3177 3178 /* 3179 * Returns true if the user's preferences allow for smooth scrolling. 3180 */ 3181 static bool IsSmoothScrollingEnabled(); 3182 3183 /* 3184 * Recompute the default value of general.smoothScroll based on 3185 * the system settings for prefers-reduced-motion. 3186 * 3187 * Note: Must only be called from the main thread. 3188 */ 3189 static void RecomputeSmoothScrollDefault(); 3190 3191 /** 3192 * Get the union of the rects of aFrame and its continuations (but not if the 3193 * context is paginated and they're on a different page, as it doesn't make 3194 * sense to "merge" their rects in that case). 3195 * 3196 * @param aFrame The target frame whose combined fragments are wanted. 3197 * @param aRelativeToSelf If true, return rect relative to aFrame's origin; 3198 * if false, return rect in aFrame's parent's space. 3199 */ 3200 static nsRect GetCombinedFragmentRects(const nsIFrame* aFrame, 3201 bool aRelativeToSelf = true); 3202 3203 private: 3204 /** 3205 * Helper function for LogTestDataForPaint(). 3206 */ 3207 static void DoLogTestDataForPaint( 3208 mozilla::layers::WebRenderLayerManager* aManager, ViewID aScrollId, 3209 const std::string& aKey, const std::string& aValue); 3210 3211 static bool IsAPZTestLoggingEnabled(); 3212 3213 // doubles only because nscoord_max and nscoord_min cannot be represented 3214 // exactly by floats. 3215 static void ConstrainToCoordValues(double& aStart, double& aSize); 3216 }; 3217 3218 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsLayoutUtils::PaintFrameFlags) 3219 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsLayoutUtils::GetPopupFrameForPointFlags) 3220 3221 template <typename PointType, typename RectType, typename CoordType> 3222 /* static */ bool nsLayoutUtils::PointIsCloserToRect( 3223 PointType aPoint, const RectType& aRect, CoordType& aClosestXDistance, 3224 CoordType& aClosestYDistance) { 3225 CoordType fromLeft = aPoint.x - aRect.x; 3226 CoordType fromRight = aPoint.x - aRect.XMost(); 3227 3228 CoordType xDistance; 3229 if (fromLeft >= 0 && fromRight <= 0) { 3230 xDistance = 0; 3231 } else { 3232 xDistance = std::min(abs(fromLeft), abs(fromRight)); 3233 } 3234 3235 if (xDistance <= aClosestXDistance) { 3236 if (xDistance < aClosestXDistance) { 3237 aClosestYDistance = std::numeric_limits<CoordType>::max(); 3238 } 3239 3240 CoordType fromTop = aPoint.y - aRect.y; 3241 CoordType fromBottom = aPoint.y - aRect.YMost(); 3242 3243 CoordType yDistance; 3244 if (fromTop >= 0 && fromBottom <= 0) { 3245 yDistance = 0; 3246 } else { 3247 yDistance = std::min(abs(fromTop), abs(fromBottom)); 3248 } 3249 3250 if (yDistance < aClosestYDistance) { 3251 aClosestXDistance = xDistance; 3252 aClosestYDistance = yDistance; 3253 return true; 3254 } 3255 } 3256 3257 return false; 3258 } 3259 3260 template <typename T> 3261 nsRect nsLayoutUtils::RoundGfxRectToAppRect(const T& aRect, 3262 const float aFactor) { 3263 // Get a new Rect whose units are app units by scaling by the specified 3264 // factor. 3265 T scaledRect = aRect; 3266 scaledRect.ScaleRoundOut(aFactor); 3267 3268 nsRect retval; 3269 3270 double start = double(scaledRect.x); 3271 double size = double(scaledRect.width); 3272 // We now need to constrain our results to the max and min values for coords. 3273 ConstrainToCoordValues(start, size); 3274 // ConstrainToCoordValues ensures casting to nscoord is safe. 3275 retval.x = nscoord(start); 3276 retval.width = nscoord(size); 3277 3278 start = double(scaledRect.y); 3279 size = double(scaledRect.height); 3280 ConstrainToCoordValues(start, size); 3281 retval.y = nscoord(start); 3282 retval.height = nscoord(size); 3283 3284 if (!aRect.Width()) { 3285 retval.SetWidth(0); 3286 } 3287 3288 if (!aRect.Height()) { 3289 retval.SetHeight(0); 3290 } 3291 3292 return retval; 3293 } 3294 3295 template <typename T> 3296 nsRect nsLayoutUtils::ScaleThenRoundGfxRectToAppRect(const T& aRect, 3297 const float aFactor) { 3298 // Get a new Rect whose units are app units by scaling by the specified 3299 // factor. 3300 T scaledRect = aRect; 3301 scaledRect.Scale(aFactor); 3302 3303 nsRect retval; 3304 3305 double start = double(scaledRect.x); 3306 double size = double(scaledRect.width); 3307 // We now need to constrain our results to the max and min values for coords. 3308 ConstrainToCoordValues(start, size); 3309 // ConstrainToCoordValues ensures converting to nscoord is safe. 3310 retval.x = NSToCoordRoundWithClamp(start); 3311 retval.width = NSToCoordRoundWithClamp(size); 3312 3313 start = double(scaledRect.y); 3314 size = double(scaledRect.height); 3315 ConstrainToCoordValues(start, size); 3316 retval.y = NSToCoordRoundWithClamp(start); 3317 retval.height = NSToCoordRoundWithClamp(size); 3318 3319 if (!aRect.Width()) { 3320 retval.SetWidth(0); 3321 } 3322 3323 if (!aRect.Height()) { 3324 retval.SetHeight(0); 3325 } 3326 3327 return retval; 3328 } 3329 3330 namespace mozilla { 3331 3332 /** 3333 * Converts an nsPoint in app units to a Moz2D Point in pixels (whether those 3334 * are device pixels or CSS px depends on what the caller chooses to pass as 3335 * aAppUnitsPerPixel). 3336 */ 3337 inline gfx::Point NSPointToPoint(const nsPoint& aPoint, 3338 int32_t aAppUnitsPerPixel) { 3339 return gfx::Point(gfx::Float(aPoint.x) / aAppUnitsPerPixel, 3340 gfx::Float(aPoint.y) / aAppUnitsPerPixel); 3341 } 3342 3343 /** 3344 * Converts an nsRect in app units to a Moz2D Rect in pixels (whether those 3345 * are device pixels or CSS px depends on what the caller chooses to pass as 3346 * aAppUnitsPerPixel). 3347 */ 3348 gfx::Rect NSRectToRect(const nsRect& aRect, double aAppUnitsPerPixel); 3349 3350 /** 3351 * Converts an nsRect in app units to a Moz2D Rect in pixels (whether those 3352 * are device pixels or CSS px depends on what the caller chooses to pass as 3353 * aAppUnitsPerPixel). 3354 * 3355 * The passed DrawTarget is used to additionally snap the returned Rect to 3356 * device pixels, if appropriate (as decided and carried out by Moz2D's 3357 * MaybeSnapToDevicePixels helper, which this function calls to do any 3358 * snapping). 3359 */ 3360 gfx::Rect NSRectToSnappedRect(const nsRect& aRect, double aAppUnitsPerPixel, 3361 const gfx::DrawTarget& aSnapDT); 3362 3363 /** 3364 * Converts, where possible, an nsRect in app units to a Moz2D Rect in pixels 3365 * (whether those are device pixels or CSS px depends on what the caller 3366 * chooses to pass as aAppUnitsPerPixel). 3367 * 3368 * If snapping results in a rectangle with zero width or height, the affected 3369 * coordinates are left unsnapped 3370 */ 3371 gfx::Rect NSRectToNonEmptySnappedRect(const nsRect& aRect, 3372 double aAppUnitsPerPixel, 3373 const gfx::DrawTarget& aSnapDT); 3374 3375 void StrokeLineWithSnapping( 3376 const nsPoint& aP1, const nsPoint& aP2, int32_t aAppUnitsPerDevPixel, 3377 gfx::DrawTarget& aDrawTarget, const gfx::Pattern& aPattern, 3378 const gfx::StrokeOptions& aStrokeOptions = gfx::StrokeOptions(), 3379 const gfx::DrawOptions& aDrawOptions = gfx::DrawOptions()); 3380 3381 namespace layout { 3382 3383 /** 3384 * An RAII class which will, for the duration of its lifetime, 3385 * **if** the frame given is a container for font size inflation, 3386 * set the current inflation container on the pres context to null 3387 * (and then, in its destructor, restore the old value). 3388 */ 3389 class AutoMaybeDisableFontInflation { 3390 public: 3391 explicit AutoMaybeDisableFontInflation(nsIFrame* aFrame); 3392 3393 ~AutoMaybeDisableFontInflation(); 3394 3395 private: 3396 nsPresContext* mPresContext; 3397 bool mOldValue; 3398 }; 3399 3400 } // namespace layout 3401 } // namespace mozilla 3402 3403 class nsSetAttrRunnable : public mozilla::Runnable { 3404 public: 3405 nsSetAttrRunnable(mozilla::dom::Element* aElement, nsAtom* aAttrName, 3406 const nsAString& aValue); 3407 nsSetAttrRunnable(mozilla::dom::Element* aElement, nsAtom* aAttrName, 3408 int32_t aValue); 3409 3410 NS_DECL_NSIRUNNABLE 3411 3412 RefPtr<mozilla::dom::Element> mElement; 3413 RefPtr<nsAtom> mAttrName; 3414 nsAutoString mValue; 3415 }; 3416 3417 class nsUnsetAttrRunnable : public mozilla::Runnable { 3418 public: 3419 nsUnsetAttrRunnable(mozilla::dom::Element* aElement, nsAtom* aAttrName); 3420 3421 NS_DECL_NSIRUNNABLE 3422 3423 RefPtr<mozilla::dom::Element> mElement; 3424 RefPtr<nsAtom> mAttrName; 3425 }; 3426 3427 // This class allows you to easily set any pointer variable and ensure it's 3428 // set to nullptr when leaving its scope. 3429 template <typename T> 3430 class MOZ_RAII SetAndNullOnExit { 3431 public: 3432 SetAndNullOnExit(T*& aVariable, T* aValue) { 3433 aVariable = aValue; 3434 mVariable = &aVariable; 3435 } 3436 ~SetAndNullOnExit() { *mVariable = nullptr; } 3437 3438 private: 3439 T** mVariable; 3440 }; 3441 3442 #endif // nsLayoutUtils_h__