Bug 1879449 [wpt PR 44489] - [wptrunner] Add `infrastructure/expected-fail/` test...
[gecko.git] / layout / base / nsLayoutUtils.h
blob697b139ed91a3e1154930f5091ede8cd7eb68faf
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 nsIScrollableFrame;
53 class nsRegion;
54 enum nsChangeHint : uint32_t;
55 class nsFontMetrics;
56 class nsFontFaceList;
57 class nsIImageLoadingContent;
58 class nsBlockFrame;
59 class nsContainerFrame;
60 class nsView;
61 class nsIFrame;
62 class nsPIDOMWindowOuter;
63 class imgIRequest;
64 struct nsStyleFont;
66 namespace mozilla {
67 class nsDisplayItem;
68 class nsDisplayList;
69 class nsDisplayListBuilder;
70 enum class nsDisplayListBuilderMode : uint8_t;
71 class RetainedDisplayListBuilder;
72 struct AspectRatio;
73 class ComputedStyle;
74 class DisplayPortUtils;
75 class PresShell;
76 enum class PseudoStyleType : uint8_t;
77 class EventListenerManager;
78 enum class LayoutFrameType : uint8_t;
79 struct IntrinsicSize;
80 class ReflowOutput;
81 class WritingMode;
82 class DisplayItemClip;
83 class EffectSet;
84 struct ActiveScrolledRoot;
85 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 scrollable frame for a given content element.
218 static nsIScrollableFrame* FindScrollableFrameFor(nsIContent* aContent);
221 * Find the scrollable frame for a given ID.
223 static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId);
226 * Helper for FindScrollableFrameFor(), also used in DisplayPortUtils.
227 * Most clients should use FindScrollableFrameFor().
229 static nsIFrame* GetScrollFrameFromContent(nsIContent* aContent);
232 * Find the ID for a given scrollable frame.
234 static ViewID FindIDForScrollableFrame(nsIScrollableFrame* aScrollable);
237 * Notify the scroll frame with the given scroll id that its scroll offset
238 * is being sent to APZ as part of a paint-skip transaction.
240 * Normally, this notification happens during painting, after calls to
241 * ComputeScrollMetadata(). During paint-skipping that code is skipped,
242 * but it's still important for the scroll frame to be notified for
243 * correctness of relative scroll updates, so the code that sends the
244 * empty paint-skip transaction needs to call this.
246 static void NotifyPaintSkipTransaction(ViewID aScrollId);
249 * Use heuristics to figure out the child list that
250 * aChildFrame is currently in.
252 static mozilla::FrameChildListID GetChildListNameFor(nsIFrame* aChildFrame);
255 * Returns the ::before pseudo-element for aContent, if any.
257 static mozilla::dom::Element* GetBeforePseudo(const nsIContent* aContent);
260 * Returns the frame corresponding to the ::before pseudo-element for
261 * aContent, if any.
263 static nsIFrame* GetBeforeFrame(const nsIContent* aContent);
266 * Returns the ::after pseudo-element for aContent, if any.
268 static mozilla::dom::Element* GetAfterPseudo(const nsIContent* aContent);
271 * Returns the frame corresponding to the ::after pseudo-element for aContent,
272 * if any.
274 static nsIFrame* GetAfterFrame(const nsIContent* aContent);
277 * Returns the ::marker pseudo-element for aContent, if any.
279 static mozilla::dom::Element* GetMarkerPseudo(const nsIContent* aContent);
282 * Returns the frame corresponding to the ::marker pseudo-element for
283 * aContent, if any.
285 static nsIFrame* GetMarkerFrame(const nsIContent* aContent);
287 #ifdef ACCESSIBILITY
289 * Set aText to the spoken text for the given ::marker content (aContent)
290 * if it has a frame, or the empty string otherwise.
292 static void GetMarkerSpokenText(const nsIContent* aContent, nsAString& aText);
293 #endif
296 * Given a frame, search up the frame tree until we find an
297 * ancestor that (or the frame itself) is of type aFrameType, if any.
299 * @param aFrame the frame to start at
300 * @param aFrameType the frame type to look for
301 * @param aStopAt a frame to stop at after we checked it
302 * @return a frame of the given type or nullptr if no
303 * such ancestor exists
305 static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame,
306 mozilla::LayoutFrameType aFrameType,
307 nsIFrame* aStopAt = nullptr);
310 * Given a frame, search up the frame tree until we find an
311 * ancestor that (or the frame itself) is a "Page" frame, if any.
313 * @param aFrame the frame to start at
314 * @return a frame of type mozilla::LayoutFrameType::Page or nullptr if no
315 * such ancestor exists
317 static nsIFrame* GetPageFrame(nsIFrame* aFrame);
320 * Given a frame which is the primary frame for an element,
321 * return the frame that has the non-pseudoelement ComputedStyle for
322 * the content.
323 * This is aPrimaryFrame itself except for tableWrapper frames.
325 * Given a non-null input, this will return null if and only if its
326 * argument is a table wrapper frame that is mid-destruction (and its
327 * table frame has been destroyed).
329 static nsIFrame* GetStyleFrame(nsIFrame* aPrimaryFrame);
330 static const nsIFrame* GetStyleFrame(const nsIFrame* aPrimaryFrame);
333 * Given a content node,
334 * return the frame that has the non-pseudoelement ComputedStyle for
335 * the content. May return null.
336 * This is aContent->GetPrimaryFrame() except for tableWrapper frames.
338 static nsIFrame* GetStyleFrame(const nsIContent* aContent);
341 * Returns the placeholder size for when the scrollbar is unthemed.
343 static mozilla::CSSIntCoord UnthemedScrollbarSize(
344 mozilla::StyleScrollbarWidth);
347 * The inverse of GetStyleFrame. Returns |aStyleFrame| unless it is an inner
348 * table frame, in which case the table wrapper frame is returned.
350 static nsIFrame* GetPrimaryFrameFromStyleFrame(nsIFrame* aStyleFrame);
351 static const nsIFrame* GetPrimaryFrameFromStyleFrame(
352 const nsIFrame* aStyleFrame);
355 * Similar to nsIFrame::IsPrimaryFrame except that this will return true
356 * for the inner table frame rather than for its wrapper frame.
358 static bool IsPrimaryStyleFrame(const nsIFrame* aFrame);
361 * CompareTreePosition determines whether aFrame1 comes before or
362 * after aFrame2 in a preorder traversal of the frame tree, where out
363 * of flow frames are treated as children of their placeholders. This is
364 * basically the same ordering as DoCompareTreePosition(nsIContent*) except
365 * that it handles anonymous content properly and there are subtleties with
366 * continuations.
368 * @param aCommonAncestor either null, or a common ancestor of
369 * aContent1 and aContent2. Actually this is
370 * only a hint; if it's not an ancestor of
371 * aContent1 or aContent2, this function will
372 * still work, but it will be slower than
373 * normal.
374 * @return < 0 if aContent1 is before aContent2
375 * > 0 if aContent1 is after aContent2,
376 * 0 otherwise (meaning they're the same, or they're in
377 * different frame trees)
379 static int32_t CompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
380 nsIFrame* aCommonAncestor = nullptr) {
381 return DoCompareTreePosition(aFrame1, aFrame2, aCommonAncestor);
384 static int32_t CompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
385 nsTArray<nsIFrame*>& aFrame2Ancestors,
386 nsIFrame* aCommonAncestor = nullptr) {
387 return DoCompareTreePosition(aFrame1, aFrame2, aFrame2Ancestors,
388 aCommonAncestor);
391 static nsIFrame* FillAncestors(nsIFrame* aFrame, nsIFrame* aStopAtAncestor,
392 nsTArray<nsIFrame*>* aAncestors);
394 static int32_t DoCompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
395 nsIFrame* aCommonAncestor);
396 static int32_t DoCompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
397 nsTArray<nsIFrame*>& aFrame2Ancestors,
398 nsIFrame* aCommonAncestor);
401 * LastContinuationWithChild gets the last continuation in aFrame's chain
402 * that has a child, or the first continuation if the frame has no children.
404 static nsContainerFrame* LastContinuationWithChild(nsContainerFrame* aFrame);
407 * GetLastSibling simply finds the last sibling of aFrame, or returns nullptr
408 * if aFrame is null.
410 static nsIFrame* GetLastSibling(nsIFrame* aFrame);
413 * FindSiblingViewFor locates the child of aParentView that aFrame's
414 * view should be inserted 'above' (i.e., before in sibling view
415 * order). This is the first child view of aParentView whose
416 * corresponding content is before aFrame's content (view siblings
417 * are in reverse content order).
419 static nsView* FindSiblingViewFor(nsView* aParentView, nsIFrame* aFrame);
422 * Get the parent of aFrame. If aFrame is the root frame for a document,
423 * and the document has a parent document in the same view hierarchy, then
424 * we try to return the subdocumentframe in the parent document.
425 * @param aCrossDocOffset [in/out] if non-null, then as we cross documents
426 * an extra offset may be required and it will be added to aCrossDocOffset.
427 * Be careful dealing with this extra offset as it is in app units of the
428 * parent document, which may have a different app units per dev pixel ratio
429 * than the child document.
430 * Note that, while this function crosses document boundaries, it (naturally)
431 * cannot cross process boundaries.
433 static nsIFrame* GetCrossDocParentFrameInProcess(
434 const nsIFrame* aFrame, nsPoint* aCrossDocOffset = nullptr);
437 * Does the same thing as GetCrossDocParentFrameInProcess().
438 * The purpose of having two functions is to more easily track which call
439 * sites have been audited to consider out-of-process iframes (bug 1599913).
440 * Once all call sites have been audited, this function can be removed.
442 static nsIFrame* GetCrossDocParentFrame(const nsIFrame* aFrame,
443 nsPoint* aCrossDocOffset = nullptr);
446 * IsProperAncestorFrame checks whether aAncestorFrame is an ancestor
447 * of aFrame and not equal to aFrame.
448 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
449 * aAncestorFrame. If non-null, this can bound the search and speed up
450 * the function
452 static bool IsProperAncestorFrame(const nsIFrame* aAncestorFrame,
453 const nsIFrame* aFrame,
454 const nsIFrame* aCommonAncestor = nullptr);
457 * Like IsProperAncestorFrame, but looks across document boundaries.
459 * Just like IsAncestorFrameCrossDoc, except that it returns false when
460 * aFrame == aAncestorFrame.
461 * TODO: Once after we fixed bug 1715932, this function should be removed.
463 static bool IsProperAncestorFrameCrossDoc(
464 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
465 const nsIFrame* aCommonAncestor = nullptr);
468 * Like IsProperAncestorFrame, but looks across document boundaries.
470 * Just like IsAncestorFrameCrossDoc, except that it returns false when
471 * aFrame == aAncestorFrame.
473 static bool IsProperAncestorFrameCrossDocInProcess(
474 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
475 const nsIFrame* aCommonAncestor = nullptr);
478 * IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor
479 * of aFrame or equal to aFrame, looking across document boundaries.
480 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
481 * aAncestorFrame. If non-null, this can bound the search and speed up
482 * the function.
484 * Just like IsProperAncestorFrameCrossDoc, except that it returns true when
485 * aFrame == aAncestorFrame.
487 * TODO: Bug 1700245, all call sites of this function will be eventually
488 * replaced by IsAncestorFrameCrossDocInProcess.
490 static bool IsAncestorFrameCrossDoc(
491 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
492 const nsIFrame* aCommonAncestor = nullptr);
495 * IsAncestorFrameCrossDocInProcess checks whether aAncestorFrame is an
496 * ancestor of aFrame or equal to aFrame, looking across document boundaries
497 * in the same process.
498 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
499 * aAncestorFrame. If non-null, this can bound the search and speed up
500 * the function.
502 * Just like IsProperAncestorFrameCrossDoc, except that it returns true when
503 * aFrame == aAncestorFrame.
505 * NOTE: This function doesn't return true even if |aAncestorFrame| and
506 * |aFrame| is in the same process but they are not directly connected, e.g.
507 * both |aAncestorFrame| and |aFrame| in A domain documents, but there's
508 * another an iframe document domain B, such as A1 -> B1 ->A2 document tree.
510 static bool IsAncestorFrameCrossDocInProcess(
511 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
512 const nsIFrame* aCommonAncestor = nullptr);
514 static mozilla::SideBits GetSideBitsForFixedPositionContent(
515 const nsIFrame* aFixedPosFrame);
518 * Get the scroll id for the root scrollframe of the presshell of the given
519 * prescontext. Returns NULL_SCROLL_ID if it couldn't be found.
521 static ViewID ScrollIdForRootScrollFrame(nsPresContext* aPresContext);
524 * GetScrollableFrameFor returns the scrollable frame for a scrolled frame
526 static nsIScrollableFrame* GetScrollableFrameFor(
527 const nsIFrame* aScrolledFrame);
530 * GetNearestScrollableFrameForDirection locates the first ancestor of
531 * aFrame (or aFrame itself) that is scrollable with overflow:scroll or
532 * overflow:auto in the given direction and where either the scrollbar for
533 * that direction is visible or the frame can be scrolled by some
534 * positive amount in that direction.
535 * The search extends across document boundaries.
537 * @param aFrame the frame to start with
538 * @param aDirection Whether it's for horizontal or vertical scrolling.
539 * @return the nearest scrollable frame or nullptr if not found
541 static nsIScrollableFrame* GetNearestScrollableFrameForDirection(
542 nsIFrame* aFrame, mozilla::layers::ScrollDirections aDirections);
544 enum {
546 * If the SCROLLABLE_SAME_DOC flag is set, then we only walk the frame tree
547 * up to the root frame in the current document.
549 SCROLLABLE_SAME_DOC = 0x01,
551 * If the SCROLLABLE_INCLUDE_HIDDEN flag is set then we allow
552 * overflow:hidden scrollframes to be returned as scrollable frames.
554 SCROLLABLE_INCLUDE_HIDDEN = 0x02,
556 * If the SCROLLABLE_ONLY_ASYNC_SCROLLABLE flag is set, then we only
557 * want to match scrollable frames for which WantAsyncScroll() returns
558 * true.
560 SCROLLABLE_ONLY_ASYNC_SCROLLABLE = 0x04,
562 * If the SCROLLABLE_ALWAYS_MATCH_ROOT flag is set, then we will always
563 * return the root scrollable frame for the root document (in the current
564 * process) if we encounter it, whether or not it is async scrollable or
565 * overflow: hidden.
567 SCROLLABLE_ALWAYS_MATCH_ROOT = 0x08,
569 * If the SCROLLABLE_FIXEDPOS_FINDS_ROOT flag is set, then for fixed-pos
570 * frames return the root scrollable frame for that document.
572 SCROLLABLE_FIXEDPOS_FINDS_ROOT = 0x10,
574 * If the SCROLLABLE_STOP_AT_PAGE flag is set, then we stop searching
575 * for scrollable ancestors when seeing a nsPageFrame. This can be used
576 * to avoid finding the viewport scroll frame in Print Preview (which
577 * would be undesirable as a 'position:sticky' container for content).
579 SCROLLABLE_STOP_AT_PAGE = 0x20,
582 * GetNearestScrollableFrame locates the first ancestor of aFrame
583 * (or aFrame itself) that is scrollable with overflow:scroll or
584 * overflow:auto in some direction.
586 * @param aFrame the frame to start with
587 * @param aFlags if SCROLLABLE_SAME_DOC is set, do not search across
588 * document boundaries. If SCROLLABLE_INCLUDE_HIDDEN is set, include
589 * frames scrollable with overflow:hidden.
590 * @return the nearest scrollable frame or nullptr if not found
592 static nsIScrollableFrame* GetNearestScrollableFrame(nsIFrame* aFrame,
593 uint32_t aFlags = 0);
596 * GetScrolledRect returns the range of allowable scroll offsets
597 * for aScrolledFrame, assuming the scrollable overflow area is
598 * aScrolledFrameOverflowArea and the scrollport size is aScrollPortSize.
600 static nsRect GetScrolledRect(nsIFrame* aScrolledFrame,
601 const nsRect& aScrolledFrameOverflowArea,
602 const nsSize& aScrollPortSize,
603 mozilla::StyleDirection);
606 * HasPseudoStyle returns true if aContent (whose primary style
607 * context is aComputedStyle) has the aPseudoElement pseudo-style
608 * attached to it; returns false otherwise.
610 * @param aContent the content node we're looking at
611 * @param aComputedStyle aContent's ComputedStyle
612 * @param aPseudoElement the id of the pseudo style we care about
613 * @param aPresContext the presentation context
614 * @return whether aContent has aPseudoElement style attached to it
616 static bool HasPseudoStyle(nsIContent* aContent,
617 ComputedStyle* aComputedStyle,
618 mozilla::PseudoStyleType aPseudoElement,
619 nsPresContext* aPresContext);
622 * If this frame is a placeholder for a float, then return the float,
623 * otherwise return nullptr. aPlaceholder must be a placeholder frame.
625 static nsIFrame* GetFloatFromPlaceholder(nsIFrame* aPlaceholder);
627 // Combine aOrigClearType with aNewClearType, but limit the clear types
628 // to StyleClear::Left, Right, Both.
629 static mozilla::StyleClear CombineClearType(
630 mozilla::StyleClear aOrigClearType, mozilla::StyleClear aNewClearType);
633 * Get the coordinates of a given DOM mouse event, relative to a given
634 * frame. Works only for DOM events generated by WidgetGUIEvents.
635 * @param aDOMEvent the event
636 * @param aFrame the frame to make coordinates relative to
637 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
638 * for some reason the coordinates for the mouse are not known (e.g.,
639 * the event is not a GUI event).
641 static nsPoint GetDOMEventCoordinatesRelativeTo(
642 mozilla::dom::Event* aDOMEvent, nsIFrame* aFrame);
645 * Get the coordinates of a given native mouse event, relative to a given
646 * frame.
647 * @param aEvent the event
648 * @param aFrame the frame to make coordinates relative to
649 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
650 * for some reason the coordinates for the mouse are not known (e.g.,
651 * the event is not a GUI event).
653 static nsPoint GetEventCoordinatesRelativeTo(
654 const mozilla::WidgetEvent* aEvent, RelativeTo aFrame);
657 * Get the coordinates of a given point relative to an event and a
658 * given frame.
659 * @param aEvent the event
660 * @param aPoint the point to get the coordinates relative to
661 * @param aFrame the frame to make coordinates relative to
662 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
663 * for some reason the coordinates for the mouse are not known (e.g.,
664 * the event is not a GUI event).
666 static nsPoint GetEventCoordinatesRelativeTo(
667 const mozilla::WidgetEvent* aEvent,
668 const mozilla::LayoutDeviceIntPoint& aPoint, RelativeTo aFrame);
671 * Get the coordinates of a given point relative to a widget and a
672 * given frame.
673 * @param aWidget the event src widget
674 * @param aPoint the point to get the coordinates relative to
675 * @param aFrame the frame to make coordinates relative to
676 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
677 * for some reason the coordinates for the mouse are not known (e.g.,
678 * the event is not a GUI event).
680 static nsPoint GetEventCoordinatesRelativeTo(
681 nsIWidget* aWidget, const mozilla::LayoutDeviceIntPoint& aPoint,
682 RelativeTo aFrame);
685 * Get the popup frame of a given native mouse event.
686 * @param aRootPresContext only check popups within aRootPresContext or a
687 * descendant
688 * @param aEvent the event.
689 * @return Null, if there is no popup frame at the point, otherwise,
690 * returns top-most popup frame at the point.
692 static nsIFrame* GetPopupFrameForEventCoordinates(
693 nsPresContext* aRootPresContext, const mozilla::WidgetEvent* aEvent);
696 * Get the popup frame of a given point relative to a widget.
697 * @param aRootPresContext only check popups within aRootPresContext or a
698 * descendant
699 * @param aEvent the event.
700 * @return Null, if there is no popup frame at the point, otherwise,
701 * returns top-most popup frame at the point.
703 enum class GetPopupFrameForPointFlags : uint8_t {
704 OnlyReturnFramesWithWidgets = 0x1,
706 static nsIFrame* GetPopupFrameForPoint(
707 nsPresContext* aRootPresContext, nsIWidget* aWidget,
708 const mozilla::LayoutDeviceIntPoint& aPoint,
709 GetPopupFrameForPointFlags aFlags = GetPopupFrameForPointFlags(0));
712 * Get container and offset if aEvent collapses Selection.
713 * @param aPresShell The PresShell handling aEvent.
714 * @param aEvent The event having coordinates where you want to
715 * collapse Selection.
716 * @param aContainer Returns the container node at the point.
717 * Set nullptr if you don't need this.
718 * @param aOffset Returns offset in the container node at the point.
719 * Set nullptr if you don't need this.
721 MOZ_CAN_RUN_SCRIPT
722 static void GetContainerAndOffsetAtEvent(PresShell* aPresShell,
723 const mozilla::WidgetEvent* aEvent,
724 nsIContent** aContainer,
725 int32_t* aOffset);
728 * Translate from widget coordinates to the view's coordinates
729 * @param aPresContext the PresContext for the view
730 * @param aWidget the widget
731 * @param aPt the point relative to the widget
732 * @param aView view to which returned coordinates are relative
733 * @return the point in the view's coordinates
735 static nsPoint TranslateWidgetToView(nsPresContext* aPresContext,
736 nsIWidget* aWidget,
737 const mozilla::LayoutDeviceIntPoint& aPt,
738 nsView* aView);
741 * Translate from view coordinates to the widget's coordinates.
742 * @param aPresContext the PresContext for the view
743 * @param aView the view
744 * @param aPt the point relative to the view
745 * @param aViewportType whether the point is in visual or layout coordinates
746 * @param aWidget the widget to which returned coordinates are relative
747 * @return the point in the view's coordinates
749 static mozilla::LayoutDeviceIntPoint TranslateViewToWidget(
750 nsPresContext* aPresContext, nsView* aView, nsPoint aPt,
751 ViewportType aViewportType, nsIWidget* aWidget);
753 static mozilla::LayoutDeviceIntPoint WidgetToWidgetOffset(
754 nsIWidget* aFromWidget, nsIWidget* aToWidget);
756 enum class FrameForPointOption {
758 * When set, paint suppression is ignored, so we'll return non-root page
759 * elements even if paint suppression is stopping them from painting.
761 IgnorePaintSuppression = 1,
763 * When set, clipping due to the root scroll frame (and any other viewport-
764 * related clipping) is ignored.
766 IgnoreRootScrollFrame,
768 * When set, return only content in the same document as aFrame.
770 IgnoreCrossDoc,
772 * When set, return only content that is actually visible.
774 OnlyVisible,
777 struct FrameForPointOptions {
778 using Bits = mozilla::EnumSet<FrameForPointOption>;
780 Bits mBits;
781 // If mBits contains OnlyVisible, what is the opacity threshold which we
782 // consider "opaque enough" to clobber stuff underneath.
783 float mVisibleThreshold;
785 FrameForPointOptions(Bits aBits, float aVisibleThreshold)
786 : mBits(aBits), mVisibleThreshold(aVisibleThreshold){};
788 MOZ_IMPLICIT FrameForPointOptions(Bits aBits)
789 : FrameForPointOptions(aBits, 1.0f) {}
791 FrameForPointOptions() : FrameForPointOptions(Bits()){};
795 * Given aFrame, the root frame of a stacking context, find its descendant
796 * frame under the point aPt that receives a mouse event at that location,
797 * or nullptr if there is no such frame.
798 * @param aPt the point, relative to the frame origin, in either visual
799 * or layout coordinates depending on aRelativeTo.mViewportType
801 static nsIFrame* GetFrameForPoint(RelativeTo aRelativeTo, nsPoint aPt,
802 const FrameForPointOptions& = {});
805 * Given aFrame, the root frame of a stacking context, find all descendant
806 * frames under the area of a rectangle that receives a mouse event,
807 * or nullptr if there is no such frame.
808 * @param aRect the rect, relative to the frame origin, in either visual
809 * or layout coordinates depending on aRelativeTo.mViewportType
810 * @param aOutFrames an array to add all the frames found
812 static nsresult GetFramesForArea(RelativeTo aRelativeTo, const nsRect& aRect,
813 nsTArray<nsIFrame*>& aOutFrames,
814 const FrameForPointOptions& = {});
817 * Transform aRect relative to aFrame up to the coordinate system of
818 * aAncestor. Computes the bounding-box of the true quadrilateral.
819 * Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if
820 * we only need to use a 2d transform that PreservesAxisAlignedRectangles().
821 * The corner positions of aRect are treated as meaningful even if aRect is
822 * empty.
824 * |aMatrixCache| allows for optimizations in recomputing the same matrix over
825 * and over. The argument can be one of the following values:
827 * nullptr (the default) - No optimization; the transform matrix is computed
828 * on every call to this function.
830 * non-null pointer to an empty Maybe<Matrix4x4> - Upon return, the Maybe is
831 * filled with the transform matrix that was computed. This can then be passed
832 * in to subsequent calls with the same source and destination frames to avoid
833 * recomputing the matrix.
835 * non-null pointer to a non-empty Matrix4x4 - The provided matrix will be
836 * used as the transform matrix and applied to the rect.
838 static nsRect TransformFrameRectToAncestor(
839 const nsIFrame* aFrame, const nsRect& aRect, const nsIFrame* aAncestor,
840 bool* aPreservesAxisAlignedRectangles = nullptr,
841 mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr,
842 bool aStopAtStackingContextAndDisplayPortAndOOFFrame = false,
843 nsIFrame** aOutAncestor = nullptr) {
844 return TransformFrameRectToAncestor(
845 aFrame, aRect, RelativeTo{aAncestor}, aPreservesAxisAlignedRectangles,
846 aMatrixCache, aStopAtStackingContextAndDisplayPortAndOOFFrame,
847 aOutAncestor);
849 static nsRect TransformFrameRectToAncestor(
850 const nsIFrame* aFrame, const nsRect& aRect, RelativeTo aAncestor,
851 bool* aPreservesAxisAlignedRectangles = nullptr,
852 mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr,
853 bool aStopAtStackingContextAndDisplayPortAndOOFFrame = false,
854 nsIFrame** aOutAncestor = nullptr);
857 * Gets the transform for aFrame relative to aAncestor. Pass null for
858 * aAncestor to go up to the root frame. Including nsIFrame::IN_CSS_UNITS
859 * flag in aFlags will return CSS pixels, by default it returns device
860 * pixels.
861 * More info can be found in nsIFrame::GetTransformMatrix.
863 * Some notes on the possible combinations of |aFrame.mViewportType| and
864 * |aAncestor.mViewportType|:
866 * | aFrame. | aAncestor. | Notes
867 * | mViewportType | mViewportType |
868 * ==========================================================================
869 * | Layout | Layout | Commonplace, when both source and target
870 * | | | are inside zoom boundary.
871 * | | |
872 * | | | Could also happen in non-e10s setups
873 * | | | when both source and target are outside
874 * | | | the zoom boundary and the code is
875 * | | | oblivious to the existence of a zoom
876 * | | | boundary.
877 * ==========================================================================
878 * | Layout | Visual | Commonplace, used when hit testing visual
879 * | | | coordinates (e.g. coming from user input
880 * | | | events). We expected to encounter a
881 * | | | zoomed content root during traversal and
882 * | | | apply a layout-to-visual transform.
883 * ==========================================================================
884 * | Visual | Layout | Should never happen, will assert.
885 * ==========================================================================
886 * | Visual | Visual | In e10s setups, should only happen if
887 * | | | aFrame and aAncestor are both the
888 * | | | RCD viewport frame.
889 * | | |
890 * | | | In non-e10s setups, could happen with
891 * | | | different frames if they are both
892 * | | | outside the zoom boundary.
893 * ==========================================================================
895 static Matrix4x4Flagged GetTransformToAncestor(
896 RelativeTo aFrame, RelativeTo aAncestor, uint32_t aFlags = 0,
897 nsIFrame** aOutAncestor = nullptr);
900 * Gets the scale factors of the transform for aFrame relative to the root
901 * frame if this transform can be drawn 2D, or the identity scale factors
902 * otherwise.
904 static MatrixScales GetTransformToAncestorScale(const nsIFrame* aFrame);
907 * Gets the scale factors of the transform for aFrame relative to the root
908 * frame if this transform is 2D, or the identity scale factors otherwise.
909 * If some frame on the path from aFrame to the display root frame may have an
910 * animated scale, returns the identity scale factors.
912 static MatrixScales GetTransformToAncestorScaleExcludingAnimated(
913 nsIFrame* aFrame);
916 * Gets a scale that includes CSS transforms in this process as well as the
917 * transform to ancestor scale passed down from our direct ancestor process
918 * (which includes any enclosing CSS transforms and resolution). Note: this
919 * does not include any resolution in the current process (this is on purpose
920 * because that is what the transform to ancestor field on FrameMetrics needs,
921 * see its definition for explanation as to why). This is the transform to
922 * ancestor scale to set on FrameMetrics.
924 static mozilla::ParentLayerToScreenScale2D
925 GetTransformToAncestorScaleCrossProcessForFrameMetrics(
926 const nsIFrame* aFrame);
929 * Find the nearest common ancestor frame for aFrame1 and aFrame2. The
930 * ancestor frame could be cross-doc.
932 static const nsIFrame* FindNearestCommonAncestorFrame(
933 const nsIFrame* aFrame1, const nsIFrame* aFrame2);
936 * Find the nearest common ancestor frame for aFrame1 and aFrame2, assuming
937 * that they are within the same block.
939 * Returns null if they are not within the same block.
941 static const nsIFrame* FindNearestCommonAncestorFrameWithinBlock(
942 const nsTextFrame* aFrame1, const nsTextFrame* aFrame2);
945 * Whether author-specified borders / backgrounds disable theming for a given
946 * appearance value.
948 static bool AuthorSpecifiedBorderBackgroundDisablesTheming(
949 mozilla::StyleAppearance);
952 * Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into
953 * account all relevant transformations on the frames up to (but excluding)
954 * their nearest common ancestor.
955 * If we encounter a transform that we need to invert but which is
956 * non-invertible, we return NONINVERTIBLE_TRANSFORM. If the frames have
957 * no common ancestor, we return NO_COMMON_ANCESTOR.
958 * If this returns TRANSFORM_SUCCEEDED, the points in aPoints are transformed
959 * in-place, otherwise they are untouched.
961 enum TransformResult {
962 TRANSFORM_SUCCEEDED,
963 NO_COMMON_ANCESTOR,
964 NONINVERTIBLE_TRANSFORM
966 static TransformResult TransformPoints(RelativeTo aFromFrame,
967 RelativeTo aToFrame,
968 uint32_t aPointCount,
969 CSSPoint* aPoints);
972 * Same as above function, but transform points in app units and
973 * handle 1 point per call.
975 static TransformResult TransformPoint(RelativeTo aFromFrame,
976 RelativeTo aToFrame, nsPoint& aPoint);
979 * Transforms a rect from aFromFrame to aToFrame. In app units.
980 * Returns the bounds of the actual rect if the transform requires rotation
981 * or anything complex like that.
983 static TransformResult TransformRect(const nsIFrame* aFromFrame,
984 const nsIFrame* aToFrame, nsRect& aRect);
987 * Converts app units to pixels (with optional snapping) and appends as a
988 * translation to aTransform.
990 static void PostTranslate(Matrix4x4& aTransform, const nsPoint& aOrigin,
991 float aAppUnitsPerPixel, bool aRounded);
994 * Whether the frame should snap to grid. This will end up being passed
995 * as the aRounded parameter in PostTranslate above. SVG frames should
996 * not have their translation rounded.
998 static bool ShouldSnapToGrid(const nsIFrame* aFrame);
1001 * Get the border-box of aElement's primary frame, transformed it to be
1002 * relative to aFrame.
1004 static nsRect GetRectRelativeToFrame(mozilla::dom::Element* aElement,
1005 nsIFrame* aFrame);
1008 * Returns true if aRect with border inflation of size aInflateSize contains
1009 * aPoint.
1011 static bool ContainsPoint(const nsRect& aRect, const nsPoint& aPoint,
1012 nscoord aInflateSize);
1015 * Clamp aRect relative to aFrame to the scroll frames boundary searching from
1016 * aFrame.
1018 static nsRect ClampRectToScrollFrames(nsIFrame* aFrame, const nsRect& aRect);
1021 * Given a point in the global coordinate space, returns that point expressed
1022 * in the coordinate system of aFrame. This effectively inverts all
1023 * transforms between this point and the root frame.
1025 * @param aFromType Specifies whether |aPoint| is in layout or visual
1026 * coordinates.
1027 * @param aFrame The frame that acts as the coordinate space container.
1028 * @param aPoint The point, in global layout or visual coordinates (as per
1029 * |aFromType|, to get in the frame-local space.
1030 * @return aPoint, expressed in aFrame's canonical coordinate space.
1032 static nsPoint TransformRootPointToFrame(ViewportType aFromType,
1033 RelativeTo aFrame,
1034 const nsPoint& aPoint) {
1035 return TransformAncestorPointToFrame(aFrame, aPoint,
1036 RelativeTo{nullptr, aFromType});
1040 * Transform aPoint relative to aAncestor down to the coordinate system of
1041 * aFrame.
1043 static nsPoint TransformAncestorPointToFrame(RelativeTo aFrame,
1044 const nsPoint& aPoint,
1045 RelativeTo aAncestor);
1048 * Helper function that, given a rectangle and a matrix, returns the smallest
1049 * rectangle containing the image of the source rectangle.
1051 * @param aBounds The rectangle to transform.
1052 * @param aMatrix The matrix to transform it with.
1053 * @param aFactor The number of app units per graphics unit.
1054 * @return The smallest rect that contains the image of aBounds.
1056 static nsRect MatrixTransformRect(const nsRect& aBounds,
1057 const Matrix4x4& aMatrix, float aFactor);
1058 static nsRect MatrixTransformRect(const nsRect& aBounds,
1059 const Matrix4x4Flagged& aMatrix,
1060 float aFactor);
1063 * Helper function that, given a point and a matrix, returns the image
1064 * of that point under the matrix transform.
1066 * @param aPoint The point to transform.
1067 * @param aMatrix The matrix to transform it with.
1068 * @param aFactor The number of app units per graphics unit.
1069 * @return The image of the point under the transform.
1071 static nsPoint MatrixTransformPoint(const nsPoint& aPoint,
1072 const Matrix4x4& aMatrix, float aFactor);
1075 * Given a graphics rectangle in graphics space, return a rectangle in
1076 * app space that contains the graphics rectangle, rounding out as necessary.
1078 * @param aRect The graphics rect to round outward.
1079 * @param aFactor The number of app units per graphics unit.
1080 * @return The smallest rectangle in app space that contains aRect.
1082 template <typename T>
1083 static nsRect RoundGfxRectToAppRect(const T& aRect, const float aFactor);
1086 * Returns a subrectangle of aContainedRect that is entirely inside the
1087 * rounded rect. Complex cases are handled conservatively by returning a
1088 * smaller rect than necessary.
1090 static nsRegion RoundedRectIntersectRect(const nsRect& aRoundedRect,
1091 const nscoord aRadii[8],
1092 const nsRect& aContainedRect);
1093 static nsIntRegion RoundedRectIntersectIntRect(
1094 const nsIntRect& aRoundedRect, const RectCornerRadii& aCornerRadii,
1095 const nsIntRect& aContainedRect);
1098 * Return whether any part of aTestRect is inside of the rounded
1099 * rectangle formed by aBounds and aRadii (which are indexed by the
1100 * enum HalfCorner constants in gfx/2d/Types.h). This is precise.
1102 static bool RoundedRectIntersectsRect(const nsRect& aRoundedRect,
1103 const nscoord aRadii[8],
1104 const nsRect& aTestRect);
1106 enum class PaintFrameFlags : uint32_t {
1107 InTransform = 0x01,
1108 SyncDecodeImages = 0x02,
1109 WidgetLayers = 0x04,
1110 IgnoreSuppression = 0x08,
1111 DocumentRelative = 0x10,
1112 HideCaret = 0x20,
1113 ToWindow = 0x40,
1114 ExistingTransaction = 0x80,
1115 ForWebRender = 0x100,
1116 UseHighQualityScaling = 0x200,
1117 ResetViewportScrolling = 0x400,
1121 * Given aFrame, the root frame of a stacking context, paint it and its
1122 * descendants to aRenderingContext.
1123 * @param aRenderingContext a rendering context translated so that (0,0)
1124 * is the origin of aFrame; for best results, (0,0) should transform
1125 * to pixel-aligned coordinates. This can be null, in which case
1126 * aFrame must be a "display root" (root frame for a root document,
1127 * or the root of a popup) with an associated widget and we draw using
1128 * the layer manager for the frame's widget.
1129 * @param aDirtyRegion the region that must be painted, in the coordinates
1130 * of aFrame.
1131 * @param aBackstop paint the dirty area with this color before drawing
1132 * the actual content; pass NS_RGBA(0,0,0,0) to draw no background.
1133 * @param aBuilderMode Passed through to the display-list builder.
1134 * @param aFlags if PAINT_IN_TRANSFORM is set, then we assume
1135 * this is inside a transform or SVG foreignObject. If
1136 * PAINT_SYNC_DECODE_IMAGES is set, we force synchronous decode on all
1137 * images. If PAINT_WIDGET_LAYERS is set, aFrame must be a display root,
1138 * and we will use the frame's widget's layer manager to paint
1139 * even if aRenderingContext is non-null. This is useful if you want
1140 * to force rendering to use the widget's layer manager for testing
1141 * or speed. PAINT_WIDGET_LAYERS must be set if aRenderingContext is null.
1142 * If PAINT_DOCUMENT_RELATIVE is used, the visible region is interpreted
1143 * as being relative to the document (normally it's relative to the CSS
1144 * viewport) and the document is painted as if no scrolling has occured.
1145 * Only considered if PresShell::IgnoringViewportScrolling is true.
1146 * If ResetViewportScrolling is used, then the root scroll frame's scroll
1147 * position is set to 0 during painting, so that position:fixed elements
1148 * are drawn in their initial position.
1149 * PAINT_TO_WINDOW sets painting to window to true on the display list
1150 * builder even if we can't tell that we are painting to the window.
1151 * If PAINT_EXISTING_TRANSACTION is set, then BeginTransaction() has already
1152 * been called on aFrame's widget's layer manager and should not be
1153 * called again.
1154 * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to
1155 * compressed mode to avoid short cut optimizations.
1157 * So there are three possible behaviours:
1158 * 1) PAINT_WIDGET_LAYERS is set and aRenderingContext is null; we paint
1159 * by calling BeginTransaction on the widget's layer manager.
1160 * 2) PAINT_WIDGET_LAYERS is set and aRenderingContext is non-null; we
1161 * paint by calling BeginTransactionWithTarget on the widget's layer
1162 * manager.
1163 * 3) PAINT_WIDGET_LAYERS is not set and aRenderingContext is non-null;
1164 * we paint by construct a BasicLayerManager and calling
1165 * BeginTransactionWithTarget on it. This is desirable if we're doing
1166 * something like drawWindow in a mode where what gets rendered doesn't
1167 * necessarily correspond to what's visible in the window; we don't
1168 * want to mess up the widget's layer tree.
1170 static void PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
1171 const nsRegion& aDirtyRegion, nscolor aBackstop,
1172 nsDisplayListBuilderMode aBuilderMode,
1173 PaintFrameFlags aFlags = PaintFrameFlags(0));
1176 * Uses a binary search for find where the cursor falls in the line of text
1177 * It also keeps track of the part of the string that has already been
1178 * measured so it doesn't have to keep measuring the same text over and over.
1180 * @param "aBaseWidth" contains the width in twips of the portion
1181 * of the text that has already been measured, and aBaseInx contains
1182 * the index of the text that has already been measured.
1184 * @param aTextWidth returns (in twips) the length of the text that falls
1185 * before the cursor aIndex contains the index of the text where the cursor
1186 * falls.
1188 static bool BinarySearchForPosition(DrawTarget* aDrawTarget,
1189 nsFontMetrics& aFontMetrics,
1190 const char16_t* aText, int32_t aBaseWidth,
1191 int32_t aBaseInx, int32_t aStartInx,
1192 int32_t aEndInx, int32_t aCursorPos,
1193 int32_t& aIndex, int32_t& aTextWidth);
1195 class BoxCallback {
1196 public:
1197 BoxCallback() = default;
1198 virtual void AddBox(nsIFrame* aFrame) = 0;
1199 bool mIncludeCaptionBoxForTable = true;
1200 // Whether we are in a continuation or ib-split-sibling of the target we're
1201 // measuring. This is useful because if we know we're in the target subtree
1202 // and measuring against it we can avoid finding the common ancestor.
1203 bool mInTargetContinuation = false;
1206 * Collect all CSS boxes associated with aFrame and its
1207 * continuations, "drilling down" through table wrapper frames and
1208 * some anonymous blocks since they're not real CSS boxes.
1209 * If aFrame is null, no boxes are returned.
1210 * SVG frames return a single box, themselves.
1212 static void GetAllInFlowBoxes(nsIFrame* aFrame, BoxCallback* aCallback);
1215 * Like GetAllInFlowBoxes, but doesn't include continuations.
1217 static void AddBoxesForFrame(nsIFrame* aFrame, BoxCallback* aCallback);
1220 * Find the first frame descendant of aFrame (including aFrame) which is
1221 * not an anonymous frame that getBoxQuads/getClientRects should ignore.
1223 static nsIFrame* GetFirstNonAnonymousFrame(nsIFrame* aFrame);
1225 struct RectAccumulator : public mozilla::RectCallback {
1226 nsRect mResultRect;
1227 nsRect mFirstRect;
1228 bool mSeenFirstRect;
1230 RectAccumulator();
1232 virtual void AddRect(const nsRect& aRect) override;
1235 struct RectListBuilder : public mozilla::RectCallback {
1236 DOMRectList* mRectList;
1238 explicit RectListBuilder(DOMRectList* aList);
1239 virtual void AddRect(const nsRect& aRect) override;
1242 static nsIFrame* GetContainingBlockForClientRect(nsIFrame* aFrame);
1244 enum {
1245 RECTS_ACCOUNT_FOR_TRANSFORMS = 0x01,
1246 // Two bits for specifying which box type to use.
1247 // With neither bit set (default), use the border box.
1248 RECTS_USE_CONTENT_BOX = 0x02,
1249 RECTS_USE_PADDING_BOX = 0x04,
1250 RECTS_USE_MARGIN_BOX = 0x06, // both bits set
1251 RECTS_WHICH_BOX_MASK = 0x06 // bitmask for these two bits
1254 * Collect all CSS boxes (content, padding, border, or margin) associated
1255 * with aFrame and its continuations, "drilling down" through table wrapper
1256 * frames and some anonymous blocks since they're not real CSS boxes.
1257 * The boxes are positioned relative to aRelativeTo (taking scrolling
1258 * into account) and passed to the callback in frame-tree order.
1259 * If aFrame is null, no boxes are returned.
1260 * For SVG frames, returns one rectangle, the bounding box.
1261 * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting
1262 * the boxes into aRelativeTo coordinates, transforms (including CSS
1263 * and SVG transforms) are taken into account.
1264 * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX,
1265 * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used.
1266 * Otherwise (by default), the border box is used.
1268 static void GetAllInFlowRects(nsIFrame* aFrame, const nsIFrame* aRelativeTo,
1269 mozilla::RectCallback* aCallback,
1270 uint32_t aFlags = 0);
1272 static void GetAllInFlowRectsAndTexts(
1273 nsIFrame* aFrame, const nsIFrame* aRelativeTo,
1274 mozilla::RectCallback* aCallback,
1275 mozilla::dom::Sequence<nsString>* aTextList, uint32_t aFlags = 0);
1278 * Computes the union of all rects returned by GetAllInFlowRects. If
1279 * the union is empty, returns the first rect.
1280 * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting
1281 * the boxes into aRelativeTo coordinates, transforms (including CSS
1282 * and SVG transforms) are taken into account.
1283 * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX,
1284 * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used.
1285 * Otherwise (by default), the border box is used.
1287 static nsRect GetAllInFlowRectsUnion(nsIFrame* aFrame,
1288 const nsIFrame* aRelativeTo,
1289 uint32_t aFlags = 0);
1291 enum { EXCLUDE_BLUR_SHADOWS = 0x01 };
1293 * Takes a text-shadow array from the style properties of a given nsIFrame and
1294 * computes the union of those shadows along with the given initial rect.
1295 * If there are no shadows, the initial rect is returned.
1297 static nsRect GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect,
1298 nsIFrame* aFrame, uint32_t aFlags = 0);
1301 * Computes the destination rect that a given replaced element should render
1302 * into, based on its CSS 'object-fit' and 'object-position' properties.
1304 * @param aConstraintRect The constraint rect that we have at our disposal,
1305 * which would e.g. be exactly filled by the image
1306 * if we had "object-fit: fill".
1307 * @param aIntrinsicSize The replaced content's intrinsic size, as reported
1308 * by nsIFrame::GetIntrinsicSize().
1309 * @param aIntrinsicRatio The replaced content's intrinsic ratio, as reported
1310 * by nsIFrame::GetIntrinsicRatio().
1311 * @param aStylePos The nsStylePosition struct that contains the 'object-fit'
1312 * and 'object-position' values that we should rely on.
1313 * (This should usually be the nsStylePosition for the
1314 * replaced element in question, but not always. For
1315 * example, a <video>'s poster-image has a dedicated
1316 * anonymous element & child-frame, but we should still use
1317 * the <video>'s 'object-fit' and 'object-position' values.)
1318 * @param aAnchorPoint [out] A point that should be pixel-aligned by functions
1319 * like nsLayoutUtils::DrawImage. See documentation
1320 * in nsCSSRendering.h for ComputeObjectAnchorPoint.
1321 * @return The nsRect into which we should render the replaced content (using
1322 * the same coordinate space as the passed-in aConstraintRect).
1324 static nsRect ComputeObjectDestRect(const nsRect& aConstraintRect,
1325 const IntrinsicSize& aIntrinsicSize,
1326 const AspectRatio& aIntrinsicRatio,
1327 const nsStylePosition* aStylePos,
1328 nsPoint* aAnchorPoint = nullptr);
1331 * Get the font metrics corresponding to the frame's style data.
1332 * @param aFrame the frame
1333 * @param aSizeInflation number to multiply font size by
1335 static already_AddRefed<nsFontMetrics> GetFontMetricsForFrame(
1336 const nsIFrame* aFrame, float aSizeInflation);
1338 static already_AddRefed<nsFontMetrics> GetInflatedFontMetricsForFrame(
1339 const nsIFrame* aFrame) {
1340 return GetFontMetricsForFrame(aFrame, FontSizeInflationFor(aFrame));
1344 * Get the font metrics corresponding to the given style data.
1345 * @param aComputedStyle the style data
1346 * @param aSizeInflation number to multiply font size by
1348 static already_AddRefed<nsFontMetrics> GetFontMetricsForComputedStyle(
1349 const ComputedStyle* aComputedStyle, nsPresContext* aPresContext,
1350 float aSizeInflation = 1.0f,
1351 uint8_t aVariantWidth = NS_FONT_VARIANT_WIDTH_NORMAL);
1354 * Get the font metrics of emphasis marks corresponding to the given
1355 * style data. The result is same as GetFontMetricsForComputedStyle
1356 * except that the font size is scaled down to 50%.
1357 * @param aComputedStyle the style data
1358 * @param aInflation number to multiple font size by
1360 static already_AddRefed<nsFontMetrics> GetFontMetricsOfEmphasisMarks(
1361 ComputedStyle* aComputedStyle, nsPresContext* aPresContext,
1362 float aInflation) {
1363 return GetFontMetricsForComputedStyle(aComputedStyle, aPresContext,
1364 aInflation * 0.5f);
1368 * Find the immediate child of aParent whose frame subtree contains
1369 * aDescendantFrame. Returns null if aDescendantFrame is not a descendant
1370 * of aParent.
1372 static nsIFrame* FindChildContainingDescendant(nsIFrame* aParent,
1373 nsIFrame* aDescendantFrame);
1376 * Find the nearest ancestor that's a block
1378 static nsBlockFrame* FindNearestBlockAncestor(nsIFrame* aFrame);
1381 * Find the nearest ancestor that's not for generated content. Will return
1382 * aFrame if aFrame is not for generated content.
1384 static nsIFrame* GetNonGeneratedAncestor(nsIFrame* aFrame);
1387 * Whether the frame is an nsBlockFrame which is not a wrapper block.
1389 static bool IsNonWrapperBlock(nsIFrame* aFrame);
1392 * If aFrame is an out of flow frame, return its placeholder, otherwise
1393 * return its parent.
1395 static nsIFrame* GetParentOrPlaceholderFor(const nsIFrame* aFrame);
1398 * If aFrame is an out of flow frame, return its placeholder, otherwise
1399 * return its (possibly cross-doc) parent.
1401 static nsIFrame* GetParentOrPlaceholderForCrossDoc(const nsIFrame* aFrame);
1404 * Returns the frame that would act as the parent of aFrame when
1405 * descending through the frame tree in display list building.
1406 * Usually the same as GetParentOrPlaceholderForCrossDoc, except
1407 * that pushed floats are treated as children of their containing
1408 * block.
1410 static nsIFrame* GetDisplayListParent(nsIFrame* aFrame);
1413 * Get a frame's previous continuation, or, if it doesn't have one, its
1414 * previous block-in-inline-split sibling.
1416 static nsIFrame* GetPrevContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1419 * Get a frame's next continuation, or, if it doesn't have one, its
1420 * block-in-inline-split sibling.
1422 static nsIFrame* GetNextContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1425 * Get the first frame in the continuation-plus-ib-split-sibling chain
1426 * containing aFrame.
1428 static nsIFrame* FirstContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1431 * Get the last frame in the continuation-plus-ib-split-sibling chain
1432 * containing aFrame.
1434 static nsIFrame* LastContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1437 * Is FirstContinuationOrIBSplitSibling(aFrame) going to return
1438 * aFrame?
1440 static bool IsFirstContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1443 * Check whether aFrame is a part of the scrollbar or scrollcorner of
1444 * the root content.
1445 * @param aFrame the checking frame.
1446 * @return true if the frame is a part of the scrollbar or scrollcorner of
1447 * the root content.
1449 static bool IsViewportScrollbarFrame(nsIFrame* aFrame);
1452 * Get the contribution of aFrame to its containing block's intrinsic
1453 * size for the given physical axis. This considers the child's intrinsic
1454 * width, its 'width', 'min-width', and 'max-width' properties (or 'height'
1455 * variations if that's what matches aAxis) and its padding, border and margin
1456 * in the corresponding dimension.
1457 * @param aPercentageBasis an optional percentage basis (in aFrame's WM).
1458 * If the basis is indefinite in a given axis, pass a size with
1459 * NS_UNCONSTRAINEDSIZE in that component.
1460 * If you pass Nothing() a percentage basis will be calculated from aFrame's
1461 * ancestors' computed size in the relevant axis, if needed.
1462 * @param aMarginBoxMinSizeClamp make the result fit within this margin-box
1463 * size by reducing the *content size* (flooring at zero). This is used for:
1464 * https://drafts.csswg.org/css-grid/#min-size-auto
1466 enum {
1467 IGNORE_PADDING = 0x01,
1468 BAIL_IF_REFLOW_NEEDED = 0x02, // returns NS_INTRINSIC_ISIZE_UNKNOWN if so
1469 MIN_INTRINSIC_ISIZE = 0x04, // use min-width/height instead of width/height
1471 static nscoord IntrinsicForAxis(
1472 mozilla::PhysicalAxis aAxis, gfxContext* aRenderingContext,
1473 nsIFrame* aFrame, mozilla::IntrinsicISizeType aType,
1474 const mozilla::Maybe<LogicalSize>& aPercentageBasis = mozilla::Nothing(),
1475 uint32_t aFlags = 0, nscoord aMarginBoxMinSizeClamp = NS_MAXSIZE);
1477 * Calls IntrinsicForAxis with aFrame's parent's inline physical axis.
1479 static nscoord IntrinsicForContainer(gfxContext* aRenderingContext,
1480 nsIFrame* aFrame,
1481 mozilla::IntrinsicISizeType aType,
1482 uint32_t aFlags = 0);
1485 * Get the definite size contribution of aFrame for the given physical axis.
1486 * This considers the child's 'min-width' property (or 'min-height' if the
1487 * given axis is vertical), and its padding, border, and margin in the
1488 * corresponding dimension. If the 'min-' property is 'auto' (and 'overflow'
1489 * is 'visible') and the corresponding 'width'/'height' is definite it returns
1490 * the "specified size" for:
1491 * https://drafts.csswg.org/css-grid/#min-size-auto
1492 * Note that the "transferred size" is not handled here; use IntrinsicForAxis.
1493 * Note that any percentage in 'width'/'height' makes it count as indefinite.
1494 * If the 'min-' property is 'auto' and 'overflow' is not 'visible', then it
1495 * calculates the result as if the 'min-' computed value is zero.
1496 * Otherwise, return NS_UNCONSTRAINEDSIZE.
1498 * @param aPercentageBasis the percentage basis (in aFrame's WM).
1499 * Pass NS_UNCONSTRAINEDSIZE if the basis is indefinite in either/both axes.
1500 * @note this behavior is specific to Grid/Flexbox (currently) so aFrame
1501 * should be a grid/flex item.
1503 static nscoord MinSizeContributionForAxis(mozilla::PhysicalAxis aAxis,
1504 gfxContext* aRC, nsIFrame* aFrame,
1505 mozilla::IntrinsicISizeType aType,
1506 const LogicalSize& aPercentageBasis,
1507 uint32_t aFlags = 0);
1510 * Convert LengthPercentage to nscoord when percentages depend on the
1511 * containing block size.
1512 * @param aPercentBasis The width or height of the containing block
1513 * (whichever the client wants to use for resolving percentages).
1515 static nscoord ComputeCBDependentValue(nscoord aPercentBasis,
1516 const LengthPercentage& aCoord) {
1517 NS_ASSERTION(
1518 aPercentBasis != NS_UNCONSTRAINEDSIZE,
1519 "have unconstrained width or height; this should only result from very "
1520 "large sizes, not attempts at intrinsic size calculation");
1521 return aCoord.Resolve(aPercentBasis);
1523 static nscoord ComputeCBDependentValue(nscoord aPercentBasis,
1524 const LengthPercentageOrAuto& aCoord) {
1525 if (aCoord.IsAuto()) {
1526 return 0;
1528 return ComputeCBDependentValue(aPercentBasis, aCoord.AsLengthPercentage());
1531 static nscoord ComputeBSizeDependentValue(nscoord aContainingBlockBSize,
1532 const LengthPercentageOrAuto&);
1534 static nscoord ComputeBSizeValue(nscoord aContainingBlockBSize,
1535 nscoord aContentEdgeToBoxSizingBoxEdge,
1536 const LengthPercentage& aCoord) {
1537 MOZ_ASSERT(aContainingBlockBSize != nscoord_MAX || !aCoord.HasPercent(),
1538 "caller must deal with %% of unconstrained block-size");
1540 nscoord result = aCoord.Resolve(aContainingBlockBSize);
1541 // Clamp calc(), and the subtraction for box-sizing.
1542 return std::max(0, result - aContentEdgeToBoxSizingBoxEdge);
1546 * The "extremum length" values (see ExtremumLength) were originally aimed at
1547 * inline-size (or width, as it was before logicalization). For now, we return
1548 * true for those here, so that we don't call ComputeBSizeValue with value
1549 * types that it doesn't understand. (See bug 1113216.)
1551 * FIXME (bug 567039, bug 527285)
1552 * This isn't correct for the 'fill' value or for the 'min-*' or 'max-*'
1553 * properties, which need to be handled differently by the callers of
1554 * IsAutoBSize().
1556 template <typename SizeOrMaxSize>
1557 static bool IsAutoBSize(const SizeOrMaxSize& aCoord, nscoord aCBBSize) {
1558 return aCoord.BehavesLikeInitialValueOnBlockAxis() ||
1559 (aCBBSize == nscoord_MAX && aCoord.HasPercent());
1562 static bool IsPaddingZero(const LengthPercentage& aLength) {
1563 // clamp negative calc() to 0
1564 return aLength.Resolve(nscoord_MAX) <= 0 && aLength.Resolve(0) <= 0;
1567 static bool IsMarginZero(const LengthPercentage& aLength) {
1568 return aLength.Resolve(nscoord_MAX) == 0 && aLength.Resolve(0) == 0;
1571 static void MarkDescendantsDirty(nsIFrame* aSubtreeRoot);
1573 static void MarkIntrinsicISizesDirtyIfDependentOnBSize(nsIFrame* aFrame);
1576 * Calculate the used values for 'width' and 'height' when width
1577 * and height are 'auto'. The tentWidth and tentHeight arguments should be
1578 * the result of applying the rules for computing intrinsic sizes and ratios.
1579 * as specified by CSS 2.1 sections 10.3.2 and 10.6.2
1581 static nsSize ComputeAutoSizeWithIntrinsicDimensions(
1582 nscoord minWidth, nscoord minHeight, nscoord maxWidth, nscoord maxHeight,
1583 nscoord tentWidth, nscoord tentHeight);
1585 // Implement nsIFrame::GetPrefISize in terms of nsIFrame::AddInlinePrefISize
1586 static nscoord PrefISizeFromInline(nsIFrame* aFrame,
1587 gfxContext* aRenderingContext);
1589 // Implement nsIFrame::GetMinISize in terms of nsIFrame::AddInlineMinISize
1590 static nscoord MinISizeFromInline(nsIFrame* aFrame,
1591 gfxContext* aRenderingContext);
1593 // Get a suitable foreground color for painting aColor for aFrame.
1594 static nscolor DarkenColorIfNeeded(nsIFrame* aFrame, nscolor aColor);
1596 // Get a suitable foreground color for painting aField for aFrame.
1597 // Type of aFrame is made a template parameter because nsIFrame is not
1598 // a complete type in the header. Type-safety is not harmed given that
1599 // DarkenColorIfNeeded requires an nsIFrame pointer.
1600 template <typename Frame, typename T, typename S>
1601 static nscolor GetColor(Frame* aFrame, T S::*aField) {
1602 nscolor color = aFrame->GetVisitedDependentColor(aField);
1603 return DarkenColorIfNeeded(aFrame, color);
1606 // Get a baseline y position in app units that is snapped to device pixels.
1607 static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
1608 nscoord aY, nscoord aAscent);
1609 // Ditto for an x position (for vertical text). Note that for vertical-rl
1610 // writing mode, the ascent value should be negated by the caller.
1611 static gfxFloat GetSnappedBaselineX(nsIFrame* aFrame, gfxContext* aContext,
1612 nscoord aX, nscoord aAscent);
1614 static nscoord AppUnitWidthOfString(char16_t aC, nsFontMetrics& aFontMetrics,
1615 DrawTarget* aDrawTarget) {
1616 return AppUnitWidthOfString(&aC, 1, aFontMetrics, aDrawTarget);
1618 static nscoord AppUnitWidthOfString(mozilla::Span<const char16_t> aString,
1619 nsFontMetrics& aFontMetrics,
1620 DrawTarget* aDrawTarget) {
1621 return nsLayoutUtils::AppUnitWidthOfString(
1622 aString.Elements(), aString.Length(), aFontMetrics, aDrawTarget);
1624 static nscoord AppUnitWidthOfString(const char16_t* aString, uint32_t aLength,
1625 nsFontMetrics& aFontMetrics,
1626 DrawTarget* aDrawTarget);
1627 static nscoord AppUnitWidthOfStringBidi(const nsString& aString,
1628 const nsIFrame* aFrame,
1629 nsFontMetrics& aFontMetrics,
1630 gfxContext& aContext) {
1631 return nsLayoutUtils::AppUnitWidthOfStringBidi(
1632 aString.get(), aString.Length(), aFrame, aFontMetrics, aContext);
1634 static nscoord AppUnitWidthOfStringBidi(const char16_t* aString,
1635 uint32_t aLength,
1636 const nsIFrame* aFrame,
1637 nsFontMetrics& aFontMetrics,
1638 gfxContext& aContext);
1640 static bool StringWidthIsGreaterThan(const nsString& aString,
1641 nsFontMetrics& aFontMetrics,
1642 DrawTarget* aDrawTarget, nscoord aWidth);
1644 static nsBoundingMetrics AppUnitBoundsOfString(const char16_t* aString,
1645 uint32_t aLength,
1646 nsFontMetrics& aFontMetrics,
1647 DrawTarget* aDrawTarget);
1649 static void DrawString(const nsIFrame* aFrame, nsFontMetrics& aFontMetrics,
1650 gfxContext* aContext, const char16_t* aString,
1651 int32_t aLength, nsPoint aPoint,
1652 ComputedStyle* aComputedStyle = nullptr,
1653 DrawStringFlags aFlags = DrawStringFlags::Default);
1655 static nsPoint GetBackgroundFirstTilePos(const nsPoint& aDest,
1656 const nsPoint& aFill,
1657 const nsSize& aRepeatSize);
1660 * Supports only LTR or RTL. Bidi (mixed direction) is not supported.
1662 static void DrawUniDirString(const char16_t* aString, uint32_t aLength,
1663 const nsPoint& aPoint,
1664 nsFontMetrics& aFontMetrics,
1665 gfxContext& aContext);
1668 * Helper function for drawing text-shadow. The callback's job
1669 * is to draw whatever needs to be blurred onto the given context.
1671 typedef void (*TextShadowCallback)(gfxContext* aCtx, nsPoint aShadowOffset,
1672 const nscolor& aShadowColor, void* aData);
1674 static void PaintTextShadow(const nsIFrame* aFrame, gfxContext* aContext,
1675 const nsRect& aTextRect, const nsRect& aDirtyRect,
1676 const nscolor& aForegroundColor,
1677 TextShadowCallback aCallback,
1678 void* aCallbackData);
1681 * Gets the baseline to vertically center text from a font within a
1682 * line of specified height.
1683 * aIsInverted: true if the text is inverted relative to the block
1684 * direction, so that the block-dir "ascent" corresponds to font
1685 * descent. (Applies to sideways text in vertical-lr mode.)
1687 * Returns the baseline position relative to the top of the line.
1689 static nscoord GetCenteredFontBaseline(nsFontMetrics* aFontMetrics,
1690 nscoord aLineHeight, bool aIsInverted);
1693 * Derive a baseline of |aFrame| (measured from its top border edge)
1694 * from its first in-flow line box (not descending into anything with
1695 * 'overflow' not 'visible', potentially including aFrame itself).
1697 * Returns true if a baseline was found (and fills in aResult).
1698 * Otherwise returns false.
1700 static bool GetFirstLineBaseline(mozilla::WritingMode aWritingMode,
1701 const nsIFrame* aFrame, nscoord* aResult);
1704 * Just like GetFirstLineBaseline, except also returns the top and
1705 * bottom of the line with the baseline.
1707 * Returns true if a line was found (and fills in aResult).
1708 * Otherwise returns false.
1710 struct LinePosition {
1711 nscoord mBStart{nscoord_MAX};
1712 nscoord mBaseline{nscoord_MAX};
1713 nscoord mBEnd{nscoord_MAX};
1715 LinePosition operator+(nscoord aOffset) const {
1716 LinePosition result;
1717 result.mBStart = mBStart + aOffset;
1718 result.mBaseline = mBaseline + aOffset;
1719 result.mBEnd = mBEnd + aOffset;
1720 return result;
1723 static bool GetFirstLinePosition(mozilla::WritingMode aWritingMode,
1724 const nsIFrame* aFrame,
1725 LinePosition* aResult);
1728 * Derive a baseline of |aFrame| (measured from its top border edge)
1729 * from its last in-flow line box (not descending into anything with
1730 * 'overflow' not 'visible', potentially including aFrame itself).
1732 * Returns true if a baseline was found (and fills in aResult).
1733 * Otherwise returns false.
1735 static bool GetLastLineBaseline(mozilla::WritingMode aWritingMode,
1736 const nsIFrame* aFrame, nscoord* aResult);
1739 * Returns a block-dir coordinate relative to this frame's origin that
1740 * represents the logical block-end of the frame or its visible content,
1741 * whichever is further from the origin.
1742 * Relative positioning is ignored and margins and glyph bounds are not
1743 * considered.
1744 * This value will be >= mRect.BSize() and <= overflowRect.BEnd() unless
1745 * relative positioning is applied.
1747 static nscoord CalculateContentBEnd(mozilla::WritingMode aWritingMode,
1748 nsIFrame* aFrame);
1751 * Gets the closest frame (the frame passed in or one of its parents) that
1752 * qualifies as a "layer"; used in DOM0 methods that depends upon that
1753 * definition. This is the nearest frame that is either positioned or scrolled
1754 * (the child of a scroll frame).
1756 static nsIFrame* GetClosestLayer(nsIFrame* aFrame);
1759 * Gets the graphics sampling filter for the frame
1761 static SamplingFilter GetSamplingFilterForFrame(nsIFrame* aFrame);
1763 static inline void InitDashPattern(StrokeOptions& aStrokeOptions,
1764 mozilla::StyleBorderStyle aBorderStyle) {
1765 if (aBorderStyle == mozilla::StyleBorderStyle::Dotted) {
1766 static Float dot[] = {1.f, 1.f};
1767 aStrokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dot);
1768 aStrokeOptions.mDashPattern = dot;
1769 } else if (aBorderStyle == mozilla::StyleBorderStyle::Dashed) {
1770 static Float dash[] = {5.f, 5.f};
1771 aStrokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dash);
1772 aStrokeOptions.mDashPattern = dash;
1773 } else {
1774 aStrokeOptions.mDashLength = 0;
1775 aStrokeOptions.mDashPattern = nullptr;
1780 * Convert an nsRect to a gfxRect.
1782 static gfxRect RectToGfxRect(const nsRect& aRect,
1783 int32_t aAppUnitsPerDevPixel);
1785 static gfxPoint PointToGfxPoint(const nsPoint& aPoint,
1786 int32_t aAppUnitsPerPixel) {
1787 return gfxPoint(gfxFloat(aPoint.x) / aAppUnitsPerPixel,
1788 gfxFloat(aPoint.y) / aAppUnitsPerPixel);
1791 /* N.B. The only difference between variants of the Draw*Image
1792 * functions below is the type of the aImage argument.
1796 * Draw a background image. The image's dimensions are as specified in aDest;
1797 * the image itself is not consulted to determine a size.
1798 * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering
1800 * @param aContext
1801 * The context to draw to, already set up with an appropriate scale and
1802 * transform for drawing in app units.
1803 * @param aForFrame
1804 * The nsIFrame that we're drawing this image for.
1805 * @param aImage
1806 * The image.
1807 * @param aDest
1808 * The position and scaled area where one copy of the image should be drawn.
1809 * This area represents the image itself in its correct position as defined
1810 * with the background-position css property.
1811 * @param aFill
1812 * The area to be filled with copies of the image.
1813 * @param aRepeatSize
1814 * The distance between the positions of two subsequent repeats of the image.
1815 * Sizes larger than aDest.Size() create gaps between the images.
1816 * @param aAnchor
1817 * A point in aFill which we will ensure is pixel-aligned in the output.
1818 * @param aDirty
1819 * Pixels outside this area may be skipped.
1820 * @param aImageFlags
1821 * Image flags of the imgIContainer::FLAG_* variety.
1822 * @param aExtendMode
1823 * How to extend the image over the dest rect.
1825 static ImgDrawResult DrawBackgroundImage(
1826 gfxContext& aContext, nsIFrame* aForFrame, nsPresContext* aPresContext,
1827 imgIContainer* aImage, SamplingFilter aSamplingFilter,
1828 const nsRect& aDest, const nsRect& aFill, const nsSize& aRepeatSize,
1829 const nsPoint& aAnchor, const nsRect& aDirty, uint32_t aImageFlags,
1830 ExtendMode aExtendMode, float aOpacity);
1833 * Draw an image.
1834 * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering
1835 * @param aRenderingContext Where to draw the image, set up with an
1836 * appropriate scale and transform for drawing in
1837 * app units.
1838 * @param aComputedStyle The ComputedStyle of the nsIFrame (or
1839 * pseudo-element) for which this image is being
1840 * drawn.
1841 * @param aImage The image.
1842 * @param aDest Where one copy of the image should mapped to.
1843 * @param aFill The area to be filled with copies of the
1844 * image.
1845 * @param aAnchor A point in aFill which we will ensure is
1846 * pixel-aligned in the output.
1847 * @param aDirty Pixels outside this area may be skipped.
1848 * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety
1850 static ImgDrawResult DrawImage(gfxContext& aContext,
1851 ComputedStyle* aComputedStyle,
1852 nsPresContext* aPresContext,
1853 imgIContainer* aImage,
1854 const SamplingFilter aSamplingFilter,
1855 const nsRect& aDest, const nsRect& aFill,
1856 const nsPoint& aAnchor, const nsRect& aDirty,
1857 uint32_t aImageFlags, float aOpacity = 1.0);
1860 * Draw a whole image without scaling or tiling.
1862 * @param aRenderingContext Where to draw the image, set up with an
1863 * appropriate scale and transform for drawing in
1864 * app units.
1865 * @param aImage The image.
1866 * @param aDest The top-left where the image should be drawn.
1867 * @param aDirty If non-null, then pixels outside this area may
1868 * be skipped.
1869 * @param aSVGContext Optionally provides an SVGImageContext.
1870 * Callers should pass an SVGImageContext with at
1871 * least the viewport size set if aImage may be of
1872 * type imgIContainer::TYPE_VECTOR, or pass
1873 * Nothing() if it is of type
1874 * imgIContainer::TYPE_RASTER (to save cycles
1875 * constructing an SVGImageContext, since this
1876 * argument will be ignored for raster images).
1877 * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety
1878 * @param aSourceArea If non-null, this area is extracted from
1879 * the image and drawn at aDest. It's
1880 * in appunits. For best results it should
1881 * be aligned with image pixels.
1883 static ImgDrawResult DrawSingleUnscaledImage(
1884 gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage,
1885 const SamplingFilter aSamplingFilter, const nsPoint& aDest,
1886 const nsRect* aDirty, const mozilla::SVGImageContext& aSVGContext,
1887 uint32_t aImageFlags, const nsRect* aSourceArea = nullptr);
1890 * Draw a whole image without tiling.
1892 * @param aRenderingContext Where to draw the image, set up with an
1893 * appropriate scale and transform for drawing in
1894 * app units.
1895 * @param aImage The image.
1896 * @param aDest The area that the image should fill.
1897 * @param aDirty Pixels outside this area may be skipped.
1898 * @param aSVGContext Optionally provides an SVGImageContext.
1899 * Callers should pass an SVGImageContext with at
1900 * least the viewport size set if aImage may be of
1901 * type imgIContainer::TYPE_VECTOR, or pass
1902 * Nothing() if it is of type
1903 * imgIContainer::TYPE_RASTER (to save cycles
1904 * constructing an SVGImageContext, since this
1905 * argument will be ignored for raster images).
1906 * @param aImageFlags Image flags of the imgIContainer::FLAG_*
1907 * variety.
1908 * @param aAnchor If non-null, a point which we will ensure
1909 * is pixel-aligned in the output.
1911 static ImgDrawResult DrawSingleImage(
1912 gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage,
1913 SamplingFilter aSamplingFilter, const nsRect& aDest, const nsRect& aDirty,
1914 const mozilla::SVGImageContext& aSVGContext, uint32_t aImageFlags,
1915 const nsPoint* aAnchorPoint = nullptr);
1918 * Given an imgIContainer, this method attempts to obtain an intrinsic
1919 * px-valued height & width for it. If the imgIContainer has a non-pixel
1920 * value for either height or width, this method tries to generate a pixel
1921 * value for that dimension using the intrinsic ratio (if available). The
1922 * intrinsic ratio will be assigned to aIntrinsicRatio; if there's no
1923 * intrinsic ratio then (0, 0) will be assigned.
1925 * This method will always set aGotWidth and aGotHeight to indicate whether
1926 * we were able to successfully obtain (or compute) a value for each
1927 * dimension.
1929 * NOTE: This method is similar to ComputeSizeWithIntrinsicDimensions. The
1930 * difference is that this one is simpler and is suited to places where we
1931 * have less information about the frame tree.
1933 * @param aResolution The resolution specified by the author for the image, or
1934 * its intrinsic resolution.
1936 * This will affect the intrinsic size size of the image
1937 * (so e.g., if resolution is 2, and the image is 100x100,
1938 * the intrinsic size of the image will be 50x50).
1940 static void ComputeSizeForDrawing(imgIContainer* aImage,
1941 const mozilla::image::Resolution&,
1942 CSSIntSize& aImageSize,
1943 AspectRatio& aIntrinsicRatio,
1944 bool& aGotWidth, bool& aGotHeight);
1947 * Given an imgIContainer, this method attempts to obtain an intrinsic
1948 * px-valued height & width for it. If the imgIContainer has a non-pixel
1949 * value for either height or width, this method tries to generate a pixel
1950 * value for that dimension using the intrinsic ratio (if available). If,
1951 * after trying all these methods, no value is available for one or both
1952 * dimensions, the corresponding dimension of aFallbackSize is used instead.
1954 static CSSIntSize ComputeSizeForDrawingWithFallback(
1955 imgIContainer* aImage, const mozilla::image::Resolution&,
1956 const nsSize& aFallbackSize);
1959 * Given the image container, frame, and dest rect, determine the best fitting
1960 * size to decode the image at, and calculate any necessary SVG parameters.
1962 static mozilla::gfx::IntSize ComputeImageContainerDrawingParameters(
1963 imgIContainer* aImage, nsIFrame* aForFrame,
1964 const LayoutDeviceRect& aDestRect, const LayoutDeviceRect& aFillRect,
1965 const StackingContextHelper& aSc, uint32_t aFlags,
1966 mozilla::SVGImageContext& aSVGContext,
1967 mozilla::Maybe<mozilla::image::ImageIntRegion>& aRegion);
1970 * Given a source area of an image (in appunits) and a destination area
1971 * that we want to map that source area too, computes the area that
1972 * would be covered by the whole image. This is useful for passing to
1973 * the aDest parameter of DrawImage, when we want to draw a subimage
1974 * of an overall image.
1976 static nsRect GetWholeImageDestination(const nsSize& aWholeImageSize,
1977 const nsRect& aImageSourceArea,
1978 const nsRect& aDestArea);
1981 * Given an image container and an orientation, returns an image container
1982 * that contains the same image, reoriented appropriately. May return the
1983 * original image container if no changes are needed.
1985 * @param aContainer The image container to apply the orientation to.
1986 * @param aOrientation The desired orientation.
1988 static already_AddRefed<imgIContainer> OrientImage(
1989 imgIContainer* aContainer,
1990 const mozilla::StyleImageOrientation& aOrientation);
1993 * Given an image request, determine if the request uses CORS.
1995 static bool ImageRequestUsesCORS(imgIRequest* aRequest);
1998 * Determine if any corner radius is of nonzero size
1999 * @param aCorners the |BorderRadius| object to check
2000 * @return true unless all the coordinates are 0%, 0 or null.
2002 * A corner radius with one dimension zero and one nonzero is
2003 * treated as a nonzero-radius corner, even though it will end up
2004 * being rendered like a zero-radius corner. This is because such
2005 * corners are not expected to appear outside of test cases, and it's
2006 * simpler to implement the test this way.
2008 static bool HasNonZeroCorner(const mozilla::BorderRadius& aCorners);
2011 * Determine if there is any corner radius on corners adjacent to the
2012 * given side.
2014 static bool HasNonZeroCornerOnSide(const mozilla::BorderRadius& aCorners,
2015 mozilla::Side aSide);
2018 * Determine if a widget is likely to require transparency or translucency.
2019 * @param aBackgroundFrame The frame that the background is set on. For
2020 * <window>s, this will be the canvas frame.
2021 * @param aCSSRootFrame The frame that holds CSS properties affecting
2022 * the widget's transparency. For menupopups,
2023 * aBackgroundFrame and aCSSRootFrame will be the
2024 * same.
2025 * @return a value suitable for passing to SetWindowTranslucency.
2027 using TransparencyMode = mozilla::widget::TransparencyMode;
2028 static TransparencyMode GetFrameTransparency(nsIFrame* aBackgroundFrame,
2029 nsIFrame* aCSSRootFrame);
2032 * A frame is a popup if it has its own floating window. Menus, panels
2033 * and combobox dropdowns are popups.
2035 static bool IsPopup(const nsIFrame* aFrame);
2038 * Find the nearest "display root". This is the nearest enclosing
2039 * popup frame or the root prescontext's root frame.
2041 static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame);
2042 static const nsIFrame* GetDisplayRootFrame(const nsIFrame* aFrame);
2045 * Get the reference frame that would be used when constructing a
2046 * display item for this frame. Rather than using their own frame
2047 * as a reference frame.)
2049 * This duplicates some of the logic of GetDisplayRootFrame above and
2050 * of nsDisplayListBuilder::FindReferenceFrameFor.
2052 * If you have an nsDisplayListBuilder, you should get the reference
2053 * frame from it instead of calling this.
2055 static nsIFrame* GetReferenceFrame(nsIFrame* aFrame);
2058 * Get textrun construction flags determined by a given style; in particular
2059 * some combination of:
2060 * -- TEXT_DISABLE_OPTIONAL_LIGATURES if letter-spacing is in use
2061 * -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size
2062 * and prefs indicate we should be optimizing for speed over quality
2064 static mozilla::gfx::ShapedTextFlags GetTextRunFlagsForStyle(
2065 const ComputedStyle*, nsPresContext*, const nsStyleFont*,
2066 const nsStyleText*, nscoord aLetterSpacing);
2069 * Get orientation flags for textrun construction.
2071 static mozilla::gfx::ShapedTextFlags GetTextRunOrientFlagsForStyle(
2072 const ComputedStyle*);
2075 * Takes two rectangles whose origins must be the same, and computes
2076 * the difference between their union and their intersection as two
2077 * rectangles. (This difference is a superset of the difference
2078 * between the two rectangles.)
2080 static void GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2,
2081 nsRect* aHStrip, nsRect* aVStrip);
2084 * Get a device context that can be used to get up-to-date device
2085 * dimensions for the given window. For some reason, this is more
2086 * complicated than it ought to be in multi-monitor situations.
2088 static nsDeviceContext* GetDeviceContextForScreenInfo(
2089 nsPIDOMWindowOuter* aWindow);
2092 * Some frames with 'position: fixed' (nsStyleDisplay::mPosition ==
2093 * StylePositionProperty::Fixed) are not really fixed positioned, since
2094 * they're inside a transformed element or other element that establishes a
2095 * fixed-pos containing block). This function says whether such an element is
2096 * a real fixed-pos element.
2098 static bool IsReallyFixedPos(const nsIFrame* aFrame);
2101 * This function says whether `aFrame` would really be a fixed positioned
2102 * frame if the frame was created with StylePositionProperty::Fixed.
2104 * It is effectively the same as IsReallyFixedPos, but without asserting the
2105 * position value. Use it only when you know what you're doing, like when
2106 * tearing down the frame tree (where styles may have changed due to
2107 * ::first-line reparenting and rule changes at the same time).
2109 static bool MayBeReallyFixedPos(const nsIFrame* aFrame);
2112 * Returns true if |aFrame| is inside position:fixed subtree.
2114 static bool IsInPositionFixedSubtree(const nsIFrame* aFrame);
2117 * Obtain a SourceSurface from the given DOM element, if possible.
2118 * This obtains the most natural surface from the element; that
2119 * is, the one that can be obtained with the fewest conversions.
2121 * The flags below can modify the behaviour of this function. The
2122 * result is returned as a SurfaceFromElementResult struct, also
2123 * defined below.
2125 * Currently, this will do:
2126 * - HTML Canvas elements: will return the underlying canvas surface
2127 * - HTML Video elements: will return the current video frame
2128 * - Image elements: will return the image
2130 * The above results are modified by the below flags (copying,
2131 * forcing image surface, etc.).
2134 enum {
2135 /* Whether to extract the first frame (as opposed to the
2136 current frame) in the case that the element is an image. */
2137 SFE_WANT_FIRST_FRAME_IF_IMAGE = 1 << 0,
2138 /* Whether we should skip colorspace/gamma conversion */
2139 SFE_NO_COLORSPACE_CONVERSION = 1 << 1,
2140 /* Caller handles SFER::mAlphaType = NonPremult */
2141 SFE_ALLOW_NON_PREMULT = 1 << 2,
2142 /* Whether we should skip getting a surface for vector images and
2143 return a DirectDrawInfo containing an imgIContainer instead. */
2144 SFE_NO_RASTERIZING_VECTORS = 1 << 3,
2145 /* If image type is vector, the return surface size will same as
2146 element size, not image's intrinsic size. */
2147 SFE_USE_ELEMENT_SIZE_IF_VECTOR = 1 << 4,
2148 /* Ensure that the returned surface has a size that matches the
2149 * SurfaceFromElementResult::mSize. This is mostly a convenience thing so
2150 * that callers who want this don't have to deal with it themselves.
2151 * The surface might be different for, e.g., a EXIF-scaled raster image, if
2152 * we don't rescale during decode. */
2153 SFE_EXACT_SIZE_SURFACE = 1 << 6,
2154 /* Use orientation from image */
2155 SFE_ORIENTATION_FROM_IMAGE = 1 << 7,
2156 /* Caller handles SFER::mCropRect.isSome() */
2157 SFE_ALLOW_UNCROPPED_UNSCALED = 1 << 8,
2160 // This function can be called on any thread.
2161 static mozilla::SurfaceFromElementResult SurfaceFromOffscreenCanvas(
2162 mozilla::dom::OffscreenCanvas* aOffscreenCanvas, uint32_t aSurfaceFlags,
2163 RefPtr<DrawTarget>& aTarget);
2164 static mozilla::SurfaceFromElementResult SurfaceFromOffscreenCanvas(
2165 mozilla::dom::OffscreenCanvas* aOffscreenCanvas,
2166 uint32_t aSurfaceFlags = 0) {
2167 RefPtr<DrawTarget> target = nullptr;
2168 return SurfaceFromOffscreenCanvas(aOffscreenCanvas, aSurfaceFlags, target);
2170 // This function can be called on any thread.
2171 static mozilla::SurfaceFromElementResult SurfaceFromVideoFrame(
2172 mozilla::dom::VideoFrame* aVideoFrame, uint32_t aSurfaceFlags,
2173 RefPtr<DrawTarget>& aTarget);
2174 static mozilla::SurfaceFromElementResult SurfaceFromVideoFrame(
2175 mozilla::dom::VideoFrame* aVideoFrame, uint32_t aSurfaceFlags = 0) {
2176 RefPtr<DrawTarget> target = nullptr;
2177 return SurfaceFromVideoFrame(aVideoFrame, aSurfaceFlags, target);
2179 // This function can be called on any thread.
2180 static mozilla::SurfaceFromElementResult SurfaceFromImageBitmap(
2181 mozilla::dom::ImageBitmap* aImageBitmap, uint32_t aSurfaceFlags);
2183 static mozilla::SurfaceFromElementResult SurfaceFromElement(
2184 mozilla::dom::Element* aElement,
2185 const mozilla::Maybe<int32_t>& aResizeWidth,
2186 const mozilla::Maybe<int32_t>& aResizeHeight, uint32_t aSurfaceFlags,
2187 RefPtr<DrawTarget>& aTarget);
2188 static mozilla::SurfaceFromElementResult SurfaceFromElement(
2189 mozilla::dom::Element* aElement, uint32_t aSurfaceFlags = 0) {
2190 RefPtr<DrawTarget> target = nullptr;
2191 return SurfaceFromElement(aElement, mozilla::Nothing(), mozilla::Nothing(),
2192 aSurfaceFlags, target);
2194 static mozilla::SurfaceFromElementResult SurfaceFromElement(
2195 mozilla::dom::Element* aElement, uint32_t aSurfaceFlags,
2196 RefPtr<DrawTarget>& aTarget) {
2197 return SurfaceFromElement(aElement, mozilla::Nothing(), mozilla::Nothing(),
2198 aSurfaceFlags, aTarget);
2200 static mozilla::SurfaceFromElementResult SurfaceFromElement(
2201 mozilla::dom::Element* aElement,
2202 const mozilla::Maybe<int32_t>& aResizeWidth,
2203 const mozilla::Maybe<int32_t>& aResizeHeight,
2204 uint32_t aSurfaceFlags = 0) {
2205 RefPtr<DrawTarget> target = nullptr;
2206 return SurfaceFromElement(aElement, aResizeWidth, aResizeHeight,
2207 aSurfaceFlags, target);
2210 // There are a bunch of callers of SurfaceFromElement. Just mark it as
2211 MOZ_CAN_RUN_SCRIPT_BOUNDARY
2212 static mozilla::SurfaceFromElementResult SurfaceFromElement(
2213 nsIImageLoadingContent* aElement,
2214 const mozilla::Maybe<int32_t>& aResizeWidth,
2215 const mozilla::Maybe<int32_t>& aResizeHeight, uint32_t aSurfaceFlags,
2216 RefPtr<DrawTarget>& aTarget);
2217 // Need an HTMLImageElement overload, because otherwise the
2218 // nsIImageLoadingContent and mozilla::dom::Element overloads are ambiguous
2219 // for HTMLImageElement.
2220 static mozilla::SurfaceFromElementResult SurfaceFromElement(
2221 mozilla::dom::HTMLImageElement* aElement, uint32_t aSurfaceFlags,
2222 RefPtr<DrawTarget>& aTarget);
2223 static mozilla::SurfaceFromElementResult SurfaceFromElement(
2224 mozilla::dom::HTMLCanvasElement* aElement, uint32_t aSurfaceFlags,
2225 RefPtr<DrawTarget>& aTarget);
2226 static mozilla::SurfaceFromElementResult SurfaceFromElement(
2227 mozilla::dom::HTMLCanvasElement* aElement, uint32_t aSurfaceFlags) {
2228 RefPtr<DrawTarget> target = nullptr;
2229 return SurfaceFromElement(aElement, aSurfaceFlags, target);
2231 static mozilla::SurfaceFromElementResult SurfaceFromElement(
2232 mozilla::dom::HTMLVideoElement* aElement, uint32_t aSurfaceFlags,
2233 RefPtr<DrawTarget>& aTarget);
2236 * When the document is editable by contenteditable attribute of its root
2237 * content or body content.
2239 * Be aware, this returns nullptr if it's in designMode.
2241 * For example:
2243 * <html contenteditable="true"><body></body></html>
2244 * returns the <html>.
2246 * <html><body contenteditable="true"></body></html>
2247 * <body contenteditable="true"></body>
2248 * With these cases, this returns the <body>.
2249 * NOTE: The latter case isn't created normally, however, it can be
2250 * created by script with XHTML.
2252 * <body><p contenteditable="true"></p></body>
2253 * returns nullptr because <body> isn't editable.
2255 static mozilla::dom::Element* GetEditableRootContentByContentEditable(
2256 mozilla::dom::Document* aDocument);
2258 static void AddExtraBackgroundItems(nsDisplayListBuilder* aBuilder,
2259 nsDisplayList* aList, nsIFrame* aFrame,
2260 const nsRect& aCanvasArea,
2261 const nsRegion& aVisibleRegion,
2262 nscolor aBackstop);
2265 * Returns true if the passed in prescontext needs the dark grey background
2266 * that goes behind the page of a print preview presentation.
2268 static bool NeedsPrintPreviewBackground(nsPresContext* aPresContext);
2271 * Types used by the helpers for InspectorUtils.getUsedFontFaces.
2272 * The API returns an array (UsedFontFaceList) that owns the
2273 * InspectorFontFace instances, but during range traversal we also
2274 * want to maintain a mapping from gfxFontEntry to InspectorFontFace
2275 * records, so use a temporary hashtable for that.
2277 typedef nsTArray<mozilla::UniquePtr<mozilla::dom::InspectorFontFace>>
2278 UsedFontFaceList;
2279 typedef nsTHashMap<nsPtrHashKey<gfxFontEntry>,
2280 mozilla::dom::InspectorFontFace*>
2281 UsedFontFaceTable;
2284 * Adds all font faces used in the frame tree starting from aFrame
2285 * to the list aFontFaceList.
2286 * aMaxRanges: maximum number of text ranges to record for each face.
2288 static nsresult GetFontFacesForFrames(nsIFrame* aFrame,
2289 UsedFontFaceList& aResult,
2290 UsedFontFaceTable& aFontFaces,
2291 uint32_t aMaxRanges,
2292 bool aSkipCollapsedWhitespace);
2295 * Adds all font faces used within the specified range of text in aFrame,
2296 * and optionally its continuations, to the list in aFontFaceList.
2297 * Pass 0 and INT32_MAX for aStartOffset and aEndOffset to specify the
2298 * entire text is to be considered.
2299 * aMaxRanges: maximum number of text ranges to record for each face.
2301 static void GetFontFacesForText(nsIFrame* aFrame, int32_t aStartOffset,
2302 int32_t aEndOffset, bool aFollowContinuations,
2303 UsedFontFaceList& aResult,
2304 UsedFontFaceTable& aFontFaces,
2305 uint32_t aMaxRanges,
2306 bool aSkipCollapsedWhitespace);
2309 * Walks the frame tree starting at aFrame looking for textRuns.
2310 * If |clear| is true, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag
2311 * on each textRun found (and |aMallocSizeOf| is not used).
2312 * If |clear| is false, adds the storage used for each textRun to the
2313 * total, and sets the TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double-
2314 * accounting. (Runs with this flag already set will be skipped.)
2315 * Expected usage pattern is therefore to call twice:
2316 * (void)SizeOfTextRunsForFrames(rootFrame, nullptr, true);
2317 * total = SizeOfTextRunsForFrames(rootFrame, mallocSizeOf, false);
2319 static size_t SizeOfTextRunsForFrames(nsIFrame* aFrame,
2320 mozilla::MallocSizeOf aMallocSizeOf,
2321 bool clear);
2324 * Returns true if |aFrame| has an animation of a property in |aPropertySet|
2325 * regardless of whether any property in the set is overridden by an
2326 * !important rule.
2328 static bool HasAnimationOfPropertySet(const nsIFrame* aFrame,
2329 const nsCSSPropertyIDSet& aPropertySet);
2332 * A variant of the above HasAnimationOfPropertySet that takes an optional
2333 * EffectSet parameter as an optimization to save redundant lookups of the
2334 * EffectSet.
2336 static bool HasAnimationOfPropertySet(const nsIFrame* aFrame,
2337 const nsCSSPropertyIDSet& aPropertySet,
2338 mozilla::EffectSet* aEffectSet);
2341 * A variant of the above HasAnimationOfPropertySet. This is especially for
2342 * tranform-like properties with motion-path.
2343 * For transform-like properties with motion-path, we need to check if
2344 * offset-path has effect. If we don't have any animation on offset-path and
2345 * offset-path is none, there is no effective motion-path, and so we don't
2346 * care other offset-* properties. In this case, this function only checks the
2347 * rest of transform-like properties (i.e. transform/translate/rotate/scale).
2349 static bool HasAnimationOfTransformAndMotionPath(const nsIFrame* aFrame);
2352 * Returns true if |aFrame| has an animation of |aProperty| which is
2353 * not overridden by !important rules.
2355 static bool HasEffectiveAnimation(const nsIFrame* aFrame,
2356 nsCSSPropertyID aProperty);
2359 * Returns true if |aFrame| has an animation where at least one of the
2360 * properties in |aPropertySet| is not overridden by !important rules.
2362 * If |aPropertySet| includes transform-like properties (transform, rotate,
2363 * etc.) however, this will return false if any of the transform-like
2364 * properties is overriden by an !important rule since these properties should
2365 * be combined on the compositor.
2367 static bool HasEffectiveAnimation(const nsIFrame* aFrame,
2368 const nsCSSPropertyIDSet& aPropertySet);
2371 * Returns all effective animated CSS properties on |aStyleFrame| and its
2372 * corresponding primary frame (for content that makes this distinction,
2373 * notable display:table content) that can be animated on the compositor.
2375 * Properties that can be animated on the compositor but which are overridden
2376 * by !important rules are not returned.
2378 * Unlike HasEffectiveAnimation, however, this does not check the set of
2379 * transform-like properties to ensure that if any such properties are
2380 * overridden by !important rules, the other transform-like properties are
2381 * not run on the compositor (see bug 1534884).
2383 static nsCSSPropertyIDSet GetAnimationPropertiesForCompositor(
2384 const nsIFrame* aStyleFrame);
2387 * Checks if off-main-thread animations are enabled.
2389 static bool AreAsyncAnimationsEnabled();
2392 * Checks if retained display lists are enabled.
2394 static bool AreRetainedDisplayListsEnabled();
2396 static bool DisplayRootHasRetainedDisplayListBuilder(nsIFrame* aFrame);
2398 static RetainedDisplayListBuilder* GetRetainedDisplayListBuilder(
2399 nsIFrame* aFrame);
2402 * Find a suitable scale for a element (aFrame's content) over the course of
2403 * any animations and transitions of the CSS transform property on the element
2404 * that run on the compositor thread. It will check the maximum and minimum
2405 * scale during the animations and transitions and return a suitable value for
2406 * performance and quality. Will return scale(1,1) if there are no such
2407 * animations. Always returns a positive value.
2408 * @param aVisibleSize is the size of the area we want to paint
2409 * @param aDisplaySize is the size of the display area of the pres context
2411 static MatrixScales ComputeSuitableScaleForAnimation(
2412 const nsIFrame* aFrame, const nsSize& aVisibleSize,
2413 const nsSize& aDisplaySize);
2416 * Checks whether we want to use the GPU to scale images when
2417 * possible.
2419 static bool GPUImageScalingEnabled();
2422 * Unions the overflow areas of the children of aFrame with aOverflowAreas.
2423 * aSkipChildLists specifies any child lists that should be skipped.
2424 * FrameChildListID::Popup is always skipped.
2426 static void UnionChildOverflow(
2427 nsIFrame* aFrame, mozilla::OverflowAreas& aOverflowAreas,
2428 mozilla::FrameChildListIDs aSkipChildLists = {});
2431 * Return the font size inflation *ratio* for a given frame. This is
2432 * the factor by which font sizes should be inflated; it is never
2433 * smaller than 1.
2435 static float FontSizeInflationFor(const nsIFrame* aFrame);
2438 * Perform the first half of the computation of FontSizeInflationFor
2439 * (see above).
2440 * This includes determining whether inflation should be performed
2441 * within this container and returning 0 if it should not be.
2443 * The result is guaranteed not to vary between line participants
2444 * (inlines, text frames) within a line.
2446 * The result should not be used directly since font sizes slightly
2447 * above the minimum should always be adjusted as done by
2448 * FontSizeInflationInner.
2450 static nscoord InflationMinFontSizeFor(const nsIFrame* aFrame);
2453 * Perform the second half of the computation done by
2454 * FontSizeInflationFor (see above).
2456 * aMinFontSize must be the result of one of the
2457 * InflationMinFontSizeFor methods above.
2459 static float FontSizeInflationInner(const nsIFrame* aFrame,
2460 nscoord aMinFontSize);
2462 static bool FontSizeInflationEnabled(nsPresContext* aPresContext);
2465 * Returns true if the nglayout.debug.invalidation pref is set to true.
2467 static bool InvalidationDebuggingIsEnabled() {
2468 return mozilla::StaticPrefs::nglayout_debug_invalidation() ||
2469 getenv("MOZ_DUMP_INVALIDATION") != 0;
2472 static void Initialize();
2473 static void Shutdown();
2476 * Register an imgIRequest object with a refresh driver.
2478 * @param aPresContext The nsPresContext whose refresh driver we want to
2479 * register with.
2480 * @param aRequest A pointer to the imgIRequest object which the client wants
2481 * to register with the refresh driver.
2482 * @param aRequestRegistered A pointer to a boolean value which indicates
2483 * whether the given image request is registered. If
2484 * *aRequestRegistered is true, then this request will not be
2485 * registered again. If the request is registered by this function,
2486 * then *aRequestRegistered will be set to true upon the completion of
2487 * this function.
2490 static void RegisterImageRequest(nsPresContext* aPresContext,
2491 imgIRequest* aRequest,
2492 bool* aRequestRegistered);
2495 * Register an imgIRequest object with a refresh driver, but only if the
2496 * request is for an image that is animated.
2498 * @param aPresContext The nsPresContext whose refresh driver we want to
2499 * register with.
2500 * @param aRequest A pointer to the imgIRequest object which the client wants
2501 * to register with the refresh driver.
2502 * @param aRequestRegistered A pointer to a boolean value which indicates
2503 * whether the given image request is registered. If
2504 * *aRequestRegistered is true, then this request will not be
2505 * registered again. If the request is registered by this function,
2506 * then *aRequestRegistered will be set to true upon the completion of
2507 * this function.
2510 static void RegisterImageRequestIfAnimated(nsPresContext* aPresContext,
2511 imgIRequest* aRequest,
2512 bool* aRequestRegistered);
2515 * Deregister an imgIRequest object from a refresh driver.
2517 * @param aPresContext The nsPresContext whose refresh driver we want to
2518 * deregister from.
2519 * @param aRequest A pointer to the imgIRequest object with which the client
2520 * previously registered and now wants to deregister from the refresh
2521 * driver.
2522 * @param aRequestRegistered A pointer to a boolean value which indicates
2523 * whether the given image request is registered. If
2524 * *aRequestRegistered is false, then this request will not be
2525 * deregistered. If the request is deregistered by this function,
2526 * then *aRequestRegistered will be set to false upon the completion of
2527 * this function.
2529 static void DeregisterImageRequest(nsPresContext* aPresContext,
2530 imgIRequest* aRequest,
2531 bool* aRequestRegistered);
2534 * Shim to nsCSSFrameConstructor::PostRestyleEvent. Exists so that we
2535 * can avoid including nsCSSFrameConstructor.h and all its dependencies
2536 * in content files.
2538 static void PostRestyleEvent(mozilla::dom::Element*, mozilla::RestyleHint,
2539 nsChangeHint aMinChangeHint);
2542 * Updates a pair of x and y distances if a given point is closer to a given
2543 * rectangle than the original distance values. If aPoint is closer to
2544 * aRect than aClosestXDistance and aClosestYDistance indicate, then those
2545 * two variables are updated with the distance between aPoint and aRect,
2546 * and true is returned. If aPoint is not closer, then aClosestXDistance
2547 * and aClosestYDistance are left unchanged, and false is returned.
2549 * Distances are measured in the two dimensions separately; a closer x
2550 * distance beats a closer y distance.
2552 template <typename PointType, typename RectType, typename CoordType>
2553 static bool PointIsCloserToRect(PointType aPoint, const RectType& aRect,
2554 CoordType& aClosestXDistance,
2555 CoordType& aClosestYDistance);
2557 * Computes the box shadow rect for the frame, or returns an empty rect if
2558 * there are no shadows.
2560 * @param aFrame Frame to compute shadows for.
2561 * @param aFrameSize Size of aFrame (in case it hasn't been set yet).
2563 static nsRect GetBoxShadowRectForFrame(nsIFrame* aFrame,
2564 const nsSize& aFrameSize);
2566 #ifdef DEBUG
2568 * Assert that there are no duplicate continuations of the same frame
2569 * within aFrameList. Optimize the tests by assuming that all frames
2570 * in aFrameList have parent aContainer.
2572 static void AssertNoDuplicateContinuations(nsIFrame* aContainer,
2573 const nsFrameList& aFrameList);
2576 * Assert that the frame tree rooted at |aSubtreeRoot| is empty, i.e.,
2577 * that it contains no first-in-flows.
2579 static void AssertTreeOnlyEmptyNextInFlows(nsIFrame* aSubtreeRoot);
2580 #endif
2583 * Helper method to transform |aBounds| from aFrame to aAncestorFrame,
2584 * and combine it with |aPreciseTargetDest| if it is axis-aligned, or
2585 * combine it with |aImpreciseTargetDest| if not. The transformed rect is
2586 * clipped to |aClip|; if |aClip| has rounded corners, that also causes
2587 * the imprecise target to be used.
2589 static void TransformToAncestorAndCombineRegions(
2590 const nsRegion& aRegion, nsIFrame* aFrame, const nsIFrame* aAncestorFrame,
2591 nsRegion* aPreciseTargetDest, nsRegion* aImpreciseTargetDest,
2592 mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache,
2593 const mozilla::DisplayItemClip* aClip);
2596 * Populate aOutSize with the size of the content viewer corresponding
2597 * to the given prescontext. Return true if the size was set, false
2598 * otherwise.
2600 enum class SubtractDynamicToolbar { No, Yes };
2601 static bool GetDocumentViewerSize(
2602 const nsPresContext* aPresContext, LayoutDeviceIntSize& aOutSize,
2603 SubtractDynamicToolbar = SubtractDynamicToolbar::Yes);
2606 * Whether to include the dynamic toolbar area automatically (depending
2607 * whether the root container is scrollable or not) or forcibly in below
2608 * UpdateCompositionBoundsForRCDRSF and CalculateCompositionSizeForFrame
2609 * functions.
2611 enum class IncludeDynamicToolbar { Auto, Force };
2613 private:
2614 static bool UpdateCompositionBoundsForRCDRSF(
2615 mozilla::ParentLayerRect& aCompBounds, const nsPresContext* aPresContext,
2616 IncludeDynamicToolbar aIncludeDynamicToolbar =
2617 IncludeDynamicToolbar::Auto);
2619 public:
2621 * Calculate the compostion size for a frame. See FrameMetrics.h for
2622 * defintion of composition size (or bounds).
2623 * Note that for the root content document's root scroll frame (RCD-RSF),
2624 * the returned size does not change as the document's resolution changes,
2625 * but for all other frames it does. This means that callers that pass in
2626 * a frame that may or may not be the RCD-RSF (which is most callers),
2627 * are likely to need special-case handling of the RCD-RSF.
2629 static nsSize CalculateCompositionSizeForFrame(
2630 nsIFrame* aFrame, bool aSubtractScrollbars = true,
2631 const nsSize* aOverrideScrollPortSize = nullptr,
2632 IncludeDynamicToolbar aIncludeDynamicToolbar =
2633 IncludeDynamicToolbar::Auto);
2636 * Calculate a size suitable for bounding the size of the composition bounds
2637 * of scroll frames in the current process. This should be at most the
2638 * composition size of the cross-process RCD-RSF, but it may be a tighter
2639 * bounding size.
2640 * @param aFrame A frame in the (in-process) root content document (or a
2641 * descendant of it).
2642 * @param aIsRootContentDocRootScrollFrame Whether aFrame is the root
2643 * scroll frame of the *cross-process* root content document.
2644 * In this case we just use aFrame's own composition size.
2645 * @param aMetrics A partially populated FrameMetrics for aFrame. Must have at
2646 * least mCompositionBounds, mCumulativeResolution, and
2647 * mDevPixelsPerCSSPixel set.
2649 static CSSSize CalculateBoundingCompositionSize(
2650 const nsIFrame* aFrame, bool aIsRootContentDocRootScrollFrame,
2651 const FrameMetrics& aMetrics);
2654 * Calculate the scrollable rect for a frame. See FrameMetrics.h for
2655 * defintion of scrollable rect. aScrollableFrame is the scroll frame to
2656 * calculate the scrollable rect for. If it's null then we calculate the
2657 * scrollable rect as the rect of the root frame.
2659 static nsRect CalculateScrollableRectForFrame(
2660 const nsIScrollableFrame* aScrollableFrame, 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, ComputeFrameMetrics() computes all the fields, but requires
2746 * extra inputs and can only be called during frame layer building.
2748 static FrameMetrics CalculateBasicFrameMetrics(
2749 nsIScrollableFrame* aScrollFrame);
2751 static nsIScrollableFrame* GetAsyncScrollableAncestorFrame(nsIFrame* aTarget);
2753 static void SetBSizeFromFontMetrics(
2754 const nsIFrame* aFrame, mozilla::ReflowOutput& aMetrics,
2755 const mozilla::LogicalMargin& aFramePadding, mozilla::WritingMode aLineWM,
2756 mozilla::WritingMode aFrameWM);
2758 static bool HasDocumentLevelListenersForApzAwareEvents(PresShell* aPresShell);
2761 * Returns true if the given scroll origin is "higher priority" than APZ.
2762 * In general any content programmatic scrolls (e.g. scrollTo calls) are
2763 * higher priority, and take precedence over APZ scrolling. This function
2764 * returns true for those, and returns false for other origins like APZ
2765 * itself, or scroll position updates from the history restore code.
2767 static bool CanScrollOriginClobberApz(ScrollOrigin aScrollOrigin);
2769 static ScrollMetadata ComputeScrollMetadata(
2770 const nsIFrame* aForFrame, const nsIFrame* aScrollFrame,
2771 nsIContent* aContent, const nsIFrame* aItemFrame,
2772 const nsPoint& aOffsetToReferenceFrame,
2773 mozilla::layers::WebRenderLayerManager* aLayerManager,
2774 ViewID aScrollParentId, const nsSize& aScrollPortSize, bool aIsRoot);
2777 * Returns the metadata to put onto the root layer of a layer tree, if one is
2778 * needed. The last argument is a callback function to check if the caller
2779 * already has a metadata for a given scroll id.
2781 static mozilla::Maybe<ScrollMetadata> GetRootMetadata(
2782 nsDisplayListBuilder* aBuilder,
2783 mozilla::layers::WebRenderLayerManager* aLayerManager,
2784 const std::function<bool(ViewID& aScrollId)>& aCallback);
2787 * If the given scroll frame needs an area excluded from its composition
2788 * bounds due to scrollbars, return that area, otherwise return an empty
2789 * margin.
2790 * There is no need to exclude scrollbars in the following cases:
2791 * - If the scroll frame is not the RCD-RSF; in that case, the composition
2792 * bounds is calculated based on the scroll port which already excludes
2793 * the scrollbar area.
2794 * - If the scrollbars are overlay, since then they are drawn on top of the
2795 * scrollable content.
2797 static nsMargin ScrollbarAreaToExcludeFromCompositionBoundsFor(
2798 const nsIFrame* aScrollFrame);
2800 static bool ShouldUseNoFramesSheet(mozilla::dom::Document*);
2803 * Get the text content inside the frame. This methods traverse the
2804 * frame tree and collect the content from text frames. Note that this
2805 * method is similiar to nsContentUtils::GetNodeTextContent, but it at
2806 * least differs from that method in the following things:
2807 * 1. it skips text content inside nodes like style, script, textarea
2808 * which don't generate an in-tree text frame for the text;
2809 * 2. it skips elements with display property set to none;
2810 * 3. it skips out-of-flow elements;
2811 * 4. it includes content inside pseudo elements;
2812 * 5. it may include part of text content of a node if a text frame
2813 * inside is split to different continuations.
2815 static void GetFrameTextContent(nsIFrame* aFrame, nsAString& aResult);
2818 * Same as GetFrameTextContent but appends the result rather than sets it.
2820 static void AppendFrameTextContent(nsIFrame* aFrame, nsAString& aResult);
2823 * Takes a selection, and returns selection's bounding rect which is relative
2824 * to its root frame.
2826 * @param aSel Selection to check
2828 static nsRect GetSelectionBoundingRect(const mozilla::dom::Selection* aSel);
2831 * Calculate the bounding rect of |aContent|, relative to the origin
2832 * of the scrolled content of |aRootScrollFrame|.
2833 * Where the element is contained inside a scrollable subframe, the
2834 * bounding rect is clipped to the bounds of the subframe.
2835 * If non-null aOutNearestScrollClip will be filled in with the rect of the
2836 * nearest scroll frame (excluding aRootScrollFrame) that is an ancestor of
2837 * the frame of aContent, if such exists, in the same coords are the returned
2838 * rect. This rect is used to clip the result.
2840 static CSSRect GetBoundingContentRect(
2841 const nsIContent* aContent, const nsIScrollableFrame* aRootScrollFrame,
2842 mozilla::Maybe<CSSRect>* aOutNearestScrollClip = nullptr);
2845 * Similar to GetBoundingContentRect for nsIFrame.
2847 static CSSRect GetBoundingFrameRect(
2848 nsIFrame* aFrame, const nsIScrollableFrame* aRootScrollFrame,
2849 mozilla::Maybe<CSSRect>* aOutNearestScrollClip = nullptr);
2852 * Returns the first ancestor who is a float containing block.
2854 static nsBlockFrame* GetFloatContainingBlock(nsIFrame* aFrame);
2857 * Walks up the frame tree from |aForFrame| up to |aTopFrame|, or to the
2858 * root of the frame tree if |aTopFrame| is nullptr, and returns true if
2859 * a transformed frame is encountered.
2861 static bool IsTransformed(nsIFrame* aForFrame, nsIFrame* aTopFrame = nullptr);
2864 * Walk up from aFrame to the cross-doc root, accumulating all the APZ
2865 * callback transforms on the content elements encountered along the way.
2866 * Return the accumulated value.
2867 * XXX: Note that this does not take into account CSS transforms, nor
2868 * differences in structure between the frame tree and the layer tree (which
2869 * is probably what we *want* to be computing).
2871 static CSSPoint GetCumulativeApzCallbackTransform(nsIFrame* aFrame);
2874 * Compute a rect to pre-render in cases where we want to render more of
2875 * something than what is visible (usually to support async transformation).
2876 * @param aFrame the target frame to be pre-rendered
2877 * @param aDirtyRect the area that's visible in the coordinate system of
2878 * |aFrame|.
2879 * @param aOverflow the total size of the thing we're rendering in the
2880 * coordinate system of |aFrame|.
2881 * @param aPrerenderSize how large of an area we're willing to render in the
2882 * coordinate system of the root frame.
2883 * @return A rectangle that includes |aDirtyRect|, is clamped to |aOverflow|,
2884 * and is no larger than |aPrerenderSize| (unless |aPrerenderSize| is
2885 * smaller than |aDirtyRect|, in which case the returned rect will
2886 * still include |aDirtyRect| and thus be larger than
2887 * |aPrerenderSize|).
2889 static nsRect ComputePartialPrerenderArea(nsIFrame* aFrame,
2890 const nsRect& aDirtyRect,
2891 const nsRect& aOverflow,
2892 const nsSize& aPrerenderSize);
2895 * Checks whether a node is an invisible break.
2896 * If not, returns the first frame on the next line if such a next line
2897 * exists.
2899 * @return
2900 * true if the node is an invisible break. aNextLineFrame is returned null
2901 * in this case.
2903 * false if the node causes a visible break or if the node is no break.
2905 * @param aNextLineFrame
2906 * assigned to first frame on the next line if such a next line exists, null
2907 * otherwise.
2909 static bool IsInvisibleBreak(nsINode* aNode,
2910 nsIFrame** aNextLineFrame = nullptr);
2912 static nsRect ComputeSVGOriginBox(mozilla::dom::SVGViewportElement*);
2914 // Compute the geometry box for SVG layout. The caller should map the CSS box
2915 // into the proper SVG box.
2916 // |aMayHaveCyclicDependency| is used for stroke-box to avoid the cyclic
2917 // dependency if any of its descendants uses non-scaling-stroke.
2918 enum class MayHaveNonScalingStrokeCyclicDependency : bool { No, Yes };
2919 static nsRect ComputeSVGReferenceRect(
2920 nsIFrame*, StyleGeometryBox,
2921 MayHaveNonScalingStrokeCyclicDependency =
2922 MayHaveNonScalingStrokeCyclicDependency::No);
2924 // Compute the geometry box for CSS layout. The caller should map the SVG box
2925 // into the proper CSS box.
2926 static nsRect ComputeHTMLReferenceRect(const nsIFrame*, StyleGeometryBox);
2928 static nsRect ComputeClipPathGeometryBox(
2929 nsIFrame*, const mozilla::StyleShapeGeometryBox&);
2931 static nsPoint ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder,
2932 nsIFrame* aFrame);
2934 // Callers are responsible to ensure the user-font-set is up-to-date if
2935 // aUseUserFontSet is true.
2936 static already_AddRefed<nsFontMetrics> GetMetricsFor(
2937 nsPresContext* aPresContext, bool aIsVertical,
2938 const nsStyleFont* aStyleFont, mozilla::Length aFontSize,
2939 bool aUseUserFontSet);
2941 static void ComputeSystemFont(nsFont* aSystemFont,
2942 mozilla::StyleSystemFont aFontID,
2943 const nsFont& aDefaultVariableFont,
2944 const mozilla::dom::Document* aDocument);
2946 static uint32_t ParseFontLanguageOverride(const nsAString& aLangTag);
2949 * Returns true if there are any preferences or overrides that indicate a
2950 * need to handle <meta name="viewport"> tags.
2952 static bool ShouldHandleMetaViewport(const mozilla::dom::Document*);
2955 * Resolve a CSS <length-percentage> value to a definite size.
2957 template <bool clampNegativeResultToZero>
2958 static nscoord ResolveToLength(const LengthPercentage& aLengthPercentage,
2959 nscoord aPercentageBasis) {
2960 nscoord value = (aPercentageBasis == NS_UNCONSTRAINEDSIZE)
2961 ? aLengthPercentage.Resolve(0)
2962 : aLengthPercentage.Resolve(aPercentageBasis);
2963 return clampNegativeResultToZero ? std::max(0, value) : value;
2967 * Resolve a column-gap/row-gap to a definite size.
2968 * @note This method resolves 'normal' to zero.
2969 * Callers who want different behavior should handle 'normal' on their own.
2971 static nscoord ResolveGapToLength(
2972 const mozilla::NonNegativeLengthPercentageOrNormal& aGap,
2973 nscoord aPercentageBasis) {
2974 if (aGap.IsNormal()) {
2975 return nscoord(0);
2977 return ResolveToLength<true>(aGap.AsLengthPercentage(), aPercentageBasis);
2981 * Get the computed style from which the scrollbar style should be
2982 * used for the given scrollbar part frame.
2984 static ComputedStyle* StyleForScrollbar(const nsIFrame* aScrollbarPart);
2987 * Returns true if |aFrame| is scrolled out of view by a scrollable element in
2988 * a cross-process ancestor document.
2989 * Note this function only works for frames in out-of-process iframes.
2991 static bool FrameIsScrolledOutOfViewInCrossProcess(const nsIFrame* aFrame);
2994 * Similar to above FrameIsScrolledOutViewInCrossProcess but returns true even
2995 * if |aFrame| is not fully scrolled out of view and its visible area width or
2996 * height is smaller than |aMargin|.
2998 static bool FrameIsMostlyScrolledOutOfViewInCrossProcess(
2999 const nsIFrame* aFrame, nscoord aMargin);
3002 * Expand the height of |aSize| to the size of `vh` units.
3004 * With dynamic toolbar(s) the height for `vh` units is greater than the
3005 * ICB height, we need to expand it in some places.
3007 static nsSize ExpandHeightForViewportUnits(nsPresContext* aPresContext,
3008 const nsSize& aSize);
3010 static CSSSize ExpandHeightForDynamicToolbar(
3011 const nsPresContext* aPresContext, const CSSSize& aSize);
3012 static nsSize ExpandHeightForDynamicToolbar(const nsPresContext* aPresContext,
3013 const nsSize& aSize);
3016 * Returns the nsIFrame which clips overflow regions of the given |aFrame|.
3017 * Note CSS clip or clip-path isn't accounted for.
3019 static nsIFrame* GetNearestOverflowClipFrame(nsIFrame* aFrame);
3022 * Returns true if the user's preferences allow for smooth scrolling.
3024 static bool IsSmoothScrollingEnabled();
3027 * Recompute the default value of general.smoothScroll based on
3028 * the system settings for prefers-reduced-motion.
3030 * Note: Must only be called from the main thread.
3032 static void RecomputeSmoothScrollDefault();
3034 private:
3036 * Helper function for LogTestDataForPaint().
3038 static void DoLogTestDataForPaint(
3039 mozilla::layers::WebRenderLayerManager* aManager, ViewID aScrollId,
3040 const std::string& aKey, const std::string& aValue);
3042 static bool IsAPZTestLoggingEnabled();
3044 static void ConstrainToCoordValues(gfxFloat& aStart, gfxFloat& aSize);
3045 static void ConstrainToCoordValues(float& aStart, float& aSize);
3048 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsLayoutUtils::PaintFrameFlags)
3049 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsLayoutUtils::GetPopupFrameForPointFlags)
3051 template <typename PointType, typename RectType, typename CoordType>
3052 /* static */ bool nsLayoutUtils::PointIsCloserToRect(
3053 PointType aPoint, const RectType& aRect, CoordType& aClosestXDistance,
3054 CoordType& aClosestYDistance) {
3055 CoordType fromLeft = aPoint.x - aRect.x;
3056 CoordType fromRight = aPoint.x - aRect.XMost();
3058 CoordType xDistance;
3059 if (fromLeft >= 0 && fromRight <= 0) {
3060 xDistance = 0;
3061 } else {
3062 xDistance = std::min(abs(fromLeft), abs(fromRight));
3065 if (xDistance <= aClosestXDistance) {
3066 if (xDistance < aClosestXDistance) {
3067 aClosestYDistance = std::numeric_limits<CoordType>::max();
3070 CoordType fromTop = aPoint.y - aRect.y;
3071 CoordType fromBottom = aPoint.y - aRect.YMost();
3073 CoordType yDistance;
3074 if (fromTop >= 0 && fromBottom <= 0) {
3075 yDistance = 0;
3076 } else {
3077 yDistance = std::min(abs(fromTop), abs(fromBottom));
3080 if (yDistance < aClosestYDistance) {
3081 aClosestXDistance = xDistance;
3082 aClosestYDistance = yDistance;
3083 return true;
3087 return false;
3090 template <typename T>
3091 nsRect nsLayoutUtils::RoundGfxRectToAppRect(const T& aRect,
3092 const float aFactor) {
3093 // Get a new Rect whose units are app units by scaling by the specified
3094 // factor.
3095 T scaledRect = aRect;
3096 scaledRect.ScaleRoundOut(aFactor);
3098 // We now need to constrain our results to the max and min values for coords.
3099 ConstrainToCoordValues(scaledRect.x, scaledRect.width);
3100 ConstrainToCoordValues(scaledRect.y, scaledRect.height);
3102 if (!aRect.Width()) {
3103 scaledRect.SetWidth(0);
3106 if (!aRect.Height()) {
3107 scaledRect.SetHeight(0);
3110 // Now typecast everything back. This is guaranteed to be safe.
3111 return nsRect(nscoord(scaledRect.X()), nscoord(scaledRect.Y()),
3112 nscoord(scaledRect.Width()), nscoord(scaledRect.Height()));
3115 namespace mozilla {
3118 * Converts an nsPoint in app units to a Moz2D Point in pixels (whether those
3119 * are device pixels or CSS px depends on what the caller chooses to pass as
3120 * aAppUnitsPerPixel).
3122 inline gfx::Point NSPointToPoint(const nsPoint& aPoint,
3123 int32_t aAppUnitsPerPixel) {
3124 return gfx::Point(gfx::Float(aPoint.x) / aAppUnitsPerPixel,
3125 gfx::Float(aPoint.y) / aAppUnitsPerPixel);
3129 * Converts an nsRect in app units to a Moz2D Rect in pixels (whether those
3130 * are device pixels or CSS px depends on what the caller chooses to pass as
3131 * aAppUnitsPerPixel).
3133 gfx::Rect NSRectToRect(const nsRect& aRect, double aAppUnitsPerPixel);
3136 * Converts an nsRect in app units to a Moz2D Rect in pixels (whether those
3137 * are device pixels or CSS px depends on what the caller chooses to pass as
3138 * aAppUnitsPerPixel).
3140 * The passed DrawTarget is used to additionally snap the returned Rect to
3141 * device pixels, if appropriate (as decided and carried out by Moz2D's
3142 * MaybeSnapToDevicePixels helper, which this function calls to do any
3143 * snapping).
3145 gfx::Rect NSRectToSnappedRect(const nsRect& aRect, double aAppUnitsPerPixel,
3146 const gfx::DrawTarget& aSnapDT);
3149 * Converts, where possible, an nsRect in app units to a Moz2D Rect in pixels
3150 * (whether those are device pixels or CSS px depends on what the caller
3151 * chooses to pass as aAppUnitsPerPixel).
3153 * If snapping results in a rectangle with zero width or height, the affected
3154 * coordinates are left unsnapped
3156 gfx::Rect NSRectToNonEmptySnappedRect(const nsRect& aRect,
3157 double aAppUnitsPerPixel,
3158 const gfx::DrawTarget& aSnapDT);
3160 void StrokeLineWithSnapping(
3161 const nsPoint& aP1, const nsPoint& aP2, int32_t aAppUnitsPerDevPixel,
3162 gfx::DrawTarget& aDrawTarget, const gfx::Pattern& aPattern,
3163 const gfx::StrokeOptions& aStrokeOptions = gfx::StrokeOptions(),
3164 const gfx::DrawOptions& aDrawOptions = gfx::DrawOptions());
3166 namespace layout {
3169 * An RAII class which will, for the duration of its lifetime,
3170 * **if** the frame given is a container for font size inflation,
3171 * set the current inflation container on the pres context to null
3172 * (and then, in its destructor, restore the old value).
3174 class AutoMaybeDisableFontInflation {
3175 public:
3176 explicit AutoMaybeDisableFontInflation(nsIFrame* aFrame);
3178 ~AutoMaybeDisableFontInflation();
3180 private:
3181 nsPresContext* mPresContext;
3182 bool mOldValue;
3185 } // namespace layout
3186 } // namespace mozilla
3188 class nsSetAttrRunnable : public mozilla::Runnable {
3189 public:
3190 nsSetAttrRunnable(mozilla::dom::Element* aElement, nsAtom* aAttrName,
3191 const nsAString& aValue);
3192 nsSetAttrRunnable(mozilla::dom::Element* aElement, nsAtom* aAttrName,
3193 int32_t aValue);
3195 NS_DECL_NSIRUNNABLE
3197 RefPtr<mozilla::dom::Element> mElement;
3198 RefPtr<nsAtom> mAttrName;
3199 nsAutoString mValue;
3202 class nsUnsetAttrRunnable : public mozilla::Runnable {
3203 public:
3204 nsUnsetAttrRunnable(mozilla::dom::Element* aElement, nsAtom* aAttrName);
3206 NS_DECL_NSIRUNNABLE
3208 RefPtr<mozilla::dom::Element> mElement;
3209 RefPtr<nsAtom> mAttrName;
3212 // This class allows you to easily set any pointer variable and ensure it's
3213 // set to nullptr when leaving its scope.
3214 template <typename T>
3215 class MOZ_RAII SetAndNullOnExit {
3216 public:
3217 SetAndNullOnExit(T*& aVariable, T* aValue) {
3218 aVariable = aValue;
3219 mVariable = &aVariable;
3221 ~SetAndNullOnExit() { *mVariable = nullptr; }
3223 private:
3224 T** mVariable;
3227 #endif // nsLayoutUtils_h__