tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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__