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.PointF; | 8 import android.graphics.PointF; |
9 import android.graphics.Rect; | |
8 import android.graphics.RectF; | 10 import android.graphics.RectF; |
9 | 11 |
10 /** | 12 /** |
11 * This class is responsible for transforming the desktop image matrix. | 13 * This class is responsible for transforming the desktop image matrix. |
12 */ | 14 */ |
13 public class DesktopCanvas { | 15 public class DesktopCanvas { |
14 /** | 16 /** |
15 * Maximum allowed zoom level - see {@link #repositionImageWithZoom()}. | 17 * Maximum allowed zoom level - see {@link #repositionImageWithZoom()}. |
16 */ | 18 */ |
17 private static final float MAX_ZOOM_FACTOR = 100.0f; | 19 private static final float MAX_ZOOM_FACTOR = 100.0f; |
18 | 20 |
19 private final DesktopViewInterface mViewer; | 21 private final DesktopViewInterface mViewer; |
20 private final RenderData mRenderData; | 22 private final RenderData mRenderData; |
21 | 23 |
22 /** | 24 /** |
23 * Represents the desired center of the viewport. This value may not repres ent the actual | 25 * Represents the desired center of the viewport. This value may not repres ent the actual |
24 * center of the viewport as adjustments are made to ensure as much of the d esktop is visible as | 26 * center of the viewport as adjustments are made to ensure as much of the d esktop is visible as |
25 * possible. This value needs to be a pair of floats so the desktop image c an be positioned | 27 * possible. This value needs to be a pair of floats so the desktop image c an be positioned |
26 * with sub-pixel accuracy for smoother panning animations at high zoom leve ls. | 28 * with sub-pixel accuracy for smoother panning animations at high zoom leve ls. |
27 */ | 29 */ |
28 private PointF mViewportPosition = new PointF(); | 30 private PointF mViewportPosition = new PointF(); |
29 | 31 |
30 /** | 32 /** |
31 * Represents the amount of vertical space in pixels used by the soft input device and | 33 * Represents the amount of space, in pixels, used by system UI. |
32 * accompanying system UI. | |
33 */ | 34 */ |
34 private int mInputMethodOffsetY = 0; | 35 private Rect mSystemUiOffsetPx = new Rect(); |
Lambros
2016/06/29 20:43:37
Pixels instead of Px?
Is Rect the right choice he
joedow
2016/06/30 16:03:26
Updated the name. Rect/RectF doesn't require the
| |
35 | |
36 /** | |
37 * Represents the amount of horizontal space in pixels used by the soft inpu t device and | |
38 * accompanying system UI. | |
39 */ | |
40 private int mInputMethodOffsetX = 0; | |
41 | 36 |
42 public DesktopCanvas(DesktopViewInterface viewer, RenderData renderData) { | 37 public DesktopCanvas(DesktopViewInterface viewer, RenderData renderData) { |
43 mViewer = viewer; | 38 mViewer = viewer; |
44 mRenderData = renderData; | 39 mRenderData = renderData; |
45 } | 40 } |
46 | 41 |
47 /** | 42 /** |
48 * Returns the desired center position of the viewport. Note that this may not represent the | 43 * Shifts the viewport by the passed in deltas (in image coordinates). |
49 * true center of the viewport as other calculations are done to maximize th e viewable area. | |
50 * | 44 * |
51 * @return A point representing the desired position of the viewport. | 45 * @param useScreenCenter Determines whether to use the desired viewport pos ition or the actual |
46 * center of the screen for positioning. | |
47 * @param deltaX The distance (in image coordinates) to move the viewport al ong the x-axis. | |
48 * @param deltaY The distance (in image coordinates) to move the viewport al ong the y-axis. | |
49 * @return A point representing the desired center position of the viewport. | |
52 */ | 50 */ |
53 public PointF getViewportPosition() { | 51 public PointF moveViewportCenter(boolean useScreenCenter, float deltaX, floa t deltaY) { |
54 return new PointF(mViewportPosition.x, mViewportPosition.y); | 52 PointF viewportCenter; |
55 } | 53 synchronized (mRenderData) { |
54 RectF bounds = new RectF(0, 0, mRenderData.imageWidth, mRenderData.i mageHeight); | |
55 if (useScreenCenter) { | |
56 viewportCenter = getTrueViewportCenter(); | |
57 } else { | |
58 viewportCenter = new PointF(mViewportPosition.x, mViewportPositi on.y); | |
59 } | |
56 | 60 |
57 /** | 61 viewportCenter.set(viewportCenter.x + deltaX, viewportCenter.y + del taY); |
Lambros
2016/06/29 20:43:37
viewportCenter.offset(deltaX, deltaY);
joedow
2016/06/30 16:03:26
Good call.
| |
58 * Sets the desired center position of the viewport. | 62 if (viewportCenter.x < bounds.left) { |
59 * | 63 viewportCenter.x = bounds.left; |
60 * @param newX The new x coordinate value for the desired center position. | 64 } else if (viewportCenter.x > bounds.right) { |
61 * @param newY The new y coordinate value for the desired center position. | 65 viewportCenter.x = bounds.right; |
62 */ | 66 } |
63 public void setViewportPosition(float newX, float newY) { | |
64 mViewportPosition.set(newX, newY); | |
65 } | |
66 | 67 |
67 /** | 68 if (viewportCenter.y < bounds.top) { |
68 * Sets the offset values used to calculate the space used by the current so ft input method. | 69 viewportCenter.y = bounds.top; |
69 * | 70 } else if (viewportCenter.y > bounds.bottom) { |
70 * @param offsetX The space used by the soft input method UI on the right ed ge of the screen. | 71 viewportCenter.y = bounds.bottom; |
71 * @param offsetY The space used by the soft input method UI on the bottom e dge of the screen. | 72 } |
72 */ | 73 |
73 public void setInputMethodOffsetValues(int offsetX, int offsetY) { | 74 mViewportPosition.set(viewportCenter); |
74 mInputMethodOffsetX = offsetX; | 75 } |
75 mInputMethodOffsetY = offsetY; | 76 |
77 return viewportCenter; | |
76 } | 78 } |
77 | 79 |
78 /** | 80 /** |
79 * Returns the current size of the viewport. This size includes the offset calculations for | 81 * Returns the current size of the viewport. This size includes the offset calculations for |
80 * any visible Input Method UI. | 82 * any visible system UI. |
81 * | 83 * |
82 * @return A point representing the current size of the viewport. | 84 * @return A point representing the current size of the viewport. |
83 */ | 85 */ |
84 public PointF getViewportSize() { | 86 private PointF getViewportSize() { |
85 float adjustedScreenWidth, adjustedScreenHeight; | 87 float adjustedScreenWidth, adjustedScreenHeight; |
86 synchronized (mRenderData) { | 88 synchronized (mRenderData) { |
87 adjustedScreenWidth = mRenderData.screenWidth - mInputMethodOffsetX; | 89 adjustedScreenWidth = mRenderData.screenWidth - mSystemUiOffsetPx.ri ght; |
Lambros
2016/06/29 20:43:36
Need to subtract left as well as right?
joedow
2016/06/30 16:03:26
Not for this CL. I am not changing previous behav
| |
88 adjustedScreenHeight = mRenderData.screenHeight - mInputMethodOffset Y; | 90 adjustedScreenHeight = mRenderData.screenHeight - mSystemUiOffsetPx. bottom; |
Lambros
2016/06/29 20:43:37
top as well as bottom?
joedow
2016/06/30 16:03:26
Next CL as needed.
| |
89 } | 91 } |
90 | 92 |
91 return new PointF(adjustedScreenWidth, adjustedScreenHeight); | 93 return new PointF(adjustedScreenWidth, adjustedScreenHeight); |
92 } | 94 } |
93 | 95 |
96 /** | |
97 * Returns the true center position of the viewport (in image coordinates). | |
98 * | |
99 * @return A point representing the true center position of the viewport. | |
100 */ | |
101 private PointF getTrueViewportCenter() { | |
102 synchronized (mRenderData) { | |
103 PointF viewportSize = getViewportSize(); | |
104 // Find the center point of the viewport on the screen. | |
Lambros
2016/06/29 20:43:36
Please add blank line above comment.
joedow
2016/06/30 16:03:26
Done.
| |
105 float[] viewportPosition = {((float) viewportSize.x / 2), ((float) v iewportSize.y / 2)}; | |
106 // Convert the screen position to an image position. | |
Lambros
2016/06/29 20:43:37
and here.
joedow
2016/06/30 16:03:26
Done.
| |
107 Matrix screenToImage = new Matrix(); | |
108 mRenderData.transform.invert(screenToImage); | |
109 screenToImage.mapPoints(viewportPosition); | |
110 return new PointF(viewportPosition[0], viewportPosition[1]); | |
111 } | |
112 } | |
113 | |
114 /** | |
115 * Sets the offset values used to calculate the space used by system UI. | |
116 * | |
117 * @param left The space used by system UI on the left edge of the screen. | |
118 * @param top The space used by system UI on the top edge of the screen. | |
119 * @param right The space used by system UI on the right edge of the screen. | |
120 * @param bottom The space used by system UI on the bottom edge of the scree n. | |
121 */ | |
122 public void setSystemUiOffsetValues(int left, int top, int right, int bottom ) { | |
123 synchronized (mRenderData) { | |
124 mSystemUiOffsetPx.set(left, top, right, bottom); | |
125 } | |
126 } | |
127 | |
94 /** Repositions the image by zooming it such that the image is displayed wit hout borders. */ | 128 /** Repositions the image by zooming it such that the image is displayed wit hout borders. */ |
95 public void resizeImageToFitScreen() { | 129 public void resizeImageToFitScreen() { |
96 synchronized (mRenderData) { | 130 synchronized (mRenderData) { |
97 // Protect against being called before the image has been initialize d. | 131 // Protect against being called before the image has been initialize d. |
98 if (mRenderData.imageWidth == 0 || mRenderData.imageHeight == 0) { | 132 if (mRenderData.imageWidth == 0 || mRenderData.imageHeight == 0) { |
99 return; | 133 return; |
100 } | 134 } |
101 | 135 |
102 float widthRatio = (float) mRenderData.screenWidth / mRenderData.ima geWidth; | 136 float widthRatio = (float) mRenderData.screenWidth / mRenderData.ima geWidth; |
103 float heightRatio = (float) mRenderData.screenHeight / mRenderData.i mageHeight; | 137 float heightRatio = (float) mRenderData.screenHeight / mRenderData.i mageHeight; |
104 float screenToImageScale = Math.max(widthRatio, heightRatio); | 138 float screenToImageScale = Math.max(widthRatio, heightRatio); |
105 | 139 |
106 // If the image is smaller than the screen in either dimension, then we want to scale it | 140 // If the image is smaller than the screen in either dimension, then we want to scale it |
107 // up to fit both and fill the screen with the image of the remote d esktop. | 141 // up to fit both and fill the screen with the image of the remote d esktop. |
108 if (screenToImageScale > 1.0f) { | 142 if (screenToImageScale > 1.0f) { |
109 mRenderData.transform.setScale(screenToImageScale, screenToImage Scale); | 143 mRenderData.transform.setScale(screenToImageScale, screenToImage Scale); |
110 } | 144 } |
111 } | 145 } |
112 | 146 |
113 repositionImage(false); | 147 repositionImage(false); |
114 } | 148 } |
115 | 149 |
116 /** | 150 /** |
117 * Repositions the image by translating it (without affecting the zoom level ). | 151 * Repositions the image by translating it (without affecting the zoom level ). |
118 * | 152 * |
119 * @param centerViewport Determines whether the viewport will be translated to the desired | 153 * @param centerViewport Determines whether the viewport will be translated to the desired |
120 * center position before being adjusted to fit the sc reen boundaries. | 154 * center position before being adjusted to fit the sc reen boundaries. |
121 */ | 155 */ |
122 public void repositionImage(boolean centerViewport) { | 156 public void repositionImage(boolean centerViewport) { |
123 PointF adjustedViewportSize = getViewportSize(); | 157 PointF viewportSize = getViewportSize(); |
124 synchronized (mRenderData) { | 158 synchronized (mRenderData) { |
125 // The goal of the code below is to position the viewport as close t o the desired center | 159 // The goal of the code below is to position the viewport as close t o the desired center |
126 // position as possible whilst keeping as much of the desktop in vie w as possible. | 160 // position as possible whilst keeping as much of the desktop in vie w as possible. |
127 // To achieve these goals, we first position the desktop image at th e desired center | 161 // To achieve these goals, we first position the desktop image at th e desired center |
128 // point and then re-position it to maximize the viewable area. | 162 // point and then re-position it to maximize the viewable area. |
129 if (centerViewport) { | 163 if (centerViewport) { |
130 // Map the current viewport position to screen coordinates. | 164 // Map the current viewport position to screen coordinates. |
131 float[] viewportPosition = {mViewportPosition.x, mViewportPositi on.y}; | 165 float[] viewportPosition = {mViewportPosition.x, mViewportPositi on.y}; |
132 mRenderData.transform.mapPoints(viewportPosition); | 166 mRenderData.transform.mapPoints(viewportPosition); |
133 | 167 |
134 // Translate so the viewport is displayed in the middle of the s creen. | 168 // Translate so the viewport is displayed in the middle of the s creen. |
135 mRenderData.transform.postTranslate( | 169 mRenderData.transform.postTranslate( |
136 (float) adjustedViewportSize.x / 2 - viewportPosition[0] , | 170 ((float) viewportSize.x / 2) - viewportPosition[0], |
137 (float) adjustedViewportSize.y / 2 - viewportPosition[1] ); | 171 ((float) viewportSize.y / 2) - viewportPosition[1]); |
138 } | 172 } |
139 | 173 |
140 // Get the coordinates of the desktop rectangle (top-left/bottom-rig ht corners) in | 174 // Get the coordinates of the desktop rectangle (top-left/bottom-rig ht corners) in |
141 // screen coordinates. Order is: left, top, right, bottom. | 175 // screen coordinates. Order is: left, top, right, bottom. |
142 RectF rectScreen = new RectF(0, 0, mRenderData.imageWidth, mRenderDa ta.imageHeight); | 176 RectF rectScreen = new RectF(0, 0, mRenderData.imageWidth, mRenderDa ta.imageHeight); |
143 mRenderData.transform.mapRect(rectScreen); | 177 mRenderData.transform.mapRect(rectScreen); |
144 | 178 |
145 float leftDelta = rectScreen.left; | 179 float leftDelta = rectScreen.left; |
146 float rightDelta = rectScreen.right - mRenderData.screenWidth + mInp utMethodOffsetX; | 180 float rightDelta = rectScreen.right - mRenderData.screenWidth + mSys temUiOffsetPx.right; |
Lambros
2016/06/29 20:43:37
Same here? It looks like you never use mSystemUiOf
joedow
2016/06/30 16:03:26
Not yet, they are needed in the next CL.
| |
147 float topDelta = rectScreen.top; | 181 float topDelta = rectScreen.top; |
148 float bottomDelta = rectScreen.bottom - mRenderData.screenHeight + m InputMethodOffsetY; | 182 float bottomDelta = |
183 rectScreen.bottom - mRenderData.screenHeight + mSystemUiOffs etPx.bottom; | |
149 float xAdjust = 0; | 184 float xAdjust = 0; |
150 float yAdjust = 0; | 185 float yAdjust = 0; |
151 | 186 |
152 if (rectScreen.right - rectScreen.left < adjustedViewportSize.x) { | 187 if (rectScreen.right - rectScreen.left < viewportSize.x) { |
153 // Image is narrower than the screen, so center it. | 188 // Image is narrower than the screen, so center it. |
154 xAdjust = -(rightDelta + leftDelta) / 2; | 189 xAdjust = -(rightDelta + leftDelta) / 2; |
155 } else if (leftDelta > 0 && rightDelta > 0) { | 190 } else if (leftDelta > 0 && rightDelta > 0) { |
156 // Panning the image left will show more of it. | 191 // Panning the image left will show more of it. |
157 xAdjust = -Math.min(leftDelta, rightDelta); | 192 xAdjust = -Math.min(leftDelta, rightDelta); |
158 } else if (leftDelta < 0 && rightDelta < 0) { | 193 } else if (leftDelta < 0 && rightDelta < 0) { |
159 // Pan the image right. | 194 // Pan the image right. |
160 xAdjust = Math.min(-leftDelta, -rightDelta); | 195 xAdjust = Math.min(-leftDelta, -rightDelta); |
161 } | 196 } |
162 | 197 |
163 // Apply similar logic for yAdjust. | 198 // Apply similar logic for yAdjust. |
164 if (rectScreen.bottom - rectScreen.top < adjustedViewportSize.y) { | 199 if (rectScreen.bottom - rectScreen.top < viewportSize.y) { |
165 yAdjust = -(bottomDelta + topDelta) / 2; | 200 yAdjust = -(bottomDelta + topDelta) / 2; |
166 } else if (topDelta > 0 && bottomDelta > 0) { | 201 } else if (topDelta > 0 && bottomDelta > 0) { |
167 yAdjust = -Math.min(topDelta, bottomDelta); | 202 yAdjust = -Math.min(topDelta, bottomDelta); |
168 } else if (topDelta < 0 && bottomDelta < 0) { | 203 } else if (topDelta < 0 && bottomDelta < 0) { |
169 yAdjust = Math.min(-topDelta, -bottomDelta); | 204 yAdjust = Math.min(-topDelta, -bottomDelta); |
170 } | 205 } |
171 | 206 |
172 mRenderData.transform.postTranslate(xAdjust, yAdjust); | 207 mRenderData.transform.postTranslate(xAdjust, yAdjust); |
173 | 208 |
174 mViewer.transformationChanged(); | 209 mViewer.transformationChanged(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
206 // level needed to fit either the width or height. | 241 // level needed to fit either the width or height. |
207 float scale = Math.min((float) mRenderData.screenWidth / mRender Data.imageWidth, | 242 float scale = Math.min((float) mRenderData.screenWidth / mRender Data.imageWidth, |
208 (float) mRenderData.screenHeight / mRende rData.imageHeight); | 243 (float) mRenderData.screenHeight / mRende rData.imageHeight); |
209 mRenderData.transform.setScale(scale, scale); | 244 mRenderData.transform.setScale(scale, scale); |
210 } | 245 } |
211 } | 246 } |
212 | 247 |
213 repositionImage(centerViewport); | 248 repositionImage(centerViewport); |
214 } | 249 } |
215 } | 250 } |
OLD | NEW |