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