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