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