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