Bug 1646700 [wpt PR 24235] - Update picture-in-picture idlharness test, a=testonly
[gecko.git] / layout / base / nsLayoutUtils.h
blob28eb76efe405d375b80b122fdf5039a2efb8248e
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/ReflowOutput.h"
16 #include "mozilla/RelativeTo.h"
17 #include "mozilla/StaticPrefs_nglayout.h"
18 #include "mozilla/SVGImageContext.h"
19 #include "mozilla/ToString.h"
20 #include "mozilla/TypedEnumBits.h"
21 #include "mozilla/UniquePtr.h"
22 #include "mozilla/layout/FrameChildList.h"
23 #include "mozilla/layers/ScrollableLayerGuid.h"
24 #include "mozilla/gfx/2D.h"
25 #include "gfx2DGlue.h"
26 #include "gfxPoint.h"
27 #include "nsBoundingMetrics.h"
28 #include "nsCSSPropertyIDSet.h"
29 #include "nsClassHashtable.h"
30 #include "nsGkAtoms.h"
31 #include "nsThreadUtils.h"
32 #include "ImageContainer.h" // for layers::Image
33 #include "Units.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 class nsDisplayListBuilder;
55 enum class nsDisplayListBuilderMode : uint8_t;
56 enum nsChangeHint : uint32_t;
57 class nsDisplayItem;
58 class nsFontMetrics;
59 class nsFontFaceList;
60 class nsIImageLoadingContent;
61 class nsBlockFrame;
62 class nsContainerFrame;
63 class nsView;
64 class nsIFrame;
65 class nsPIDOMWindowOuter;
66 class imgIRequest;
67 struct nsStyleFont;
68 struct nsOverflowAreas;
70 namespace mozilla {
71 struct AspectRatio;
72 class ComputedStyle;
73 class PresShell;
74 enum class PseudoStyleType : uint8_t;
75 class EventListenerManager;
76 enum class LayoutFrameType : uint8_t;
77 struct IntrinsicSize;
78 struct ContainerLayerParameters;
79 class WritingMode;
80 class DisplayItemClip;
81 class EffectSet;
82 struct ActiveScrolledRoot;
83 enum class ScrollOrigin : uint8_t;
84 enum class StyleImageOrientation : uint8_t;
85 namespace dom {
86 class CanvasRenderingContext2D;
87 class DOMRectList;
88 class Document;
89 class Element;
90 class Event;
91 class HTMLImageElement;
92 class HTMLCanvasElement;
93 class HTMLVideoElement;
94 class InspectorFontFace;
95 class OffscreenCanvas;
96 class Selection;
97 } // namespace dom
98 namespace gfx {
99 struct RectCornerRadii;
100 enum class ShapedTextFlags : uint16_t;
101 } // namespace gfx
102 namespace layers {
103 struct FrameMetrics;
104 struct ScrollMetadata;
105 class Image;
106 class StackingContextHelper;
107 class Layer;
108 } // namespace layers
109 } // namespace mozilla
111 namespace mozilla {
113 struct DisplayPortPropertyData {
114 DisplayPortPropertyData(const nsRect& aRect, uint32_t aPriority,
115 bool aPainted)
116 : mRect(aRect), mPriority(aPriority), mPainted(aPainted) {}
117 nsRect mRect;
118 uint32_t mPriority;
119 bool mPainted;
122 struct DisplayPortMarginsPropertyData {
123 DisplayPortMarginsPropertyData(const ScreenMargin& aMargins,
124 uint32_t aPriority, bool aPainted)
125 : mMargins(aMargins), mPriority(aPriority), mPainted(aPainted) {}
126 ScreenMargin mMargins;
127 uint32_t mPriority;
128 bool mPainted;
131 } // namespace mozilla
133 // For GetDisplayPort
134 enum class DisplayportRelativeTo { ScrollPort, ScrollFrame };
136 // Flags to customize the behavior of nsLayoutUtils::DrawString.
137 enum class DrawStringFlags {
138 Default = 0x0,
139 ForceHorizontal = 0x1 // Forces the text to be drawn horizontally.
141 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DrawStringFlags)
144 * nsLayoutUtils is a namespace class used for various helper
145 * functions that are useful in multiple places in layout. The goal
146 * is not to define multiple copies of the same static helper.
148 class nsLayoutUtils {
149 typedef mozilla::AspectRatio AspectRatio;
150 typedef mozilla::ComputedStyle ComputedStyle;
151 typedef mozilla::LengthPercentage LengthPercentage;
152 typedef mozilla::LengthPercentageOrAuto LengthPercentageOrAuto;
153 typedef mozilla::dom::DOMRectList DOMRectList;
154 typedef mozilla::layers::Layer Layer;
155 typedef mozilla::layers::StackingContextHelper StackingContextHelper;
156 typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
157 typedef mozilla::IntrinsicSize IntrinsicSize;
158 typedef mozilla::RelativeTo RelativeTo;
159 typedef mozilla::ScrollOrigin ScrollOrigin;
160 typedef mozilla::ViewportType ViewportType;
161 typedef mozilla::gfx::SourceSurface SourceSurface;
162 typedef mozilla::gfx::sRGBColor sRGBColor;
163 typedef mozilla::gfx::DrawTarget DrawTarget;
164 typedef mozilla::gfx::ExtendMode ExtendMode;
165 typedef mozilla::gfx::SamplingFilter SamplingFilter;
166 typedef mozilla::gfx::Float Float;
167 typedef mozilla::gfx::Point Point;
168 typedef mozilla::gfx::Rect Rect;
169 typedef mozilla::gfx::RectDouble RectDouble;
170 typedef mozilla::gfx::Size Size;
171 typedef mozilla::gfx::Matrix4x4 Matrix4x4;
172 typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged;
173 typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
174 typedef mozilla::gfx::StrokeOptions StrokeOptions;
175 typedef mozilla::image::ImgDrawResult ImgDrawResult;
177 public:
178 typedef mozilla::layers::FrameMetrics FrameMetrics;
179 typedef mozilla::layers::ScrollMetadata ScrollMetadata;
180 typedef mozilla::layers::ScrollableLayerGuid::ViewID ViewID;
181 typedef mozilla::CSSPoint CSSPoint;
182 typedef mozilla::CSSSize CSSSize;
183 typedef mozilla::CSSIntSize CSSIntSize;
184 typedef mozilla::CSSRect CSSRect;
185 typedef mozilla::ScreenMargin ScreenMargin;
186 typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize;
187 typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
188 typedef mozilla::PresShell PresShell;
189 typedef mozilla::StyleGeometryBox StyleGeometryBox;
190 typedef mozilla::SVGImageContext SVGImageContext;
191 typedef mozilla::LogicalSize LogicalSize;
194 * Finds previously assigned ViewID for the given content element, if any.
195 * Returns whether a ViewID was previously assigned.
197 static bool FindIDFor(const nsIContent* aContent, ViewID* aOutViewId);
200 * Finds previously assigned or generates a unique ViewID for the given
201 * content element.
203 static ViewID FindOrCreateIDFor(nsIContent* aContent);
206 * Find content for given ID.
208 static nsIContent* FindContentFor(ViewID aId);
211 * Find the scrollable frame for a given content element.
213 static nsIScrollableFrame* FindScrollableFrameFor(nsIContent* aContent);
216 * Find the scrollable frame for a given ID.
218 static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId);
221 * Find the ID for a given scrollable frame.
223 static ViewID FindIDForScrollableFrame(nsIScrollableFrame* aScrollable);
226 * Get display port for the given element, relative to the specified entity,
227 * defaulting to the scrollport.
229 static bool GetDisplayPort(
230 nsIContent* aContent, nsRect* aResult,
231 DisplayportRelativeTo aRelativeTo = DisplayportRelativeTo::ScrollPort,
232 bool* aOutPainted = nullptr);
235 * Check whether the given element has a displayport.
237 static bool HasDisplayPort(nsIContent* aContent);
240 * Check whether the given element has a displayport that has already
241 * been sent to the compositor via a layers or WR transaction.
243 static bool HasPaintedDisplayPort(nsIContent* aContent);
246 * Mark the displayport of a given element as having been sent to
247 * the compositor via a layers or WR transaction.
249 static void MarkDisplayPortAsPainted(nsIContent* aContent);
252 * Check whether the given frame has a displayport. It returns false
253 * for scrolled frames and true for the corresponding scroll frame.
254 * Optionally pass the child, and it only returns true if the child is the
255 * scrolled frame for the displayport.
257 static bool FrameHasDisplayPort(nsIFrame* aFrame,
258 const nsIFrame* aScrolledFrame = nullptr);
261 * Check if the given element has a margins based displayport but is missing a
262 * displayport base rect that it needs to properly compute a displayport rect.
264 static bool IsMissingDisplayPortBaseRect(nsIContent* aContent);
267 * Go through the IPC Channel and update displayport margins for content
268 * elements based on UpdateFrame messages. The messages are left in the
269 * queue and will be fully processed when dequeued. The aim is to paint
270 * the most up-to-date displayport without waiting for these message to
271 * go through the message queue.
273 static void UpdateDisplayPortMarginsFromPendingMessages();
276 * @return the display port for the given element which should be used for
277 * visibility testing purposes.
279 * If low-precision buffers are enabled, this is the critical display port;
280 * otherwise, it's the same display port returned by GetDisplayPort().
282 static bool GetDisplayPortForVisibilityTesting(
283 nsIContent* aContent, nsRect* aResult,
284 DisplayportRelativeTo aRelativeTo = DisplayportRelativeTo::ScrollPort);
286 enum class RepaintMode : uint8_t { Repaint, DoNotRepaint };
289 * Invalidate for displayport change.
291 static void InvalidateForDisplayPortChange(
292 nsIContent* aContent, bool aHadDisplayPort, const nsRect& aOldDisplayPort,
293 const nsRect& aNewDisplayPort,
294 RepaintMode aRepaintMode = RepaintMode::Repaint);
297 * Set the display port margins for a content element to be used with a
298 * display port base (see SetDisplayPortBase()).
299 * See also nsIDOMWindowUtils.setDisplayPortMargins.
300 * @param aContent the content element for which to set the margins
301 * @param aPresShell the pres shell for the document containing the element
302 * @param aMargins the margins to set
303 * @param aAlignmentX, alignmentY the amount of pixels to which to align the
304 * displayport built by combining the base
305 * rect with the margins, in either direction
306 * @param aPriority a priority value to determine which margins take effect
307 * when multiple callers specify margins
308 * @param aRepaintMode whether to schedule a paint after setting the margins
309 * @return true if the new margins were applied.
311 static bool SetDisplayPortMargins(
312 nsIContent* aContent, PresShell* aPresShell, const ScreenMargin& aMargins,
313 uint32_t aPriority = 0, RepaintMode aRepaintMode = RepaintMode::Repaint);
316 * Set the display port base rect for given element to be used with display
317 * port margins.
318 * SetDisplayPortBaseIfNotSet is like SetDisplayPortBase except it only sets
319 * the display port base to aBase if no display port base is currently set.
321 static void SetDisplayPortBase(nsIContent* aContent, const nsRect& aBase);
322 static void SetDisplayPortBaseIfNotSet(nsIContent* aContent,
323 const nsRect& aBase);
326 * Get the critical display port for the given element.
328 static bool GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult,
329 bool* aOutPainted = nullptr);
332 * Check whether the given element has a critical display port.
334 static bool HasCriticalDisplayPort(nsIContent* aContent);
337 * If low-precision painting is turned on, delegates to
338 * GetCriticalDisplayPort. Otherwise, delegates to GetDisplayPort.
340 static bool GetHighResolutionDisplayPort(nsIContent* aContent,
341 nsRect* aResult,
342 bool* aOutPainted = nullptr);
345 * Remove the displayport for the given element.
347 static void RemoveDisplayPort(nsIContent* aContent);
350 * Notify the scroll frame with the given scroll id that its scroll offset
351 * is being sent to APZ as part of a paint-skip transaction.
353 * Normally, this notification happens during painting, after calls to
354 * ComputeScrollMetadata(). During paint-skipping that code is skipped,
355 * but it's still important for the scroll frame to be notified for
356 * correctness of relative scroll updates, so the code that sends the
357 * empty paint-skip transaction needs to call this.
359 static void NotifyPaintSkipTransaction(ViewID aScrollId);
362 * Use heuristics to figure out the child list that
363 * aChildFrame is currently in.
365 static mozilla::layout::FrameChildListID GetChildListNameFor(
366 nsIFrame* aChildFrame);
369 * Returns the ::before pseudo-element for aContent, if any.
371 static mozilla::dom::Element* GetBeforePseudo(const nsIContent* aContent);
374 * Returns the frame corresponding to the ::before pseudo-element for
375 * aContent, if any.
377 static nsIFrame* GetBeforeFrame(const nsIContent* aContent);
380 * Returns the ::after pseudo-element for aContent, if any.
382 static mozilla::dom::Element* GetAfterPseudo(const nsIContent* aContent);
385 * Returns the frame corresponding to the ::after pseudo-element for aContent,
386 * if any.
388 static nsIFrame* GetAfterFrame(const nsIContent* aContent);
391 * Returns the ::marker pseudo-element for aContent, if any.
393 static mozilla::dom::Element* GetMarkerPseudo(const nsIContent* aContent);
396 * Returns the frame corresponding to the ::marker pseudo-element for
397 * aContent, if any.
399 static nsIFrame* GetMarkerFrame(const nsIContent* aContent);
402 * Given a frame, search up the frame tree until we find an
403 * ancestor that (or the frame itself) is of type aFrameType, if any.
405 * @param aFrame the frame to start at
406 * @param aFrameType the frame type to look for
407 * @param aStopAt a frame to stop at after we checked it
408 * @return a frame of the given type or nullptr if no
409 * such ancestor exists
411 static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame,
412 mozilla::LayoutFrameType aFrameType,
413 nsIFrame* aStopAt = nullptr);
416 * Given a frame, search up the frame tree until we find an
417 * ancestor that (or the frame itself) is a "Page" frame, if any.
419 * @param aFrame the frame to start at
420 * @return a frame of type mozilla::LayoutFrameType::Page or nullptr if no
421 * such ancestor exists
423 static nsIFrame* GetPageFrame(nsIFrame* aFrame);
426 * Given a frame which is the primary frame for an element,
427 * return the frame that has the non-pseudoelement ComputedStyle for
428 * the content.
429 * This is aPrimaryFrame itself except for tableWrapper frames.
431 * Given a non-null input, this will return null if and only if its
432 * argument is a table wrapper frame that is mid-destruction (and its
433 * table frame has been destroyed).
435 static nsIFrame* GetStyleFrame(nsIFrame* aPrimaryFrame);
436 static const nsIFrame* GetStyleFrame(const nsIFrame* aPrimaryFrame);
439 * Given a content node,
440 * return the frame that has the non-pseudoelement ComputedStyle for
441 * the content. May return null.
442 * This is aContent->GetPrimaryFrame() except for tableWrapper frames.
444 static nsIFrame* GetStyleFrame(const nsIContent* aContent);
447 * The inverse of GetStyleFrame. Returns |aStyleFrame| unless it is an inner
448 * table frame, in which case the table wrapper frame is returned.
450 static nsIFrame* GetPrimaryFrameFromStyleFrame(nsIFrame* aStyleFrame);
451 static const nsIFrame* GetPrimaryFrameFromStyleFrame(
452 const nsIFrame* aStyleFrame);
455 * Similar to nsIFrame::IsPrimaryFrame except that this will return true
456 * for the inner table frame rather than for its wrapper frame.
458 static bool IsPrimaryStyleFrame(const nsIFrame* aFrame);
460 #ifdef DEBUG
461 // TODO: remove, see bug 598468.
462 static bool gPreventAssertInCompareTreePosition;
463 #endif // DEBUG
466 * CompareTreePosition determines whether aContent1 comes before or
467 * after aContent2 in a preorder traversal of the content tree.
469 * @param aCommonAncestor either null, or a common ancestor of
470 * aContent1 and aContent2. Actually this is
471 * only a hint; if it's not an ancestor of
472 * aContent1 or aContent2, this function will
473 * still work, but it will be slower than
474 * normal.
475 * @return < 0 if aContent1 is before aContent2
476 * > 0 if aContent1 is after aContent2,
477 * 0 otherwise (meaning they're the same, or they're in
478 * different documents)
480 static int32_t CompareTreePosition(
481 nsIContent* aContent1, nsIContent* aContent2,
482 const nsIContent* aCommonAncestor = nullptr) {
483 return DoCompareTreePosition(aContent1, aContent2, -1, 1, aCommonAncestor);
487 * More generic version of |CompareTreePosition|. |aIf1Ancestor|
488 * gives the value to return when 1 is an ancestor of 2, and likewise
489 * for |aIf2Ancestor|. Passing (-1, 1) gives preorder traversal
490 * order, and (1, -1) gives postorder traversal order.
492 static int32_t DoCompareTreePosition(
493 nsIContent* aContent1, nsIContent* aContent2, int32_t aIf1Ancestor,
494 int32_t aIf2Ancestor, const nsIContent* aCommonAncestor = nullptr);
497 * CompareTreePosition determines whether aFrame1 comes before or
498 * after aFrame2 in a preorder traversal of the frame tree, where out
499 * of flow frames are treated as children of their placeholders. This is
500 * basically the same ordering as DoCompareTreePosition(nsIContent*) except
501 * that it handles anonymous content properly and there are subtleties with
502 * continuations.
504 * @param aCommonAncestor either null, or a common ancestor of
505 * aContent1 and aContent2. Actually this is
506 * only a hint; if it's not an ancestor of
507 * aContent1 or aContent2, this function will
508 * still work, but it will be slower than
509 * normal.
510 * @return < 0 if aContent1 is before aContent2
511 * > 0 if aContent1 is after aContent2,
512 * 0 otherwise (meaning they're the same, or they're in
513 * different frame trees)
515 static int32_t CompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
516 nsIFrame* aCommonAncestor = nullptr) {
517 return DoCompareTreePosition(aFrame1, aFrame2, -1, 1, aCommonAncestor);
520 static int32_t CompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
521 nsTArray<nsIFrame*>& aFrame2Ancestors,
522 nsIFrame* aCommonAncestor = nullptr) {
523 return DoCompareTreePosition(aFrame1, aFrame2, aFrame2Ancestors, -1, 1,
524 aCommonAncestor);
528 * More generic version of |CompareTreePosition|. |aIf1Ancestor|
529 * gives the value to return when 1 is an ancestor of 2, and likewise
530 * for |aIf2Ancestor|. Passing (-1, 1) gives preorder traversal
531 * order, and (1, -1) gives postorder traversal order.
533 static int32_t DoCompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
534 int32_t aIf1Ancestor,
535 int32_t aIf2Ancestor,
536 nsIFrame* aCommonAncestor = nullptr);
538 static nsIFrame* FillAncestors(nsIFrame* aFrame, nsIFrame* aStopAtAncestor,
539 nsTArray<nsIFrame*>* aAncestors);
541 static int32_t DoCompareTreePosition(nsIFrame* aFrame1, nsIFrame* aFrame2,
542 nsTArray<nsIFrame*>& aFrame2Ancestors,
543 int32_t aIf1Ancestor,
544 int32_t aIf2Ancestor,
545 nsIFrame* aCommonAncestor);
548 * LastContinuationWithChild gets the last continuation in aFrame's chain
549 * that has a child, or the first continuation if the frame has no children.
551 static nsContainerFrame* LastContinuationWithChild(nsContainerFrame* aFrame);
554 * GetLastSibling simply finds the last sibling of aFrame, or returns nullptr
555 * if aFrame is null.
557 static nsIFrame* GetLastSibling(nsIFrame* aFrame);
560 * FindSiblingViewFor locates the child of aParentView that aFrame's
561 * view should be inserted 'above' (i.e., before in sibling view
562 * order). This is the first child view of aParentView whose
563 * corresponding content is before aFrame's content (view siblings
564 * are in reverse content order).
566 static nsView* FindSiblingViewFor(nsView* aParentView, nsIFrame* aFrame);
569 * Get the parent of aFrame. If aFrame is the root frame for a document,
570 * and the document has a parent document in the same view hierarchy, then
571 * we try to return the subdocumentframe in the parent document.
572 * @param aExtraOffset [in/out] if non-null, then as we cross documents
573 * an extra offset may be required and it will be added to aCrossDocOffset.
574 * Be careful dealing with this extra offset as it is in app units of the
575 * parent document, which may have a different app units per dev pixel ratio
576 * than the child document.
578 static nsIFrame* GetCrossDocParentFrame(const nsIFrame* aFrame,
579 nsPoint* aCrossDocOffset = nullptr);
582 * IsProperAncestorFrame checks whether aAncestorFrame is an ancestor
583 * of aFrame and not equal to aFrame.
584 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
585 * aAncestorFrame. If non-null, this can bound the search and speed up
586 * the function
588 static bool IsProperAncestorFrame(const nsIFrame* aAncestorFrame,
589 const nsIFrame* aFrame,
590 const nsIFrame* aCommonAncestor = nullptr);
593 * Like IsProperAncestorFrame, but looks across document boundaries.
595 * Just like IsAncestorFrameCrossDoc, except that it returns false when
596 * aFrame == aAncestorFrame.
598 static bool IsProperAncestorFrameCrossDoc(
599 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
600 const nsIFrame* aCommonAncestor = nullptr);
603 * IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor
604 * of aFrame or equal to aFrame, looking across document boundaries.
605 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
606 * aAncestorFrame. If non-null, this can bound the search and speed up
607 * the function.
609 * Just like IsProperAncestorFrameCrossDoc, except that it returns true when
610 * aFrame == aAncestorFrame.
612 static bool IsAncestorFrameCrossDoc(
613 const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
614 const nsIFrame* aCommonAncestor = nullptr);
617 * Sets the fixed-pos metadata properties on aLayer.
618 * aAnchorRect is the basic anchor rectangle. If aFixedPosFrame is not a
619 * viewport frame, then we pick a corner of aAnchorRect to as the anchor point
620 * for the fixed-pos layer (i.e. the point to remain stable during zooming),
621 * based on which of the fixed-pos frame's CSS absolute positioning offset
622 * properties (top, left, right, bottom) are auto. aAnchorRect is in the
623 * coordinate space of aLayer's container layer (i.e. relative to the
624 * reference frame of the display item which is building aLayer's container
625 * layer).
627 static void SetFixedPositionLayerData(
628 Layer* aLayer, const nsIFrame* aViewportFrame, const nsRect& aAnchorRect,
629 const nsIFrame* aFixedPosFrame, nsPresContext* aPresContext,
630 const ContainerLayerParameters& aContainerParameters);
632 static mozilla::SideBits GetSideBitsAndAdjustAnchorForFixedPositionContent(
633 const nsIFrame* aViewportFrame, const nsIFrame* aFixedPosFrame,
634 mozilla::LayerPoint* aAnchor, const Rect* aAnchorRect);
635 static mozilla::SideBits GetSideBitsForFixedPositionContent(
636 const nsIFrame* aFixedPosFrame);
639 * Get the scroll id for the root scrollframe of the presshell of the given
640 * prescontext. Returns NULL_SCROLL_ID if it couldn't be found.
642 static ViewID ScrollIdForRootScrollFrame(nsPresContext* aPresContext);
645 * Return true if aPresContext's viewport has a displayport.
647 static bool ViewportHasDisplayPort(nsPresContext* aPresContext);
650 * Return true if aFrame is a fixed-pos frame and is a child of a viewport
651 * which has a displayport. These frames get special treatment from the
652 * compositor. aDisplayPort, if non-null, is set to the display port rectangle
653 * (relative to the viewport).
655 static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame);
658 * GetScrollableFrameFor returns the scrollable frame for a scrolled frame
660 static nsIScrollableFrame* GetScrollableFrameFor(
661 const nsIFrame* aScrolledFrame);
664 * GetNearestScrollableFrameForDirection locates the first ancestor of
665 * aFrame (or aFrame itself) that is scrollable with overflow:scroll or
666 * overflow:auto in the given direction and where either the scrollbar for
667 * that direction is visible or the frame can be scrolled by some
668 * positive amount in that direction.
669 * The search extends across document boundaries.
671 * @param aFrame the frame to start with
672 * @param aDirection Whether it's for horizontal or vertical scrolling.
673 * @return the nearest scrollable frame or nullptr if not found
675 enum Direction { eHorizontal, eVertical };
676 static nsIScrollableFrame* GetNearestScrollableFrameForDirection(
677 nsIFrame* aFrame, Direction aDirection);
679 enum {
681 * If the SCROLLABLE_SAME_DOC flag is set, then we only walk the frame tree
682 * up to the root frame in the current document.
684 SCROLLABLE_SAME_DOC = 0x01,
686 * If the SCROLLABLE_INCLUDE_HIDDEN flag is set then we allow
687 * overflow:hidden scrollframes to be returned as scrollable frames.
689 SCROLLABLE_INCLUDE_HIDDEN = 0x02,
691 * If the SCROLLABLE_ONLY_ASYNC_SCROLLABLE flag is set, then we only
692 * want to match scrollable frames for which WantAsyncScroll() returns
693 * true.
695 SCROLLABLE_ONLY_ASYNC_SCROLLABLE = 0x04,
697 * If the SCROLLABLE_ALWAYS_MATCH_ROOT flag is set, then we will always
698 * return the root scrollable frame for the root document (in the current
699 * process) if we encounter it, whether or not it is async scrollable or
700 * overflow: hidden.
702 SCROLLABLE_ALWAYS_MATCH_ROOT = 0x08,
704 * If the SCROLLABLE_FIXEDPOS_FINDS_ROOT flag is set, then for fixed-pos
705 * frames return the root scrollable frame for that document.
707 SCROLLABLE_FIXEDPOS_FINDS_ROOT = 0x10,
709 * If the SCROLLABLE_STOP_AT_PAGE flag is set, then we stop searching
710 * for scrollable ancestors when seeing a nsPageFrame. This can be used
711 * to avoid finding the viewport scroll frame in Print Preview (which
712 * would be undesirable as a 'position:sticky' container for content).
714 SCROLLABLE_STOP_AT_PAGE = 0x20,
717 * GetNearestScrollableFrame locates the first ancestor of aFrame
718 * (or aFrame itself) that is scrollable with overflow:scroll or
719 * overflow:auto in some direction.
721 * @param aFrame the frame to start with
722 * @param aFlags if SCROLLABLE_SAME_DOC is set, do not search across
723 * document boundaries. If SCROLLABLE_INCLUDE_HIDDEN is set, include
724 * frames scrollable with overflow:hidden.
725 * @return the nearest scrollable frame or nullptr if not found
727 static nsIScrollableFrame* GetNearestScrollableFrame(nsIFrame* aFrame,
728 uint32_t aFlags = 0);
731 * GetScrolledRect returns the range of allowable scroll offsets
732 * for aScrolledFrame, assuming the scrollable overflow area is
733 * aScrolledFrameOverflowArea and the scrollport size is aScrollPortSize.
735 static nsRect GetScrolledRect(nsIFrame* aScrolledFrame,
736 const nsRect& aScrolledFrameOverflowArea,
737 const nsSize& aScrollPortSize,
738 mozilla::StyleDirection);
741 * HasPseudoStyle returns true if aContent (whose primary style
742 * context is aComputedStyle) has the aPseudoElement pseudo-style
743 * attached to it; returns false otherwise.
745 * @param aContent the content node we're looking at
746 * @param aComputedStyle aContent's ComputedStyle
747 * @param aPseudoElement the id of the pseudo style we care about
748 * @param aPresContext the presentation context
749 * @return whether aContent has aPseudoElement style attached to it
751 static bool HasPseudoStyle(nsIContent* aContent,
752 ComputedStyle* aComputedStyle,
753 mozilla::PseudoStyleType aPseudoElement,
754 nsPresContext* aPresContext);
757 * If this frame is a placeholder for a float, then return the float,
758 * otherwise return nullptr. aPlaceholder must be a placeholder frame.
760 static nsIFrame* GetFloatFromPlaceholder(nsIFrame* aPlaceholder);
762 // Combine aNewBreakType with aOrigBreakType, but limit the break types
763 // to StyleClear::Left, Right, Both.
764 static mozilla::StyleClear CombineBreakType(
765 mozilla::StyleClear aOrigBreakType, mozilla::StyleClear aNewBreakType);
768 * Get the coordinates of a given DOM mouse event, relative to a given
769 * frame. Works only for DOM events generated by WidgetGUIEvents.
770 * @param aDOMEvent the event
771 * @param aFrame the frame to make coordinates relative to
772 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
773 * for some reason the coordinates for the mouse are not known (e.g.,
774 * the event is not a GUI event).
776 static nsPoint GetDOMEventCoordinatesRelativeTo(
777 mozilla::dom::Event* aDOMEvent, nsIFrame* aFrame);
780 * Get the coordinates of a given native mouse event, relative to a given
781 * frame.
782 * @param aEvent the event
783 * @param aFrame the frame to make coordinates relative to
784 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
785 * for some reason the coordinates for the mouse are not known (e.g.,
786 * the event is not a GUI event).
788 static nsPoint GetEventCoordinatesRelativeTo(
789 const mozilla::WidgetEvent* aEvent, RelativeTo aFrame);
792 * Get the coordinates of a given point relative to an event and a
793 * given frame.
794 * @param aEvent the event
795 * @param aPoint the point to get the coordinates relative to
796 * @param aFrame the frame to make coordinates relative to
797 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
798 * for some reason the coordinates for the mouse are not known (e.g.,
799 * the event is not a GUI event).
801 static nsPoint GetEventCoordinatesRelativeTo(
802 const mozilla::WidgetEvent* aEvent,
803 const mozilla::LayoutDeviceIntPoint& aPoint, RelativeTo aFrame);
806 * Get the coordinates of a given point relative to a widget and a
807 * given frame.
808 * @param aWidget the event src widget
809 * @param aPoint the point to get the coordinates relative to
810 * @param aFrame the frame to make coordinates relative to
811 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
812 * for some reason the coordinates for the mouse are not known (e.g.,
813 * the event is not a GUI event).
815 static nsPoint GetEventCoordinatesRelativeTo(
816 nsIWidget* aWidget, const mozilla::LayoutDeviceIntPoint& aPoint,
817 RelativeTo aFrame);
820 * Get the popup frame of a given native mouse event.
821 * @param aPresContext only check popups within aPresContext or a descendant
822 * @param aEvent the event.
823 * @return Null, if there is no popup frame at the point, otherwise,
824 * returns top-most popup frame at the point.
826 static nsIFrame* GetPopupFrameForEventCoordinates(
827 nsPresContext* aPresContext, const mozilla::WidgetEvent* aEvent);
830 * Get container and offset if aEvent collapses Selection.
831 * @param aPresShell The PresShell handling aEvent.
832 * @param aEvent The event having coordinates where you want to
833 * collapse Selection.
834 * @param aContainer Returns the container node at the point.
835 * Set nullptr if you don't need this.
836 * @param aOffset Returns offset in the container node at the point.
837 * Set nullptr if you don't need this.
839 MOZ_CAN_RUN_SCRIPT
840 static void GetContainerAndOffsetAtEvent(PresShell* aPresShell,
841 const mozilla::WidgetEvent* aEvent,
842 nsIContent** aContainer,
843 int32_t* aOffset);
846 * Translate from widget coordinates to the view's coordinates
847 * @param aPresContext the PresContext for the view
848 * @param aWidget the widget
849 * @param aPt the point relative to the widget
850 * @param aView view to which returned coordinates are relative
851 * @return the point in the view's coordinates
853 static nsPoint TranslateWidgetToView(nsPresContext* aPresContext,
854 nsIWidget* aWidget,
855 const mozilla::LayoutDeviceIntPoint& aPt,
856 nsView* aView);
859 * Translate from view coordinates to the widget's coordinates.
860 * @param aPresContext the PresContext for the view
861 * @param aView the view
862 * @param aPt the point relative to the view
863 * @param aViewportType whether the point is in visual or layout coordinates
864 * @param aWidget the widget to which returned coordinates are relative
865 * @return the point in the view's coordinates
867 static mozilla::LayoutDeviceIntPoint TranslateViewToWidget(
868 nsPresContext* aPresContext, nsView* aView, nsPoint aPt,
869 ViewportType aViewportType, nsIWidget* aWidget);
871 static mozilla::LayoutDeviceIntPoint WidgetToWidgetOffset(
872 nsIWidget* aFromWidget, nsIWidget* aToWidget);
874 enum class FrameForPointOption {
876 * When set, paint suppression is ignored, so we'll return non-root page
877 * elements even if paint suppression is stopping them from painting.
879 IgnorePaintSuppression = 1,
881 * When set, clipping due to the root scroll frame (and any other viewport-
882 * related clipping) is ignored.
884 IgnoreRootScrollFrame,
886 * When set, return only content in the same document as aFrame.
888 IgnoreCrossDoc,
890 * When set, return only content that is actually visible.
892 OnlyVisible,
896 * Given aFrame, the root frame of a stacking context, find its descendant
897 * frame under the point aPt that receives a mouse event at that location,
898 * or nullptr if there is no such frame.
899 * @param aPt the point, relative to the frame origin, in either visual
900 * or layout coordinates depending on aRelativeTo.mViewportType
901 * @param aFlags some combination of FrameForPointOption.
903 static nsIFrame* GetFrameForPoint(RelativeTo aRelativeTo, nsPoint aPt,
904 mozilla::EnumSet<FrameForPointOption> = {});
907 * Given aFrame, the root frame of a stacking context, find all descendant
908 * frames under the area of a rectangle that receives a mouse event,
909 * or nullptr if there is no such frame.
910 * @param aRect the rect, relative to the frame origin, in either visual
911 * or layout coordinates depending on aRelativeTo.mViewportType
912 * @param aOutFrames an array to add all the frames found
913 * @param aFlags some combination of FrameForPointOption.
915 static nsresult GetFramesForArea(RelativeTo aRelativeTo, const nsRect& aRect,
916 nsTArray<nsIFrame*>& aOutFrames,
917 mozilla::EnumSet<FrameForPointOption> = {});
920 * Transform aRect relative to aFrame up to the coordinate system of
921 * aAncestor. Computes the bounding-box of the true quadrilateral.
922 * Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if
923 * we only need to use a 2d transform that PreservesAxisAlignedRectangles().
924 * The corner positions of aRect are treated as meaningful even if aRect is
925 * empty.
927 * |aMatrixCache| allows for optimizations in recomputing the same matrix over
928 * and over. The argument can be one of the following values:
930 * nullptr (the default) - No optimization; the transform matrix is computed
931 * on every call to this function.
933 * non-null pointer to an empty Maybe<Matrix4x4> - Upon return, the Maybe is
934 * filled with the transform matrix that was computed. This can then be passed
935 * in to subsequent calls with the same source and destination frames to avoid
936 * recomputing the matrix.
938 * non-null pointer to a non-empty Matrix4x4 - The provided matrix will be
939 * used as the transform matrix and applied to the rect.
941 static nsRect TransformFrameRectToAncestor(
942 const nsIFrame* aFrame, const nsRect& aRect, const nsIFrame* aAncestor,
943 bool* aPreservesAxisAlignedRectangles = nullptr,
944 mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr,
945 bool aStopAtStackingContextAndDisplayPortAndOOFFrame = false,
946 nsIFrame** aOutAncestor = nullptr) {
947 return TransformFrameRectToAncestor(
948 aFrame, aRect, RelativeTo{aAncestor}, aPreservesAxisAlignedRectangles,
949 aMatrixCache, aStopAtStackingContextAndDisplayPortAndOOFFrame,
950 aOutAncestor);
952 static nsRect TransformFrameRectToAncestor(
953 const nsIFrame* aFrame, const nsRect& aRect, RelativeTo aAncestor,
954 bool* aPreservesAxisAlignedRectangles = nullptr,
955 mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache = nullptr,
956 bool aStopAtStackingContextAndDisplayPortAndOOFFrame = false,
957 nsIFrame** aOutAncestor = nullptr);
960 * Gets the transform for aFrame relative to aAncestor. Pass null for
961 * aAncestor to go up to the root frame. Including nsIFrame::IN_CSS_UNITS
962 * flag in aFlags will return CSS pixels, by default it returns device
963 * pixels.
964 * More info can be found in nsIFrame::GetTransformMatrix.
966 * Some notes on the possible combinations of |aFrame.mViewportType| and
967 * |aAncestor.mViewportType|:
969 * | aFrame. | aAncestor. | Notes
970 * | mViewportType | mViewportType |
971 * ==========================================================================
972 * | Layout | Layout | Commonplace, when both source and target
973 * | | | are inside zoom boundary.
974 * | | |
975 * | | | Could also happen in non-e10s setups
976 * | | | when both source and target are outside
977 * | | | the zoom boundary and the code is
978 * | | | oblivious to the existence of a zoom
979 * | | | boundary.
980 * ==========================================================================
981 * | Layout | Visual | Commonplace, used when hit testing visual
982 * | | | coordinates (e.g. coming from user input
983 * | | | events). We expected to encounter a
984 * | | | zoomed content root during traversal and
985 * | | | apply a layout-to-visual transform.
986 * ==========================================================================
987 * | Visual | Layout | Should never happen, will assert.
988 * ==========================================================================
989 * | Visual | Visual | In e10s setups, should only happen if
990 * | | | aFrame and aAncestor are both the
991 * | | | RCD viewport frame.
992 * | | |
993 * | | | In non-e10s setups, could happen with
994 * | | | different frames if they are both
995 * | | | outside the zoom boundary.
996 * ==========================================================================
998 static Matrix4x4Flagged GetTransformToAncestor(
999 RelativeTo aFrame, RelativeTo aAncestor, uint32_t aFlags = 0,
1000 nsIFrame** aOutAncestor = nullptr);
1003 * Gets the scale factors of the transform for aFrame relative to the root
1004 * frame if this transform is 2D, or the identity scale factors otherwise.
1006 static gfxSize GetTransformToAncestorScale(nsIFrame* aFrame);
1009 * Gets the scale factors of the transform for aFrame relative to the root
1010 * frame if this transform is 2D, or the identity scale factors otherwise.
1011 * If some frame on the path from aFrame to the display root frame may have an
1012 * animated scale, returns the identity scale factors.
1014 static gfxSize GetTransformToAncestorScaleExcludingAnimated(nsIFrame* aFrame);
1017 * Find the nearest common ancestor frame for aFrame1 and aFrame2. The
1018 * ancestor frame could be cross-doc.
1020 static const nsIFrame* FindNearestCommonAncestorFrame(
1021 const nsIFrame* aFrame1, const nsIFrame* aFrame2);
1024 * Find the nearest common ancestor frame for aFrame1 and aFrame2, assuming
1025 * that they are within the same block.
1027 * Returns null if they are not within the same block.
1029 static const nsIFrame* FindNearestCommonAncestorFrameWithinBlock(
1030 const nsTextFrame* aFrame1, const nsTextFrame* aFrame2);
1033 * Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into
1034 * account all relevant transformations on the frames up to (but excluding)
1035 * their nearest common ancestor.
1036 * If we encounter a transform that we need to invert but which is
1037 * non-invertible, we return NONINVERTIBLE_TRANSFORM. If the frames have
1038 * no common ancestor, we return NO_COMMON_ANCESTOR.
1039 * If this returns TRANSFORM_SUCCEEDED, the points in aPoints are transformed
1040 * in-place, otherwise they are untouched.
1042 enum TransformResult {
1043 TRANSFORM_SUCCEEDED,
1044 NO_COMMON_ANCESTOR,
1045 NONINVERTIBLE_TRANSFORM
1047 static TransformResult TransformPoints(nsIFrame* aFromFrame,
1048 nsIFrame* aToFrame,
1049 uint32_t aPointCount,
1050 CSSPoint* aPoints);
1053 * Same as above function, but transform points in app units and
1054 * handle 1 point per call.
1056 static TransformResult TransformPoint(RelativeTo aFromFrame,
1057 RelativeTo aToFrame, nsPoint& aPoint);
1060 * Transforms a rect from aFromFrame to aToFrame. In app units.
1061 * Returns the bounds of the actual rect if the transform requires rotation
1062 * or anything complex like that.
1064 static TransformResult TransformRect(const nsIFrame* aFromFrame,
1065 const nsIFrame* aToFrame, nsRect& aRect);
1068 * Converts app units to pixels (with optional snapping) and appends as a
1069 * translation to aTransform.
1071 static void PostTranslate(Matrix4x4& aTransform, const nsPoint& aOrigin,
1072 float aAppUnitsPerPixel, bool aRounded);
1075 * Whether the frame should snap to grid. This will end up being passed
1076 * as the aRounded parameter in PostTranslate above. SVG frames should
1077 * not have their translation rounded.
1079 static bool ShouldSnapToGrid(const nsIFrame* aFrame);
1082 * Get the border-box of aElement's primary frame, transformed it to be
1083 * relative to aFrame.
1085 static nsRect GetRectRelativeToFrame(mozilla::dom::Element* aElement,
1086 nsIFrame* aFrame);
1089 * Returns true if aRect with border inflation of size aInflateSize contains
1090 * aPoint.
1092 static bool ContainsPoint(const nsRect& aRect, const nsPoint& aPoint,
1093 nscoord aInflateSize);
1096 * Clamp aRect relative to aFrame to the scroll frames boundary searching from
1097 * aFrame.
1099 static nsRect ClampRectToScrollFrames(nsIFrame* aFrame, const nsRect& aRect);
1102 * Return true if a "layer transform" could be computed for aFrame,
1103 * and optionally return the computed transform. The returned
1104 * transform is what would be set on the layer currently if a layers
1105 * transaction were opened at the time this helper is called.
1107 static bool GetLayerTransformForFrame(nsIFrame* aFrame,
1108 Matrix4x4Flagged* aTransform);
1111 * Given a point in the global coordinate space, returns that point expressed
1112 * in the coordinate system of aFrame. This effectively inverts all
1113 * transforms between this point and the root frame.
1115 * @param aFromType Specifies whether |aPoint| is in layout or visual
1116 * coordinates.
1117 * @param aFrame The frame that acts as the coordinate space container.
1118 * @param aPoint The point, in global layout or visual coordinates (as per
1119 * |aFromType|, to get in the frame-local space.
1120 * @return aPoint, expressed in aFrame's canonical coordinate space.
1122 static nsPoint TransformRootPointToFrame(ViewportType aFromType,
1123 RelativeTo aFrame,
1124 const nsPoint& aPoint) {
1125 return TransformAncestorPointToFrame(aFrame, aPoint,
1126 RelativeTo{nullptr, aFromType});
1130 * Transform aPoint relative to aAncestor down to the coordinate system of
1131 * aFrame.
1133 static nsPoint TransformAncestorPointToFrame(RelativeTo aFrame,
1134 const nsPoint& aPoint,
1135 RelativeTo aAncestor);
1138 * Helper function that, given a rectangle and a matrix, returns the smallest
1139 * rectangle containing the image of the source rectangle.
1141 * @param aBounds The rectangle to transform.
1142 * @param aMatrix The matrix to transform it with.
1143 * @param aFactor The number of app units per graphics unit.
1144 * @return The smallest rect that contains the image of aBounds.
1146 static nsRect MatrixTransformRect(const nsRect& aBounds,
1147 const Matrix4x4& aMatrix, float aFactor);
1148 static nsRect MatrixTransformRect(const nsRect& aBounds,
1149 const Matrix4x4Flagged& aMatrix,
1150 float aFactor);
1153 * Helper function that, given a point and a matrix, returns the image
1154 * of that point under the matrix transform.
1156 * @param aPoint The point to transform.
1157 * @param aMatrix The matrix to transform it with.
1158 * @param aFactor The number of app units per graphics unit.
1159 * @return The image of the point under the transform.
1161 static nsPoint MatrixTransformPoint(const nsPoint& aPoint,
1162 const Matrix4x4& aMatrix, float aFactor);
1165 * Given a graphics rectangle in graphics space, return a rectangle in
1166 * app space that contains the graphics rectangle, rounding out as necessary.
1168 * @param aRect The graphics rect to round outward.
1169 * @param aFactor The number of app units per graphics unit.
1170 * @return The smallest rectangle in app space that contains aRect.
1172 template <typename T>
1173 static nsRect RoundGfxRectToAppRect(const T& aRect, const float aFactor);
1176 * Returns a subrectangle of aContainedRect that is entirely inside the
1177 * rounded rect. Complex cases are handled conservatively by returning a
1178 * smaller rect than necessary.
1180 static nsRegion RoundedRectIntersectRect(const nsRect& aRoundedRect,
1181 const nscoord aRadii[8],
1182 const nsRect& aContainedRect);
1183 static nsIntRegion RoundedRectIntersectIntRect(
1184 const nsIntRect& aRoundedRect, const RectCornerRadii& aCornerRadii,
1185 const nsIntRect& aContainedRect);
1188 * Return whether any part of aTestRect is inside of the rounded
1189 * rectangle formed by aBounds and aRadii (which are indexed by the
1190 * enum HalfCorner constants in gfx/2d/Types.h). This is precise.
1192 static bool RoundedRectIntersectsRect(const nsRect& aRoundedRect,
1193 const nscoord aRadii[8],
1194 const nsRect& aTestRect);
1196 static bool MaybeCreateDisplayPortInFirstScrollFrameEncountered(
1197 nsIFrame* aFrame, nsDisplayListBuilder* aBuilder);
1199 enum class PaintFrameFlags : uint32_t {
1200 InTransform = 0x01,
1201 SyncDecodeImages = 0x02,
1202 WidgetLayers = 0x04,
1203 IgnoreSuppression = 0x08,
1204 DocumentRelative = 0x10,
1205 HideCaret = 0x20,
1206 ToWindow = 0x40,
1207 ExistingTransaction = 0x80,
1208 NoComposite = 0x100,
1209 Compressed = 0x200,
1210 ForWebRender = 0x400,
1211 UseHighQualityScaling = 0x800,
1215 * Given aFrame, the root frame of a stacking context, paint it and its
1216 * descendants to aRenderingContext.
1217 * @param aRenderingContext a rendering context translated so that (0,0)
1218 * is the origin of aFrame; for best results, (0,0) should transform
1219 * to pixel-aligned coordinates. This can be null, in which case
1220 * aFrame must be a "display root" (root frame for a root document,
1221 * or the root of a popup) with an associated widget and we draw using
1222 * the layer manager for the frame's widget.
1223 * @param aDirtyRegion the region that must be painted, in the coordinates
1224 * of aFrame.
1225 * @param aBackstop paint the dirty area with this color before drawing
1226 * the actual content; pass NS_RGBA(0,0,0,0) to draw no background.
1227 * @param aBuilderMode Passed through to the display-list builder.
1228 * @param aFlags if PAINT_IN_TRANSFORM is set, then we assume
1229 * this is inside a transform or SVG foreignObject. If
1230 * PAINT_SYNC_DECODE_IMAGES is set, we force synchronous decode on all
1231 * images. If PAINT_WIDGET_LAYERS is set, aFrame must be a display root,
1232 * and we will use the frame's widget's layer manager to paint
1233 * even if aRenderingContext is non-null. This is useful if you want
1234 * to force rendering to use the widget's layer manager for testing
1235 * or speed. PAINT_WIDGET_LAYERS must be set if aRenderingContext is null.
1236 * If PAINT_DOCUMENT_RELATIVE is used, the visible region is interpreted
1237 * as being relative to the document (normally it's relative to the CSS
1238 * viewport) and the document is painted as if no scrolling has occured.
1239 * Only considered if PresShell::IgnoringViewportScrolling is true.
1240 * PAINT_TO_WINDOW sets painting to window to true on the display list
1241 * builder even if we can't tell that we are painting to the window.
1242 * If PAINT_EXISTING_TRANSACTION is set, then BeginTransaction() has already
1243 * been called on aFrame's widget's layer manager and should not be
1244 * called again.
1245 * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to
1246 * compressed mode to avoid short cut optimizations.
1248 * So there are three possible behaviours:
1249 * 1) PAINT_WIDGET_LAYERS is set and aRenderingContext is null; we paint
1250 * by calling BeginTransaction on the widget's layer manager.
1251 * 2) PAINT_WIDGET_LAYERS is set and aRenderingContext is non-null; we
1252 * paint by calling BeginTransactionWithTarget on the widget's layer
1253 * manager.
1254 * 3) PAINT_WIDGET_LAYERS is not set and aRenderingContext is non-null;
1255 * we paint by construct a BasicLayerManager and calling
1256 * BeginTransactionWithTarget on it. This is desirable if we're doing
1257 * something like drawWindow in a mode where what gets rendered doesn't
1258 * necessarily correspond to what's visible in the window; we don't
1259 * want to mess up the widget's layer tree.
1261 static nsresult PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
1262 const nsRegion& aDirtyRegion, nscolor aBackstop,
1263 nsDisplayListBuilderMode aBuilderMode,
1264 PaintFrameFlags aFlags = PaintFrameFlags(0));
1267 * Uses a binary search for find where the cursor falls in the line of text
1268 * It also keeps track of the part of the string that has already been
1269 * measured so it doesn't have to keep measuring the same text over and over.
1271 * @param "aBaseWidth" contains the width in twips of the portion
1272 * of the text that has already been measured, and aBaseInx contains
1273 * the index of the text that has already been measured.
1275 * @param aTextWidth returns (in twips) the length of the text that falls
1276 * before the cursor aIndex contains the index of the text where the cursor
1277 * falls.
1279 static bool BinarySearchForPosition(DrawTarget* aDrawTarget,
1280 nsFontMetrics& aFontMetrics,
1281 const char16_t* aText, int32_t aBaseWidth,
1282 int32_t aBaseInx, int32_t aStartInx,
1283 int32_t aEndInx, int32_t aCursorPos,
1284 int32_t& aIndex, int32_t& aTextWidth);
1286 class BoxCallback {
1287 public:
1288 BoxCallback() : mIncludeCaptionBoxForTable(true) {}
1289 virtual void AddBox(nsIFrame* aFrame) = 0;
1290 bool mIncludeCaptionBoxForTable;
1293 * Collect all CSS boxes associated with aFrame and its
1294 * continuations, "drilling down" through table wrapper frames and
1295 * some anonymous blocks since they're not real CSS boxes.
1296 * If aFrame is null, no boxes are returned.
1297 * SVG frames return a single box, themselves.
1299 static void GetAllInFlowBoxes(nsIFrame* aFrame, BoxCallback* aCallback);
1302 * Like GetAllInFlowBoxes, but doesn't include continuations.
1304 static void AddBoxesForFrame(nsIFrame* aFrame, BoxCallback* aCallback);
1307 * Find the first frame descendant of aFrame (including aFrame) which is
1308 * not an anonymous frame that getBoxQuads/getClientRects should ignore.
1310 static nsIFrame* GetFirstNonAnonymousFrame(nsIFrame* aFrame);
1312 class RectCallback {
1313 public:
1314 virtual void AddRect(const nsRect& aRect) = 0;
1317 struct RectAccumulator : public RectCallback {
1318 nsRect mResultRect;
1319 nsRect mFirstRect;
1320 bool mSeenFirstRect;
1322 RectAccumulator();
1324 virtual void AddRect(const nsRect& aRect) override;
1327 struct RectListBuilder : public RectCallback {
1328 DOMRectList* mRectList;
1330 explicit RectListBuilder(DOMRectList* aList);
1331 virtual void AddRect(const nsRect& aRect) override;
1334 static nsIFrame* GetContainingBlockForClientRect(nsIFrame* aFrame);
1336 enum {
1337 RECTS_ACCOUNT_FOR_TRANSFORMS = 0x01,
1338 // Two bits for specifying which box type to use.
1339 // With neither bit set (default), use the border box.
1340 RECTS_USE_CONTENT_BOX = 0x02,
1341 RECTS_USE_PADDING_BOX = 0x04,
1342 RECTS_USE_MARGIN_BOX = 0x06, // both bits set
1343 RECTS_WHICH_BOX_MASK = 0x06 // bitmask for these two bits
1346 * Collect all CSS boxes (content, padding, border, or margin) associated
1347 * with aFrame and its continuations, "drilling down" through table wrapper
1348 * frames and some anonymous blocks since they're not real CSS boxes.
1349 * The boxes are positioned relative to aRelativeTo (taking scrolling
1350 * into account) and passed to the callback in frame-tree order.
1351 * If aFrame is null, no boxes are returned.
1352 * For SVG frames, returns one rectangle, the bounding box.
1353 * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting
1354 * the boxes into aRelativeTo coordinates, transforms (including CSS
1355 * and SVG transforms) are taken into account.
1356 * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX,
1357 * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used.
1358 * Otherwise (by default), the border box is used.
1360 static void GetAllInFlowRects(nsIFrame* aFrame, const nsIFrame* aRelativeTo,
1361 RectCallback* aCallback, uint32_t aFlags = 0);
1363 static void GetAllInFlowRectsAndTexts(
1364 nsIFrame* aFrame, const nsIFrame* aRelativeTo, RectCallback* aCallback,
1365 mozilla::dom::Sequence<nsString>* aTextList, uint32_t aFlags = 0);
1368 * Computes the union of all rects returned by GetAllInFlowRects. If
1369 * the union is empty, returns the first rect.
1370 * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting
1371 * the boxes into aRelativeTo coordinates, transforms (including CSS
1372 * and SVG transforms) are taken into account.
1373 * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX,
1374 * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used.
1375 * Otherwise (by default), the border box is used.
1377 static nsRect GetAllInFlowRectsUnion(nsIFrame* aFrame,
1378 const nsIFrame* aRelativeTo,
1379 uint32_t aFlags = 0);
1381 enum { EXCLUDE_BLUR_SHADOWS = 0x01 };
1383 * Takes a text-shadow array from the style properties of a given nsIFrame and
1384 * computes the union of those shadows along with the given initial rect.
1385 * If there are no shadows, the initial rect is returned.
1387 static nsRect GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect,
1388 nsIFrame* aFrame, uint32_t aFlags = 0);
1391 * Computes the destination rect that a given replaced element should render
1392 * into, based on its CSS 'object-fit' and 'object-position' properties.
1394 * @param aConstraintRect The constraint rect that we have at our disposal,
1395 * which would e.g. be exactly filled by the image
1396 * if we had "object-fit: fill".
1397 * @param aIntrinsicSize The replaced content's intrinsic size, as reported
1398 * by nsIFrame::GetIntrinsicSize().
1399 * @param aIntrinsicRatio The replaced content's intrinsic ratio, as reported
1400 * by nsIFrame::GetIntrinsicRatio().
1401 * @param aStylePos The nsStylePosition struct that contains the 'object-fit'
1402 * and 'object-position' values that we should rely on.
1403 * (This should usually be the nsStylePosition for the
1404 * replaced element in question, but not always. For
1405 * example, a <video>'s poster-image has a dedicated
1406 * anonymous element & child-frame, but we should still use
1407 * the <video>'s 'object-fit' and 'object-position' values.)
1408 * @param aAnchorPoint [out] A point that should be pixel-aligned by functions
1409 * like nsLayoutUtils::DrawImage. See documentation
1410 * in nsCSSRendering.h for ComputeObjectAnchorPoint.
1411 * @return The nsRect into which we should render the replaced content (using
1412 * the same coordinate space as the passed-in aConstraintRect).
1414 static nsRect ComputeObjectDestRect(const nsRect& aConstraintRect,
1415 const IntrinsicSize& aIntrinsicSize,
1416 const AspectRatio& aIntrinsicRatio,
1417 const nsStylePosition* aStylePos,
1418 nsPoint* aAnchorPoint = nullptr);
1421 * Get the font metrics corresponding to the frame's style data.
1422 * @param aFrame the frame
1423 * @param aSizeInflation number to multiply font size by
1425 static already_AddRefed<nsFontMetrics> GetFontMetricsForFrame(
1426 const nsIFrame* aFrame, float aSizeInflation);
1428 static already_AddRefed<nsFontMetrics> GetInflatedFontMetricsForFrame(
1429 const nsIFrame* aFrame) {
1430 return GetFontMetricsForFrame(aFrame, FontSizeInflationFor(aFrame));
1434 * Get the font metrics corresponding to the given style data.
1435 * @param aComputedStyle the style data
1436 * @param aSizeInflation number to multiply font size by
1438 static already_AddRefed<nsFontMetrics> GetFontMetricsForComputedStyle(
1439 ComputedStyle* aComputedStyle, nsPresContext* aPresContext,
1440 float aSizeInflation = 1.0f,
1441 uint8_t aVariantWidth = NS_FONT_VARIANT_WIDTH_NORMAL);
1444 * Get the font metrics of emphasis marks corresponding to the given
1445 * style data. The result is same as GetFontMetricsForComputedStyle
1446 * except that the font size is scaled down to 50%.
1447 * @param aComputedStyle the style data
1448 * @param aInflation number to multiple font size by
1450 static already_AddRefed<nsFontMetrics> GetFontMetricsOfEmphasisMarks(
1451 ComputedStyle* aComputedStyle, nsPresContext* aPresContext,
1452 float aInflation) {
1453 return GetFontMetricsForComputedStyle(aComputedStyle, aPresContext,
1454 aInflation * 0.5f);
1458 * Find the immediate child of aParent whose frame subtree contains
1459 * aDescendantFrame. Returns null if aDescendantFrame is not a descendant
1460 * of aParent.
1462 static nsIFrame* FindChildContainingDescendant(nsIFrame* aParent,
1463 nsIFrame* aDescendantFrame);
1466 * Find the nearest ancestor that's a block
1468 static nsBlockFrame* FindNearestBlockAncestor(nsIFrame* aFrame);
1471 * Find the nearest ancestor that's not for generated content. Will return
1472 * aFrame if aFrame is not for generated content.
1474 static nsIFrame* GetNonGeneratedAncestor(nsIFrame* aFrame);
1477 * Whether the frame is an nsBlockFrame which is not a wrapper block.
1479 static bool IsNonWrapperBlock(nsIFrame* aFrame);
1482 * If aFrame is an out of flow frame, return its placeholder, otherwise
1483 * return its parent.
1485 static nsIFrame* GetParentOrPlaceholderFor(const nsIFrame* aFrame);
1488 * If aFrame is an out of flow frame, return its placeholder, otherwise
1489 * return its (possibly cross-doc) parent.
1491 static nsIFrame* GetParentOrPlaceholderForCrossDoc(nsIFrame* aFrame);
1494 * Returns the frame that would act as the parent of aFrame when
1495 * descending through the frame tree in display list building.
1496 * Usually the same as GetParentOrPlaceholderForCrossDoc, except
1497 * that pushed floats are treated as children of their containing
1498 * block.
1500 static nsIFrame* GetDisplayListParent(nsIFrame* aFrame);
1503 * Get a frame's previous continuation, or, if it doesn't have one, its
1504 * previous block-in-inline-split sibling.
1506 static nsIFrame* GetPrevContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1509 * Get a frame's next continuation, or, if it doesn't have one, its
1510 * block-in-inline-split sibling.
1512 static nsIFrame* GetNextContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1515 * Get the first frame in the continuation-plus-ib-split-sibling chain
1516 * containing aFrame.
1518 static nsIFrame* FirstContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1521 * Get the last frame in the continuation-plus-ib-split-sibling chain
1522 * containing aFrame.
1524 static nsIFrame* LastContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1527 * Is FirstContinuationOrIBSplitSibling(aFrame) going to return
1528 * aFrame?
1530 static bool IsFirstContinuationOrIBSplitSibling(const nsIFrame* aFrame);
1533 * Check whether aFrame is a part of the scrollbar or scrollcorner of
1534 * the root content.
1535 * @param aFrame the checking frame.
1536 * @return true if the frame is a part of the scrollbar or scrollcorner of
1537 * the root content.
1539 static bool IsViewportScrollbarFrame(nsIFrame* aFrame);
1542 * Get the contribution of aFrame to its containing block's intrinsic
1543 * size for the given physical axis. This considers the child's intrinsic
1544 * width, its 'width', 'min-width', and 'max-width' properties (or 'height'
1545 * variations if that's what matches aAxis) and its padding, border and margin
1546 * in the corresponding dimension.
1547 * @param aPercentageBasis an optional percentage basis (in aFrame's WM).
1548 * If the basis is indefinite in a given axis, pass a size with
1549 * NS_UNCONSTRAINEDSIZE in that component.
1550 * If you pass Nothing() a percentage basis will be calculated from aFrame's
1551 * ancestors' computed size in the relevant axis, if needed.
1552 * @param aMarginBoxMinSizeClamp make the result fit within this margin-box
1553 * size by reducing the *content size* (flooring at zero). This is used for:
1554 * https://drafts.csswg.org/css-grid/#min-size-auto
1556 enum class IntrinsicISizeType { MinISize, PrefISize };
1557 static const auto MIN_ISIZE = IntrinsicISizeType::MinISize;
1558 static const auto PREF_ISIZE = IntrinsicISizeType::PrefISize;
1559 enum {
1560 IGNORE_PADDING = 0x01,
1561 BAIL_IF_REFLOW_NEEDED = 0x02, // returns NS_INTRINSIC_ISIZE_UNKNOWN if so
1562 MIN_INTRINSIC_ISIZE = 0x04, // use min-width/height instead of width/height
1564 static nscoord IntrinsicForAxis(
1565 mozilla::PhysicalAxis aAxis, gfxContext* aRenderingContext,
1566 nsIFrame* aFrame, IntrinsicISizeType aType,
1567 const mozilla::Maybe<LogicalSize>& aPercentageBasis = mozilla::Nothing(),
1568 uint32_t aFlags = 0, nscoord aMarginBoxMinSizeClamp = NS_MAXSIZE);
1570 * Calls IntrinsicForAxis with aFrame's parent's inline physical axis.
1572 static nscoord IntrinsicForContainer(gfxContext* aRenderingContext,
1573 nsIFrame* aFrame,
1574 IntrinsicISizeType aType,
1575 uint32_t aFlags = 0);
1578 * Get the definite size contribution of aFrame for the given physical axis.
1579 * This considers the child's 'min-width' property (or 'min-height' if the
1580 * given axis is vertical), and its padding, border, and margin in the
1581 * corresponding dimension. If the 'min-' property is 'auto' (and 'overflow'
1582 * is 'visible') and the corresponding 'width'/'height' is definite it returns
1583 * the "specified size" for:
1584 * https://drafts.csswg.org/css-grid/#min-size-auto
1585 * Note that the "transferred size" is not handled here; use IntrinsicForAxis.
1586 * Note that any percentage in 'width'/'height' makes it count as indefinite.
1587 * If the 'min-' property is 'auto' and 'overflow' is not 'visible', then it
1588 * calculates the result as if the 'min-' computed value is zero.
1589 * Otherwise, return NS_UNCONSTRAINEDSIZE.
1591 * @param aPercentageBasis the percentage basis (in aFrame's WM).
1592 * Pass NS_UNCONSTRAINEDSIZE if the basis is indefinite in either/both axes.
1593 * @note this behavior is specific to Grid/Flexbox (currently) so aFrame
1594 * should be a grid/flex item.
1596 static nscoord MinSizeContributionForAxis(mozilla::PhysicalAxis aAxis,
1597 gfxContext* aRC, nsIFrame* aFrame,
1598 IntrinsicISizeType aType,
1599 const LogicalSize& aPercentageBasis,
1600 uint32_t aFlags = 0);
1603 * Convert LengthPercentage to nscoord when percentages depend on the
1604 * containing block size.
1605 * @param aPercentBasis The width or height of the containing block
1606 * (whichever the client wants to use for resolving percentages).
1608 static nscoord ComputeCBDependentValue(nscoord aPercentBasis,
1609 const LengthPercentage& aCoord) {
1610 NS_WARNING_ASSERTION(
1611 aPercentBasis != NS_UNCONSTRAINEDSIZE,
1612 "have unconstrained width or height; this should only result from very "
1613 "large sizes, not attempts at intrinsic size calculation");
1614 return aCoord.Resolve(aPercentBasis);
1616 static nscoord ComputeCBDependentValue(nscoord aPercentBasis,
1617 const LengthPercentageOrAuto& aCoord) {
1618 if (aCoord.IsAuto()) {
1619 return 0;
1621 return ComputeCBDependentValue(aPercentBasis, aCoord.AsLengthPercentage());
1624 static nscoord ComputeBSizeDependentValue(nscoord aContainingBlockBSize,
1625 const LengthPercentageOrAuto&);
1627 static nscoord ComputeBSizeValue(nscoord aContainingBlockBSize,
1628 nscoord aContentEdgeToBoxSizingBoxEdge,
1629 const LengthPercentage& aCoord) {
1630 MOZ_ASSERT(aContainingBlockBSize != nscoord_MAX || !aCoord.HasPercent(),
1631 "caller must deal with %% of unconstrained block-size");
1633 nscoord result = aCoord.Resolve(aContainingBlockBSize);
1634 // Clamp calc(), and the subtraction for box-sizing.
1635 return std::max(0, result - aContentEdgeToBoxSizingBoxEdge);
1639 * The "extremum length" values (see ExtremumLength) were originally aimed at
1640 * inline-size (or width, as it was before logicalization). For now, we return
1641 * true for those here, so that we don't call ComputeBSizeValue with value
1642 * types that it doesn't understand. (See bug 1113216.)
1644 * FIXME (bug 567039, bug 527285)
1645 * This isn't correct for the 'fill' value or for the 'min-*' or 'max-*'
1646 * properties, which need to be handled differently by the callers of
1647 * IsAutoBSize().
1649 template <typename SizeOrMaxSize>
1650 static bool IsAutoBSize(const SizeOrMaxSize& aCoord, nscoord aCBBSize) {
1651 return aCoord.BehavesLikeInitialValueOnBlockAxis() ||
1652 (aCBBSize == nscoord_MAX && aCoord.HasPercent());
1655 static bool IsPaddingZero(const LengthPercentage& aLength) {
1656 // clamp negative calc() to 0
1657 return aLength.Resolve(nscoord_MAX) <= 0 && aLength.Resolve(0) <= 0;
1660 static bool IsMarginZero(const LengthPercentage& aLength) {
1661 return aLength.Resolve(nscoord_MAX) == 0 && aLength.Resolve(0) == 0;
1664 static void MarkDescendantsDirty(nsIFrame* aSubtreeRoot);
1666 static void MarkIntrinsicISizesDirtyIfDependentOnBSize(nsIFrame* aFrame);
1669 * Calculate the used values for 'width' and 'height' when width
1670 * and height are 'auto'. The tentWidth and tentHeight arguments should be
1671 * the result of applying the rules for computing intrinsic sizes and ratios.
1672 * as specified by CSS 2.1 sections 10.3.2 and 10.6.2
1674 static nsSize ComputeAutoSizeWithIntrinsicDimensions(
1675 nscoord minWidth, nscoord minHeight, nscoord maxWidth, nscoord maxHeight,
1676 nscoord tentWidth, nscoord tentHeight);
1678 // Implement nsIFrame::GetPrefISize in terms of nsIFrame::AddInlinePrefISize
1679 static nscoord PrefISizeFromInline(nsIFrame* aFrame,
1680 gfxContext* aRenderingContext);
1682 // Implement nsIFrame::GetMinISize in terms of nsIFrame::AddInlineMinISize
1683 static nscoord MinISizeFromInline(nsIFrame* aFrame,
1684 gfxContext* aRenderingContext);
1686 // Get a suitable foreground color for painting aColor for aFrame.
1687 static nscolor DarkenColorIfNeeded(nsIFrame* aFrame, nscolor aColor);
1689 // Get a suitable foreground color for painting aField for aFrame.
1690 // Type of aFrame is made a template parameter because nsIFrame is not
1691 // a complete type in the header. Type-safety is not harmed given that
1692 // DarkenColorIfNeeded requires an nsIFrame pointer.
1693 template <typename Frame, typename T, typename S>
1694 static nscolor GetColor(Frame* aFrame, T S::*aField) {
1695 nscolor color = aFrame->GetVisitedDependentColor(aField);
1696 return DarkenColorIfNeeded(aFrame, color);
1699 // Get a baseline y position in app units that is snapped to device pixels.
1700 static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
1701 nscoord aY, nscoord aAscent);
1702 // Ditto for an x position (for vertical text). Note that for vertical-rl
1703 // writing mode, the ascent value should be negated by the caller.
1704 static gfxFloat GetSnappedBaselineX(nsIFrame* aFrame, gfxContext* aContext,
1705 nscoord aX, nscoord aAscent);
1707 static nscoord AppUnitWidthOfString(char16_t aC, nsFontMetrics& aFontMetrics,
1708 DrawTarget* aDrawTarget) {
1709 return AppUnitWidthOfString(&aC, 1, aFontMetrics, aDrawTarget);
1711 static nscoord AppUnitWidthOfString(const nsString& aString,
1712 nsFontMetrics& aFontMetrics,
1713 DrawTarget* aDrawTarget) {
1714 return nsLayoutUtils::AppUnitWidthOfString(aString.get(), aString.Length(),
1715 aFontMetrics, aDrawTarget);
1717 static nscoord AppUnitWidthOfString(const char16_t* aString, uint32_t aLength,
1718 nsFontMetrics& aFontMetrics,
1719 DrawTarget* aDrawTarget);
1720 static nscoord AppUnitWidthOfStringBidi(const nsString& aString,
1721 const nsIFrame* aFrame,
1722 nsFontMetrics& aFontMetrics,
1723 gfxContext& aContext) {
1724 return nsLayoutUtils::AppUnitWidthOfStringBidi(
1725 aString.get(), aString.Length(), aFrame, aFontMetrics, aContext);
1727 static nscoord AppUnitWidthOfStringBidi(const char16_t* aString,
1728 uint32_t aLength,
1729 const nsIFrame* aFrame,
1730 nsFontMetrics& aFontMetrics,
1731 gfxContext& aContext);
1733 static bool StringWidthIsGreaterThan(const nsString& aString,
1734 nsFontMetrics& aFontMetrics,
1735 DrawTarget* aDrawTarget, nscoord aWidth);
1737 static nsBoundingMetrics AppUnitBoundsOfString(const char16_t* aString,
1738 uint32_t aLength,
1739 nsFontMetrics& aFontMetrics,
1740 DrawTarget* aDrawTarget);
1742 static void DrawString(const nsIFrame* aFrame, nsFontMetrics& aFontMetrics,
1743 gfxContext* aContext, const char16_t* aString,
1744 int32_t aLength, nsPoint aPoint,
1745 ComputedStyle* aComputedStyle = nullptr,
1746 DrawStringFlags aFlags = DrawStringFlags::Default);
1748 static nsPoint GetBackgroundFirstTilePos(const nsPoint& aDest,
1749 const nsPoint& aFill,
1750 const nsSize& aRepeatSize);
1753 * Supports only LTR or RTL. Bidi (mixed direction) is not supported.
1755 static void DrawUniDirString(const char16_t* aString, uint32_t aLength,
1756 const nsPoint& aPoint,
1757 nsFontMetrics& aFontMetrics,
1758 gfxContext& aContext);
1761 * Helper function for drawing text-shadow. The callback's job
1762 * is to draw whatever needs to be blurred onto the given context.
1764 typedef void (*TextShadowCallback)(gfxContext* aCtx, nsPoint aShadowOffset,
1765 const nscolor& aShadowColor, void* aData);
1767 static void PaintTextShadow(const nsIFrame* aFrame, gfxContext* aContext,
1768 const nsRect& aTextRect, const nsRect& aDirtyRect,
1769 const nscolor& aForegroundColor,
1770 TextShadowCallback aCallback,
1771 void* aCallbackData);
1774 * Gets the baseline to vertically center text from a font within a
1775 * line of specified height.
1776 * aIsInverted: true if the text is inverted relative to the block
1777 * direction, so that the block-dir "ascent" corresponds to font
1778 * descent. (Applies to sideways text in vertical-lr mode.)
1780 * Returns the baseline position relative to the top of the line.
1782 static nscoord GetCenteredFontBaseline(nsFontMetrics* aFontMetrics,
1783 nscoord aLineHeight, bool aIsInverted);
1786 * Derive a baseline of |aFrame| (measured from its top border edge)
1787 * from its first in-flow line box (not descending into anything with
1788 * 'overflow' not 'visible', potentially including aFrame itself).
1790 * Returns true if a baseline was found (and fills in aResult).
1791 * Otherwise returns false.
1793 static bool GetFirstLineBaseline(mozilla::WritingMode aWritingMode,
1794 const nsIFrame* aFrame, nscoord* aResult);
1797 * Just like GetFirstLineBaseline, except also returns the top and
1798 * bottom of the line with the baseline.
1800 * Returns true if a line was found (and fills in aResult).
1801 * Otherwise returns false.
1803 struct LinePosition {
1804 nscoord mBStart, mBaseline, mBEnd;
1806 LinePosition operator+(nscoord aOffset) const {
1807 LinePosition result;
1808 result.mBStart = mBStart + aOffset;
1809 result.mBaseline = mBaseline + aOffset;
1810 result.mBEnd = mBEnd + aOffset;
1811 return result;
1814 static bool GetFirstLinePosition(mozilla::WritingMode aWritingMode,
1815 const nsIFrame* aFrame,
1816 LinePosition* aResult);
1819 * Derive a baseline of |aFrame| (measured from its top border edge)
1820 * from its last in-flow line box (not descending into anything with
1821 * 'overflow' not 'visible', potentially including aFrame itself).
1823 * Returns true if a baseline was found (and fills in aResult).
1824 * Otherwise returns false.
1826 static bool GetLastLineBaseline(mozilla::WritingMode aWritingMode,
1827 const nsIFrame* aFrame, nscoord* aResult);
1830 * Returns a block-dir coordinate relative to this frame's origin that
1831 * represents the logical block-end of the frame or its visible content,
1832 * whichever is further from the origin.
1833 * Relative positioning is ignored and margins and glyph bounds are not
1834 * considered.
1835 * This value will be >= mRect.BSize() and <= overflowRect.BEnd() unless
1836 * relative positioning is applied.
1838 static nscoord CalculateContentBEnd(mozilla::WritingMode aWritingMode,
1839 nsIFrame* aFrame);
1842 * Gets the closest frame (the frame passed in or one of its parents) that
1843 * qualifies as a "layer"; used in DOM0 methods that depends upon that
1844 * definition. This is the nearest frame that is either positioned or scrolled
1845 * (the child of a scroll frame).
1847 static nsIFrame* GetClosestLayer(nsIFrame* aFrame);
1850 * Gets the graphics sampling filter for the frame
1852 static SamplingFilter GetSamplingFilterForFrame(nsIFrame* aFrame);
1854 static inline void InitDashPattern(StrokeOptions& aStrokeOptions,
1855 mozilla::StyleBorderStyle aBorderStyle) {
1856 if (aBorderStyle == mozilla::StyleBorderStyle::Dotted) {
1857 static Float dot[] = {1.f, 1.f};
1858 aStrokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dot);
1859 aStrokeOptions.mDashPattern = dot;
1860 } else if (aBorderStyle == mozilla::StyleBorderStyle::Dashed) {
1861 static Float dash[] = {5.f, 5.f};
1862 aStrokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dash);
1863 aStrokeOptions.mDashPattern = dash;
1864 } else {
1865 aStrokeOptions.mDashLength = 0;
1866 aStrokeOptions.mDashPattern = nullptr;
1871 * Convert an nsRect to a gfxRect.
1873 static gfxRect RectToGfxRect(const nsRect& aRect,
1874 int32_t aAppUnitsPerDevPixel);
1876 static gfxPoint PointToGfxPoint(const nsPoint& aPoint,
1877 int32_t aAppUnitsPerPixel) {
1878 return gfxPoint(gfxFloat(aPoint.x) / aAppUnitsPerPixel,
1879 gfxFloat(aPoint.y) / aAppUnitsPerPixel);
1882 /* N.B. The only difference between variants of the Draw*Image
1883 * functions below is the type of the aImage argument.
1887 * Draw a background image. The image's dimensions are as specified in aDest;
1888 * the image itself is not consulted to determine a size.
1889 * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering
1891 * @param aContext
1892 * The context to draw to, already set up with an appropriate scale and
1893 * transform for drawing in app units.
1894 * @param aForFrame
1895 * The nsIFrame that we're drawing this image for.
1896 * @param aImage
1897 * The image.
1898 * @param aDest
1899 * The position and scaled area where one copy of the image should be drawn.
1900 * This area represents the image itself in its correct position as defined
1901 * with the background-position css property.
1902 * @param aFill
1903 * The area to be filled with copies of the image.
1904 * @param aRepeatSize
1905 * The distance between the positions of two subsequent repeats of the image.
1906 * Sizes larger than aDest.Size() create gaps between the images.
1907 * @param aAnchor
1908 * A point in aFill which we will ensure is pixel-aligned in the output.
1909 * @param aDirty
1910 * Pixels outside this area may be skipped.
1911 * @param aImageFlags
1912 * Image flags of the imgIContainer::FLAG_* variety.
1913 * @param aExtendMode
1914 * How to extend the image over the dest rect.
1916 static ImgDrawResult DrawBackgroundImage(
1917 gfxContext& aContext, nsIFrame* aForFrame, nsPresContext* aPresContext,
1918 imgIContainer* aImage, SamplingFilter aSamplingFilter,
1919 const nsRect& aDest, const nsRect& aFill, const nsSize& aRepeatSize,
1920 const nsPoint& aAnchor, const nsRect& aDirty, uint32_t aImageFlags,
1921 ExtendMode aExtendMode, float aOpacity);
1924 * Draw an image.
1925 * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering
1926 * @param aRenderingContext Where to draw the image, set up with an
1927 * appropriate scale and transform for drawing in
1928 * app units.
1929 * @param aComputedStyle The ComputedStyle of the nsIFrame (or
1930 * pseudo-element) for which this image is being
1931 * drawn.
1932 * @param aImage The image.
1933 * @param aDest Where one copy of the image should mapped to.
1934 * @param aFill The area to be filled with copies of the
1935 * image.
1936 * @param aAnchor A point in aFill which we will ensure is
1937 * pixel-aligned in the output.
1938 * @param aDirty Pixels outside this area may be skipped.
1939 * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety
1941 static ImgDrawResult DrawImage(gfxContext& aContext,
1942 ComputedStyle* aComputedStyle,
1943 nsPresContext* aPresContext,
1944 imgIContainer* aImage,
1945 const SamplingFilter aSamplingFilter,
1946 const nsRect& aDest, const nsRect& aFill,
1947 const nsPoint& aAnchor, const nsRect& aDirty,
1948 uint32_t aImageFlags, float aOpacity = 1.0);
1951 * Draw a whole image without scaling or tiling.
1953 * @param aRenderingContext Where to draw the image, set up with an
1954 * appropriate scale and transform for drawing in
1955 * app units.
1956 * @param aImage The image.
1957 * @param aDest The top-left where the image should be drawn.
1958 * @param aDirty If non-null, then pixels outside this area may
1959 * be skipped.
1960 * @param aSVGContext Optionally provides an SVGImageContext.
1961 * Callers should pass an SVGImageContext with at
1962 * least the viewport size set if aImage may be of
1963 * type imgIContainer::TYPE_VECTOR, or pass
1964 * Nothing() if it is of type
1965 * imgIContainer::TYPE_RASTER (to save cycles
1966 * constructing an SVGImageContext, since this
1967 * argument will be ignored for raster images).
1968 * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety
1969 * @param aSourceArea If non-null, this area is extracted from
1970 * the image and drawn at aDest. It's
1971 * in appunits. For best results it should
1972 * be aligned with image pixels.
1974 static ImgDrawResult DrawSingleUnscaledImage(
1975 gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage,
1976 const SamplingFilter aSamplingFilter, const nsPoint& aDest,
1977 const nsRect* aDirty, const mozilla::Maybe<SVGImageContext>& aSVGContext,
1978 uint32_t aImageFlags, const nsRect* aSourceArea = nullptr);
1981 * Draw a whole image without tiling.
1983 * @param aRenderingContext Where to draw the image, set up with an
1984 * appropriate scale and transform for drawing in
1985 * app units.
1986 * @param aImage The image.
1987 * @param aDest The area that the image should fill.
1988 * @param aDirty Pixels outside this area may be skipped.
1989 * @param aSVGContext Optionally provides an SVGImageContext.
1990 * Callers should pass an SVGImageContext with at
1991 * least the viewport size set if aImage may be of
1992 * type imgIContainer::TYPE_VECTOR, or pass
1993 * Nothing() if it is of type
1994 * imgIContainer::TYPE_RASTER (to save cycles
1995 * constructing an SVGImageContext, since this
1996 * argument will be ignored for raster images).
1997 * @param aImageFlags Image flags of the imgIContainer::FLAG_*
1998 * variety.
1999 * @param aAnchor If non-null, a point which we will ensure
2000 * is pixel-aligned in the output.
2001 * @param aSourceArea If non-null, this area is extracted from
2002 * the image and drawn in aDest. It's
2003 * in appunits. For best results it should
2004 * be aligned with image pixels.
2006 static ImgDrawResult DrawSingleImage(
2007 gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage,
2008 const SamplingFilter aSamplingFilter, const nsRect& aDest,
2009 const nsRect& aDirty, const mozilla::Maybe<SVGImageContext>& aSVGContext,
2010 uint32_t aImageFlags, const nsPoint* aAnchorPoint = nullptr,
2011 const nsRect* aSourceArea = nullptr);
2014 * Given an imgIContainer, this method attempts to obtain an intrinsic
2015 * px-valued height & width for it. If the imgIContainer has a non-pixel
2016 * value for either height or width, this method tries to generate a pixel
2017 * value for that dimension using the intrinsic ratio (if available). The
2018 * intrinsic ratio will be assigned to aIntrinsicRatio; if there's no
2019 * intrinsic ratio then (0, 0) will be assigned.
2021 * This method will always set aGotWidth and aGotHeight to indicate whether
2022 * we were able to successfully obtain (or compute) a value for each
2023 * dimension.
2025 * NOTE: This method is similar to ComputeSizeWithIntrinsicDimensions. The
2026 * difference is that this one is simpler and is suited to places where we
2027 * have less information about the frame tree.
2029 static void ComputeSizeForDrawing(imgIContainer* aImage,
2030 CSSIntSize& aImageSize,
2031 AspectRatio& aIntrinsicRatio,
2032 bool& aGotWidth, bool& aGotHeight);
2035 * Given an imgIContainer, this method attempts to obtain an intrinsic
2036 * px-valued height & width for it. If the imgIContainer has a non-pixel
2037 * value for either height or width, this method tries to generate a pixel
2038 * value for that dimension using the intrinsic ratio (if available). If,
2039 * after trying all these methods, no value is available for one or both
2040 * dimensions, the corresponding dimension of aFallbackSize is used instead.
2042 static CSSIntSize ComputeSizeForDrawingWithFallback(
2043 imgIContainer* aImage, const nsSize& aFallbackSize);
2046 * Given the image container, frame, and dest rect, determine the best fitting
2047 * size to decode the image at, and calculate any necessary SVG parameters.
2049 static mozilla::gfx::IntSize ComputeImageContainerDrawingParameters(
2050 imgIContainer* aImage, nsIFrame* aForFrame,
2051 const LayoutDeviceRect& aDestRect, const StackingContextHelper& aSc,
2052 uint32_t aFlags, mozilla::Maybe<SVGImageContext>& aSVGContext);
2055 * Given a source area of an image (in appunits) and a destination area
2056 * that we want to map that source area too, computes the area that
2057 * would be covered by the whole image. This is useful for passing to
2058 * the aDest parameter of DrawImage, when we want to draw a subimage
2059 * of an overall image.
2061 static nsRect GetWholeImageDestination(const nsSize& aWholeImageSize,
2062 const nsRect& aImageSourceArea,
2063 const nsRect& aDestArea);
2066 * Given an image container and an orientation, returns an image container
2067 * that contains the same image, reoriented appropriately. May return the
2068 * original image container if no changes are needed.
2070 * @param aContainer The image container to apply the orientation to.
2071 * @param aOrientation The desired orientation.
2073 static already_AddRefed<imgIContainer> OrientImage(
2074 imgIContainer* aContainer,
2075 const mozilla::StyleImageOrientation& aOrientation);
2078 * Determine if any corner radius is of nonzero size
2079 * @param aCorners the |BorderRadius| object to check
2080 * @return true unless all the coordinates are 0%, 0 or null.
2082 * A corner radius with one dimension zero and one nonzero is
2083 * treated as a nonzero-radius corner, even though it will end up
2084 * being rendered like a zero-radius corner. This is because such
2085 * corners are not expected to appear outside of test cases, and it's
2086 * simpler to implement the test this way.
2088 static bool HasNonZeroCorner(const mozilla::BorderRadius& aCorners);
2091 * Determine if there is any corner radius on corners adjacent to the
2092 * given side.
2094 static bool HasNonZeroCornerOnSide(const mozilla::BorderRadius& aCorners,
2095 mozilla::Side aSide);
2098 * Determine if a widget is likely to require transparency or translucency.
2099 * @param aBackgroundFrame The frame that the background is set on. For
2100 * <window>s, this will be the canvas frame.
2101 * @param aCSSRootFrame The frame that holds CSS properties affecting
2102 * the widget's transparency. For menupopups,
2103 * aBackgroundFrame and aCSSRootFrame will be the
2104 * same.
2105 * @return a value suitable for passing to SetWindowTranslucency.
2107 static nsTransparencyMode GetFrameTransparency(nsIFrame* aBackgroundFrame,
2108 nsIFrame* aCSSRootFrame);
2111 * A frame is a popup if it has its own floating window. Menus, panels
2112 * and combobox dropdowns are popups.
2114 static bool IsPopup(const nsIFrame* aFrame);
2117 * Find the nearest "display root". This is the nearest enclosing
2118 * popup frame or the root prescontext's root frame.
2120 static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame);
2123 * Get the reference frame that would be used when constructing a
2124 * display item for this frame. Rather than using their own frame
2125 * as a reference frame.)
2127 * This duplicates some of the logic of GetDisplayRootFrame above and
2128 * of nsDisplayListBuilder::FindReferenceFrameFor.
2130 * If you have an nsDisplayListBuilder, you should get the reference
2131 * frame from it instead of calling this.
2133 static nsIFrame* GetReferenceFrame(nsIFrame* aFrame);
2136 * Get textrun construction flags determined by a given style; in particular
2137 * some combination of:
2138 * -- TEXT_DISABLE_OPTIONAL_LIGATURES if letter-spacing is in use
2139 * -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size
2140 * and prefs indicate we should be optimizing for speed over quality
2142 static mozilla::gfx::ShapedTextFlags GetTextRunFlagsForStyle(
2143 ComputedStyle* aComputedStyle, nsPresContext* aPresContext,
2144 const nsStyleFont* aStyleFont, const nsStyleText* aStyleText,
2145 nscoord aLetterSpacing);
2148 * Get orientation flags for textrun construction.
2150 static mozilla::gfx::ShapedTextFlags GetTextRunOrientFlagsForStyle(
2151 ComputedStyle* aComputedStyle);
2154 * Takes two rectangles whose origins must be the same, and computes
2155 * the difference between their union and their intersection as two
2156 * rectangles. (This difference is a superset of the difference
2157 * between the two rectangles.)
2159 static void GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2,
2160 nsRect* aHStrip, nsRect* aVStrip);
2163 * Get a device context that can be used to get up-to-date device
2164 * dimensions for the given window. For some reason, this is more
2165 * complicated than it ought to be in multi-monitor situations.
2167 static nsDeviceContext* GetDeviceContextForScreenInfo(
2168 nsPIDOMWindowOuter* aWindow);
2171 * Some frames with 'position: fixed' (nsStyleDisplay::mPosition ==
2172 * StylePositionProperty::Fixed) are not really fixed positioned, since
2173 * they're inside an element with -moz-transform. This function says
2174 * whether such an element is a real fixed-pos element.
2176 static bool IsReallyFixedPos(const nsIFrame* aFrame);
2179 * This function says whether `aFrame` would really be a fixed positioned
2180 * frame if the frame was created with StylePositionProperty::Fixed.
2182 * It is effectively the same as IsReallyFixedPos, but without asserting the
2183 * position value. Use it only when you know what you're doing, like when
2184 * tearing down the frame tree (where styles may have changed due to
2185 * ::first-line reparenting and rule changes at the same time).
2187 static bool MayBeReallyFixedPos(const nsIFrame* aFrame);
2190 * Returns true if |aFrame| is inside position:fixed subtree.
2192 static bool IsInPositionFixedSubtree(const nsIFrame* aFrame);
2195 * Obtain a SourceSurface from the given DOM element, if possible.
2196 * This obtains the most natural surface from the element; that
2197 * is, the one that can be obtained with the fewest conversions.
2199 * The flags below can modify the behaviour of this function. The
2200 * result is returned as a SurfaceFromElementResult struct, also
2201 * defined below.
2203 * Currently, this will do:
2204 * - HTML Canvas elements: will return the underlying canvas surface
2205 * - HTML Video elements: will return the current video frame
2206 * - Image elements: will return the image
2208 * The above results are modified by the below flags (copying,
2209 * forcing image surface, etc.).
2212 enum {
2213 /* When creating a new surface, create an image surface */
2214 SFE_WANT_IMAGE_SURFACE = 1 << 0,
2215 /* Whether to extract the first frame (as opposed to the
2216 current frame) in the case that the element is an image. */
2217 SFE_WANT_FIRST_FRAME_IF_IMAGE = 1 << 1,
2218 /* Whether we should skip colorspace/gamma conversion */
2219 SFE_NO_COLORSPACE_CONVERSION = 1 << 2,
2220 /* Caller handles SFER::mAlphaType = NonPremult */
2221 SFE_ALLOW_NON_PREMULT = 1 << 3,
2222 /* Whether we should skip getting a surface for vector images and
2223 return a DirectDrawInfo containing an imgIContainer instead. */
2224 SFE_NO_RASTERIZING_VECTORS = 1 << 4,
2225 /* If image type is vector, the return surface size will same as
2226 element size, not image's intrinsic size. */
2227 SFE_USE_ELEMENT_SIZE_IF_VECTOR = 1 << 5
2230 struct DirectDrawInfo {
2231 /* imgIContainer to directly draw to a context */
2232 nsCOMPtr<imgIContainer> mImgContainer;
2233 /* which frame to draw */
2234 uint32_t mWhichFrame;
2235 /* imgIContainer flags to use when drawing */
2236 uint32_t mDrawingFlags;
2239 struct SurfaceFromElementResult {
2240 friend class mozilla::dom::CanvasRenderingContext2D;
2241 friend class nsLayoutUtils;
2243 /* If SFEResult contains a valid surface, it either mLayersImage or
2244 * mSourceSurface will be non-null, and GetSourceSurface() will not be null.
2246 * For valid surfaces, mSourceSurface may be null if mLayersImage is
2247 * non-null, but GetSourceSurface() will create mSourceSurface from
2248 * mLayersImage when called.
2251 /* Video elements (at least) often are already decoded as layers::Images. */
2252 RefPtr<mozilla::layers::Image> mLayersImage;
2254 protected:
2255 /* GetSourceSurface() fills this and returns its non-null value if this
2256 * SFEResult was successful. */
2257 RefPtr<mozilla::gfx::SourceSurface> mSourceSurface;
2259 public:
2260 /* Contains info for drawing when there is no mSourceSurface. */
2261 DirectDrawInfo mDrawInfo;
2263 /* The size of the surface */
2264 mozilla::gfx::IntSize mSize;
2265 /* The size the surface is intended to be rendered at */
2266 mozilla::gfx::IntSize mIntrinsicSize;
2267 /* The principal associated with the element whose surface was returned.
2268 If there is a surface, this will never be null. */
2269 nsCOMPtr<nsIPrincipal> mPrincipal;
2270 /* The image request, if the element is an nsIImageLoadingContent */
2271 nsCOMPtr<imgIRequest> mImageRequest;
2272 /* True if cross-origins redirects have been done in order to load this
2273 * resource */
2274 bool mHadCrossOriginRedirects;
2275 /* Whether the element was "write only", that is, the bits should not be
2276 * exposed to content */
2277 bool mIsWriteOnly;
2278 /* Whether the element was still loading. Some consumers need to handle
2279 this case specially. */
2280 bool mIsStillLoading;
2281 /* Whether the element has a valid size. */
2282 bool mHasSize;
2283 /* Whether the element used CORS when loading. */
2284 bool mCORSUsed;
2286 gfxAlphaType mAlphaType;
2288 // Methods:
2290 SurfaceFromElementResult();
2292 // Gets mSourceSurface, or makes a SourceSurface from mLayersImage.
2293 const RefPtr<mozilla::gfx::SourceSurface>& GetSourceSurface();
2296 // This function can be called on any thread.
2297 static SurfaceFromElementResult SurfaceFromOffscreenCanvas(
2298 mozilla::dom::OffscreenCanvas* aOffscreenCanvas, uint32_t aSurfaceFlags,
2299 RefPtr<DrawTarget>& aTarget);
2300 static SurfaceFromElementResult SurfaceFromOffscreenCanvas(
2301 mozilla::dom::OffscreenCanvas* aOffscreenCanvas,
2302 uint32_t aSurfaceFlags = 0) {
2303 RefPtr<DrawTarget> target = nullptr;
2304 return SurfaceFromOffscreenCanvas(aOffscreenCanvas, aSurfaceFlags, target);
2307 static SurfaceFromElementResult SurfaceFromElement(
2308 mozilla::dom::Element* aElement, uint32_t aSurfaceFlags,
2309 RefPtr<DrawTarget>& aTarget);
2310 static SurfaceFromElementResult SurfaceFromElement(
2311 mozilla::dom::Element* aElement, uint32_t aSurfaceFlags = 0) {
2312 RefPtr<DrawTarget> target = nullptr;
2313 return SurfaceFromElement(aElement, aSurfaceFlags, target);
2316 // There are a bunch of callers of SurfaceFromElement. Just mark it as
2317 MOZ_CAN_RUN_SCRIPT_BOUNDARY
2318 static SurfaceFromElementResult SurfaceFromElement(
2319 nsIImageLoadingContent* aElement, uint32_t aSurfaceFlags,
2320 RefPtr<DrawTarget>& aTarget);
2321 // Need an HTMLImageElement overload, because otherwise the
2322 // nsIImageLoadingContent and mozilla::dom::Element overloads are ambiguous
2323 // for HTMLImageElement.
2324 static SurfaceFromElementResult SurfaceFromElement(
2325 mozilla::dom::HTMLImageElement* aElement, uint32_t aSurfaceFlags,
2326 RefPtr<DrawTarget>& aTarget);
2327 static SurfaceFromElementResult SurfaceFromElement(
2328 mozilla::dom::HTMLCanvasElement* aElement, uint32_t aSurfaceFlags,
2329 RefPtr<DrawTarget>& aTarget);
2330 static SurfaceFromElementResult SurfaceFromElement(
2331 mozilla::dom::HTMLVideoElement* aElement, uint32_t aSurfaceFlags,
2332 RefPtr<DrawTarget>& aTarget);
2335 * When the document is editable by contenteditable attribute of its root
2336 * content or body content.
2338 * Be aware, this returns nullptr if it's in designMode.
2340 * For example:
2342 * <html contenteditable="true"><body></body></html>
2343 * returns the <html>.
2345 * <html><body contenteditable="true"></body></html>
2346 * <body contenteditable="true"></body>
2347 * With these cases, this returns the <body>.
2348 * NOTE: The latter case isn't created normally, however, it can be
2349 * created by script with XHTML.
2351 * <body><p contenteditable="true"></p></body>
2352 * returns nullptr because <body> isn't editable.
2354 static mozilla::dom::Element* GetEditableRootContentByContentEditable(
2355 mozilla::dom::Document* aDocument);
2357 static void AddExtraBackgroundItems(nsDisplayListBuilder* aBuilder,
2358 nsDisplayList* aList, nsIFrame* aFrame,
2359 const nsRect& aCanvasArea,
2360 const nsRegion& aVisibleRegion,
2361 nscolor aBackstop);
2364 * Returns true if the passed in prescontext needs the dark grey background
2365 * that goes behind the page of a print preview presentation.
2367 static bool NeedsPrintPreviewBackground(nsPresContext* aPresContext);
2370 * Types used by the helpers for InspectorUtils.getUsedFontFaces.
2371 * The API returns an array (UsedFontFaceList) that owns the
2372 * InspectorFontFace instances, but during range traversal we also
2373 * want to maintain a mapping from gfxFontEntry to InspectorFontFace
2374 * records, so use a temporary hashtable for that.
2376 typedef nsTArray<mozilla::UniquePtr<mozilla::dom::InspectorFontFace>>
2377 UsedFontFaceList;
2378 typedef nsDataHashtable<nsPtrHashKey<gfxFontEntry>,
2379 mozilla::dom::InspectorFontFace*>
2380 UsedFontFaceTable;
2383 * Adds all font faces used in the frame tree starting from aFrame
2384 * to the list aFontFaceList.
2385 * aMaxRanges: maximum number of text ranges to record for each face.
2387 static nsresult GetFontFacesForFrames(nsIFrame* aFrame,
2388 UsedFontFaceList& aResult,
2389 UsedFontFaceTable& aFontFaces,
2390 uint32_t aMaxRanges,
2391 bool aSkipCollapsedWhitespace);
2394 * Adds all font faces used within the specified range of text in aFrame,
2395 * and optionally its continuations, to the list in aFontFaceList.
2396 * Pass 0 and INT32_MAX for aStartOffset and aEndOffset to specify the
2397 * entire text is to be considered.
2398 * aMaxRanges: maximum number of text ranges to record for each face.
2400 static void GetFontFacesForText(nsIFrame* aFrame, int32_t aStartOffset,
2401 int32_t aEndOffset, bool aFollowContinuations,
2402 UsedFontFaceList& aResult,
2403 UsedFontFaceTable& aFontFaces,
2404 uint32_t aMaxRanges,
2405 bool aSkipCollapsedWhitespace);
2408 * Walks the frame tree starting at aFrame looking for textRuns.
2409 * If |clear| is true, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag
2410 * on each textRun found (and |aMallocSizeOf| is not used).
2411 * If |clear| is false, adds the storage used for each textRun to the
2412 * total, and sets the TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double-
2413 * accounting. (Runs with this flag already set will be skipped.)
2414 * Expected usage pattern is therefore to call twice:
2415 * (void)SizeOfTextRunsForFrames(rootFrame, nullptr, true);
2416 * total = SizeOfTextRunsForFrames(rootFrame, mallocSizeOf, false);
2418 static size_t SizeOfTextRunsForFrames(nsIFrame* aFrame,
2419 mozilla::MallocSizeOf aMallocSizeOf,
2420 bool clear);
2423 * Returns true if |aFrame| has an animation of a property in |aPropertySet|
2424 * regardless of whether any property in the set is overridden by an
2425 * !important rule.
2427 static bool HasAnimationOfPropertySet(const nsIFrame* aFrame,
2428 const nsCSSPropertyIDSet& aPropertySet);
2431 * A variant of the above HasAnimationOfPropertySet that takes an optional
2432 * EffectSet parameter as an optimization to save redundant lookups of the
2433 * EffectSet.
2435 static bool HasAnimationOfPropertySet(const nsIFrame* aFrame,
2436 const nsCSSPropertyIDSet& aPropertySet,
2437 mozilla::EffectSet* aEffectSet);
2440 * A variant of the above HasAnimationOfPropertySet. This is especially for
2441 * tranform-like properties with motion-path.
2442 * For transform-like properties with motion-path, we need to check if
2443 * offset-path has effect. If we don't have any animation on offset-path and
2444 * offset-path is none, there is no effective motion-path, and so we don't
2445 * care other offset-* properties. In this case, this function only checks the
2446 * rest of transform-like properties (i.e. transform/translate/rotate/scale).
2448 static bool HasAnimationOfTransformAndMotionPath(const nsIFrame* aFrame);
2451 * Returns true if |aFrame| has an animation of |aProperty| which is
2452 * not overridden by !important rules.
2454 static bool HasEffectiveAnimation(const nsIFrame* aFrame,
2455 nsCSSPropertyID aProperty);
2458 * Returns true if |aFrame| has an animation where at least one of the
2459 * properties in |aPropertySet| is not overridden by !important rules.
2461 * If |aPropertySet| includes transform-like properties (transform, rotate,
2462 * etc.) however, this will return false if any of the transform-like
2463 * properties is overriden by an !important rule since these properties should
2464 * be combined on the compositor.
2466 static bool HasEffectiveAnimation(const nsIFrame* aFrame,
2467 const nsCSSPropertyIDSet& aPropertySet);
2470 * Returns all effective animated CSS properties on |aStyleFrame| and its
2471 * corresponding primary frame (for content that makes this distinction,
2472 * notable display:table content) that can be animated on the compositor.
2474 * Properties that can be animated on the compositor but which are overridden
2475 * by !important rules are not returned.
2477 * Unlike HasEffectiveAnimation, however, this does not check the set of
2478 * transform-like properties to ensure that if any such properties are
2479 * overridden by !important rules, the other transform-like properties are
2480 * not run on the compositor (see bug 1534884).
2482 static nsCSSPropertyIDSet GetAnimationPropertiesForCompositor(
2483 const nsIFrame* aStyleFrame);
2486 * Checks if off-main-thread animations are enabled.
2488 static bool AreAsyncAnimationsEnabled();
2491 * Checks if retained display lists are enabled.
2493 static bool AreRetainedDisplayListsEnabled();
2495 static bool DisplayRootHasRetainedDisplayListBuilder(nsIFrame* aFrame);
2498 * Find a suitable scale for a element (aFrame's content) over the course of
2499 * any animations and transitions of the CSS transform property on the element
2500 * that run on the compositor thread. It will check the maximum and minimum
2501 * scale during the animations and transitions and return a suitable value for
2502 * performance and quality. Will return scale(1,1) if there are no such
2503 * animations. Always returns a positive value.
2504 * @param aVisibleSize is the size of the area we want to paint
2505 * @param aDisplaySize is the size of the display area of the pres context
2507 static Size ComputeSuitableScaleForAnimation(const nsIFrame* aFrame,
2508 const nsSize& aVisibleSize,
2509 const nsSize& aDisplaySize);
2512 * Checks whether we want to use the GPU to scale images when
2513 * possible.
2515 static bool GPUImageScalingEnabled();
2518 * Unions the overflow areas of the children of aFrame with aOverflowAreas.
2519 * aSkipChildLists specifies any child lists that should be skipped.
2520 * kSelectPopupList and kPopupList are always skipped.
2522 static void UnionChildOverflow(
2523 nsIFrame* aFrame, nsOverflowAreas& aOverflowAreas,
2524 mozilla::layout::FrameChildListIDs aSkipChildLists =
2525 mozilla::layout::FrameChildListIDs());
2528 * Return the font size inflation *ratio* for a given frame. This is
2529 * the factor by which font sizes should be inflated; it is never
2530 * smaller than 1.
2532 static float FontSizeInflationFor(const nsIFrame* aFrame);
2535 * Perform the first half of the computation of FontSizeInflationFor
2536 * (see above).
2537 * This includes determining whether inflation should be performed
2538 * within this container and returning 0 if it should not be.
2540 * The result is guaranteed not to vary between line participants
2541 * (inlines, text frames) within a line.
2543 * The result should not be used directly since font sizes slightly
2544 * above the minimum should always be adjusted as done by
2545 * FontSizeInflationInner.
2547 static nscoord InflationMinFontSizeFor(const nsIFrame* aFrame);
2550 * Perform the second half of the computation done by
2551 * FontSizeInflationFor (see above).
2553 * aMinFontSize must be the result of one of the
2554 * InflationMinFontSizeFor methods above.
2556 static float FontSizeInflationInner(const nsIFrame* aFrame,
2557 nscoord aMinFontSize);
2559 static bool FontSizeInflationEnabled(nsPresContext* aPresContext);
2562 * Returns true if the nglayout.debug.invalidation pref is set to true.
2564 static bool InvalidationDebuggingIsEnabled() {
2565 return mozilla::StaticPrefs::nglayout_debug_invalidation() ||
2566 getenv("MOZ_DUMP_INVALIDATION") != 0;
2569 static void Initialize();
2570 static void Shutdown();
2573 * Register an imgIRequest object with a refresh driver.
2575 * @param aPresContext The nsPresContext whose refresh driver we want to
2576 * register with.
2577 * @param aRequest A pointer to the imgIRequest object which the client wants
2578 * to register with the refresh driver.
2579 * @param aRequestRegistered A pointer to a boolean value which indicates
2580 * whether the given image request is registered. If
2581 * *aRequestRegistered is true, then this request will not be
2582 * registered again. If the request is registered by this function,
2583 * then *aRequestRegistered will be set to true upon the completion of
2584 * this function.
2587 static void RegisterImageRequest(nsPresContext* aPresContext,
2588 imgIRequest* aRequest,
2589 bool* aRequestRegistered);
2592 * Register an imgIRequest object with a refresh driver, but only if the
2593 * request is for an image that is animated.
2595 * @param aPresContext The nsPresContext whose refresh driver we want to
2596 * register with.
2597 * @param aRequest A pointer to the imgIRequest object which the client wants
2598 * to register with the refresh driver.
2599 * @param aRequestRegistered A pointer to a boolean value which indicates
2600 * whether the given image request is registered. If
2601 * *aRequestRegistered is true, then this request will not be
2602 * registered again. If the request is registered by this function,
2603 * then *aRequestRegistered will be set to true upon the completion of
2604 * this function.
2607 static void RegisterImageRequestIfAnimated(nsPresContext* aPresContext,
2608 imgIRequest* aRequest,
2609 bool* aRequestRegistered);
2612 * Deregister an imgIRequest object from a refresh driver.
2614 * @param aPresContext The nsPresContext whose refresh driver we want to
2615 * deregister from.
2616 * @param aRequest A pointer to the imgIRequest object with which the client
2617 * previously registered and now wants to deregister from the refresh
2618 * driver.
2619 * @param aRequestRegistered A pointer to a boolean value which indicates
2620 * whether the given image request is registered. If
2621 * *aRequestRegistered is false, then this request will not be
2622 * deregistered. If the request is deregistered by this function,
2623 * then *aRequestRegistered will be set to false upon the completion of
2624 * this function.
2626 static void DeregisterImageRequest(nsPresContext* aPresContext,
2627 imgIRequest* aRequest,
2628 bool* aRequestRegistered);
2631 * Shim to nsCSSFrameConstructor::PostRestyleEvent. Exists so that we
2632 * can avoid including nsCSSFrameConstructor.h and all its dependencies
2633 * in content files.
2635 static void PostRestyleEvent(mozilla::dom::Element*, mozilla::RestyleHint,
2636 nsChangeHint aMinChangeHint);
2639 * Updates a pair of x and y distances if a given point is closer to a given
2640 * rectangle than the original distance values. If aPoint is closer to
2641 * aRect than aClosestXDistance and aClosestYDistance indicate, then those
2642 * two variables are updated with the distance between aPoint and aRect,
2643 * and true is returned. If aPoint is not closer, then aClosestXDistance
2644 * and aClosestYDistance are left unchanged, and false is returned.
2646 * Distances are measured in the two dimensions separately; a closer x
2647 * distance beats a closer y distance.
2649 template <typename PointType, typename RectType, typename CoordType>
2650 static bool PointIsCloserToRect(PointType aPoint, const RectType& aRect,
2651 CoordType& aClosestXDistance,
2652 CoordType& aClosestYDistance);
2654 * Computes the box shadow rect for the frame, or returns an empty rect if
2655 * there are no shadows.
2657 * @param aFrame Frame to compute shadows for.
2658 * @param aFrameSize Size of aFrame (in case it hasn't been set yet).
2660 static nsRect GetBoxShadowRectForFrame(nsIFrame* aFrame,
2661 const nsSize& aFrameSize);
2663 #ifdef DEBUG
2665 * Assert that there are no duplicate continuations of the same frame
2666 * within aFrameList. Optimize the tests by assuming that all frames
2667 * in aFrameList have parent aContainer.
2669 static void AssertNoDuplicateContinuations(nsIFrame* aContainer,
2670 const nsFrameList& aFrameList);
2673 * Assert that the frame tree rooted at |aSubtreeRoot| is empty, i.e.,
2674 * that it contains no first-in-flows.
2676 static void AssertTreeOnlyEmptyNextInFlows(nsIFrame* aSubtreeRoot);
2677 #endif
2680 * Helper method to get touch action behaviour from the frame
2682 static mozilla::StyleTouchAction GetTouchActionFromFrame(nsIFrame* aFrame);
2685 * Helper method to transform |aBounds| from aFrame to aAncestorFrame,
2686 * and combine it with |aPreciseTargetDest| if it is axis-aligned, or
2687 * combine it with |aImpreciseTargetDest| if not. The transformed rect is
2688 * clipped to |aClip|; if |aClip| has rounded corners, that also causes
2689 * the imprecise target to be used.
2691 static void TransformToAncestorAndCombineRegions(
2692 const nsRegion& aRegion, nsIFrame* aFrame, const nsIFrame* aAncestorFrame,
2693 nsRegion* aPreciseTargetDest, nsRegion* aImpreciseTargetDest,
2694 mozilla::Maybe<Matrix4x4Flagged>* aMatrixCache,
2695 const mozilla::DisplayItemClip* aClip);
2698 * Populate aOutSize with the size of the content viewer corresponding
2699 * to the given prescontext. Return true if the size was set, false
2700 * otherwise.
2702 enum class SubtractDynamicToolbar { No, Yes };
2703 static bool GetContentViewerSize(
2704 nsPresContext* aPresContext, LayoutDeviceIntSize& aOutSize,
2705 SubtractDynamicToolbar = SubtractDynamicToolbar::Yes);
2707 private:
2708 static bool UpdateCompositionBoundsForRCDRSF(
2709 mozilla::ParentLayerRect& aCompBounds, nsPresContext* aPresContext);
2711 public:
2713 * Calculate the compostion size for a frame. See FrameMetrics.h for
2714 * defintion of composition size (or bounds).
2715 * Note that for the root content document's root scroll frame (RCD-RSF),
2716 * the returned size does not change as the document's resolution changes,
2717 * but for all other frames it does. This means that callers that pass in
2718 * a frame that may or may not be the RCD-RSF (which is most callers),
2719 * are likely to need special-case handling of the RCD-RSF.
2721 static nsSize CalculateCompositionSizeForFrame(
2722 nsIFrame* aFrame, bool aSubtractScrollbars = true,
2723 const nsSize* aOverrideScrollPortSize = nullptr);
2726 * Calculate the composition size for the root scroll frame of the root
2727 * content document.
2728 * @param aFrame A frame in the root content document (or a descendant of it).
2729 * @param aIsRootContentDocRootScrollFrame Whether aFrame is already the root
2730 * scroll frame of the root content document. In this case we just
2731 * use aFrame's own composition size.
2732 * @param aMetrics A partially populated FrameMetrics for aFrame. Must have at
2733 * least mCompositionBounds, mCumulativeResolution, and
2734 * mDevPixelsPerCSSPixel set.
2736 static CSSSize CalculateRootCompositionSize(
2737 nsIFrame* aFrame, bool aIsRootContentDocRootScrollFrame,
2738 const FrameMetrics& aMetrics);
2741 * Calculate the scrollable rect for a frame. See FrameMetrics.h for
2742 * defintion of scrollable rect. aScrollableFrame is the scroll frame to
2743 * calculate the scrollable rect for. If it's null then we calculate the
2744 * scrollable rect as the rect of the root frame.
2746 static nsRect CalculateScrollableRectForFrame(
2747 nsIScrollableFrame* aScrollableFrame, nsIFrame* aRootFrame);
2750 * Calculate the expanded scrollable rect for a frame. See FrameMetrics.h for
2751 * defintion of expanded scrollable rect.
2753 static nsRect CalculateExpandedScrollableRect(nsIFrame* aFrame);
2756 * Returns true if the widget owning the given frame uses asynchronous
2757 * scrolling.
2759 static bool UsesAsyncScrolling(nsIFrame* aFrame);
2762 * Returns true if the widget owning the given frame has builtin APZ support
2763 * enabled.
2765 static bool AsyncPanZoomEnabled(nsIFrame* aFrame);
2768 * Returns the current APZ Resolution Scale. When Java Pan/Zoom is
2769 * enabled in Fennec it will always return 1.0.
2771 static float GetCurrentAPZResolutionScale(PresShell* aPresShell);
2774 * Returns true if aDocument should be allowed to use resolution
2775 * zooming.
2777 static bool AllowZoomingForDocument(const mozilla::dom::Document* aDocument);
2780 * Returns true if we need to disable async scrolling for this particular
2781 * element. Note that this does a partial disabling - the displayport still
2782 * exists but uses a very small margin, and the compositor doesn't apply the
2783 * async transform. However, the content may still be layerized.
2785 static bool ShouldDisableApzForElement(nsIContent* aContent);
2788 * Log a key/value pair as "additional data" (not associated with a paint)
2789 * for APZ testing.
2790 * While the data is not associated with a paint, the APZTestData object
2791 * is still owned by {Client,WebRender}LayerManager, so we need to be passed
2792 * something from which we can derive the layer manager.
2793 * This function takes a display list builder as the object to derive the
2794 * layer manager from, to facilitate logging test data during display list
2795 * building, but other overloads that take other objects could be added if
2796 * desired.
2798 static void LogAdditionalTestData(nsDisplayListBuilder* aBuilder,
2799 const std::string& aKey,
2800 const std::string& aValue);
2803 * Log a key/value pair for APZ testing during a paint.
2804 * @param aManager The data will be written to the APZTestData associated
2805 * with this layer manager.
2806 * @param aScrollId Identifies the scroll frame to which the data pertains.
2807 * @param aKey The key under which to log the data.
2808 * @param aValue The value of the data to be logged.
2810 static void LogTestDataForPaint(mozilla::layers::LayerManager* aManager,
2811 ViewID aScrollId, const std::string& aKey,
2812 const std::string& aValue) {
2813 DoLogTestDataForPaint(aManager, aScrollId, aKey, aValue);
2817 * A convenience overload of LogTestDataForPaint() that accepts any type
2818 * as the value, and passes it through mozilla::ToString() to obtain a string
2819 * value. The type passed must support streaming to an std::ostream.
2821 template <typename Value>
2822 static void LogTestDataForPaint(mozilla::layers::LayerManager* aManager,
2823 ViewID aScrollId, const std::string& aKey,
2824 const Value& aValue) {
2825 DoLogTestDataForPaint(aManager, aScrollId, aKey, mozilla::ToString(aValue));
2829 * Calculate a basic FrameMetrics with enough fields set to perform some
2830 * layout calculations. The fields set are dev-to-css ratio, pres shell
2831 * resolution, cumulative resolution, zoom, composition size, root
2832 * composition size, scroll offset and scrollable rect.
2834 * Note that for the RCD-RSF, the scroll offset returned is the layout
2835 * viewport offset; if you need the visual viewport offset, that needs to
2836 * be queried independently via PresShell::GetVisualViewportOffset().
2838 * By contrast, ComputeFrameMetrics() computes all the fields, but requires
2839 * extra inputs and can only be called during frame layer building.
2841 static FrameMetrics CalculateBasicFrameMetrics(
2842 nsIScrollableFrame* aScrollFrame);
2845 * Calculate a default set of displayport margins for the given scrollframe
2846 * and set them on the scrollframe's content element. The margins are set with
2847 * the default priority, which may clobber previously set margins. The repaint
2848 * mode provided is passed through to the call to SetDisplayPortMargins.
2849 * The |aScrollFrame| parameter must be non-null and queryable to an nsIFrame.
2850 * @return true iff the call to SetDisplayPortMargins returned true.
2852 static bool CalculateAndSetDisplayPortMargins(
2853 nsIScrollableFrame* aScrollFrame, RepaintMode aRepaintMode);
2856 * If |aScrollFrame| WantsAsyncScroll() and we don't have a scrollable
2857 * displayport yet (as tracked by |aBuilder|), calculate and set a
2858 * displayport.
2860 * If this is called during display list building pass DoNotRepaint in
2861 * aRepaintMode.
2863 * Returns true if there is a displayport on an async scrollable scrollframe
2864 * after this call, either because one was just added or it already existed.
2866 static bool MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
2867 nsIFrame* aScrollFrame,
2868 RepaintMode aRepaintMode);
2870 static nsIScrollableFrame* GetAsyncScrollableAncestorFrame(nsIFrame* aTarget);
2873 * Sets a zero margin display port on all proper ancestors of aFrame that
2874 * are async scrollable.
2876 static void SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
2877 nsIFrame* aFrame);
2879 * Finds the closest ancestor async scrollable frame from aFrame that has a
2880 * displayport and attempts to trigger the displayport expiry on that
2881 * ancestor.
2883 static void ExpireDisplayPortOnAsyncScrollableAncestor(nsIFrame* aFrame);
2885 static void SetBSizeFromFontMetrics(
2886 const nsIFrame* aFrame, mozilla::ReflowOutput& aMetrics,
2887 const mozilla::LogicalMargin& aFramePadding, mozilla::WritingMode aLineWM,
2888 mozilla::WritingMode aFrameWM);
2890 static bool HasDocumentLevelListenersForApzAwareEvents(PresShell* aPresShell);
2893 * Returns true if the given scroll origin is "higher priority" than APZ.
2894 * In general any content programmatic scrolls (e.g. scrollTo calls) are
2895 * higher priority, and take precedence over APZ scrolling. This function
2896 * returns true for those, and returns false for other origins like APZ
2897 * itself, or scroll position updates from the history restore code.
2899 static bool CanScrollOriginClobberApz(ScrollOrigin aScrollOrigin);
2901 static ScrollMetadata ComputeScrollMetadata(
2902 nsIFrame* aForFrame, nsIFrame* aScrollFrame, nsIContent* aContent,
2903 const nsIFrame* aReferenceFrame,
2904 mozilla::layers::LayerManager* aLayerManager, ViewID aScrollParentId,
2905 const nsRect& aViewport, const mozilla::Maybe<nsRect>& aClipRect,
2906 bool aIsRoot,
2907 const mozilla::Maybe<ContainerLayerParameters>& aContainerParameters);
2910 * Returns the metadata to put onto the root layer of a layer tree, if one is
2911 * needed. The last argument is a callback function to check if the caller
2912 * already has a metadata for a given scroll id.
2914 static mozilla::Maybe<ScrollMetadata> GetRootMetadata(
2915 nsDisplayListBuilder* aBuilder,
2916 mozilla::layers::LayerManager* aLayerManager,
2917 const ContainerLayerParameters& aContainerParameters,
2918 const std::function<bool(ViewID& aScrollId)>& aCallback);
2921 * If the given scroll frame needs an area excluded from its composition
2922 * bounds due to scrollbars, return that area, otherwise return an empty
2923 * margin.
2924 * There is no need to exclude scrollbars in the following cases:
2925 * - If the scroll frame is not the RCD-RSF; in that case, the composition
2926 * bounds is calculated based on the scroll port which already excludes
2927 * the scrollbar area.
2928 * - If the scrollbars are overlay, since then they are drawn on top of the
2929 * scrollable content.
2931 static nsMargin ScrollbarAreaToExcludeFromCompositionBoundsFor(
2932 nsIFrame* aScrollFrame);
2935 * Looks in the layer subtree rooted at aLayer for a metrics with scroll id
2936 * aScrollId. Returns true if such is found.
2938 static bool ContainsMetricsWithId(const Layer* aLayer,
2939 const ViewID& aScrollId);
2941 static bool ShouldUseNoScriptSheet(mozilla::dom::Document*);
2942 static bool ShouldUseNoFramesSheet(mozilla::dom::Document*);
2945 * Get the text content inside the frame. This methods traverse the
2946 * frame tree and collect the content from text frames. Note that this
2947 * method is similiar to nsContentUtils::GetNodeTextContent, but it at
2948 * least differs from that method in the following things:
2949 * 1. it skips text content inside nodes like style, script, textarea
2950 * which don't generate an in-tree text frame for the text;
2951 * 2. it skips elements with display property set to none;
2952 * 3. it skips out-of-flow elements;
2953 * 4. it includes content inside pseudo elements;
2954 * 5. it may include part of text content of a node if a text frame
2955 * inside is split to different continuations.
2957 static void GetFrameTextContent(nsIFrame* aFrame, nsAString& aResult);
2960 * Same as GetFrameTextContent but appends the result rather than sets it.
2962 static void AppendFrameTextContent(nsIFrame* aFrame, nsAString& aResult);
2965 * Takes a selection, and returns selection's bounding rect which is relative
2966 * to its root frame.
2968 * @param aSel Selection to check
2970 static nsRect GetSelectionBoundingRect(mozilla::dom::Selection* aSel);
2973 * Calculate the bounding rect of |aContent|, relative to the origin
2974 * of the scrolled content of |aRootScrollFrame|.
2975 * Where the element is contained inside a scrollable subframe, the
2976 * bounding rect is clipped to the bounds of the subframe.
2978 static CSSRect GetBoundingContentRect(
2979 const nsIContent* aContent, const nsIScrollableFrame* aRootScrollFrame);
2982 * Returns the first ancestor who is a float containing block.
2984 static nsBlockFrame* GetFloatContainingBlock(nsIFrame* aFrame);
2987 * Walks up the frame tree from |aForFrame| up to |aTopFrame|, or to the
2988 * root of the frame tree if |aTopFrame| is nullptr, and returns true if
2989 * a transformed frame is encountered.
2991 static bool IsTransformed(nsIFrame* aForFrame, nsIFrame* aTopFrame = nullptr);
2994 * Walk up from aFrame to the cross-doc root, accumulating all the APZ
2995 * callback transforms on the content elements encountered along the way.
2996 * Return the accumulated value.
2997 * XXX: Note that this does not take into account CSS transforms, nor
2998 * differences in structure between the frame tree and the layer tree (which
2999 * is probably what we *want* to be computing).
3001 static CSSPoint GetCumulativeApzCallbackTransform(nsIFrame* aFrame);
3004 * Compute a rect to pre-render in cases where we want to render more of
3005 * something than what is visible (usually to support async transformation).
3006 * @param aFrame the target frame to be pre-rendered
3007 * @param aDirtyRect the area that's visible in the coordinate system of
3008 * |aFrame|.
3009 * @param aOverflow the total size of the thing we're rendering in the
3010 * coordinate system of |aFrame|.
3011 * @param aPrerenderSize how large of an area we're willing to render in the
3012 * coordinate system of the root frame.
3013 * @return A rectangle that includes |aDirtyRect|, is clamped to |aOverflow|,
3014 * and is no larger than |aPrerenderSize| (unless |aPrerenderSize| is
3015 * smaller than |aDirtyRect|, in which case the returned rect will
3016 * still include |aDirtyRect| and thus be larger than
3017 * |aPrerenderSize|).
3019 static nsRect ComputePartialPrerenderArea(nsIFrame* aFrame,
3020 const nsRect& aDirtyRect,
3021 const nsRect& aOverflow,
3022 const nsSize& aPrerenderSize);
3025 * Checks whether a node is an invisible break.
3026 * If not, returns the first frame on the next line if such a next line
3027 * exists.
3029 * @return
3030 * true if the node is an invisible break. aNextLineFrame is returned null
3031 * in this case.
3033 * false if the node causes a visible break or if the node is no break.
3035 * @param aNextLineFrame
3036 * assigned to first frame on the next line if such a next line exists, null
3037 * otherwise.
3039 static bool IsInvisibleBreak(nsINode* aNode,
3040 nsIFrame** aNextLineFrame = nullptr);
3042 static nsRect ComputeGeometryBox(nsIFrame*, StyleGeometryBox);
3044 static nsRect ComputeGeometryBox(nsIFrame*,
3045 const mozilla::StyleShapeGeometryBox&);
3047 static nsRect ComputeGeometryBox(nsIFrame*, const mozilla::StyleShapeBox&);
3049 static nsPoint ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder,
3050 nsIFrame* aFrame);
3052 // Return the default value to be used for -moz-control-character-visibility,
3053 // from preferences.
3054 static mozilla::StyleControlCharacterVisibility
3055 ControlCharVisibilityDefault();
3057 // Callers are responsible to ensure the user-font-set is up-to-date if
3058 // aUseUserFontSet is true.
3059 static already_AddRefed<nsFontMetrics> GetMetricsFor(
3060 nsPresContext* aPresContext, bool aIsVertical,
3061 const nsStyleFont* aStyleFont, mozilla::Length aFontSize,
3062 bool aUseUserFontSet);
3064 static void ComputeSystemFont(nsFont* aSystemFont,
3065 mozilla::LookAndFeel::FontID aFontID,
3066 const nsFont* aDefaultVariableFont);
3068 static uint32_t ParseFontLanguageOverride(const nsAString& aLangTag);
3071 * Returns true if there are any preferences or overrides that indicate a
3072 * need to handle <meta name="viewport"> tags.
3074 static bool ShouldHandleMetaViewport(const mozilla::dom::Document*);
3077 * Resolve a CSS <length-percentage> value to a definite size.
3079 template <bool clampNegativeResultToZero>
3080 static nscoord ResolveToLength(const LengthPercentage& aLengthPercentage,
3081 nscoord aPercentageBasis) {
3082 nscoord value = (aPercentageBasis == NS_UNCONSTRAINEDSIZE)
3083 ? aLengthPercentage.Resolve(0)
3084 : aLengthPercentage.Resolve(aPercentageBasis);
3085 return clampNegativeResultToZero ? std::max(0, value) : value;
3089 * Resolve a column-gap/row-gap to a definite size.
3090 * @note This method resolves 'normal' to zero.
3091 * Callers who want different behavior should handle 'normal' on their own.
3093 static nscoord ResolveGapToLength(
3094 const mozilla::NonNegativeLengthPercentageOrNormal& aGap,
3095 nscoord aPercentageBasis) {
3096 if (aGap.IsNormal()) {
3097 return nscoord(0);
3099 return ResolveToLength<true>(aGap.AsLengthPercentage(), aPercentageBasis);
3103 * Get the computed style from which the scrollbar style should be
3104 * used for the given scrollbar part frame.
3106 static ComputedStyle* StyleForScrollbar(nsIFrame* aScrollbarPart);
3109 * Returns true if |aFrame| is scrolled out of view by a scrollable element in
3110 * a cross-process ancestor document.
3111 * Note this function only works for frames in out-of-process iframes.
3113 static bool FrameIsScrolledOutOfViewInCrossProcess(const nsIFrame* aFrame);
3116 * Similar to above FrameIsScrolledOutViewInCrossProcess but returns true even
3117 * if |aFrame| is not fully scrolled out of view and its visible area width or
3118 * height is smaller than |aMargin|.
3120 static bool FrameIsMostlyScrolledOutOfViewInCrossProcess(
3121 const nsIFrame* aFrame, nscoord aMargin);
3124 * Expand the height of |aSize| to the size of `vh` units.
3126 * With dynamic toolbar(s) the height for `vh` units is greater than the
3127 * ICB height, we need to expand it in some places.
3129 static nsSize ExpandHeightForViewportUnits(nsPresContext* aPresContext,
3130 const nsSize& aSize);
3132 static CSSSize ExpandHeightForDynamicToolbar(nsPresContext* aPresContext,
3133 const CSSSize& aSize);
3134 static nsSize ExpandHeightForDynamicToolbar(nsPresContext* aPresContext,
3135 const nsSize& aSize);
3137 private:
3139 * Helper function for LogTestDataForPaint().
3141 static void DoLogTestDataForPaint(mozilla::layers::LayerManager* aManager,
3142 ViewID aScrollId, const std::string& aKey,
3143 const std::string& aValue);
3145 static bool IsAPZTestLoggingEnabled();
3147 static void ConstrainToCoordValues(gfxFloat& aStart, gfxFloat& aSize);
3148 static void ConstrainToCoordValues(float& aStart, float& aSize);
3151 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsLayoutUtils::PaintFrameFlags)
3153 template <typename PointType, typename RectType, typename CoordType>
3154 /* static */ bool nsLayoutUtils::PointIsCloserToRect(
3155 PointType aPoint, const RectType& aRect, CoordType& aClosestXDistance,
3156 CoordType& aClosestYDistance) {
3157 CoordType fromLeft = aPoint.x - aRect.x;
3158 CoordType fromRight = aPoint.x - aRect.XMost();
3160 CoordType xDistance;
3161 if (fromLeft >= 0 && fromRight <= 0) {
3162 xDistance = 0;
3163 } else {
3164 xDistance = std::min(abs(fromLeft), abs(fromRight));
3167 if (xDistance <= aClosestXDistance) {
3168 if (xDistance < aClosestXDistance) {
3169 aClosestYDistance = std::numeric_limits<CoordType>::max();
3172 CoordType fromTop = aPoint.y - aRect.y;
3173 CoordType fromBottom = aPoint.y - aRect.YMost();
3175 CoordType yDistance;
3176 if (fromTop >= 0 && fromBottom <= 0) {
3177 yDistance = 0;
3178 } else {
3179 yDistance = std::min(abs(fromTop), abs(fromBottom));
3182 if (yDistance < aClosestYDistance) {
3183 aClosestXDistance = xDistance;
3184 aClosestYDistance = yDistance;
3185 return true;
3189 return false;
3192 template <typename T>
3193 nsRect nsLayoutUtils::RoundGfxRectToAppRect(const T& aRect,
3194 const float aFactor) {
3195 // Get a new Rect whose units are app units by scaling by the specified
3196 // factor.
3197 T scaledRect = aRect;
3198 scaledRect.ScaleRoundOut(aFactor);
3200 // We now need to constrain our results to the max and min values for coords.
3201 ConstrainToCoordValues(scaledRect.x, scaledRect.width);
3202 ConstrainToCoordValues(scaledRect.y, scaledRect.height);
3204 if (!aRect.Width()) {
3205 scaledRect.SetWidth(0);
3208 if (!aRect.Height()) {
3209 scaledRect.SetHeight(0);
3212 // Now typecast everything back. This is guaranteed to be safe.
3213 return nsRect(nscoord(scaledRect.X()), nscoord(scaledRect.Y()),
3214 nscoord(scaledRect.Width()), nscoord(scaledRect.Height()));
3217 namespace mozilla {
3220 * Converts an nsPoint in app units to a Moz2D Point in pixels (whether those
3221 * are device pixels or CSS px depends on what the caller chooses to pass as
3222 * aAppUnitsPerPixel).
3224 inline gfx::Point NSPointToPoint(const nsPoint& aPoint,
3225 int32_t aAppUnitsPerPixel) {
3226 return gfx::Point(gfx::Float(aPoint.x) / aAppUnitsPerPixel,
3227 gfx::Float(aPoint.y) / aAppUnitsPerPixel);
3231 * Converts an nsRect in app units to a Moz2D Rect in pixels (whether those
3232 * are device pixels or CSS px depends on what the caller chooses to pass as
3233 * aAppUnitsPerPixel).
3235 gfx::Rect NSRectToRect(const nsRect& aRect, double aAppUnitsPerPixel);
3238 * Converts an nsRect in app units to a Moz2D Rect in pixels (whether those
3239 * are device pixels or CSS px depends on what the caller chooses to pass as
3240 * aAppUnitsPerPixel).
3242 * The passed DrawTarget is used to additionally snap the returned Rect to
3243 * device pixels, if appropriate (as decided and carried out by Moz2D's
3244 * MaybeSnapToDevicePixels helper, which this function calls to do any
3245 * snapping).
3247 gfx::Rect NSRectToSnappedRect(const nsRect& aRect, double aAppUnitsPerPixel,
3248 const gfx::DrawTarget& aSnapDT);
3251 * Converts, where possible, an nsRect in app units to a Moz2D Rect in pixels
3252 * (whether those are device pixels or CSS px depends on what the caller
3253 * chooses to pass as aAppUnitsPerPixel).
3255 * If snapping results in a rectangle with zero width or height, the affected
3256 * coordinates are left unsnapped
3258 gfx::Rect NSRectToNonEmptySnappedRect(const nsRect& aRect,
3259 double aAppUnitsPerPixel,
3260 const gfx::DrawTarget& aSnapDT);
3262 void StrokeLineWithSnapping(
3263 const nsPoint& aP1, const nsPoint& aP2, int32_t aAppUnitsPerDevPixel,
3264 gfx::DrawTarget& aDrawTarget, const gfx::Pattern& aPattern,
3265 const gfx::StrokeOptions& aStrokeOptions = gfx::StrokeOptions(),
3266 const gfx::DrawOptions& aDrawOptions = gfx::DrawOptions());
3268 namespace layout {
3271 * An RAII class which will, for the duration of its lifetime,
3272 * **if** the frame given is a container for font size inflation,
3273 * set the current inflation container on the pres context to null
3274 * (and then, in its destructor, restore the old value).
3276 class AutoMaybeDisableFontInflation {
3277 public:
3278 explicit AutoMaybeDisableFontInflation(nsIFrame* aFrame);
3280 ~AutoMaybeDisableFontInflation();
3282 private:
3283 nsPresContext* mPresContext;
3284 bool mOldValue;
3287 void MaybeSetupTransactionIdAllocator(layers::LayerManager* aManager,
3288 nsPresContext* aPresContext);
3290 } // namespace layout
3291 } // namespace mozilla
3293 class nsSetAttrRunnable : public mozilla::Runnable {
3294 public:
3295 nsSetAttrRunnable(mozilla::dom::Element* aElement, nsAtom* aAttrName,
3296 const nsAString& aValue);
3297 nsSetAttrRunnable(mozilla::dom::Element* aElement, nsAtom* aAttrName,
3298 int32_t aValue);
3300 NS_DECL_NSIRUNNABLE
3302 RefPtr<mozilla::dom::Element> mElement;
3303 RefPtr<nsAtom> mAttrName;
3304 nsAutoString mValue;
3307 class nsUnsetAttrRunnable : public mozilla::Runnable {
3308 public:
3309 nsUnsetAttrRunnable(mozilla::dom::Element* aElement, nsAtom* aAttrName);
3311 NS_DECL_NSIRUNNABLE
3313 RefPtr<mozilla::dom::Element> mElement;
3314 RefPtr<nsAtom> mAttrName;
3317 // This class allows you to easily set any pointer variable and ensure it's
3318 // set to nullptr when leaving its scope.
3319 template <typename T>
3320 class MOZ_RAII SetAndNullOnExit {
3321 public:
3322 SetAndNullOnExit(T*& aVariable, T* aValue) {
3323 aVariable = aValue;
3324 mVariable = &aVariable;
3326 ~SetAndNullOnExit() { *mVariable = nullptr; }
3328 private:
3329 T** mVariable;
3332 #endif // nsLayoutUtils_h__