1 | // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | package org.chromium.content.browser; |
6 | |
7 | /** |
8 | * Cached copy of all positions and scales (CSS-to-DIP-to-physical pixels) |
9 | * reported from the renderer. |
10 | * Provides wrappers and a utility class to help with coordinate transforms on the client side. |
11 | * Provides the internally-visible set of update methods (called from ContentViewCore). |
12 | * |
13 | * Unless stated otherwise, all coordinates are in CSS (document) coordinate space. |
14 | */ |
15 | public class RenderCoordinates { |
16 | // Scroll offset from the native in CSS. |
17 | private float mScrollXCss; |
18 | private float mScrollYCss; |
19 | |
20 | // Content size from native in CSS. |
21 | private float mContentWidthCss; |
22 | private float mContentHeightCss; |
23 | |
24 | // Last-frame render-reported viewport size in CSS. |
25 | private float mLastFrameViewportWidthCss; |
26 | private float mLastFrameViewportHeightCss; |
27 | |
28 | // Cached page scale factor from native. |
29 | private float mPageScaleFactor = 1.0f; |
30 | private float mMinPageScaleFactor = 1.0f; |
31 | private float mMaxPageScaleFactor = 1.0f; |
32 | |
33 | // Cached device density. |
34 | private float mDeviceScaleFactor; |
35 | |
36 | private float mContentOffsetYPix; |
37 | |
38 | // Internally-visible set of update methods (used by ContentViewCore). |
39 | void reset() { |
40 | mScrollXCss = mScrollYCss = 0; |
41 | mPageScaleFactor = 1.0f; |
42 | } |
43 | |
44 | void updateContentSizeCss(float contentWidthCss, float contentHeightCss) { |
45 | mContentWidthCss = contentWidthCss; |
46 | mContentHeightCss = contentHeightCss; |
47 | } |
48 | |
49 | void setDeviceScaleFactor(float deviceScaleFactor) { |
50 | mDeviceScaleFactor = deviceScaleFactor; |
51 | } |
52 | |
53 | void updateFrameInfo( |
54 | float scrollXCss, float scrollYCss, |
55 | float contentWidthCss, float contentHeightCss, |
56 | float viewportWidthCss, float viewportHeightCss, |
57 | float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor, |
58 | float contentOffsetYPix) { |
59 | mScrollXCss = scrollXCss; |
60 | mScrollYCss = scrollYCss; |
61 | mPageScaleFactor = pageScaleFactor; |
62 | mMinPageScaleFactor = minPageScaleFactor; |
63 | mMaxPageScaleFactor = maxPageScaleFactor; |
64 | mContentOffsetYPix = contentOffsetYPix; |
65 | |
66 | updateContentSizeCss(contentWidthCss, contentHeightCss); |
67 | mLastFrameViewportWidthCss = viewportWidthCss; |
68 | mLastFrameViewportHeightCss = viewportHeightCss; |
69 | } |
70 | |
71 | /** |
72 | * Handles conversion of a point from window-relative-local-dip or screen-pix |
73 | * to document-absolute-CSS space and vice versa. |
74 | */ |
75 | public class NormalizedPoint { |
76 | private float mXAbsoluteCss, mYAbsoluteCss; |
77 | |
78 | private NormalizedPoint() { |
79 | } |
80 | |
81 | /** |
82 | * @return Absolute CSS (document) X coordinate of the point. |
83 | */ |
84 | public float getXAbsoluteCss() { return mXAbsoluteCss; } |
85 | |
86 | /** |
87 | * @return Absolute CSS (document) Y coordinate of the point. |
88 | */ |
89 | public float getYAbsoluteCss() { return mYAbsoluteCss; } |
90 | |
91 | /** |
92 | * @return Local device-scale-unadjusted X coordinate of the point. |
93 | */ |
94 | public float getXLocalDip() { return (mXAbsoluteCss - mScrollXCss) * mPageScaleFactor; } |
95 | |
96 | /** |
97 | * @return Local device-scale-unadjusted Y coordinate of the point. |
98 | */ |
99 | public float getYLocalDip() { return (mYAbsoluteCss - mScrollYCss) * mPageScaleFactor; } |
100 | |
101 | /** |
102 | * @return Physical (screen) X coordinate of the point. |
103 | */ |
104 | public float getXPix() { return getXLocalDip() * mDeviceScaleFactor; } |
105 | |
106 | /** |
107 | * @return Physical (screen) Y coordinate of the point. |
108 | */ |
109 | public float getYPix() { return getYLocalDip() * mDeviceScaleFactor + mContentOffsetYPix; } |
110 | |
111 | /** |
112 | * Sets the point to the given absolute CSS (document) coordinates. |
113 | */ |
114 | public void setAbsoluteCss(float xCss, float yCss) { |
115 | mXAbsoluteCss = xCss; |
116 | mYAbsoluteCss = yCss; |
117 | } |
118 | |
119 | /** |
120 | * Sets the point to the given local device-scale-unadjusted coordinates. |
121 | */ |
122 | public void setLocalDip(float xDip, float yDip) { |
123 | setAbsoluteCss( |
124 | xDip / mPageScaleFactor + mScrollXCss, |
125 | yDip / mPageScaleFactor + mScrollYCss); |
126 | } |
127 | |
128 | /** |
129 | * Sets the point to the given physical (screen) coordinates. |
130 | */ |
131 | public void setScreen(float xPix, float yPix) { |
132 | setLocalDip(xPix / mDeviceScaleFactor, yPix / mDeviceScaleFactor); |
133 | } |
134 | } |
135 | |
136 | /** |
137 | * @return A helper to convert a point between between absolute CSS and local DIP spaces. |
138 | */ |
139 | public NormalizedPoint createNormalizedPoint() { |
140 | return new NormalizedPoint(); |
141 | } |
142 | |
143 | /** |
144 | * @return Horizontal scroll offset in CSS pixels. |
145 | */ |
146 | public float getScrollX() { return mScrollXCss; } |
147 | |
148 | /** |
149 | * @return Vertical scroll offset in CSS pixels. |
150 | */ |
151 | public float getScrollY() { return mScrollYCss; } |
152 | |
153 | /** |
154 | * @return Horizontal scroll offset in physical pixels. |
155 | */ |
156 | public float getScrollXPix() { return fromLocalCssToPix(mScrollXCss); } |
157 | |
158 | /** |
159 | * @return Vertical scroll offset in physical pixels. |
160 | */ |
161 | public float getScrollYPix() { return fromLocalCssToPix(mScrollYCss); } |
162 | |
163 | /** |
164 | * @return Horizontal scroll offset in physical pixels (approx, integer). |
165 | */ |
166 | public int getScrollXPixInt() { return (int) Math.floor(getScrollXPix()); } |
167 | |
168 | /** |
169 | * @return Vertical scroll offset in physical pixels (approx, integer). |
170 | */ |
171 | public int getScrollYPixInt() { return (int) Math.floor(getScrollYPix()); } |
172 | |
173 | /** |
174 | * @return Width of the content in CSS pixels. |
175 | */ |
176 | public float getContentWidthCss() { return mContentWidthCss; } |
177 | |
178 | /** |
179 | * @return Height of the content in CSS pixels. |
180 | */ |
181 | public float getContentHeightCss() { return mContentHeightCss; } |
182 | |
183 | /** |
184 | * @return Approximate width of the content in physical pixels. |
185 | */ |
186 | public float getContentWidthPix() { return fromLocalCssToPix(mContentWidthCss); } |
187 | |
188 | /** |
189 | * @return Approximate height of the content in physical pixels. |
190 | */ |
191 | public float getContentHeightPix() { return fromLocalCssToPix(mContentHeightCss); } |
192 | |
193 | /** |
194 | * @return Approximate width of the content in physical pixels (integer). |
195 | */ |
196 | public int getContentWidthPixInt() { return (int) Math.ceil(getContentWidthPix()); } |
197 | |
198 | /** |
199 | * @return Approximate height of the content in physical pixels (integer). |
200 | */ |
201 | public int getContentHeightPixInt() { return (int) Math.ceil(getContentHeightPix()); } |
202 | |
203 | /** |
204 | * @return Render-reported width of the viewport in CSS pixels. |
205 | */ |
206 | public float getLastFrameViewportWidthCss() { return mLastFrameViewportWidthCss; } |
207 | |
208 | /** |
209 | * @return Render-reported height of the viewport in CSS pixels. |
210 | */ |
211 | public float getLastFrameViewportHeightCss() { return mLastFrameViewportHeightCss; } |
212 | |
213 | /** |
214 | * @return Render-reported width of the viewport in physical pixels (approximate). |
215 | */ |
216 | public float getLastFrameViewportWidthPix() { |
217 | return fromLocalCssToPix(mLastFrameViewportWidthCss); |
218 | } |
219 | |
220 | /** |
221 | * @return Render-reported height of the viewport in physical pixels (approximate). |
222 | */ |
223 | public float getLastFrameViewportHeightPix() { |
224 | return fromLocalCssToPix(mLastFrameViewportHeightCss); |
225 | } |
226 | |
227 | /** |
228 | * @return Render-reported width of the viewport in physical pixels (approx, integer). |
229 | */ |
230 | public int getLastFrameViewportWidthPixInt() { |
231 | return (int) Math.ceil(getLastFrameViewportWidthPix()); |
232 | } |
233 | |
234 | /** |
235 | * @return Render-reported height of the viewport in physical pixels (approx, integer). |
236 | */ |
237 | public int getLastFrameViewportHeightPixInt() { |
238 | return (int) Math.ceil(getLastFrameViewportHeightPix()); |
239 | } |
240 | |
241 | /** |
242 | * @return The Physical on-screen Y offset amount below the top controls. |
243 | */ |
244 | public float getContentOffsetYPix() { |
245 | return mContentOffsetYPix; |
246 | } |
247 | |
248 | /** |
249 | * @return Current page scale factor (maps CSS pixels to DIP pixels). |
250 | */ |
251 | public float getPageScaleFactor() { return mPageScaleFactor; } |
252 | |
253 | /** |
254 | * @return Minimum page scale factor to be used with the content. |
255 | */ |
256 | public float getMinPageScaleFactor() { return mMinPageScaleFactor; } |
257 | |
258 | /** |
259 | * @return Maximum page scale factor to be used with the content. |
260 | */ |
261 | public float getMaxPageScaleFactor() { return mMaxPageScaleFactor; } |
262 | |
263 | /** |
264 | * @return Current device scale factor (maps DIP pixels to physical pixels). |
265 | */ |
266 | public float getDeviceScaleFactor() { return mDeviceScaleFactor; } |
267 | |
268 | /** |
269 | * @return True if the page doesn't allow zoom-in/zoom-out. |
270 | */ |
271 | public boolean hasFixedPageScale() { return mMinPageScaleFactor == mMaxPageScaleFactor; } |
272 | |
273 | /** |
274 | * @return Maximum possible horizontal scroll in physical pixels. |
275 | */ |
276 | public float getMaxHorizontalScrollPix() { |
277 | return getContentWidthPix() - getLastFrameViewportWidthPix(); |
278 | } |
279 | |
280 | /** |
281 | * @return Maximum possible vertical scroll in physical pixels. |
282 | */ |
283 | public float getMaxVerticalScrollPix() { |
284 | return getContentHeightPix() - getLastFrameViewportHeightPix(); |
285 | } |
286 | |
287 | /** |
288 | * @return Maximum possible horizontal scroll in physical pixels (approx, integer). |
289 | */ |
290 | public int getMaxHorizontalScrollPixInt() { |
291 | return (int) Math.floor(getMaxHorizontalScrollPix()); |
292 | } |
293 | |
294 | /** |
295 | * @return Maximum possible vertical scroll in physical pixels (approx, integer). |
296 | */ |
297 | public int getMaxVerticalScrollPixInt() { |
298 | return (int) Math.floor(getMaxVerticalScrollPix()); |
299 | } |
300 | |
301 | /** |
302 | * @return Physical on-screen coordinate converted to local DIP. |
303 | */ |
304 | public float fromPixToDip(float pix) { |
305 | return pix / mDeviceScaleFactor; |
306 | } |
307 | |
308 | /** |
309 | * @return Local DIP converted to physical coordinates. |
310 | */ |
311 | public float fromDipToPix(float dip) { |
312 | return dip * mDeviceScaleFactor; |
313 | } |
314 | |
315 | /** |
316 | * @return Physical coordinate converted to local CSS. |
317 | */ |
318 | public float fromPixToLocalCss(float pix) { |
319 | return pix / (mDeviceScaleFactor * mPageScaleFactor); |
320 | } |
321 | |
322 | /** |
323 | * @return Local CSS converted to physical coordinates. |
324 | */ |
325 | public float fromLocalCssToPix(float css) { |
326 | return css * mPageScaleFactor * mDeviceScaleFactor; |
327 | } |
328 | } |