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