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