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