layout/base/nsLayoutUtils.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:e609f8b20ea3
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 "nsChangeHint.h"
11 #include "nsAutoPtr.h"
12 #include "nsFrameList.h"
13 #include "mozilla/layout/FrameChildList.h"
14 #include "nsThreadUtils.h"
15 #include "nsIPrincipal.h"
16 #include "GraphicsFilter.h"
17 #include "nsCSSPseudoElements.h"
18 #include "FrameMetrics.h"
19 #include "gfx3DMatrix.h"
20 #include "nsIWidget.h"
21 #include "nsCSSProperty.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
30 #include <limits>
31 #include <algorithm>
32
33 class nsIFormControlFrame;
34 class nsPresContext;
35 class nsIContent;
36 class nsIAtom;
37 class nsIScrollableFrame;
38 class nsIDOMEvent;
39 class nsRegion;
40 class nsDisplayListBuilder;
41 class nsDisplayItem;
42 class nsFontMetrics;
43 class nsFontFaceList;
44 class nsIImageLoadingContent;
45 class nsStyleContext;
46 class nsBlockFrame;
47 class gfxASurface;
48 class gfxDrawable;
49 class nsView;
50 class nsIFrame;
51 class nsStyleCoord;
52 class nsStyleCorners;
53 class gfxContext;
54 class nsPIDOMWindow;
55 class imgIRequest;
56 class nsIDocument;
57 class gfxPoint;
58 struct nsStyleFont;
59 struct nsStyleImageOrientation;
60 struct nsOverflowAreas;
61
62 namespace mozilla {
63 class SVGImageContext;
64 struct IntrinsicSize;
65 struct ContainerLayerParameters;
66 namespace dom {
67 class DOMRectList;
68 class Element;
69 class HTMLImageElement;
70 class HTMLCanvasElement;
71 class HTMLVideoElement;
72 } // namespace dom
73 namespace layers {
74 class Layer;
75 }
76 }
77
78 namespace mozilla {
79
80 struct DisplayPortPropertyData {
81 DisplayPortPropertyData(const nsRect& aRect, uint32_t aPriority)
82 : mRect(aRect)
83 , mPriority(aPriority)
84 {}
85 nsRect mRect;
86 uint32_t mPriority;
87 };
88
89 struct DisplayPortMarginsPropertyData {
90 DisplayPortMarginsPropertyData(const LayerMargin& aMargins,
91 uint32_t aAlignmentX, uint32_t aAlignmentY,
92 uint32_t aPriority)
93 : mMargins(aMargins)
94 , mAlignmentX(aAlignmentX)
95 , mAlignmentY(aAlignmentY)
96 , mPriority(aPriority)
97 {}
98 LayerMargin mMargins;
99 uint32_t mAlignmentX;
100 uint32_t mAlignmentY;
101 uint32_t mPriority;
102 };
103
104 template <class AnimationsOrTransitions>
105 extern AnimationsOrTransitions* HasAnimationOrTransition(nsIContent* aContent,
106 nsIAtom* aAnimationProperty,
107 nsCSSProperty aProperty);
108
109 } // namespace mozilla
110
111 /**
112 * nsLayoutUtils is a namespace class used for various helper
113 * functions that are useful in multiple places in layout. The goal
114 * is not to define multiple copies of the same static helper.
115 */
116 class nsLayoutUtils
117 {
118 typedef ::GraphicsFilter GraphicsFilter;
119 typedef mozilla::dom::DOMRectList DOMRectList;
120 typedef mozilla::layers::Layer Layer;
121 typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
122 typedef mozilla::gfx::SourceSurface SourceSurface;
123 typedef mozilla::gfx::DrawTarget DrawTarget;
124 typedef mozilla::gfx::Rect Rect;
125
126 public:
127 typedef mozilla::layers::FrameMetrics FrameMetrics;
128 typedef FrameMetrics::ViewID ViewID;
129 typedef mozilla::CSSPoint CSSPoint;
130 typedef mozilla::CSSSize CSSSize;
131 typedef mozilla::LayerMargin LayerMargin;
132
133 /**
134 * Finds previously assigned ViewID for the given content element, if any.
135 * Returns whether a ViewID was previously assigned.
136 */
137 static bool FindIDFor(const nsIContent* aContent, ViewID* aOutViewId);
138
139 /**
140 * Finds previously assigned or generates a unique ViewID for the given
141 * content element.
142 */
143 static ViewID FindOrCreateIDFor(nsIContent* aContent);
144
145 /**
146 * Find content for given ID.
147 */
148 static nsIContent* FindContentFor(ViewID aId);
149
150 /**
151 * Find the scrollable frame for a given ID.
152 */
153 static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId);
154
155 /**
156 * Get display port for the given element.
157 */
158 static bool GetDisplayPort(nsIContent* aContent, nsRect *aResult = nullptr);
159
160 MOZ_BEGIN_NESTED_ENUM_CLASS(RepaintMode, uint8_t)
161 Repaint,
162 DoNotRepaint
163 MOZ_END_NESTED_ENUM_CLASS(RepaintMode)
164
165 /**
166 * Set the display port margins for a content element to be used with a
167 * display port base (see SetDisplayPortBase()).
168 * See also nsIDOMWindowUtils.setDisplayPortMargins.
169 * @param aContent the content element for which to set the margins
170 * @param aPresShell the pres shell for the document containing the element
171 * @param aMargins the margins to set
172 * @param aAlignmentX, alignmentY the amount of pixels to which to align the
173 * displayport built by combining the base
174 * rect with the margins, in either direction
175 * @param aPriority a priority value to determine which margins take effect
176 * when multiple callers specify margins
177 * @param aRepaintMode whether to schedule a paint after setting the margins
178 */
179 static void SetDisplayPortMargins(nsIContent* aContent,
180 nsIPresShell* aPresShell,
181 const LayerMargin& aMargins,
182 uint32_t aAlignmentX,
183 uint32_t aAlignmentY,
184 uint32_t aPriority = 0,
185 RepaintMode aRepaintMode = RepaintMode::Repaint);
186
187 /**
188 * Set the display port base rect for given element to be used with display
189 * port margins.
190 * SetDisplayPortBaseIfNotSet is like SetDisplayPortBase except it only sets
191 * the display port base to aBase if no display port base is currently set.
192 */
193 static void SetDisplayPortBase(nsIContent* aContent, const nsRect& aBase);
194 static void SetDisplayPortBaseIfNotSet(nsIContent* aContent, const nsRect& aBase);
195
196 /**
197 * Get the critical display port for the given element.
198 */
199 static bool GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult = nullptr);
200
201 /**
202 * Use heuristics to figure out the child list that
203 * aChildFrame is currently in.
204 */
205 static mozilla::layout::FrameChildListID GetChildListNameFor(nsIFrame* aChildFrame);
206
207 /**
208 * GetBeforeFrame returns the outermost :before frame of the given frame, if
209 * one exists. This is typically O(1). The frame passed in must be
210 * the first-in-flow.
211 *
212 * @param aFrame the frame whose :before is wanted
213 * @return the :before frame or nullptr if there isn't one
214 */
215 static nsIFrame* GetBeforeFrame(nsIFrame* aFrame);
216
217 /**
218 * GetAfterFrame returns the outermost :after frame of the given frame, if one
219 * exists. This will walk the in-flow chain to the last-in-flow if
220 * needed. This function is typically O(N) in the number of child
221 * frames, following in-flows, etc.
222 *
223 * @param aFrame the frame whose :after is wanted
224 * @return the :after frame or nullptr if there isn't one
225 */
226 static nsIFrame* GetAfterFrame(nsIFrame* aFrame);
227
228 /**
229 * Given a frame, search up the frame tree until we find an
230 * ancestor that (or the frame itself) is of type aFrameType, if any.
231 *
232 * @param aFrame the frame to start at
233 * @param aFrameType the frame type to look for
234 * @return a frame of the given type or nullptr if no
235 * such ancestor exists
236 */
237 static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame, nsIAtom* aFrameType);
238
239 /**
240 * Given a frame, search up the frame tree until we find an
241 * ancestor that (or the frame itself) is a "Page" frame, if any.
242 *
243 * @param aFrame the frame to start at
244 * @return a frame of type nsGkAtoms::pageFrame or nullptr if no
245 * such ancestor exists
246 */
247 static nsIFrame* GetPageFrame(nsIFrame* aFrame)
248 {
249 return GetClosestFrameOfType(aFrame, nsGkAtoms::pageFrame);
250 }
251
252 /**
253 * Given a frame which is the primary frame for an element,
254 * return the frame that has the non-psuedoelement style context for
255 * the content.
256 * This is aPrimaryFrame itself except for tableOuter frames.
257 */
258 static nsIFrame* GetStyleFrame(nsIFrame* aPrimaryFrame);
259
260 /**
261 * Given a content node,
262 * return the frame that has the non-psuedoelement style context for
263 * the content. May return null.
264 * This is aContent->GetPrimaryFrame() except for tableOuter frames.
265 */
266 static nsIFrame* GetStyleFrame(const nsIContent* aContent);
267
268 /**
269 * IsGeneratedContentFor returns true if aFrame is the outermost
270 * frame for generated content of type aPseudoElement for aContent.
271 * aFrame *might not* have the aPseudoElement pseudo-style! For example
272 * it might be a table outer frame and the inner table frame might
273 * have the pseudo-style.
274 *
275 * @param aContent the content node we're looking at. If this is
276 * null, then we just assume that aFrame has the right content
277 * pointer.
278 * @param aFrame the frame we're looking at
279 * @param aPseudoElement the pseudo type we're interested in
280 * @return whether aFrame is the generated aPseudoElement frame for aContent
281 */
282 static bool IsGeneratedContentFor(nsIContent* aContent, nsIFrame* aFrame,
283 nsIAtom* aPseudoElement);
284
285 #ifdef DEBUG
286 // TODO: remove, see bug 598468.
287 static bool gPreventAssertInCompareTreePosition;
288 #endif // DEBUG
289
290 /**
291 * CompareTreePosition determines whether aContent1 comes before or
292 * after aContent2 in a preorder traversal of the content tree.
293 *
294 * @param aCommonAncestor either null, or a common ancestor of
295 * aContent1 and aContent2. Actually this is
296 * only a hint; if it's not an ancestor of
297 * aContent1 or aContent2, this function will
298 * still work, but it will be slower than
299 * normal.
300 * @return < 0 if aContent1 is before aContent2
301 * > 0 if aContent1 is after aContent2,
302 * 0 otherwise (meaning they're the same, or they're in
303 * different documents)
304 */
305 static int32_t CompareTreePosition(nsIContent* aContent1,
306 nsIContent* aContent2,
307 const nsIContent* aCommonAncestor = nullptr)
308 {
309 return DoCompareTreePosition(aContent1, aContent2, -1, 1, aCommonAncestor);
310 }
311
312 /*
313 * More generic version of |CompareTreePosition|. |aIf1Ancestor|
314 * gives the value to return when 1 is an ancestor of 2, and likewise
315 * for |aIf2Ancestor|. Passing (-1, 1) gives preorder traversal
316 * order, and (1, -1) gives postorder traversal order.
317 */
318 static int32_t DoCompareTreePosition(nsIContent* aContent1,
319 nsIContent* aContent2,
320 int32_t aIf1Ancestor,
321 int32_t aIf2Ancestor,
322 const nsIContent* aCommonAncestor = nullptr);
323
324 /**
325 * CompareTreePosition determines whether aFrame1 comes before or
326 * after aFrame2 in a preorder traversal of the frame tree, where out
327 * of flow frames are treated as children of their placeholders. This is
328 * basically the same ordering as DoCompareTreePosition(nsIContent*) except
329 * that it handles anonymous content properly and there are subtleties with
330 * continuations.
331 *
332 * @param aCommonAncestor either null, or a common ancestor of
333 * aContent1 and aContent2. Actually this is
334 * only a hint; if it's not an ancestor of
335 * aContent1 or aContent2, this function will
336 * still work, but it will be slower than
337 * normal.
338 * @return < 0 if aContent1 is before aContent2
339 * > 0 if aContent1 is after aContent2,
340 * 0 otherwise (meaning they're the same, or they're in
341 * different frame trees)
342 */
343 static int32_t CompareTreePosition(nsIFrame* aFrame1,
344 nsIFrame* aFrame2,
345 nsIFrame* aCommonAncestor = nullptr)
346 {
347 return DoCompareTreePosition(aFrame1, aFrame2, -1, 1, aCommonAncestor);
348 }
349
350 static int32_t CompareTreePosition(nsIFrame* aFrame1,
351 nsIFrame* aFrame2,
352 nsTArray<nsIFrame*>& aFrame2Ancestors,
353 nsIFrame* aCommonAncestor = nullptr)
354 {
355 return DoCompareTreePosition(aFrame1, aFrame2, aFrame2Ancestors,
356 -1, 1, aCommonAncestor);
357 }
358
359 /*
360 * More generic version of |CompareTreePosition|. |aIf1Ancestor|
361 * gives the value to return when 1 is an ancestor of 2, and likewise
362 * for |aIf2Ancestor|. Passing (-1, 1) gives preorder traversal
363 * order, and (1, -1) gives postorder traversal order.
364 */
365 static int32_t DoCompareTreePosition(nsIFrame* aFrame1,
366 nsIFrame* aFrame2,
367 int32_t aIf1Ancestor,
368 int32_t aIf2Ancestor,
369 nsIFrame* aCommonAncestor = nullptr);
370
371 static nsIFrame* FillAncestors(nsIFrame* aFrame,
372 nsIFrame* aStopAtAncestor,
373 nsTArray<nsIFrame*>* aAncestors);
374
375 static int32_t DoCompareTreePosition(nsIFrame* aFrame1,
376 nsIFrame* aFrame2,
377 nsTArray<nsIFrame*>& aFrame2Ancestors,
378 int32_t aIf1Ancestor,
379 int32_t aIf2Ancestor,
380 nsIFrame* aCommonAncestor);
381
382 /**
383 * LastContinuationWithChild gets the last continuation in aFrame's chain
384 * that has a child, or the first continuation if the frame has no children.
385 */
386 static nsIFrame* LastContinuationWithChild(nsIFrame* aFrame);
387
388 /**
389 * GetLastSibling simply finds the last sibling of aFrame, or returns nullptr if
390 * aFrame is null.
391 */
392 static nsIFrame* GetLastSibling(nsIFrame* aFrame);
393
394 /**
395 * FindSiblingViewFor locates the child of aParentView that aFrame's
396 * view should be inserted 'above' (i.e., before in sibling view
397 * order). This is the first child view of aParentView whose
398 * corresponding content is before aFrame's content (view siblings
399 * are in reverse content order).
400 */
401 static nsView* FindSiblingViewFor(nsView* aParentView, nsIFrame* aFrame);
402
403 /**
404 * Get the parent of aFrame. If aFrame is the root frame for a document,
405 * and the document has a parent document in the same view hierarchy, then
406 * we try to return the subdocumentframe in the parent document.
407 * @param aExtraOffset [in/out] if non-null, then as we cross documents
408 * an extra offset may be required and it will be added to aCrossDocOffset.
409 * Be careful dealing with this extra offset as it is in app units of the
410 * parent document, which may have a different app units per dev pixel ratio
411 * than the child document.
412 */
413 static nsIFrame* GetCrossDocParentFrame(const nsIFrame* aFrame,
414 nsPoint* aCrossDocOffset = nullptr);
415
416 /**
417 * IsProperAncestorFrame checks whether aAncestorFrame is an ancestor
418 * of aFrame and not equal to aFrame.
419 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
420 * aAncestorFrame. If non-null, this can bound the search and speed up
421 * the function
422 */
423 static bool IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame,
424 nsIFrame* aCommonAncestor = nullptr);
425
426 /**
427 * Like IsProperAncestorFrame, but looks across document boundaries.
428 *
429 * Just like IsAncestorFrameCrossDoc, except that it returns false when
430 * aFrame == aAncestorFrame.
431 */
432 static bool IsProperAncestorFrameCrossDoc(nsIFrame* aAncestorFrame, nsIFrame* aFrame,
433 nsIFrame* aCommonAncestor = nullptr);
434
435 /**
436 * IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor
437 * of aFrame or equal to aFrame, looking across document boundaries.
438 * @param aCommonAncestor nullptr, or a common ancestor of aFrame and
439 * aAncestorFrame. If non-null, this can bound the search and speed up
440 * the function.
441 *
442 * Just like IsProperAncestorFrameCrossDoc, except that it returns true when
443 * aFrame == aAncestorFrame.
444 */
445 static bool IsAncestorFrameCrossDoc(const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
446 const nsIFrame* aCommonAncestor = nullptr);
447
448 /**
449 * Sets the fixed-pos metadata properties on aLayer.
450 * aAnchorRect is the basic anchor rectangle. If aFixedPosFrame is not a viewport
451 * frame, then we pick a corner of aAnchorRect to as the anchor point for the
452 * fixed-pos layer (i.e. the point to remain stable during zooming), based
453 * on which of the fixed-pos frame's CSS absolute positioning offset
454 * properties (top, left, right, bottom) are auto. aAnchorRect is in the
455 * coordinate space of aLayer's container layer (i.e. relative to the reference
456 * frame of the display item which is building aLayer's container layer).
457 */
458 static void SetFixedPositionLayerData(Layer* aLayer, const nsIFrame* aViewportFrame,
459 const nsRect& aAnchorRect,
460 const nsIFrame* aFixedPosFrame,
461 nsPresContext* aPresContext,
462 const ContainerLayerParameters& aContainerParameters);
463
464 /**
465 * Return true if aPresContext's viewport has a displayport.
466 * Fills in aDisplayPort with the displayport rectangle if non-null.
467 */
468 static bool ViewportHasDisplayPort(nsPresContext* aPresContext,
469 nsRect* aDisplayPort = nullptr);
470
471 /**
472 * Return true if aFrame is a fixed-pos frame and is a child of a viewport
473 * which has a displayport. These frames get special treatment from the compositor.
474 * aDisplayPort, if non-null, is set to the display port rectangle (relative to
475 * the viewport).
476 */
477 static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame,
478 nsRect* aDisplayPort = nullptr);
479
480 /**
481 * Finds the nearest ancestor frame to aItem that is considered to have (or
482 * will have) "animated geometry". For example the scrolled frames of
483 * scrollframes which are actively being scrolled fall into this category.
484 * Frames with certain CSS properties that are being animated (e.g.
485 * 'left'/'top' etc) are also placed in this category.
486 * Frames with different active geometry roots are in different ThebesLayers,
487 * so that we can animate the geometry root by changing its transform (either
488 * on the main thread or in the compositor).
489 * The animated geometry root is required to be a descendant (or equal to)
490 * aItem's ReferenceFrame(), which means that we will fall back to
491 * returning aItem->ReferenceFrame() when we can't find another animated
492 * geometry root.
493 */
494 static nsIFrame* GetAnimatedGeometryRootFor(nsDisplayItem* aItem,
495 nsDisplayListBuilder* aBuilder);
496
497 /**
498 * GetScrollableFrameFor returns the scrollable frame for a scrolled frame
499 */
500 static nsIScrollableFrame* GetScrollableFrameFor(const nsIFrame *aScrolledFrame);
501
502 /**
503 * GetNearestScrollableFrameForDirection locates the first ancestor of
504 * aFrame (or aFrame itself) that is scrollable with overflow:scroll or
505 * overflow:auto in the given direction and where either the scrollbar for
506 * that direction is visible or the frame can be scrolled by some
507 * positive amount in that direction.
508 * The search extends across document boundaries.
509 *
510 * @param aFrame the frame to start with
511 * @param aDirection Whether it's for horizontal or vertical scrolling.
512 * @return the nearest scrollable frame or nullptr if not found
513 */
514 enum Direction { eHorizontal, eVertical };
515 static nsIScrollableFrame* GetNearestScrollableFrameForDirection(nsIFrame* aFrame,
516 Direction aDirection);
517
518 enum {
519 SCROLLABLE_SAME_DOC = 0x01,
520 SCROLLABLE_INCLUDE_HIDDEN = 0x02
521 };
522 /**
523 * GetNearestScrollableFrame locates the first ancestor of aFrame
524 * (or aFrame itself) that is scrollable with overflow:scroll or
525 * overflow:auto in some direction.
526 *
527 * @param aFrame the frame to start with
528 * @param aFlags if SCROLLABLE_SAME_DOC is set, do not search across
529 * document boundaries. If SCROLLABLE_INCLUDE_HIDDEN is set, include
530 * frames scrollable with overflow:hidden.
531 * @return the nearest scrollable frame or nullptr if not found
532 */
533 static nsIScrollableFrame* GetNearestScrollableFrame(nsIFrame* aFrame,
534 uint32_t aFlags = 0);
535
536 /**
537 * GetScrolledRect returns the range of allowable scroll offsets
538 * for aScrolledFrame, assuming the scrollable overflow area is
539 * aScrolledFrameOverflowArea and the scrollport size is aScrollPortSize.
540 * aDirection is either NS_STYLE_DIRECTION_LTR or NS_STYLE_DIRECTION_RTL.
541 */
542 static nsRect GetScrolledRect(nsIFrame* aScrolledFrame,
543 const nsRect& aScrolledFrameOverflowArea,
544 const nsSize& aScrollPortSize,
545 uint8_t aDirection);
546
547 /**
548 * HasPseudoStyle returns true if aContent (whose primary style
549 * context is aStyleContext) has the aPseudoElement pseudo-style
550 * attached to it; returns false otherwise.
551 *
552 * @param aContent the content node we're looking at
553 * @param aStyleContext aContent's style context
554 * @param aPseudoElement the id of the pseudo style we care about
555 * @param aPresContext the presentation context
556 * @return whether aContent has aPseudoElement style attached to it
557 */
558 static bool HasPseudoStyle(nsIContent* aContent,
559 nsStyleContext* aStyleContext,
560 nsCSSPseudoElements::Type aPseudoElement,
561 nsPresContext* aPresContext);
562
563 /**
564 * If this frame is a placeholder for a float, then return the float,
565 * otherwise return nullptr. aPlaceholder must be a placeholder frame.
566 */
567 static nsIFrame* GetFloatFromPlaceholder(nsIFrame* aPlaceholder);
568
569 // Combine aNewBreakType with aOrigBreakType, but limit the break types
570 // to NS_STYLE_CLEAR_LEFT, RIGHT, LEFT_AND_RIGHT.
571 static uint8_t CombineBreakType(uint8_t aOrigBreakType, uint8_t aNewBreakType);
572
573 /**
574 * Get the coordinates of a given DOM mouse event, relative to a given
575 * frame. Works only for DOM events generated by WidgetGUIEvents.
576 * @param aDOMEvent the event
577 * @param aFrame the frame to make coordinates relative to
578 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
579 * for some reason the coordinates for the mouse are not known (e.g.,
580 * the event is not a GUI event).
581 */
582 static nsPoint GetDOMEventCoordinatesRelativeTo(nsIDOMEvent* aDOMEvent,
583 nsIFrame* aFrame);
584
585 /**
586 * Get the coordinates of a given native mouse event, relative to a given
587 * frame.
588 * @param aEvent the event
589 * @param aFrame the frame to make coordinates relative to
590 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
591 * for some reason the coordinates for the mouse are not known (e.g.,
592 * the event is not a GUI event).
593 */
594 static nsPoint GetEventCoordinatesRelativeTo(
595 const mozilla::WidgetEvent* aEvent,
596 nsIFrame* aFrame);
597
598 /**
599 * Get the coordinates of a given point relative to an event and a
600 * given frame.
601 * @param aEvent the event
602 * @param aPoint the point to get the coordinates relative to
603 * @param aFrame the frame to make coordinates relative to
604 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
605 * for some reason the coordinates for the mouse are not known (e.g.,
606 * the event is not a GUI event).
607 */
608 static nsPoint GetEventCoordinatesRelativeTo(
609 const mozilla::WidgetEvent* aEvent,
610 const nsIntPoint aPoint,
611 nsIFrame* aFrame);
612
613 /**
614 * Get the coordinates of a given point relative to a widget and a
615 * given frame.
616 * @param aWidget the event src widget
617 * @param aPoint the point to get the coordinates relative to
618 * @param aFrame the frame to make coordinates relative to
619 * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
620 * for some reason the coordinates for the mouse are not known (e.g.,
621 * the event is not a GUI event).
622 */
623 static nsPoint GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
624 const nsIntPoint aPoint,
625 nsIFrame* aFrame);
626
627 /**
628 * Get the popup frame of a given native mouse event.
629 * @param aPresContext only check popups within aPresContext or a descendant
630 * @param aEvent the event.
631 * @return Null, if there is no popup frame at the point, otherwise,
632 * returns top-most popup frame at the point.
633 */
634 static nsIFrame* GetPopupFrameForEventCoordinates(
635 nsPresContext* aPresContext,
636 const mozilla::WidgetEvent* aEvent);
637
638 /**
639 * Translate from widget coordinates to the view's coordinates
640 * @param aPresContext the PresContext for the view
641 * @param aWidget the widget
642 * @param aPt the point relative to the widget
643 * @param aView view to which returned coordinates are relative
644 * @return the point in the view's coordinates
645 */
646 static nsPoint TranslateWidgetToView(nsPresContext* aPresContext,
647 nsIWidget* aWidget, nsIntPoint aPt,
648 nsView* aView);
649
650 /**
651 * Given a matrix and a point, let T be the transformation matrix translating points
652 * in the coordinate space with origin aOrigin to the coordinate space used by the
653 * matrix. If M is the stored matrix, this function returns (T-1)MT, the matrix
654 * that's equivalent to aMatrix but in the coordinate space that treats aOrigin
655 * as the origin.
656 *
657 * @param aOrigin The origin to translate to.
658 * @param aMatrix The matrix to change the basis of.
659 * @return A matrix equivalent to aMatrix, but operating in the coordinate system with
660 * origin aOrigin.
661 */
662 static gfx3DMatrix ChangeMatrixBasis(const gfxPoint3D &aOrigin, const gfx3DMatrix &aMatrix);
663
664 /**
665 * Find IDs corresponding to a scrollable content element in the child process.
666 * In correspondence with the shadow layer tree, you can use this to perform a
667 * hit test that corresponds to a specific shadow layer that you can then perform
668 * transformations on to do parent-side scrolling.
669 *
670 * @param aFrame The root frame of a stack context
671 * @param aTarget The rect to hit test relative to the frame origin
672 * @param aOutIDs All found IDs are added here
673 * @param aIgnoreRootScrollFrame a boolean to control if the display list
674 * builder should ignore the root scroll frame
675 */
676 static nsresult GetRemoteContentIds(nsIFrame* aFrame,
677 const nsRect& aTarget,
678 nsTArray<ViewID> &aOutIDs,
679 bool aIgnoreRootScrollFrame);
680
681 enum FrameForPointFlags {
682 /**
683 * When set, paint suppression is ignored, so we'll return non-root page
684 * elements even if paint suppression is stopping them from painting.
685 */
686 IGNORE_PAINT_SUPPRESSION = 0x01,
687 /**
688 * When set, clipping due to the root scroll frame (and any other viewport-
689 * related clipping) is ignored.
690 */
691 IGNORE_ROOT_SCROLL_FRAME = 0x02,
692 /**
693 * When set, return only content in the same document as aFrame.
694 */
695 IGNORE_CROSS_DOC = 0x04
696 };
697
698 /**
699 * Given aFrame, the root frame of a stacking context, find its descendant
700 * frame under the point aPt that receives a mouse event at that location,
701 * or nullptr if there is no such frame.
702 * @param aPt the point, relative to the frame origin
703 * @param aFlags some combination of FrameForPointFlags
704 */
705 static nsIFrame* GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt,
706 uint32_t aFlags = 0);
707
708 /**
709 * Given aFrame, the root frame of a stacking context, find all descendant
710 * frames under the area of a rectangle that receives a mouse event,
711 * or nullptr if there is no such frame.
712 * @param aRect the rect, relative to the frame origin
713 * @param aOutFrames an array to add all the frames found
714 * @param aFlags some combination of FrameForPointFlags
715 */
716 static nsresult GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
717 nsTArray<nsIFrame*> &aOutFrames,
718 uint32_t aFlags = 0);
719
720 /**
721 * Transform aRect relative to aFrame up to the coordinate system of
722 * aAncestor. Computes the bounding-box of the true quadrilateral.
723 * Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if
724 * we only need to use a 2d transform that PreservesAxisAlignedRectangles().
725 */
726 static nsRect TransformFrameRectToAncestor(nsIFrame* aFrame,
727 const nsRect& aRect,
728 const nsIFrame* aAncestor,
729 bool* aPreservesAxisAlignedRectangles = nullptr);
730
731
732 /**
733 * Gets the transform for aFrame relative to aAncestor. Pass null for aAncestor
734 * to go up to the root frame.
735 */
736 static gfx3DMatrix GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor);
737
738 /**
739 * Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into
740 * account all relevant transformations on the frames up to (but excluding)
741 * their nearest common ancestor.
742 * If we encounter a transform that we need to invert but which is
743 * non-invertible, we return NONINVERTIBLE_TRANSFORM. If the frames have
744 * no common ancestor, we return NO_COMMON_ANCESTOR.
745 * If this returns TRANSFORM_SUCCEEDED, the points in aPoints are transformed
746 * in-place, otherwise they are untouched.
747 */
748 enum TransformResult {
749 TRANSFORM_SUCCEEDED,
750 NO_COMMON_ANCESTOR,
751 NONINVERTIBLE_TRANSFORM
752 };
753 static TransformResult TransformPoints(nsIFrame* aFromFrame, nsIFrame* aToFrame,
754 uint32_t aPointCount, CSSPoint* aPoints);
755
756 /**
757 * Return true if a "layer transform" could be computed for aFrame,
758 * and optionally return the computed transform. The returned
759 * transform is what would be set on the layer currently if a layers
760 * transaction were opened at the time this helper is called.
761 */
762 static bool GetLayerTransformForFrame(nsIFrame* aFrame,
763 gfx3DMatrix* aTransform);
764
765 /**
766 * Given a point in the global coordinate space, returns that point expressed
767 * in the coordinate system of aFrame. This effectively inverts all transforms
768 * between this point and the root frame.
769 *
770 * @param aFrame The frame that acts as the coordinate space container.
771 * @param aPoint The point, in the global space, to get in the frame-local space.
772 * @return aPoint, expressed in aFrame's canonical coordinate space.
773 */
774 static nsPoint TransformRootPointToFrame(nsIFrame* aFrame,
775 const nsPoint &aPoint)
776 {
777 return TransformAncestorPointToFrame(aFrame, aPoint, nullptr);
778 }
779
780 /**
781 * Transform aPoint relative to aAncestor down to the coordinate system of
782 * aFrame.
783 */
784 static nsPoint TransformAncestorPointToFrame(nsIFrame* aFrame,
785 const nsPoint& aPoint,
786 nsIFrame* aAncestor);
787
788 /**
789 * Helper function that, given a rectangle and a matrix, returns the smallest
790 * rectangle containing the image of the source rectangle.
791 *
792 * @param aBounds The rectangle to transform.
793 * @param aMatrix The matrix to transform it with.
794 * @param aFactor The number of app units per graphics unit.
795 * @return The smallest rect that contains the image of aBounds.
796 */
797 static nsRect MatrixTransformRect(const nsRect &aBounds,
798 const gfx3DMatrix &aMatrix, float aFactor);
799
800 /**
801 * Helper function that, given a rectangle and a matrix, returns the smallest
802 * rectangle containing the image of the source rectangle rounded out to the nearest
803 * pixel value.
804 *
805 * @param aBounds The rectangle to transform.
806 * @param aMatrix The matrix to transform it with.
807 * @param aFactor The number of app units per graphics unit.
808 * @return The smallest rect that contains the image of aBounds.
809 */
810 static nsRect MatrixTransformRectOut(const nsRect &aBounds,
811 const gfx3DMatrix &aMatrix, float aFactor);
812 /**
813 * Helper function that, given a point and a matrix, returns the image
814 * of that point under the matrix transform.
815 *
816 * @param aPoint The point to transform.
817 * @param aMatrix The matrix to transform it with.
818 * @param aFactor The number of app units per graphics unit.
819 * @return The image of the point under the transform.
820 */
821 static nsPoint MatrixTransformPoint(const nsPoint &aPoint,
822 const gfx3DMatrix &aMatrix, float aFactor);
823
824 /**
825 * Given a graphics rectangle in graphics space, return a rectangle in
826 * app space that contains the graphics rectangle, rounding out as necessary.
827 *
828 * @param aRect The graphics rect to round outward.
829 * @param aFactor The number of app units per graphics unit.
830 * @return The smallest rectangle in app space that contains aRect.
831 */
832 static nsRect RoundGfxRectToAppRect(const Rect &aRect, float aFactor);
833
834 /**
835 * Given a graphics rectangle in graphics space, return a rectangle in
836 * app space that contains the graphics rectangle, rounding out as necessary.
837 *
838 * @param aRect The graphics rect to round outward.
839 * @param aFactor The number of app units per graphics unit.
840 * @return The smallest rectangle in app space that contains aRect.
841 */
842 static nsRect RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor);
843
844 /**
845 * Returns a subrectangle of aContainedRect that is entirely inside the rounded
846 * rect. Complex cases are handled conservatively by returning a smaller
847 * rect than necessary.
848 */
849 static nsRegion RoundedRectIntersectRect(const nsRect& aRoundedRect,
850 const nscoord aRadii[8],
851 const nsRect& aContainedRect);
852
853 /**
854 * Return whether any part of aTestRect is inside of the rounded
855 * rectangle formed by aBounds and aRadii (which are indexed by the
856 * NS_CORNER_* constants in nsStyleConsts.h). This is precise.
857 */
858 static bool RoundedRectIntersectsRect(const nsRect& aRoundedRect,
859 const nscoord aRadii[8],
860 const nsRect& aTestRect);
861
862 enum {
863 PAINT_IN_TRANSFORM = 0x01,
864 PAINT_SYNC_DECODE_IMAGES = 0x02,
865 PAINT_WIDGET_LAYERS = 0x04,
866 PAINT_IGNORE_SUPPRESSION = 0x08,
867 PAINT_DOCUMENT_RELATIVE = 0x10,
868 PAINT_HIDE_CARET = 0x20,
869 PAINT_ALL_CONTINUATIONS = 0x40,
870 PAINT_TO_WINDOW = 0x80,
871 PAINT_EXISTING_TRANSACTION = 0x100,
872 PAINT_NO_COMPOSITE = 0x200,
873 PAINT_COMPRESSED = 0x400
874 };
875
876 /**
877 * Given aFrame, the root frame of a stacking context, paint it and its
878 * descendants to aRenderingContext.
879 * @param aRenderingContext a rendering context translated so that (0,0)
880 * is the origin of aFrame; for best results, (0,0) should transform
881 * to pixel-aligned coordinates. This can be null, in which case
882 * aFrame must be a "display root" (root frame for a root document,
883 * or the root of a popup) with an associated widget and we draw using
884 * the layer manager for the frame's widget.
885 * @param aDirtyRegion the region that must be painted, in the coordinates
886 * of aFrame
887 * @param aBackstop paint the dirty area with this color before drawing
888 * the actual content; pass NS_RGBA(0,0,0,0) to draw no background
889 * @param aFlags if PAINT_IN_TRANSFORM is set, then we assume
890 * this is inside a transform or SVG foreignObject. If
891 * PAINT_SYNC_DECODE_IMAGES is set, we force synchronous decode on all
892 * images. If PAINT_WIDGET_LAYERS is set, aFrame must be a display root,
893 * and we will use the frame's widget's layer manager to paint
894 * even if aRenderingContext is non-null. This is useful if you want
895 * to force rendering to use the widget's layer manager for testing
896 * or speed. PAINT_WIDGET_LAYERS must be set if aRenderingContext is null.
897 * If PAINT_DOCUMENT_RELATIVE is used, the visible region is interpreted
898 * as being relative to the document. (Normally it's relative to the CSS
899 * viewport.) PAINT_TO_WINDOW sets painting to window to true on the display
900 * list builder even if we can't tell that we are painting to the window.
901 * If PAINT_EXISTING_TRANSACTION is set, then BeginTransaction() has already
902 * been called on aFrame's widget's layer manager and should not be
903 * called again.
904 * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode
905 * to avoid short cut optimizations.
906 *
907 * So there are three possible behaviours:
908 * 1) PAINT_WIDGET_LAYERS is set and aRenderingContext is null; we paint
909 * by calling BeginTransaction on the widget's layer manager
910 * 2) PAINT_WIDGET_LAYERS is set and aRenderingContext is non-null; we
911 * paint by calling BeginTransactionWithTarget on the widget's layer
912 * maanger
913 * 3) PAINT_WIDGET_LAYERS is not set and aRenderingContext is non-null;
914 * we paint by construct a BasicLayerManager and calling
915 * BeginTransactionWithTarget on it. This is desirable if we're doing
916 * something like drawWindow in a mode where what gets rendered doesn't
917 * necessarily correspond to what's visible in the window; we don't
918 * want to mess up the widget's layer tree.
919 */
920 static nsresult PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFrame,
921 const nsRegion& aDirtyRegion, nscolor aBackstop,
922 uint32_t aFlags = 0);
923
924 /**
925 * Uses a binary search for find where the cursor falls in the line of text
926 * It also keeps track of the part of the string that has already been measured
927 * so it doesn't have to keep measuring the same text over and over
928 *
929 * @param "aBaseWidth" contains the width in twips of the portion
930 * of the text that has already been measured, and aBaseInx contains
931 * the index of the text that has already been measured.
932 *
933 * @param aTextWidth returns the (in twips) the length of the text that falls
934 * before the cursor aIndex contains the index of the text where the cursor falls
935 */
936 static bool
937 BinarySearchForPosition(nsRenderingContext* acx,
938 const char16_t* aText,
939 int32_t aBaseWidth,
940 int32_t aBaseInx,
941 int32_t aStartInx,
942 int32_t aEndInx,
943 int32_t aCursorPos,
944 int32_t& aIndex,
945 int32_t& aTextWidth);
946
947 class BoxCallback {
948 public:
949 virtual void AddBox(nsIFrame* aFrame) = 0;
950 };
951 /**
952 * Collect all CSS boxes associated with aFrame and its
953 * continuations, "drilling down" through outer table frames and
954 * some anonymous blocks since they're not real CSS boxes.
955 * If aFrame is null, no boxes are returned.
956 * SVG frames return a single box, themselves.
957 */
958 static void GetAllInFlowBoxes(nsIFrame* aFrame, BoxCallback* aCallback);
959
960 /**
961 * Find the first frame descendant of aFrame (including aFrame) which is
962 * not an anonymous frame that getBoxQuads/getClientRects should ignore.
963 */
964 static nsIFrame* GetFirstNonAnonymousFrame(nsIFrame* aFrame);
965
966 class RectCallback {
967 public:
968 virtual void AddRect(const nsRect& aRect) = 0;
969 };
970
971 struct RectAccumulator : public RectCallback {
972 nsRect mResultRect;
973 nsRect mFirstRect;
974 bool mSeenFirstRect;
975
976 RectAccumulator();
977
978 virtual void AddRect(const nsRect& aRect);
979 };
980
981 struct RectListBuilder : public RectCallback {
982 DOMRectList* mRectList;
983
984 RectListBuilder(DOMRectList* aList);
985 virtual void AddRect(const nsRect& aRect);
986 };
987
988 static nsIFrame* GetContainingBlockForClientRect(nsIFrame* aFrame);
989
990 enum {
991 RECTS_ACCOUNT_FOR_TRANSFORMS = 0x01,
992 // Two bits for specifying which box type to use.
993 // With neither bit set (default), use the border box.
994 RECTS_USE_CONTENT_BOX = 0x02,
995 RECTS_USE_PADDING_BOX = 0x04,
996 RECTS_USE_MARGIN_BOX = 0x06, // both bits set
997 RECTS_WHICH_BOX_MASK = 0x06 // bitmask for these two bits
998 };
999 /**
1000 * Collect all CSS boxes (content, padding, border, or margin) associated
1001 * with aFrame and its continuations, "drilling down" through outer table
1002 * frames and some anonymous blocks since they're not real CSS boxes.
1003 * The boxes are positioned relative to aRelativeTo (taking scrolling
1004 * into account) and passed to the callback in frame-tree order.
1005 * If aFrame is null, no boxes are returned.
1006 * For SVG frames, returns one rectangle, the bounding box.
1007 * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting
1008 * the boxes into aRelativeTo coordinates, transforms (including CSS
1009 * and SVG transforms) are taken into account.
1010 * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX,
1011 * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used.
1012 * Otherwise (by default), the border box is used.
1013 */
1014 static void GetAllInFlowRects(nsIFrame* aFrame, nsIFrame* aRelativeTo,
1015 RectCallback* aCallback, uint32_t aFlags = 0);
1016
1017 /**
1018 * Computes the union of all rects returned by GetAllInFlowRects. If
1019 * the union is empty, returns the first rect.
1020 * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting
1021 * the boxes into aRelativeTo coordinates, transforms (including CSS
1022 * and SVG transforms) are taken into account.
1023 * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX,
1024 * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used.
1025 * Otherwise (by default), the border box is used.
1026 */
1027 static nsRect GetAllInFlowRectsUnion(nsIFrame* aFrame, nsIFrame* aRelativeTo,
1028 uint32_t aFlags = 0);
1029
1030 enum {
1031 EXCLUDE_BLUR_SHADOWS = 0x01
1032 };
1033 /**
1034 * Takes a text-shadow array from the style properties of a given nsIFrame and
1035 * computes the union of those shadows along with the given initial rect.
1036 * If there are no shadows, the initial rect is returned.
1037 */
1038 static nsRect GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect,
1039 nsIFrame* aFrame,
1040 uint32_t aFlags = 0);
1041
1042 /**
1043 * Get the font metrics corresponding to the frame's style data.
1044 * @param aFrame the frame
1045 * @param aFontMetrics the font metrics result
1046 * @param aSizeInflation number to multiply font size by
1047 * @return success or failure code
1048 */
1049 static nsresult GetFontMetricsForFrame(const nsIFrame* aFrame,
1050 nsFontMetrics** aFontMetrics,
1051 float aSizeInflation = 1.0f);
1052
1053 /**
1054 * Get the font metrics corresponding to the given style data.
1055 * @param aStyleContext the style data
1056 * @param aFontMetrics the font metrics result
1057 * @param aSizeInflation number to multiply font size by
1058 * @return success or failure code
1059 */
1060 static nsresult GetFontMetricsForStyleContext(nsStyleContext* aStyleContext,
1061 nsFontMetrics** aFontMetrics,
1062 float aSizeInflation = 1.0f);
1063
1064 /**
1065 * Find the immediate child of aParent whose frame subtree contains
1066 * aDescendantFrame. Returns null if aDescendantFrame is not a descendant
1067 * of aParent.
1068 */
1069 static nsIFrame* FindChildContainingDescendant(nsIFrame* aParent, nsIFrame* aDescendantFrame);
1070
1071 /**
1072 * Find the nearest ancestor that's a block
1073 */
1074 static nsBlockFrame* FindNearestBlockAncestor(nsIFrame* aFrame);
1075
1076 /**
1077 * Find the nearest ancestor that's not for generated content. Will return
1078 * aFrame if aFrame is not for generated content.
1079 */
1080 static nsIFrame* GetNonGeneratedAncestor(nsIFrame* aFrame);
1081
1082 /**
1083 * Cast aFrame to an nsBlockFrame* or return null if it's not
1084 * an nsBlockFrame.
1085 */
1086 static nsBlockFrame* GetAsBlock(nsIFrame* aFrame);
1087
1088 /*
1089 * Whether the frame is an nsBlockFrame which is not a wrapper block.
1090 */
1091 static bool IsNonWrapperBlock(nsIFrame* aFrame);
1092
1093 /**
1094 * If aFrame is an out of flow frame, return its placeholder, otherwise
1095 * return its parent.
1096 */
1097 static nsIFrame* GetParentOrPlaceholderFor(nsIFrame* aFrame);
1098
1099 /**
1100 * If aFrame is an out of flow frame, return its placeholder, otherwise
1101 * return its (possibly cross-doc) parent.
1102 */
1103 static nsIFrame* GetParentOrPlaceholderForCrossDoc(nsIFrame* aFrame);
1104
1105 /**
1106 * Get a frame's next-in-flow, or, if it doesn't have one, its
1107 * block-in-inline-split sibling.
1108 */
1109 static nsIFrame*
1110 GetNextContinuationOrIBSplitSibling(nsIFrame *aFrame);
1111
1112 /**
1113 * Get the first frame in the continuation-plus-ib-split-sibling chain
1114 * containing aFrame.
1115 */
1116 static nsIFrame*
1117 FirstContinuationOrIBSplitSibling(nsIFrame *aFrame);
1118
1119 /**
1120 * Is FirstContinuationOrIBSplitSibling(aFrame) going to return
1121 * aFrame?
1122 */
1123 static bool
1124 IsFirstContinuationOrIBSplitSibling(nsIFrame *aFrame);
1125
1126 /**
1127 * Check whether aFrame is a part of the scrollbar or scrollcorner of
1128 * the root content.
1129 * @param aFrame the checking frame
1130 * @return if TRUE, the frame is a part of the scrollbar or scrollcorner of
1131 * the root content.
1132 */
1133 static bool IsViewportScrollbarFrame(nsIFrame* aFrame);
1134
1135 /**
1136 * Get the contribution of aFrame to its containing block's intrinsic
1137 * width. This considers the child's intrinsic width, its 'width',
1138 * 'min-width', and 'max-width' properties, and its padding, border,
1139 * and margin.
1140 */
1141 enum IntrinsicWidthType { MIN_WIDTH, PREF_WIDTH };
1142 enum {
1143 IGNORE_PADDING = 0x01
1144 };
1145 static nscoord IntrinsicForContainer(nsRenderingContext* aRenderingContext,
1146 nsIFrame* aFrame,
1147 IntrinsicWidthType aType,
1148 uint32_t aFlags = 0);
1149
1150 /*
1151 * Convert nsStyleCoord to nscoord when percentages depend on the
1152 * containing block size.
1153 * @param aPercentBasis The width or height of the containing block
1154 * (whichever the client wants to use for resolving percentages).
1155 */
1156 static nscoord ComputeCBDependentValue(nscoord aPercentBasis,
1157 const nsStyleCoord& aCoord);
1158
1159 /*
1160 * Convert nsStyleCoord to nscoord when percentages depend on the
1161 * containing block width, and enumerated values are for width,
1162 * min-width, or max-width. Returns the content-box width value based
1163 * on aContentEdgeToBoxSizing and aBoxSizingToMarginEdge (which are
1164 * also used for the enumerated values for width. This function does
1165 * not handle 'auto'. It ensures that the result is nonnegative.
1166 *
1167 * @param aRenderingContext Rendering context for font measurement/metrics.
1168 * @param aFrame Frame whose (min-/max-/)width is being computed
1169 * @param aContainingBlockWidth Width of aFrame's containing block.
1170 * @param aContentEdgeToBoxSizing The sum of any left/right padding and
1171 * border that goes inside the rect chosen by box-sizing.
1172 * @param aBoxSizingToMarginEdge The sum of any left/right padding, border,
1173 * and margin that goes outside the rect chosen by box-sizing.
1174 * @param aCoord The width value to compute.
1175 */
1176 static nscoord ComputeWidthValue(
1177 nsRenderingContext* aRenderingContext,
1178 nsIFrame* aFrame,
1179 nscoord aContainingBlockWidth,
1180 nscoord aContentEdgeToBoxSizing,
1181 nscoord aBoxSizingToMarginEdge,
1182 const nsStyleCoord& aCoord);
1183
1184 /*
1185 * Convert nsStyleCoord to nscoord when percentages depend on the
1186 * containing block height.
1187 */
1188 static nscoord ComputeHeightDependentValue(
1189 nscoord aContainingBlockHeight,
1190 const nsStyleCoord& aCoord);
1191
1192 /*
1193 * Likewise, but for 'height', 'min-height', or 'max-height'.
1194 */
1195 static nscoord ComputeHeightValue(nscoord aContainingBlockHeight,
1196 nscoord aContentEdgeToBoxSizingBoxEdge,
1197 const nsStyleCoord& aCoord)
1198 {
1199 MOZ_ASSERT(aContainingBlockHeight != nscoord_MAX || !aCoord.HasPercent(),
1200 "caller must deal with %% of unconstrained height");
1201 MOZ_ASSERT(aCoord.IsCoordPercentCalcUnit());
1202
1203 nscoord result =
1204 nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockHeight);
1205 // Clamp calc(), and the subtraction for box-sizing.
1206 return std::max(0, result - aContentEdgeToBoxSizingBoxEdge);
1207 }
1208
1209 static bool IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight)
1210 {
1211 nsStyleUnit unit = aCoord.GetUnit();
1212 return unit == eStyleUnit_Auto || // only for 'height'
1213 unit == eStyleUnit_None || // only for 'max-height'
1214 (aCBHeight == nscoord_MAX && aCoord.HasPercent());
1215 }
1216
1217 static bool IsPaddingZero(const nsStyleCoord &aCoord)
1218 {
1219 return (aCoord.GetUnit() == eStyleUnit_Coord &&
1220 aCoord.GetCoordValue() == 0) ||
1221 (aCoord.GetUnit() == eStyleUnit_Percent &&
1222 aCoord.GetPercentValue() == 0.0f) ||
1223 (aCoord.IsCalcUnit() &&
1224 // clamp negative calc() to 0
1225 nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) <= 0 &&
1226 nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) <= 0);
1227 }
1228
1229 static bool IsMarginZero(const nsStyleCoord &aCoord)
1230 {
1231 return (aCoord.GetUnit() == eStyleUnit_Coord &&
1232 aCoord.GetCoordValue() == 0) ||
1233 (aCoord.GetUnit() == eStyleUnit_Percent &&
1234 aCoord.GetPercentValue() == 0.0f) ||
1235 (aCoord.IsCalcUnit() &&
1236 nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) == 0 &&
1237 nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) == 0);
1238 }
1239
1240 static void MarkDescendantsDirty(nsIFrame *aSubtreeRoot);
1241
1242 /*
1243 * Calculate the used values for 'width' and 'height' for a replaced element.
1244 *
1245 * http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
1246 */
1247 static nsSize ComputeSizeWithIntrinsicDimensions(
1248 nsRenderingContext* aRenderingContext, nsIFrame* aFrame,
1249 const mozilla::IntrinsicSize& aIntrinsicSize,
1250 nsSize aIntrinsicRatio, nsSize aCBSize,
1251 nsSize aMargin, nsSize aBorder, nsSize aPadding);
1252
1253 /*
1254 * Calculate the used values for 'width' and 'height' when width
1255 * and height are 'auto'. The tentWidth and tentHeight arguments should be
1256 * the result of applying the rules for computing intrinsic sizes and ratios.
1257 * as specified by CSS 2.1 sections 10.3.2 and 10.6.2
1258 */
1259 static nsSize ComputeAutoSizeWithIntrinsicDimensions(nscoord minWidth, nscoord minHeight,
1260 nscoord maxWidth, nscoord maxHeight,
1261 nscoord tentWidth, nscoord tentHeight);
1262
1263 // Implement nsIFrame::GetPrefWidth in terms of nsIFrame::AddInlinePrefWidth
1264 static nscoord PrefWidthFromInline(nsIFrame* aFrame,
1265 nsRenderingContext* aRenderingContext);
1266
1267 // Implement nsIFrame::GetMinWidth in terms of nsIFrame::AddInlineMinWidth
1268 static nscoord MinWidthFromInline(nsIFrame* aFrame,
1269 nsRenderingContext* aRenderingContext);
1270
1271 // Get a suitable foreground color for painting aProperty for aFrame.
1272 static nscolor GetColor(nsIFrame* aFrame, nsCSSProperty aProperty);
1273
1274 // Get the native text color if appropriate. If false is returned, callers
1275 // should fallback to the CSS color.
1276 static bool GetNativeTextColor(nsIFrame* aFrame, nscolor& aColor);
1277
1278 // Get a baseline y position in app units that is snapped to device pixels.
1279 static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
1280 nscoord aY, nscoord aAscent);
1281
1282 static void DrawString(const nsIFrame* aFrame,
1283 nsRenderingContext* aContext,
1284 const char16_t* aString,
1285 int32_t aLength,
1286 nsPoint aPoint,
1287 nsStyleContext* aStyleContext = nullptr);
1288
1289 static nscoord GetStringWidth(const nsIFrame* aFrame,
1290 nsRenderingContext* aContext,
1291 const char16_t* aString,
1292 int32_t aLength);
1293
1294 /**
1295 * Helper function for drawing text-shadow. The callback's job
1296 * is to draw whatever needs to be blurred onto the given context.
1297 */
1298 typedef void (* TextShadowCallback)(nsRenderingContext* aCtx,
1299 nsPoint aShadowOffset,
1300 const nscolor& aShadowColor,
1301 void* aData);
1302
1303 static void PaintTextShadow(const nsIFrame* aFrame,
1304 nsRenderingContext* aContext,
1305 const nsRect& aTextRect,
1306 const nsRect& aDirtyRect,
1307 const nscolor& aForegroundColor,
1308 TextShadowCallback aCallback,
1309 void* aCallbackData);
1310
1311 /**
1312 * Gets the baseline to vertically center text from a font within a
1313 * line of specified height.
1314 *
1315 * Returns the baseline position relative to the top of the line.
1316 */
1317 static nscoord GetCenteredFontBaseline(nsFontMetrics* aFontMetrics,
1318 nscoord aLineHeight);
1319
1320 /**
1321 * Derive a baseline of |aFrame| (measured from its top border edge)
1322 * from its first in-flow line box (not descending into anything with
1323 * 'overflow' not 'visible', potentially including aFrame itself).
1324 *
1325 * Returns true if a baseline was found (and fills in aResult).
1326 * Otherwise returns false.
1327 */
1328 static bool GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult);
1329
1330 /**
1331 * Just like GetFirstLineBaseline, except also returns the top and
1332 * bottom of the line with the baseline.
1333 *
1334 * Returns true if a line was found (and fills in aResult).
1335 * Otherwise returns false.
1336 */
1337 struct LinePosition {
1338 nscoord mTop, mBaseline, mBottom;
1339
1340 LinePosition operator+(nscoord aOffset) const {
1341 LinePosition result;
1342 result.mTop = mTop + aOffset;
1343 result.mBaseline = mBaseline + aOffset;
1344 result.mBottom = mBottom + aOffset;
1345 return result;
1346 }
1347 };
1348 static bool GetFirstLinePosition(const nsIFrame* aFrame,
1349 LinePosition* aResult);
1350
1351
1352 /**
1353 * Derive a baseline of |aFrame| (measured from its top border edge)
1354 * from its last in-flow line box (not descending into anything with
1355 * 'overflow' not 'visible', potentially including aFrame itself).
1356 *
1357 * Returns true if a baseline was found (and fills in aResult).
1358 * Otherwise returns false.
1359 */
1360 static bool GetLastLineBaseline(const nsIFrame* aFrame, nscoord* aResult);
1361
1362 /**
1363 * Returns a y coordinate relative to this frame's origin that represents
1364 * the logical bottom of the frame or its visible content, whichever is lower.
1365 * Relative positioning is ignored and margins and glyph bounds are not
1366 * considered.
1367 * This value will be >= mRect.height() and <= overflowRect.YMost() unless
1368 * relative positioning is applied.
1369 */
1370 static nscoord CalculateContentBottom(nsIFrame* aFrame);
1371
1372 /**
1373 * Gets the closest frame (the frame passed in or one of its parents) that
1374 * qualifies as a "layer"; used in DOM0 methods that depends upon that
1375 * definition. This is the nearest frame that is either positioned or scrolled
1376 * (the child of a scroll frame).
1377 */
1378 static nsIFrame* GetClosestLayer(nsIFrame* aFrame);
1379
1380 /**
1381 * Gets the graphics filter for the frame
1382 */
1383 static GraphicsFilter GetGraphicsFilterForFrame(nsIFrame* aFrame);
1384
1385 /* N.B. The only difference between variants of the Draw*Image
1386 * functions below is the type of the aImage argument.
1387 */
1388
1389 /**
1390 * Draw a background image. The image's dimensions are as specified in aDest;
1391 * the image itself is not consulted to determine a size.
1392 * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering
1393 * @param aRenderingContext Where to draw the image, set up with an
1394 * appropriate scale and transform for drawing in
1395 * app units.
1396 * @param aImage The image.
1397 * @param aImageSize The unscaled size of the image being drawn.
1398 * (This might be the image's size if no scaling
1399 * occurs, or it might be the image's size if
1400 * the image is a vector image being rendered at
1401 * that size.)
1402 * @param aDest The position and scaled area where one copy of
1403 * the image should be drawn.
1404 * @param aFill The area to be filled with copies of the
1405 * image.
1406 * @param aAnchor A point in aFill which we will ensure is
1407 * pixel-aligned in the output.
1408 * @param aDirty Pixels outside this area may be skipped.
1409 * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety
1410 */
1411 static nsresult DrawBackgroundImage(nsRenderingContext* aRenderingContext,
1412 imgIContainer* aImage,
1413 const nsIntSize& aImageSize,
1414 GraphicsFilter aGraphicsFilter,
1415 const nsRect& aDest,
1416 const nsRect& aFill,
1417 const nsPoint& aAnchor,
1418 const nsRect& aDirty,
1419 uint32_t aImageFlags);
1420
1421 /**
1422 * Draw an image.
1423 * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering
1424 * @param aRenderingContext Where to draw the image, set up with an
1425 * appropriate scale and transform for drawing in
1426 * app units.
1427 * @param aImage The image.
1428 * @param aDest Where one copy of the image should mapped to.
1429 * @param aFill The area to be filled with copies of the
1430 * image.
1431 * @param aAnchor A point in aFill which we will ensure is
1432 * pixel-aligned in the output.
1433 * @param aDirty Pixels outside this area may be skipped.
1434 * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety
1435 */
1436 static nsresult DrawImage(nsRenderingContext* aRenderingContext,
1437 imgIContainer* aImage,
1438 GraphicsFilter aGraphicsFilter,
1439 const nsRect& aDest,
1440 const nsRect& aFill,
1441 const nsPoint& aAnchor,
1442 const nsRect& aDirty,
1443 uint32_t aImageFlags);
1444
1445 /**
1446 * Convert an nsRect to a gfxRect.
1447 */
1448 static gfxRect RectToGfxRect(const nsRect& aRect,
1449 int32_t aAppUnitsPerDevPixel);
1450
1451 /**
1452 * Draw a drawable using the pixel snapping algorithm.
1453 * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering
1454 * @param aRenderingContext Where to draw the image, set up with an
1455 * appropriate scale and transform for drawing in
1456 * app units.
1457 * @param aDrawable The drawable we want to draw.
1458 * @param aFilter The graphics filter we should draw with.
1459 * @param aDest Where one copy of the image should mapped to.
1460 * @param aFill The area to be filled with copies of the
1461 * image.
1462 * @param aAnchor A point in aFill which we will ensure is
1463 * pixel-aligned in the output.
1464 * @param aDirty Pixels outside this area may be skipped.
1465 */
1466 static void DrawPixelSnapped(nsRenderingContext* aRenderingContext,
1467 gfxDrawable* aDrawable,
1468 GraphicsFilter aFilter,
1469 const nsRect& aDest,
1470 const nsRect& aFill,
1471 const nsPoint& aAnchor,
1472 const nsRect& aDirty);
1473
1474 /**
1475 * Draw a whole image without scaling or tiling.
1476 *
1477 * @param aRenderingContext Where to draw the image, set up with an
1478 * appropriate scale and transform for drawing in
1479 * app units.
1480 * @param aImage The image.
1481 * @param aDest The top-left where the image should be drawn
1482 * @param aDirty If non-null, then pixels outside this area may
1483 * be skipped.
1484 * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety
1485 * @param aSourceArea If non-null, this area is extracted from
1486 * the image and drawn at aDest. It's
1487 * in appunits. For best results it should
1488 * be aligned with image pixels.
1489 */
1490 static nsresult DrawSingleUnscaledImage(nsRenderingContext* aRenderingContext,
1491 imgIContainer* aImage,
1492 GraphicsFilter aGraphicsFilter,
1493 const nsPoint& aDest,
1494 const nsRect* aDirty,
1495 uint32_t aImageFlags,
1496 const nsRect* aSourceArea = nullptr);
1497
1498 /**
1499 * Draw a whole image without tiling.
1500 *
1501 * @param aRenderingContext Where to draw the image, set up with an
1502 * appropriate scale and transform for drawing in
1503 * app units.
1504 * @param aImage The image.
1505 * @param aDest The area that the image should fill
1506 * @param aDirty Pixels outside this area may be skipped.
1507 * @param aSVGContext If non-null, SVG-related rendering context
1508 * such as overridden attributes on the image
1509 * document's root <svg> node. Ignored for
1510 * raster images.
1511 * @param aImageFlags Image flags of the imgIContainer::FLAG_*
1512 * variety.
1513 * @param aSourceArea If non-null, this area is extracted from
1514 * the image and drawn in aDest. It's
1515 * in appunits. For best results it should
1516 * be aligned with image pixels.
1517 */
1518 static nsresult DrawSingleImage(nsRenderingContext* aRenderingContext,
1519 imgIContainer* aImage,
1520 GraphicsFilter aGraphicsFilter,
1521 const nsRect& aDest,
1522 const nsRect& aDirty,
1523 const mozilla::SVGImageContext* aSVGContext,
1524 uint32_t aImageFlags,
1525 const nsRect* aSourceArea = nullptr);
1526
1527 /**
1528 * Given an imgIContainer, this method attempts to obtain an intrinsic
1529 * px-valued height & width for it. If the imgIContainer has a non-pixel
1530 * value for either height or width, this method tries to generate a pixel
1531 * value for that dimension using the intrinsic ratio (if available). The
1532 * intrinsic ratio will be assigned to aIntrinsicRatio; if there's no
1533 * intrinsic ratio then (0, 0) will be assigned.
1534 *
1535 * This method will always set aGotWidth and aGotHeight to indicate whether
1536 * we were able to successfully obtain (or compute) a value for each
1537 * dimension.
1538 *
1539 * NOTE: This method is similar to ComputeSizeWithIntrinsicDimensions. The
1540 * difference is that this one is simpler and is suited to places where we
1541 * have less information about the frame tree.
1542 */
1543 static void ComputeSizeForDrawing(imgIContainer* aImage,
1544 nsIntSize& aImageSize,
1545 nsSize& aIntrinsicRatio,
1546 bool& aGotWidth,
1547 bool& aGotHeight);
1548
1549 /**
1550 * Given a source area of an image (in appunits) and a destination area
1551 * that we want to map that source area too, computes the area that
1552 * would be covered by the whole image. This is useful for passing to
1553 * the aDest parameter of DrawImage, when we want to draw a subimage
1554 * of an overall image.
1555 */
1556 static nsRect GetWholeImageDestination(const nsIntSize& aWholeImageSize,
1557 const nsRect& aImageSourceArea,
1558 const nsRect& aDestArea);
1559
1560 /**
1561 * Given an image container and an orientation, returns an image container
1562 * that contains the same image, reoriented appropriately. May return the
1563 * original image container if no changes are needed.
1564 *
1565 * @param aContainer The image container to apply the orientation to.
1566 * @param aOrientation The desired orientation.
1567 */
1568 static already_AddRefed<imgIContainer>
1569 OrientImage(imgIContainer* aContainer,
1570 const nsStyleImageOrientation& aOrientation);
1571
1572 /**
1573 * Determine if any corner radius is of nonzero size
1574 * @param aCorners the |nsStyleCorners| object to check
1575 * @return true unless all the coordinates are 0%, 0 or null.
1576 *
1577 * A corner radius with one dimension zero and one nonzero is
1578 * treated as a nonzero-radius corner, even though it will end up
1579 * being rendered like a zero-radius corner. This is because such
1580 * corners are not expected to appear outside of test cases, and it's
1581 * simpler to implement the test this way.
1582 */
1583 static bool HasNonZeroCorner(const nsStyleCorners& aCorners);
1584
1585 /**
1586 * Determine if there is any corner radius on corners adjacent to the
1587 * given side.
1588 */
1589 static bool HasNonZeroCornerOnSide(const nsStyleCorners& aCorners,
1590 mozilla::css::Side aSide);
1591
1592 /**
1593 * Determine if a widget is likely to require transparency or translucency.
1594 * @param aBackgroundFrame The frame that the background is set on. For
1595 * <window>s, this will be the canvas frame.
1596 * @param aCSSRootFrame The frame that holds CSS properties affecting
1597 * the widget's transparency. For menupopups,
1598 * aBackgroundFrame and aCSSRootFrame will be the
1599 * same.
1600 * @return a value suitable for passing to SetWindowTranslucency
1601 */
1602 static nsTransparencyMode GetFrameTransparency(nsIFrame* aBackgroundFrame,
1603 nsIFrame* aCSSRootFrame);
1604
1605 /**
1606 * A frame is a popup if it has its own floating window. Menus, panels
1607 * and combobox dropdowns are popups.
1608 */
1609 static bool IsPopup(nsIFrame* aFrame);
1610
1611 /**
1612 * Find the nearest "display root". This is the nearest enclosing
1613 * popup frame or the root prescontext's root frame.
1614 */
1615 static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame);
1616
1617 /**
1618 * Get the reference frame that would be used when constructing a
1619 * display item for this frame. (Note, however, that
1620 * nsDisplayTransform use the reference frame appropriate for their
1621 * GetTransformRootFrame(), rather than using their own frame as a
1622 * reference frame.)
1623 *
1624 * This duplicates some of the logic of GetDisplayRootFrame above and
1625 * of nsDisplayListBuilder::FindReferenceFrameFor.
1626 *
1627 * If you have an nsDisplayListBuilder, you should get the reference
1628 * frame from it instead of calling this.
1629 */
1630 static nsIFrame* GetReferenceFrame(nsIFrame* aFrame);
1631
1632 /**
1633 * Get the parent of this frame, except if that parent is part of a
1634 * preserve-3d hierarchy, get the parent of the root of the
1635 * preserve-3d hierarchy.
1636 *
1637 * (This is used as the starting point for reference frame computation
1638 * for nsDisplayTransform display items.)
1639 */
1640 static nsIFrame* GetTransformRootFrame(nsIFrame* aFrame);
1641
1642 /**
1643 * Get textrun construction flags determined by a given style; in particular
1644 * some combination of:
1645 * -- TEXT_DISABLE_OPTIONAL_LIGATURES if letter-spacing is in use
1646 * -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size
1647 * and prefs indicate we should be optimizing for speed over quality
1648 */
1649 static uint32_t GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
1650 const nsStyleFont* aStyleFont,
1651 const nsStyleText* aStyleText,
1652 nscoord aLetterSpacing);
1653
1654 /**
1655 * Takes two rectangles whose origins must be the same, and computes
1656 * the difference between their union and their intersection as two
1657 * rectangles. (This difference is a superset of the difference
1658 * between the two rectangles.)
1659 */
1660 static void GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2,
1661 nsRect* aHStrip, nsRect* aVStrip);
1662
1663 /**
1664 * Get a device context that can be used to get up-to-date device
1665 * dimensions for the given window. For some reason, this is more
1666 * complicated than it ought to be in multi-monitor situations.
1667 */
1668 static nsDeviceContext*
1669 GetDeviceContextForScreenInfo(nsPIDOMWindow* aWindow);
1670
1671 /**
1672 * Some frames with 'position: fixed' (nsStylePosition::mDisplay ==
1673 * NS_STYLE_POSITION_FIXED) are not really fixed positioned, since
1674 * they're inside an element with -moz-transform. This function says
1675 * whether such an element is a real fixed-pos element.
1676 */
1677 static bool IsReallyFixedPos(nsIFrame* aFrame);
1678
1679 /**
1680 * Obtain a gfxASurface from the given DOM element, if possible.
1681 * This obtains the most natural surface from the element; that
1682 * is, the one that can be obtained with the fewest conversions.
1683 *
1684 * The flags below can modify the behaviour of this function. The
1685 * result is returned as a SurfaceFromElementResult struct, also
1686 * defined below.
1687 *
1688 * Currently, this will do:
1689 * - HTML Canvas elements: will return the underlying canvas surface
1690 * - HTML Video elements: will return the current video frame
1691 * - Image elements: will return the image
1692 *
1693 * The above results are modified by the below flags (copying,
1694 * forcing image surface, etc.).
1695 */
1696
1697 enum {
1698 /* When creating a new surface, create an image surface */
1699 SFE_WANT_IMAGE_SURFACE = 1 << 0,
1700 /* Whether to extract the first frame (as opposed to the
1701 current frame) in the case that the element is an image. */
1702 SFE_WANT_FIRST_FRAME = 1 << 1,
1703 /* Whether we should skip colorspace/gamma conversion */
1704 SFE_NO_COLORSPACE_CONVERSION = 1 << 2,
1705 /* Specifies that the caller wants unpremultiplied pixel data.
1706 If this is can be done efficiently, the result will be a
1707 DataSourceSurface and mIsPremultiplied with be set to false. */
1708 SFE_PREFER_NO_PREMULTIPLY_ALPHA = 1 << 3,
1709 /* Whether we should skip getting a surface for vector images and
1710 return a DirectDrawInfo containing an imgIContainer instead. */
1711 SFE_NO_RASTERIZING_VECTORS = 1 << 4
1712 };
1713
1714 struct DirectDrawInfo {
1715 /* imgIContainer to directly draw to a context */
1716 nsCOMPtr<imgIContainer> mImgContainer;
1717 /* which frame to draw */
1718 uint32_t mWhichFrame;
1719 /* imgIContainer flags to use when drawing */
1720 uint32_t mDrawingFlags;
1721 };
1722
1723 struct SurfaceFromElementResult {
1724 SurfaceFromElementResult();
1725
1726 /* mSurface will contain the resulting surface, or will be nullptr on error */
1727 nsRefPtr<gfxASurface> mSurface;
1728 mozilla::RefPtr<SourceSurface> mSourceSurface;
1729 /* Contains info for drawing when there is no mSourceSurface. */
1730 DirectDrawInfo mDrawInfo;
1731
1732 /* The size of the surface */
1733 gfxIntSize mSize;
1734 /* The principal associated with the element whose surface was returned.
1735 If there is a surface, this will never be null. */
1736 nsCOMPtr<nsIPrincipal> mPrincipal;
1737 /* The image request, if the element is an nsIImageLoadingContent */
1738 nsCOMPtr<imgIRequest> mImageRequest;
1739 /* Whether the element was "write only", that is, the bits should not be exposed to content */
1740 bool mIsWriteOnly;
1741 /* Whether the element was still loading. Some consumers need to handle
1742 this case specially. */
1743 bool mIsStillLoading;
1744 /* Whether the element used CORS when loading. */
1745 bool mCORSUsed;
1746 /* Whether the returned image contains premultiplied pixel data */
1747 bool mIsPremultiplied;
1748 };
1749
1750 static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::Element *aElement,
1751 uint32_t aSurfaceFlags = 0,
1752 DrawTarget *aTarget = nullptr);
1753 static SurfaceFromElementResult SurfaceFromElement(nsIImageLoadingContent *aElement,
1754 uint32_t aSurfaceFlags = 0,
1755 DrawTarget *aTarget = nullptr);
1756 // Need an HTMLImageElement overload, because otherwise the
1757 // nsIImageLoadingContent and mozilla::dom::Element overloads are ambiguous
1758 // for HTMLImageElement.
1759 static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::HTMLImageElement *aElement,
1760 uint32_t aSurfaceFlags = 0,
1761 DrawTarget *aTarget = nullptr);
1762 static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::HTMLCanvasElement *aElement,
1763 uint32_t aSurfaceFlags = 0,
1764 DrawTarget *aTarget = nullptr);
1765 static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::HTMLVideoElement *aElement,
1766 uint32_t aSurfaceFlags = 0,
1767 DrawTarget *aTarget = nullptr);
1768
1769 /**
1770 * When the document is editable by contenteditable attribute of its root
1771 * content or body content.
1772 *
1773 * Be aware, this returns nullptr if it's in designMode.
1774 *
1775 * For example:
1776 *
1777 * <html contenteditable="true"><body></body></html>
1778 * returns the <html>.
1779 *
1780 * <html><body contenteditable="true"></body></html>
1781 * <body contenteditable="true"></body>
1782 * With these cases, this returns the <body>.
1783 * NOTE: The latter case isn't created normally, however, it can be
1784 * created by script with XHTML.
1785 *
1786 * <body><p contenteditable="true"></p></body>
1787 * returns nullptr because <body> isn't editable.
1788 */
1789 static nsIContent*
1790 GetEditableRootContentByContentEditable(nsIDocument* aDocument);
1791
1792 /**
1793 * Returns true if the passed in prescontext needs the dark grey background
1794 * that goes behind the page of a print preview presentation.
1795 */
1796 static bool NeedsPrintPreviewBackground(nsPresContext* aPresContext);
1797
1798 /**
1799 * Adds all font faces used in the frame tree starting from aFrame
1800 * to the list aFontFaceList.
1801 */
1802 static nsresult GetFontFacesForFrames(nsIFrame* aFrame,
1803 nsFontFaceList* aFontFaceList);
1804
1805 /**
1806 * Adds all font faces used within the specified range of text in aFrame,
1807 * and optionally its continuations, to the list in aFontFaceList.
1808 * Pass 0 and INT32_MAX for aStartOffset and aEndOffset to specify the
1809 * entire text is to be considered.
1810 */
1811 static nsresult GetFontFacesForText(nsIFrame* aFrame,
1812 int32_t aStartOffset,
1813 int32_t aEndOffset,
1814 bool aFollowContinuations,
1815 nsFontFaceList* aFontFaceList);
1816
1817 /**
1818 * Walks the frame tree starting at aFrame looking for textRuns.
1819 * If |clear| is true, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag
1820 * on each textRun found (and |aMallocSizeOf| is not used).
1821 * If |clear| is false, adds the storage used for each textRun to the
1822 * total, and sets the TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double-
1823 * accounting. (Runs with this flag already set will be skipped.)
1824 * Expected usage pattern is therefore to call twice:
1825 * (void)SizeOfTextRunsForFrames(rootFrame, nullptr, true);
1826 * total = SizeOfTextRunsForFrames(rootFrame, mallocSizeOf, false);
1827 */
1828 static size_t SizeOfTextRunsForFrames(nsIFrame* aFrame,
1829 mozilla::MallocSizeOf aMallocSizeOf,
1830 bool clear);
1831
1832 /**
1833 * Returns true if the content node has animations or transitions that can be
1834 * performed on the compositor.
1835 */
1836 static bool HasAnimationsForCompositor(nsIContent* aContent,
1837 nsCSSProperty aProperty);
1838
1839 /**
1840 * Returns true if the content node has animations or transitions for the
1841 * property.
1842 */
1843 static bool HasAnimations(nsIContent* aContent, nsCSSProperty aProperty);
1844
1845 /**
1846 * Checks if off-main-thread animations are enabled.
1847 */
1848 static bool AreAsyncAnimationsEnabled();
1849
1850 /**
1851 * Checks if we should warn about animations that can't be async
1852 */
1853 static bool IsAnimationLoggingEnabled();
1854
1855 /**
1856 * Find a suitable scale for an element (aContent) over the course of any
1857 * animations and transitions on the element.
1858 * It will check the maximum and minimum scale during the animations and
1859 * transitions and return a suitable value for performance and quality.
1860 * Will return scale(1,1) if there is no animated scaling.
1861 * Always return positive value.
1862 */
1863 static gfxSize ComputeSuitableScaleForAnimation(nsIContent* aContent);
1864
1865 /**
1866 * Checks if we should forcibly use nearest pixel filtering for the
1867 * background.
1868 */
1869 static bool UseBackgroundNearestFiltering();
1870
1871 /**
1872 * Checks whether we want to use the GPU to scale images when
1873 * possible.
1874 */
1875 static bool GPUImageScalingEnabled();
1876
1877 /**
1878 * Checks whether we want to layerize animated images whenever possible.
1879 */
1880 static bool AnimatedImageLayersEnabled();
1881
1882 /**
1883 * Checks if we should enable parsing for CSS Filters.
1884 */
1885 static bool CSSFiltersEnabled();
1886
1887 /**
1888 * Checks whether support for the CSS-wide "unset" value is enabled.
1889 */
1890 static bool UnsetValueEnabled();
1891
1892 /**
1893 * Checks whether support for the CSS text-align (and -moz-text-align-last)
1894 * 'true' value is enabled.
1895 */
1896 static bool IsTextAlignTrueValueEnabled();
1897
1898 /**
1899 * Checks if CSS variables are currently enabled.
1900 */
1901 static bool CSSVariablesEnabled()
1902 {
1903 return sCSSVariablesEnabled;
1904 }
1905
1906 static bool InterruptibleReflowEnabled()
1907 {
1908 return sInterruptibleReflowEnabled;
1909 }
1910
1911 /**
1912 * Unions the overflow areas of the children of aFrame with aOverflowAreas.
1913 * aSkipChildLists specifies any child lists that should be skipped.
1914 * kSelectPopupList and kPopupList are always skipped.
1915 */
1916 static void UnionChildOverflow(nsIFrame* aFrame,
1917 nsOverflowAreas& aOverflowAreas,
1918 mozilla::layout::FrameChildListIDs aSkipChildLists =
1919 mozilla::layout::FrameChildListIDs());
1920
1921 /**
1922 * Return the font size inflation *ratio* for a given frame. This is
1923 * the factor by which font sizes should be inflated; it is never
1924 * smaller than 1.
1925 */
1926 static float FontSizeInflationFor(const nsIFrame *aFrame);
1927
1928 /**
1929 * Perform the first half of the computation of FontSizeInflationFor
1930 * (see above).
1931 * This includes determining whether inflation should be performed
1932 * within this container and returning 0 if it should not be.
1933 *
1934 * The result is guaranteed not to vary between line participants
1935 * (inlines, text frames) within a line.
1936 *
1937 * The result should not be used directly since font sizes slightly
1938 * above the minimum should always be adjusted as done by
1939 * FontSizeInflationInner.
1940 */
1941 static nscoord InflationMinFontSizeFor(const nsIFrame *aFrame);
1942
1943 /**
1944 * Perform the second half of the computation done by
1945 * FontSizeInflationFor (see above).
1946 *
1947 * aMinFontSize must be the result of one of the
1948 * InflationMinFontSizeFor methods above.
1949 */
1950 static float FontSizeInflationInner(const nsIFrame *aFrame,
1951 nscoord aMinFontSize);
1952
1953 static bool FontSizeInflationEnabled(nsPresContext *aPresContext);
1954
1955 /**
1956 * See comment above "font.size.inflation.maxRatio" in
1957 * modules/libpref/src/init/all.js .
1958 */
1959 static uint32_t FontSizeInflationMaxRatio() {
1960 return sFontSizeInflationMaxRatio;
1961 }
1962
1963 /**
1964 * See comment above "font.size.inflation.emPerLine" in
1965 * modules/libpref/src/init/all.js .
1966 */
1967 static uint32_t FontSizeInflationEmPerLine() {
1968 return sFontSizeInflationEmPerLine;
1969 }
1970
1971 /**
1972 * See comment above "font.size.inflation.minTwips" in
1973 * modules/libpref/src/init/all.js .
1974 */
1975 static uint32_t FontSizeInflationMinTwips() {
1976 return sFontSizeInflationMinTwips;
1977 }
1978
1979 /**
1980 * See comment above "font.size.inflation.lineThreshold" in
1981 * modules/libpref/src/init/all.js .
1982 */
1983 static uint32_t FontSizeInflationLineThreshold() {
1984 return sFontSizeInflationLineThreshold;
1985 }
1986
1987 static bool FontSizeInflationForceEnabled() {
1988 return sFontSizeInflationForceEnabled;
1989 }
1990
1991 static bool FontSizeInflationDisabledInMasterProcess() {
1992 return sFontSizeInflationDisabledInMasterProcess;
1993 }
1994
1995 /**
1996 * See comment above "font.size.inflation.mappingIntercept" in
1997 * modules/libpref/src/init/all.js .
1998 */
1999 static int32_t FontSizeInflationMappingIntercept() {
2000 return sFontSizeInflationMappingIntercept;
2001 }
2002
2003 /**
2004 * Returns true if the nglayout.debug.invalidation pref is set to true.
2005 * Note that sInvalidationDebuggingIsEnabled is declared outside this function to
2006 * allow it to be accessed an manipulated from breakpoint conditions.
2007 */
2008 static bool InvalidationDebuggingIsEnabled() {
2009 return sInvalidationDebuggingIsEnabled || getenv("MOZ_DUMP_INVALIDATION") != 0;
2010 }
2011
2012 static void Initialize();
2013 static void Shutdown();
2014
2015 /**
2016 * Register an imgIRequest object with a refresh driver.
2017 *
2018 * @param aPresContext The nsPresContext whose refresh driver we want to
2019 * register with.
2020 * @param aRequest A pointer to the imgIRequest object which the client wants
2021 * to register with the refresh driver.
2022 * @param aRequestRegistered A pointer to a boolean value which indicates
2023 * whether the given image request is registered. If
2024 * *aRequestRegistered is true, then this request will not be
2025 * registered again. If the request is registered by this function,
2026 * then *aRequestRegistered will be set to true upon the completion of
2027 * this function.
2028 *
2029 */
2030 static void RegisterImageRequest(nsPresContext* aPresContext,
2031 imgIRequest* aRequest,
2032 bool* aRequestRegistered);
2033
2034 /**
2035 * Register an imgIRequest object with a refresh driver, but only if the
2036 * request is for an image that is animated.
2037 *
2038 * @param aPresContext The nsPresContext whose refresh driver we want to
2039 * register with.
2040 * @param aRequest A pointer to the imgIRequest object which the client wants
2041 * to register with the refresh driver.
2042 * @param aRequestRegistered A pointer to a boolean value which indicates
2043 * whether the given image request is registered. If
2044 * *aRequestRegistered is true, then this request will not be
2045 * registered again. If the request is registered by this function,
2046 * then *aRequestRegistered will be set to true upon the completion of
2047 * this function.
2048 *
2049 */
2050 static void RegisterImageRequestIfAnimated(nsPresContext* aPresContext,
2051 imgIRequest* aRequest,
2052 bool* aRequestRegistered);
2053
2054 /**
2055 * Deregister an imgIRequest object from a refresh driver.
2056 *
2057 * @param aPresContext The nsPresContext whose refresh driver we want to
2058 * deregister from.
2059 * @param aRequest A pointer to the imgIRequest object with which the client
2060 * previously registered and now wants to deregister from the refresh
2061 * driver.
2062 * @param aRequestRegistered A pointer to a boolean value which indicates
2063 * whether the given image request is registered. If
2064 * *aRequestRegistered is false, then this request will not be
2065 * deregistered. If the request is deregistered by this function,
2066 * then *aRequestRegistered will be set to false upon the completion of
2067 * this function.
2068 */
2069 static void DeregisterImageRequest(nsPresContext* aPresContext,
2070 imgIRequest* aRequest,
2071 bool* aRequestRegistered);
2072
2073 /**
2074 * Shim to nsCSSFrameConstructor::PostRestyleEvent. Exists so that we
2075 * can avoid including nsCSSFrameConstructor.h and all its dependencies
2076 * in content files.
2077 */
2078 static void PostRestyleEvent(mozilla::dom::Element* aElement,
2079 nsRestyleHint aRestyleHint,
2080 nsChangeHint aMinChangeHint);
2081
2082 /**
2083 * Updates a pair of x and y distances if a given point is closer to a given
2084 * rectangle than the original distance values. If aPoint is closer to
2085 * aRect than aClosestXDistance and aClosestYDistance indicate, then those
2086 * two variables are updated with the distance between aPoint and aRect,
2087 * and true is returned. If aPoint is not closer, then aClosestXDistance
2088 * and aClosestYDistance are left unchanged, and false is returned.
2089 *
2090 * Distances are measured in the two dimensions separately; a closer x
2091 * distance beats a closer y distance.
2092 */
2093 template<typename PointType, typename RectType, typename CoordType>
2094 static bool PointIsCloserToRect(PointType aPoint, const RectType& aRect,
2095 CoordType& aClosestXDistance,
2096 CoordType& aClosestYDistance);
2097 /**
2098 * Computes the box shadow rect for the frame, or returns an empty rect if
2099 * there are no shadows.
2100 *
2101 * @param aFrame Frame to compute shadows for.
2102 * @param aFrameSize Size of aFrame (in case it hasn't been set yet).
2103 */
2104 static nsRect GetBoxShadowRectForFrame(nsIFrame* aFrame, const nsSize& aFrameSize);
2105
2106 #ifdef DEBUG
2107 /**
2108 * Assert that there are no duplicate continuations of the same frame
2109 * within aFrameList. Optimize the tests by assuming that all frames
2110 * in aFrameList have parent aContainer.
2111 */
2112 static void
2113 AssertNoDuplicateContinuations(nsIFrame* aContainer,
2114 const nsFrameList& aFrameList);
2115
2116 /**
2117 * Assert that the frame tree rooted at |aSubtreeRoot| is empty, i.e.,
2118 * that it contains no first-in-flows.
2119 */
2120 static void
2121 AssertTreeOnlyEmptyNextInFlows(nsIFrame *aSubtreeRoot);
2122 #endif
2123
2124 /**
2125 * Determine if aImageFrame (which is an nsImageFrame, nsImageControlFrame, or
2126 * nsSVGImageFrame) is visible or close to being visible via scrolling and
2127 * update the presshell with this knowledge.
2128 */
2129 static void
2130 UpdateImageVisibilityForFrame(nsIFrame* aImageFrame);
2131
2132 /**
2133 * Calculate the compostion size for a frame. See FrameMetrics.h for
2134 * defintion of composition size (or bounds).
2135 */
2136 static nsSize
2137 CalculateCompositionSizeForFrame(nsIFrame* aFrame);
2138
2139 /**
2140 * Calculate the composition size for the root scroll frame of the root
2141 * content document.
2142 * @param aFrame A frame in the root content document (or a descendant of it).
2143 * @param aIsRootContentDocRootScrollFrame Whether aFrame is already the root
2144 * scroll frame of the root content document. In this case we just
2145 * use aFrame's own composition size.
2146 * @param aMetrics A partially populated FrameMetrics for aFrame. Must have at
2147 * least mCompositionBounds, mCumulativeResolution, and
2148 * mDevPixelsPerCSSPixel set.
2149 */
2150 static CSSSize
2151 CalculateRootCompositionSize(nsIFrame* aFrame,
2152 bool aIsRootContentDocRootScrollFrame,
2153 const FrameMetrics& aMetrics);
2154
2155 /**
2156 * Calculate the scrollable rect for a frame. See FrameMetrics.h for
2157 * defintion of scrollable rect. aScrollableFrame is the scroll frame to calculate
2158 * the scrollable rect for. If it's null then we calculate the scrollable rect
2159 * as the rect of the root frame.
2160 */
2161 static nsRect
2162 CalculateScrollableRectForFrame(nsIScrollableFrame* aScrollableFrame, nsIFrame* aRootFrame);
2163
2164 /**
2165 * Calculate the expanded scrollable rect for a frame. See FrameMetrics.h for
2166 * defintion of expanded scrollable rect.
2167 */
2168 static nsRect
2169 CalculateExpandedScrollableRect(nsIFrame* aFrame);
2170
2171 /**
2172 * Return whether we want to use APZ for subframes in this process.
2173 * Currently we don't support APZ for the parent process on B2G.
2174 */
2175 static bool WantSubAPZC();
2176
2177 /**
2178 * Get the display port for |aScrollFrame|'s content. If |aScrollFrame|
2179 * WantsAsyncScroll() and we don't have a scrollable displayport yet (as
2180 * tracked by |aBuilder|), calculate and set a display port. Returns true if
2181 * there is (now) a displayport, and if so the displayport is returned in
2182 * |aOutDisplayport|.
2183 *
2184 * Note that a displayport can either be stored as a rect, or as a base
2185 * rect + margins. If it is stored as a base rect + margins, the base rect
2186 * is updated to |aDisplayPortBase|, and the rect assembled from the
2187 * base rect and margins is returned. If this function creates a displayport,
2188 * it computes margins and stores |aDisplayPortBase| as the base rect.
2189 *
2190 * This is intended to be called during display list building.
2191 */
2192 static bool GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder,
2193 nsIFrame* aScrollFrame,
2194 nsRect aDisplayPortBase,
2195 nsRect* aOutDisplayport);
2196
2197 private:
2198 static uint32_t sFontSizeInflationEmPerLine;
2199 static uint32_t sFontSizeInflationMinTwips;
2200 static uint32_t sFontSizeInflationLineThreshold;
2201 static int32_t sFontSizeInflationMappingIntercept;
2202 static uint32_t sFontSizeInflationMaxRatio;
2203 static bool sFontSizeInflationForceEnabled;
2204 static bool sFontSizeInflationDisabledInMasterProcess;
2205 static bool sInvalidationDebuggingIsEnabled;
2206 static bool sCSSVariablesEnabled;
2207 static bool sInterruptibleReflowEnabled;
2208 };
2209
2210 MOZ_FINISH_NESTED_ENUM_CLASS(nsLayoutUtils::RepaintMode)
2211
2212 template<typename PointType, typename RectType, typename CoordType>
2213 /* static */ bool
2214 nsLayoutUtils::PointIsCloserToRect(PointType aPoint, const RectType& aRect,
2215 CoordType& aClosestXDistance,
2216 CoordType& aClosestYDistance)
2217 {
2218 CoordType fromLeft = aPoint.x - aRect.x;
2219 CoordType fromRight = aPoint.x - aRect.XMost();
2220
2221 CoordType xDistance;
2222 if (fromLeft >= 0 && fromRight <= 0) {
2223 xDistance = 0;
2224 } else {
2225 xDistance = std::min(abs(fromLeft), abs(fromRight));
2226 }
2227
2228 if (xDistance <= aClosestXDistance) {
2229 if (xDistance < aClosestXDistance) {
2230 aClosestYDistance = std::numeric_limits<CoordType>::max();
2231 }
2232
2233 CoordType fromTop = aPoint.y - aRect.y;
2234 CoordType fromBottom = aPoint.y - aRect.YMost();
2235
2236 CoordType yDistance;
2237 if (fromTop >= 0 && fromBottom <= 0) {
2238 yDistance = 0;
2239 } else {
2240 yDistance = std::min(abs(fromTop), abs(fromBottom));
2241 }
2242
2243 if (yDistance < aClosestYDistance) {
2244 aClosestXDistance = xDistance;
2245 aClosestYDistance = yDistance;
2246 return true;
2247 }
2248 }
2249
2250 return false;
2251 }
2252
2253 namespace mozilla {
2254 namespace layout {
2255
2256 /**
2257 * An RAII class which will, for the duration of its lifetime,
2258 * **if** the frame given is a container for font size inflation,
2259 * set the current inflation container on the pres context to null
2260 * (and then, in its destructor, restore the old value).
2261 */
2262 class AutoMaybeDisableFontInflation {
2263 public:
2264 AutoMaybeDisableFontInflation(nsIFrame *aFrame);
2265
2266 ~AutoMaybeDisableFontInflation();
2267 private:
2268 nsPresContext *mPresContext;
2269 bool mOldValue;
2270 };
2271
2272 }
2273 }
2274
2275 class nsSetAttrRunnable : public nsRunnable
2276 {
2277 public:
2278 nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName,
2279 const nsAString& aValue);
2280 nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName,
2281 int32_t aValue);
2282
2283 NS_DECL_NSIRUNNABLE
2284
2285 nsCOMPtr<nsIContent> mContent;
2286 nsCOMPtr<nsIAtom> mAttrName;
2287 nsAutoString mValue;
2288 };
2289
2290 class nsUnsetAttrRunnable : public nsRunnable
2291 {
2292 public:
2293 nsUnsetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName);
2294
2295 NS_DECL_NSIRUNNABLE
2296
2297 nsCOMPtr<nsIContent> mContent;
2298 nsCOMPtr<nsIAtom> mAttrName;
2299 };
2300
2301 #endif // nsLayoutUtils_h__

mercurial