Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / gfx / layers / FrameMetrics.cpp
blobfe11ecea8a245aba4faedb5bff926cbbc15f1164
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "FrameMetrics.h"
9 #include <ostream>
11 #include "gfxUtils.h"
12 #include "nsStyleConsts.h"
13 #include "mozilla/gfx/Types.h"
15 namespace mozilla {
16 namespace layers {
18 const ScrollableLayerGuid::ViewID ScrollableLayerGuid::NULL_SCROLL_ID = 0;
20 std::ostream& operator<<(std::ostream& aStream, const FrameMetrics& aMetrics) {
21 aStream << "{ [cb=" << aMetrics.GetCompositionBounds()
22 << "] [sr=" << aMetrics.GetScrollableRect()
23 << "] [s=" << aMetrics.GetVisualScrollOffset();
24 if (aMetrics.GetVisualScrollUpdateType() != FrameMetrics::eNone) {
25 aStream << "] [vd=" << aMetrics.GetVisualDestination();
27 if (aMetrics.IsScrollInfoLayer()) {
28 aStream << "] [scrollinfo";
30 aStream << "] [dp=" << aMetrics.GetDisplayPort()
31 << "] [rcs=" << aMetrics.GetBoundingCompositionSize()
32 << "] [v=" << aMetrics.GetLayoutViewport()
33 << nsPrintfCString("] [z=(ld=%.3f r=%.3f",
34 aMetrics.GetDevPixelsPerCSSPixel().scale,
35 aMetrics.GetPresShellResolution())
36 .get()
37 << " cr=" << aMetrics.GetCumulativeResolution()
38 << " z=" << aMetrics.GetZoom()
39 << " t=" << aMetrics.GetTransformToAncestorScale() << " )] [u=("
40 << (int)aMetrics.GetVisualScrollUpdateType() << " "
41 << aMetrics.GetScrollGeneration()
42 << ")] scrollId=" << aMetrics.GetScrollId();
43 if (aMetrics.IsRootContent()) {
44 aStream << " [rcd]";
46 aStream << " }";
47 return aStream;
50 void FrameMetrics::RecalculateLayoutViewportOffset() {
51 // For subframes, the visual and layout viewports coincide, so just
52 // keep the layout viewport offset in sync with the visual one.
53 if (!mIsRootContent) {
54 mLayoutViewport.MoveTo(GetVisualScrollOffset());
55 return;
57 // For the root, the two viewports can diverge, but the layout
58 // viewport needs to keep enclosing the visual viewport.
59 KeepLayoutViewportEnclosingVisualViewport(GetVisualViewport(),
60 mScrollableRect, mLayoutViewport);
63 /* static */
64 void FrameMetrics::KeepLayoutViewportEnclosingVisualViewport(
65 const CSSRect& aVisualViewport, const CSSRect& aScrollableRect,
66 CSSRect& aLayoutViewport) {
67 // If the visual viewport is contained within the layout viewport, we don't
68 // need to make any adjustments, so we can exit early.
70 // Additionally, if the composition bounds changes (due to an orientation
71 // change, window resize, etc.), it may take a few frames for aLayoutViewport
72 // to update and during that time, the visual viewport may be larger than the
73 // layout viewport. In such situations, we take an early exit if the visual
74 // viewport contains the layout viewport.
75 if (aLayoutViewport.Contains(aVisualViewport) ||
76 aVisualViewport.Contains(aLayoutViewport)) {
77 return;
80 // If visual viewport size is greater than the layout viewport, move the
81 // layout viewport such that it remains inside the visual viewport. Otherwise,
82 // move the layout viewport such that the visual viewport is contained
83 // inside the layout viewport.
84 if ((aLayoutViewport.Width() < aVisualViewport.Width() &&
85 !FuzzyEqualsMultiplicative(aLayoutViewport.Width(),
86 aVisualViewport.Width())) ||
87 (aLayoutViewport.Height() < aVisualViewport.Height() &&
88 !FuzzyEqualsMultiplicative(aLayoutViewport.Height(),
89 aVisualViewport.Height()))) {
90 if (aLayoutViewport.X() < aVisualViewport.X()) {
91 // layout viewport moves right
92 aLayoutViewport.MoveToX(aVisualViewport.X());
93 } else if (aVisualViewport.XMost() < aLayoutViewport.XMost()) {
94 // layout viewport moves left
95 aLayoutViewport.MoveByX(aVisualViewport.XMost() -
96 aLayoutViewport.XMost());
98 if (aLayoutViewport.Y() < aVisualViewport.Y()) {
99 // layout viewport moves down
100 aLayoutViewport.MoveToY(aVisualViewport.Y());
101 } else if (aVisualViewport.YMost() < aLayoutViewport.YMost()) {
102 // layout viewport moves up
103 aLayoutViewport.MoveByY(aVisualViewport.YMost() -
104 aLayoutViewport.YMost());
106 } else {
107 if (aVisualViewport.X() < aLayoutViewport.X()) {
108 aLayoutViewport.MoveToX(aVisualViewport.X());
109 } else if (aLayoutViewport.XMost() < aVisualViewport.XMost()) {
110 aLayoutViewport.MoveByX(aVisualViewport.XMost() -
111 aLayoutViewport.XMost());
113 if (aVisualViewport.Y() < aLayoutViewport.Y()) {
114 aLayoutViewport.MoveToY(aVisualViewport.Y());
115 } else if (aLayoutViewport.YMost() < aVisualViewport.YMost()) {
116 aLayoutViewport.MoveByY(aVisualViewport.YMost() -
117 aLayoutViewport.YMost());
121 // Regardless of any adjustment above, the layout viewport is not allowed
122 // to go outside the scrollable rect.
123 aLayoutViewport = aLayoutViewport.MoveInsideAndClamp(aScrollableRect);
126 /* static */
127 CSSRect FrameMetrics::CalculateScrollRange(
128 const CSSRect& aScrollableRect, const ParentLayerRect& aCompositionBounds,
129 const CSSToParentLayerScale& aZoom) {
130 CSSSize scrollPortSize =
131 CalculateCompositedSizeInCssPixels(aCompositionBounds, aZoom);
132 CSSRect scrollRange = aScrollableRect;
133 scrollRange.SetWidth(
134 std::max(scrollRange.Width() - scrollPortSize.width, 0.0f));
135 scrollRange.SetHeight(
136 std::max(scrollRange.Height() - scrollPortSize.height, 0.0f));
137 return scrollRange;
140 /* static */
141 CSSSize FrameMetrics::CalculateCompositedSizeInCssPixels(
142 const ParentLayerRect& aCompositionBounds,
143 const CSSToParentLayerScale& aZoom) {
144 if (aZoom == CSSToParentLayerScale(0)) {
145 return CSSSize(); // avoid division by zero
147 return aCompositionBounds.Size() / aZoom;
150 bool FrameMetrics::ApplyScrollUpdateFrom(const ScrollPositionUpdate& aUpdate) {
151 // In applying a main-thread scroll update, try to preserve the relative
152 // offset between the visual and layout viewports.
153 CSSPoint relativeOffset = GetVisualScrollOffset() - GetLayoutScrollOffset();
154 MOZ_ASSERT(IsRootContent() || relativeOffset == CSSPoint());
155 // We need to set the two offsets together, otherwise a subsequent
156 // RecalculateLayoutViewportOffset() could see divergent layout and
157 // visual offsets.
158 bool offsetChanged = SetLayoutScrollOffset(aUpdate.GetDestination());
159 offsetChanged |=
160 ClampAndSetVisualScrollOffset(aUpdate.GetDestination() + relativeOffset);
161 return offsetChanged;
164 CSSPoint FrameMetrics::ApplyRelativeScrollUpdateFrom(
165 const ScrollPositionUpdate& aUpdate) {
166 MOZ_ASSERT(aUpdate.GetType() == ScrollUpdateType::Relative);
167 CSSPoint origin = GetVisualScrollOffset();
168 CSSPoint delta = (aUpdate.GetDestination() - aUpdate.GetSource());
169 ClampAndSetVisualScrollOffset(origin + delta);
170 return GetVisualScrollOffset() - origin;
173 CSSPoint FrameMetrics::ApplyPureRelativeScrollUpdateFrom(
174 const ScrollPositionUpdate& aUpdate) {
175 MOZ_ASSERT(aUpdate.GetType() == ScrollUpdateType::PureRelative);
176 CSSPoint origin = GetVisualScrollOffset();
177 ClampAndSetVisualScrollOffset(origin + aUpdate.GetDelta());
178 return GetVisualScrollOffset() - origin;
181 void FrameMetrics::UpdatePendingScrollInfo(const ScrollPositionUpdate& aInfo) {
182 // We only get this "pending scroll info" for paint-skip transactions,
183 // but PureRelative position updates always trigger a full paint, so
184 // we should never enter this code with a PureRelative update type. For
185 // the other types, the destination field on the ScrollPositionUpdate will
186 // tell us the final layout scroll position on the main thread.
187 MOZ_ASSERT(aInfo.GetType() != ScrollUpdateType::PureRelative);
189 // In applying a main-thread scroll update, try to preserve the relative
190 // offset between the visual and layout viewports.
191 CSSPoint relativeOffset = GetVisualScrollOffset() - GetLayoutScrollOffset();
192 MOZ_ASSERT(IsRootContent() || relativeOffset == CSSPoint());
194 SetLayoutScrollOffset(aInfo.GetDestination());
195 ClampAndSetVisualScrollOffset(aInfo.GetDestination() + relativeOffset);
196 mScrollGeneration = aInfo.GetGeneration();
199 std::ostream& operator<<(std::ostream& aStream,
200 const OverscrollBehavior& aBehavior) {
201 switch (aBehavior) {
202 case OverscrollBehavior::Auto: {
203 aStream << "auto";
204 break;
206 case OverscrollBehavior::Contain: {
207 aStream << "contain";
208 break;
210 case OverscrollBehavior::None: {
211 aStream << "none";
212 break;
215 return aStream;
218 OverscrollBehaviorInfo::OverscrollBehaviorInfo()
219 : mBehaviorX(OverscrollBehavior::Auto),
220 mBehaviorY(OverscrollBehavior::Auto) {}
222 static OverscrollBehavior ToOverscrollBehavior(
223 StyleOverscrollBehavior aBehavior) {
224 switch (aBehavior) {
225 case StyleOverscrollBehavior::Auto:
226 return OverscrollBehavior::Auto;
227 case StyleOverscrollBehavior::Contain:
228 return OverscrollBehavior::Contain;
229 case StyleOverscrollBehavior::None:
230 return OverscrollBehavior::None;
232 MOZ_ASSERT_UNREACHABLE("Invalid overscroll behavior");
233 return OverscrollBehavior::Auto;
236 OverscrollBehaviorInfo OverscrollBehaviorInfo::FromStyleConstants(
237 StyleOverscrollBehavior aBehaviorX, StyleOverscrollBehavior aBehaviorY) {
238 OverscrollBehaviorInfo result;
239 result.mBehaviorX = ToOverscrollBehavior(aBehaviorX);
240 result.mBehaviorY = ToOverscrollBehavior(aBehaviorY);
241 return result;
244 bool OverscrollBehaviorInfo::operator==(
245 const OverscrollBehaviorInfo& aOther) const {
246 return mBehaviorX == aOther.mBehaviorX && mBehaviorY == aOther.mBehaviorY;
249 std::ostream& operator<<(std::ostream& aStream,
250 const OverscrollBehaviorInfo& aInfo) {
251 if (aInfo.mBehaviorX == aInfo.mBehaviorY) {
252 aStream << aInfo.mBehaviorX;
253 } else {
254 aStream << "{ x=" << aInfo.mBehaviorX << ", y=" << aInfo.mBehaviorY << " }";
256 return aStream;
259 std::ostream& operator<<(std::ostream& aStream,
260 const ScrollMetadata& aMetadata) {
261 aStream << "{ [description=" << aMetadata.GetContentDescription()
262 << "] [metrics=" << aMetadata.GetMetrics();
263 if (aMetadata.GetScrollParentId() != ScrollableLayerGuid::NULL_SCROLL_ID) {
264 aStream << "] [scrollParent=" << aMetadata.GetScrollParentId();
266 if (aMetadata.GetHasScrollgrab()) {
267 aStream << "] [scrollgrab";
269 aStream << "] [overscroll=" << aMetadata.GetOverscrollBehavior() << "] ["
270 << aMetadata.GetScrollUpdates().Length() << " scrollupdates"
271 << "] }";
272 return aStream;
275 StaticAutoPtr<const ScrollMetadata> ScrollMetadata::sNullMetadata;
277 } // namespace layers
278 } // namespace mozilla