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