OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chromoting; | 5 package org.chromium.chromoting; |
6 | 6 |
7 import android.graphics.Matrix; | 7 import android.graphics.Matrix; |
8 import android.graphics.PointF; | 8 import android.graphics.PointF; |
9 import android.graphics.Rect; | 9 import android.graphics.Rect; |
10 import android.graphics.RectF; | 10 import android.graphics.RectF; |
11 | 11 |
12 /** | 12 /** |
13 * This class is responsible for transforming the desktop image matrix. | 13 * This class is responsible for transforming the desktop image matrix. |
14 */ | 14 */ |
15 public class DesktopCanvas { | 15 public class DesktopCanvas { |
16 /** | 16 /** |
17 * Maximum allowed zoom level - see {@link #repositionImageWithZoom()}. | 17 * Maximum allowed zoom level - see {@link #repositionImageWithZoom()}. |
18 */ | 18 */ |
19 private static final float MAX_ZOOM_FACTOR = 100.0f; | 19 private static final float MAX_ZOOM_FACTOR = 100.0f; |
20 | 20 |
21 /** | |
22 * Used to smoothly reduce the amount of padding whle the user is zooming. | |
Lambros
2016/09/30 01:59:37
s/whle/while/
joedow
2016/09/30 19:42:57
Done.
| |
23 */ | |
24 private static final float PADDING_REDUCTION_FACTOR = 0.85f; | |
25 | |
21 private final RenderStub mRenderStub; | 26 private final RenderStub mRenderStub; |
22 private final RenderData mRenderData; | 27 private final RenderData mRenderData; |
23 | 28 |
24 /** | 29 /** |
25 * Represents the actual center of the viewport. This value needs to be a p air of floats so the | 30 * Represents the actual center of the viewport. This value needs to be a p air of floats so the |
26 * desktop image can be positioned with sub-pixel accuracy for smoother pann ing animations at | 31 * desktop image can be positioned with sub-pixel accuracy for smoother pann ing animations at |
27 * high zoom levels. | 32 * high zoom levels. |
28 */ | 33 */ |
29 private PointF mViewportPosition = new PointF(); | 34 private PointF mViewportPosition = new PointF(); |
30 | 35 |
31 /** | 36 /** |
32 * Represents the desired center of the viewport. This value may not repres ent the actual | 37 * Represents the desired center of the viewport. This value may not repres ent the actual |
33 * center of the viewport as adjustments are made to ensure as much of the d esktop is visible as | 38 * center of the viewport as adjustments are made to ensure as much of the d esktop is visible as |
34 * possible. This value needs to be a pair of floats so the desktop image c an be positioned | 39 * possible. This value needs to be a pair of floats so the desktop image c an be positioned |
35 * with sub-pixel accuracy for smoother panning animations at high zoom leve ls. | 40 * with sub-pixel accuracy for smoother panning animations at high zoom leve ls. |
36 */ | 41 */ |
37 private PointF mCursorPosition = new PointF(); | 42 private PointF mCursorPosition = new PointF(); |
38 | 43 |
39 /** | 44 /** |
40 * Represents the amount of space, in pixels, used by System UI. | 45 * Represents the amount of space, in pixels, used by System UI. |
41 */ | 46 */ |
42 private Rect mSystemUiOffsetPixels = new Rect(); | 47 private Rect mSystemUiOffsetPixels = new Rect(); |
43 | 48 |
49 /** | |
50 * Represents the additional space, in pixels, for each edge of the desktop image. Used for | |
51 * positioning the desktop canvas to allow the user to scroll it below any v isible System UI. | |
Lambros
2016/09/30 01:59:36
Is this in screen or image coordinates?
Can you ex
joedow
2016/09/30 19:42:56
Added a block of text at the top of the class givi
| |
52 */ | |
53 private RectF mImagePadding = new RectF(); | |
54 | |
44 public DesktopCanvas(RenderStub renderStub, RenderData renderData) { | 55 public DesktopCanvas(RenderStub renderStub, RenderData renderData) { |
45 mRenderStub = renderStub; | 56 mRenderStub = renderStub; |
46 mRenderData = renderData; | 57 mRenderData = renderData; |
47 } | 58 } |
48 | 59 |
49 /** | 60 /** |
50 * Sets the desired center position of the viewport (a.k.a. the cursor posit ion) and ensures | 61 * Sets the desired center position of the viewport (a.k.a. the cursor posit ion) and ensures |
51 * the viewport is updated to include the cursor within it. | 62 * the viewport is updated to include the cursor within it. |
52 * | 63 * |
53 * @param newX The new x coordinate value for the desired center position. | 64 * @param newX The new x coordinate value for the desired center position. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 mRenderData.transform.mapVectors(imageSize); | 173 mRenderData.transform.mapVectors(imageSize); |
163 | 174 |
164 if (imageSize[0] < mRenderData.screenWidth && imageSize[1] < mRenderData .screenHeight) { | 175 if (imageSize[0] < mRenderData.screenWidth && imageSize[1] < mRenderData .screenHeight) { |
165 // Displayed image is too small in both directions, so apply the min imum zoom | 176 // Displayed image is too small in both directions, so apply the min imum zoom |
166 // level needed to fit either the width or height. | 177 // level needed to fit either the width or height. |
167 float scale = Math.min((float) mRenderData.screenWidth / mRenderData .imageWidth, | 178 float scale = Math.min((float) mRenderData.screenWidth / mRenderData .imageWidth, |
168 (float) mRenderData.screenHeight / mRenderDat a.imageHeight); | 179 (float) mRenderData.screenHeight / mRenderDat a.imageHeight); |
169 mRenderData.transform.setScale(scale, scale); | 180 mRenderData.transform.setScale(scale, scale); |
170 } | 181 } |
171 | 182 |
183 // Trim the image padding if the user is zooming out. This prevents cas es where the image | |
184 // pops to the center when it reaches its minimum size. Note that we do not need to do | |
185 // anything when the user is zooming in as the canvas will expand and ab sorb the padding. | |
186 if (scaleFactor < 1.0f) { | |
187 mImagePadding.set(mImagePadding.left * PADDING_REDUCTION_FACTOR, | |
188 mImagePadding.top * PADDING_REDUCTION_FACTOR, | |
189 mImagePadding.right * PADDING_REDUCTION_FACTOR, | |
190 mImagePadding.bottom * PADDING_REDUCTION_FACTOR); | |
191 } | |
192 | |
172 if (centerOnCursor) { | 193 if (centerOnCursor) { |
173 setCursorPosition(mCursorPosition.x, mCursorPosition.y); | 194 setCursorPosition(mCursorPosition.x, mCursorPosition.y); |
174 } else { | 195 } else { |
175 // Find the new screen center (it was probably changed during the zo om operation) and | 196 // Find the new screen center (it was probably changed during the zo om operation) and |
176 // update the viewport and cursor. | 197 // update the viewport and cursor. |
177 float[] mappedPoints = { | 198 float[] mappedPoints = { |
178 ((float) mRenderData.screenWidth / 2), ((float) mRenderData. screenHeight / 2)}; | 199 ((float) mRenderData.screenWidth / 2), ((float) mRenderData. screenHeight / 2)}; |
179 Matrix screenToImage = new Matrix(); | 200 Matrix screenToImage = new Matrix(); |
180 mRenderData.transform.invert(screenToImage); | 201 mRenderData.transform.invert(screenToImage); |
181 screenToImage.mapPoints(mappedPoints); | 202 screenToImage.mapPoints(mappedPoints); |
182 // The cursor is mapped to the center of the viewport in this case. | 203 // The cursor is mapped to the center of the viewport in this case. |
183 setCursorPosition(mappedPoints[0], mappedPoints[1]); | 204 setCursorPosition(mappedPoints[0], mappedPoints[1]); |
184 } | 205 } |
185 } | 206 } |
186 | 207 |
187 /** | 208 /** |
188 * Repositions the image by translating it (without affecting the zoom level ). | 209 * Repositions the image by translating it (without affecting the zoom level ). |
189 */ | 210 */ |
190 private void repositionImage() { | 211 private void repositionImage() { |
191 // Map the current viewport position to screen coordinates and adjust th e image position. | 212 // Map the current viewport position to screen coordinates and adjust th e image position. |
192 float[] viewportPosition = {mViewportPosition.x, mViewportPosition.y}; | 213 float[] viewportPosition = {mViewportPosition.x, mViewportPosition.y}; |
193 mRenderData.transform.mapPoints(viewportPosition); | 214 mRenderData.transform.mapPoints(viewportPosition); |
194 | 215 |
195 float viewportTransX = ((float) mRenderData.screenWidth / 2) - viewportP osition[0]; | 216 float viewportTransX = ((float) mRenderData.screenWidth / 2) - viewportP osition[0]; |
196 float viewportTransY = ((float) mRenderData.screenHeight / 2) - viewport Position[1]; | 217 float viewportTransY = ((float) mRenderData.screenHeight / 2) - viewport Position[1]; |
197 | 218 |
198 // Translate the image so the viewport center is displayed in the middle of the screen. | 219 // Translate the image so the viewport center is displayed in the middle of the screen. |
199 mRenderData.transform.postTranslate(viewportTransX, viewportTransY); | 220 mRenderData.transform.postTranslate(viewportTransX, viewportTransY); |
200 | 221 |
222 // Remove or add image padding based on the new position. | |
Lambros
2016/09/30 01:59:37
How is padding based on position?
joedow
2016/09/30 19:42:56
Removed comment since it wan't useful.
| |
223 adjustImagePadding(); | |
224 | |
201 mRenderStub.setTransformation(mRenderData.transform); | 225 mRenderStub.setTransformation(mRenderData.transform); |
202 } | 226 } |
203 | 227 |
204 /** | 228 /** |
205 * Updates the given point such that it refers to a coordinate within the bo unds provided. | 229 * Updates the given point such that it refers to a coordinate within the bo unds provided. |
206 * | 230 * |
207 * @param point The point to adjust, the original object is modified. | 231 * @param point The point to adjust, the original object is modified. |
208 * @param bounds The bounds used to constrain the point. | 232 * @param bounds The bounds used to constrain the point. |
209 */ | 233 */ |
210 private void constrainPointToBounds(PointF point, RectF bounds) { | 234 private void constrainPointToBounds(PointF point, RectF bounds) { |
211 if (point.x < bounds.left) { | 235 if (point.x < bounds.left) { |
212 point.x = bounds.left; | 236 point.x = bounds.left; |
213 } else if (point.x > bounds.right) { | 237 } else if (point.x > bounds.right) { |
214 point.x = bounds.right; | 238 point.x = bounds.right; |
215 } | 239 } |
216 | 240 |
217 if (point.y < bounds.top) { | 241 if (point.y < bounds.top) { |
218 point.y = bounds.top; | 242 point.y = bounds.top; |
219 } else if (point.y > bounds.bottom) { | 243 } else if (point.y > bounds.bottom) { |
220 point.y = bounds.bottom; | 244 point.y = bounds.bottom; |
221 } | 245 } |
222 } | 246 } |
223 | 247 |
224 /** Returns a region which defines the set of valid cursor values in image s pace. */ | 248 /** Returns a region which defines the set of valid cursor values in image s pace. */ |
225 private RectF getImageBounds() { | 249 private RectF getImageBounds() { |
226 return new RectF(0, 0, mRenderData.imageWidth, mRenderData.imageHeight); | 250 float[] maxPadding = getMaxPadding(); |
251 return new RectF(-maxPadding[0], -maxPadding[1], mRenderData.imageWidth + maxPadding[2], | |
Lambros
2016/09/30 01:59:36
If my reading is correct, this is the full image r
joedow
2016/09/30 19:42:56
I'll remove the maxPadding method since it is conf
| |
252 mRenderData.imageHeight + maxPadding[3]); | |
227 } | 253 } |
228 | 254 |
229 /** Returns a region which defines the set of valid viewport center values i n image space. */ | 255 /** Returns a region which defines the set of valid viewport center values i n image space. */ |
230 private RectF getViewportBounds() { | 256 private RectF getViewportBounds() { |
231 float[] screenVectors = {(float) mRenderData.screenWidth, (float) mRende rData.screenHeight}; | 257 float[] screenVectors = {(float) mRenderData.screenWidth, (float) mRende rData.screenHeight}; |
232 Matrix screenToImage = new Matrix(); | 258 Matrix screenToImage = new Matrix(); |
233 mRenderData.transform.invert(screenToImage); | 259 mRenderData.transform.invert(screenToImage); |
234 screenToImage.mapVectors(screenVectors); | 260 screenToImage.mapVectors(screenVectors); |
235 | 261 |
236 float xAdjust = 0.0f; | 262 float[] letterBoxPadding = getLetterboxPadding(); |
237 if (mRenderData.imageWidth < screenVectors[0]) { | 263 screenToImage.mapVectors(letterBoxPadding); |
238 // Image is narrower than the screen, so adjust the bounds to center it. | |
239 xAdjust = (screenVectors[0] - mRenderData.imageWidth) / 2.0f; | |
240 } | |
241 | |
242 float yAdjust = 0.0f; | |
243 if (mRenderData.imageHeight < screenVectors[1]) { | |
244 // Image is shorter than the screen, so adjust the bounds to center it. | |
245 yAdjust = (screenVectors[1] - mRenderData.imageHeight) / 2.0f; | |
246 } | |
247 | 264 |
248 // screenCenter values are 1/2 of a particular screen dimension mapped t o image space. | 265 // screenCenter values are 1/2 of a particular screen dimension mapped t o image space. |
249 float screenCenterX = screenVectors[0] / 2.0f; | 266 float screenCenterX = (screenVectors[0] / 2.0f) - letterBoxPadding[0]; |
250 float screenCenterY = screenVectors[1] / 2.0f; | 267 float screenCenterY = (screenVectors[1] / 2.0f) - letterBoxPadding[1]; |
251 return new RectF(screenCenterX - xAdjust, screenCenterY - yAdjust, | 268 RectF imageBounds = getImageBounds(); |
252 mRenderData.imageWidth - screenCenterX + xAdjust, | 269 return new RectF(imageBounds.left + screenCenterX, imageBounds.top + scr eenCenterY, |
Lambros
2016/09/30 01:59:36
return imageBounds.inset(screenCenterX, screenCent
joedow
2016/09/30 19:42:57
Done.
| |
253 mRenderData.imageHeight - screenCenterY + yAdjust); | 270 imageBounds.right - screenCenterX, imageBounds.bottom - screenCe nterY); |
271 } | |
272 | |
273 /** Returns the maximum amount of padding per edge (left, top, right, bottom ) in image space. */ | |
274 private float[] getMaxPadding() { | |
275 RectF systemUiOffsetPixels = getAdjustedSystemUiOffsets(); | |
276 float[] maxPadding = {Math.max(mImagePadding.left, systemUiOffsetPixels. left), | |
277 Math.max(mImagePadding.top, systemUiOffsetPixels.top), | |
278 Math.max(mImagePadding.right, systemUiOffsetPixels.right), | |
279 Math.max(mImagePadding.bottom, systemUiOffsetPixels.bottom)}; | |
280 Matrix screenToImage = new Matrix(); | |
281 mRenderData.transform.invert(screenToImage); | |
282 screenToImage.mapVectors(maxPadding); | |
283 | |
284 return maxPadding; | |
285 } | |
286 | |
287 /** Returns the letter box padding needed in each dimension (x and y) in scr een coordinates. */ | |
Lambros
2016/09/30 01:59:37
Maybe explain in a little more detail:
This is the
joedow
2016/09/30 19:42:57
Explained in detail at the top of the class.
| |
288 private float[] getLetterboxPadding() { | |
Lambros
2016/09/30 01:59:36
Maybe return PointF ?
joedow
2016/09/30 19:42:57
I had originally left this as a float [] to make t
| |
289 float[] imageVectors = {mRenderData.imageWidth, mRenderData.imageHeight} ; | |
290 mRenderData.transform.mapVectors(imageVectors); | |
291 | |
292 // We want to letterbox when the image is smaller than the screen in a s pecific dimension. | |
293 // Since we center the image, split the difference so it is equally dist ributed. | |
294 float widthAdjust = | |
295 Math.max(0.0f, ((float) mRenderData.screenWidth - imageVectors[0 ]) / 2.0f); | |
296 float heightAdjust = | |
297 Math.max(0.0f, ((float) mRenderData.screenHeight - imageVectors[ 1]) / 2.0f); | |
298 | |
299 return new float[] {widthAdjust, heightAdjust}; | |
300 } | |
301 | |
302 /** | |
303 * Returns the amount of System UI, adjusted for letter boxing, which should be used for | |
304 * padding calculations. | |
305 */ | |
306 private RectF getAdjustedSystemUiOffsets() { | |
307 float[] letterBoxPadding = getLetterboxPadding(); | |
308 return new RectF(Math.max(mSystemUiOffsetPixels.left - letterBoxPadding[ 0], 0.0f), | |
309 Math.max(mSystemUiOffsetPixels.top - letterBoxPadding[1], 0.0f), | |
310 Math.max(mSystemUiOffsetPixels.right - letterBoxPadding[0], 0.0f ), | |
311 Math.max(mSystemUiOffsetPixels.bottom - letterBoxPadding[1], 0.0 f)); | |
312 } | |
313 | |
314 /** Updates the padding used to allow the user to scroll the image out from under System UI. */ | |
315 private void adjustImagePadding() { | |
316 float[] letterBoxPadding = getLetterboxPadding(); | |
317 RectF systemUiOffsetPixels = getAdjustedSystemUiOffsets(); | |
318 float[] imagePoints = {0.0f, 0.0f, mRenderData.imageWidth, mRenderData.i mageHeight}; | |
319 mRenderData.transform.mapPoints(imagePoints); | |
320 | |
321 mImagePadding.set( | |
322 adjustEdge(systemUiOffsetPixels.left, mImagePadding.left, | |
323 imagePoints[0] - letterBoxPadding[0]), | |
324 adjustEdge(systemUiOffsetPixels.top, mImagePadding.top, | |
325 imagePoints[1] - letterBoxPadding[1]), | |
326 adjustEdge(systemUiOffsetPixels.right, mImagePadding.right, | |
327 mRenderData.screenWidth - imagePoints[2] - letterBoxPadd ing[0]), | |
328 adjustEdge(systemUiOffsetPixels.bottom, mImagePadding.bottom, | |
329 mRenderData.screenHeight - imagePoints[3] - letterBoxPad ding[1])); | |
330 } | |
331 | |
332 /** | |
333 * Update the current edge padding based on the current System UI and image postion state. | |
Lambros
2016/09/30 01:59:36
s/postion/position/
joedow
2016/09/30 19:42:56
Done.
| |
334 * | |
335 * @param systemUiPadding Amount of visible System UI in pixels. | |
336 * @param currentPadding Amount of padding used, in pixels, for position cal culations. | |
337 * @param visiblePixels Amount of padding actually visible, in pixels. | |
338 * @return The new value, in pixels, to be used for positioning. | |
339 */ | |
340 private float adjustEdge(float systemUiPadding, float currentPadding, float visiblePixels) { | |
341 float edgeValue; | |
342 visiblePixels = Math.max(visiblePixels, 0.0f); | |
343 if (systemUiPadding > 0.0f) { | |
344 if (systemUiPadding > currentPadding) { | |
345 // Add enough padding to allow scrolling the desktop out from un der the System UI. | |
346 edgeValue = Math.min(systemUiPadding, visiblePixels); | |
347 } else if (systemUiPadding < currentPadding) { | |
348 // Remove unneeded padding from the canvas. | |
349 edgeValue = Math.max(systemUiPadding, Math.min(currentPadding, v isiblePixels)); | |
350 } else { | |
351 // If current and system padding sizes are the same, then keep t he visible portion. | |
352 edgeValue = Math.min(currentPadding, visiblePixels); | |
353 } | |
354 } else if (currentPadding > 0.0f) { | |
355 // If we have existing padding, then trim if possible, otherwise kee p the same value. | |
356 edgeValue = Math.min(currentPadding, visiblePixels); | |
357 } else { | |
358 // Use zero padding if there is no system or current padding specifi ed. | |
359 edgeValue = 0.0f; | |
360 } | |
361 return edgeValue; | |
254 } | 362 } |
255 } | 363 } |
OLD | NEW |