Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(627)

Side by Side Diff: chrome/browser/resources/file_manager/js/image_editor/viewport.js

Issue 7541075: Pre-scaling images to speed up feedback in Image Editor. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/resources/file_manager/js/image_editor/image_util.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 /**
6 * Viewport class controls the way the image is displayed (scale, offset etc).
7 */
8 function Viewport(repaintCallback) {
9 this.repaintCallback_ = repaintCallback;
10
11 this.imageBounds_ = new Rect();
12 this.screenBounds_ = new Rect();
13
14 this.scale_ = 1;
15 this.offsetX_ = 0;
16 this.offsetY_ = 0;
17
18 this.generation_ = 0;
19
20 this.scaleControl_ = null;
21
22 this.update();
23 }
24
25 /*
26 * Viewport modification.
27 */
28
29 Viewport.prototype.setScaleControl = function(scaleControl) {
30 this.scaleControl_ = scaleControl;
31 };
32
33 Viewport.prototype.setImageSize = function(width, height) {
34 this.imageBounds_ = new Rect(width, height);
35 if (this.scaleControl_) this.scaleControl_.displayImageSize(width, height);
36 this.invalidateCaches();
37 };
38
39 Viewport.prototype.setScreenSize = function(width, height) {
40 this.screenBounds_ = new Rect(width, height);
41 if (this.scaleControl_)
42 this.scaleControl_.setMinScale(this.getFittingScale());
43 this.invalidateCaches();
44 };
45
46 Viewport.prototype.getScale = function() { return this.scale_ };
47
48 Viewport.prototype.setScale = function(scale, notify) {
49 if (this.scale_ == scale) return;
50 this.scale_ = scale;
51 if (notify && this.scaleControl_) this.scaleControl_.displayScale(scale);
52 this.invalidateCaches();
53 };
54
55 Viewport.prototype.getFittingScale = function() {
56 var scaleX = this.screenBounds_.width / this.imageBounds_.width;
57 var scaleY = this.screenBounds_.height / this.imageBounds_.height;
58 return Math.min(scaleX, scaleY) * 0.85;
59 };
60
61 Viewport.prototype.fitImage = function() {
62 var scale = this.getFittingScale();
63 if (this.scaleControl_) this.scaleControl_.setMinScale(scale);
64 this.setScale(scale, true);
65 };
66
67 Viewport.prototype.getOffsetX = function () { return this.offsetX_ };
68
69 Viewport.prototype.getOffsetY = function () { return this.offsetY_ };
70
71 Viewport.prototype.setOffset = function(x, y, ignoreClipping) {
72 if (!ignoreClipping) {
73 x = this.clampOffsetX_(x);
74 y = this.clampOffsetY_(y);
75 }
76 if (this.offsetX_ == x && this.offsetY_ == y) return;
77 this.offsetX_ = x;
78 this.offsetY_ = y;
79 this.invalidateCaches();
80 };
81
82 Viewport.prototype.setCenter = function(x, y, ignoreClipping) {
83 this.setOffset(
84 this.imageBounds_.width / 2 - x,
85 this.imageBounds_.height / 2 - y,
86 ignoreClipping);
87 };
88
89 /**
90 * Return a closure that can be called to pan the image.
91 * Useful for implementing non-trivial variants of panning (overview etc).
92 * @param {Number} originalX The x coordinate on the screen canvas that
93 * corresponds to zero change to offsetX.
94 * @param {Number} originalY The y coordinate on the screen canvas that
95 * corresponds to zero change to offsetY.
96 * @param {Function} scaleFunc returns the current image to screen scale.
97 * @param {Function} hitFunc returns true if (x,y) is in the valid region.
98 */
99 Viewport.prototype.createOffsetSetter = function (
100 originalX, originalY, scaleFunc, hitFunc) {
101 var originalOffsetX = this.offsetX_;
102 var originalOffsetY = this.offsetY_;
103 if (!hitFunc) hitFunc = function() { return true };
104 if (!scaleFunc) scaleFunc = this.getScale.bind(this);
105
106 var self = this;
107 return function(x, y) {
108 if (hitFunc(x, y)) {
109 var scale = scaleFunc();
110 self.setOffset(
111 originalOffsetX + (x - originalX) / scale,
112 originalOffsetY + (y - originalY) / scale);
113 self.repaint();
114 }
115 };
116 };
117
118 /*
119 * Access to the current viewport state.
120 */
121
122 /**
123 * @return {Rect} The image bounds in image coordinates.
124 */
125 Viewport.prototype.getImageBounds = function() { return this.imageBounds_ };
126
127 /**
128 * @return {Rect} The screen bounds in screen coordinates.
129 */
130 Viewport.prototype.getScreenBounds = function() { return this.screenBounds_ };
131
132 /**
133 * @return {Rect} The visible part of the image, in image coordinates.
134 */
135 Viewport.prototype.getImageClipped = function() { return this.imageClipped_ };
136
137 /**
138 * @return {Rect} The visible part of the image, in screen coordinates.
139 */
140 Viewport.prototype.getScreenClipped = function() { return this.screenClipped_ };
141
142 /**
143 * A counter that is incremented with each viewport state change.
144 * Clients that cache anything that depends on the viewport state should keep
145 * track of this counter.
146 */
147 Viewport.prototype.getCacheGeneration = function() { return this.generation_ };
148
149 /**
150 * Called on evert view port state change (even if repaint has not been called).
151 */
152 Viewport.prototype.invalidateCaches = function() { this.generation_++ };
153
154 /**
155 * @return {Rect} The image bounds in screen coordinates.
156 */
157 Viewport.prototype.getImageBoundsOnScreen = function() {
158 return this.imageOnScreen_;
159 };
160
161 /*
162 * Conversion between the screen and image coordinate spaces.
163 */
164
165 Viewport.prototype.screenToImageSize = function(size) {
166 return size / this.getScale();
167 };
168
169 Viewport.prototype.screenToImageX = function(x) {
170 return Math.round((x - this.imageOnScreen_.left) / this.getScale());
171 };
172
173 Viewport.prototype.screenToImageY = function(y) {
174 return Math.round((y - this.imageOnScreen_.top) / this.getScale());
175 };
176
177 Viewport.prototype.screenToImageRect = function(rect) {
178 return new Rect(
179 this.screenToImageX(rect.left),
180 this.screenToImageY(rect.top),
181 this.screenToImageSize(rect.width),
182 this.screenToImageSize(rect.height));
183 };
184
185 Viewport.prototype.imageToScreenSize = function(size) {
186 return size * this.getScale();
187 };
188
189 Viewport.prototype.imageToScreenX = function(x) {
190 return Math.round(this.imageOnScreen_.left + x * this.getScale());
191 };
192
193 Viewport.prototype.imageToScreenY = function(y) {
194 return Math.round(this.imageOnScreen_.top + y * this.getScale());
195 };
196
197 Viewport.prototype.imageToScreenRect = function(rect) {
198 return new Rect(
199 this.imageToScreenX(rect.left),
200 this.imageToScreenY(rect.top),
201 this.imageToScreenSize(rect.width),
202 this.imageToScreenSize(rect.height));
203 };
204
205 /**
206 * @return {Boolean} True if some part of the image is clipped by the screen.
207 */
208 Viewport.prototype.isClipped = function () {
209 return this.getMarginX_() < 0 || this.getMarginY_() < 0;
210 };
211
212 /**
213 * Horizontal margin. Negative if the image is clipped horizontally.
214 */
215 Viewport.prototype.getMarginX_ = function() {
216 return Math.floor(
217 (this.screenBounds_.width - this.imageBounds_.width * this.scale_) / 2);
218 };
219
220 /**
221 * Vertical margin. Negative if the image is clipped vertically.
222 */
223 Viewport.prototype.getMarginY_ = function() {
224 return Math.floor(
225 (this.screenBounds_.height - this.imageBounds_.height * this.scale_) / 2);
226 };
227
228 Viewport.prototype.clampOffsetX_ = function(x) {
229 var limit = Math.max(0, -this.getMarginX_() / this.getScale());
230 return ImageUtil.clamp(-limit, x, limit);
231 };
232
233 Viewport.prototype.clampOffsetY_ = function(y) {
234 var limit = Math.max(0, -this.getMarginY_() / this.getScale());
235 return ImageUtil.clamp(-limit, y, limit);
236 };
237
238 /**
239 * Recalculate the viewport parameters.
240 */
241 Viewport.prototype.update = function() {
242 var scale = this.getScale();
243
244 // Image bounds in screen coordinates.
245 this.imageOnScreen_ = new Rect(
246 this.getMarginX_(),
247 this.getMarginY_(),
248 Math.floor(this.imageBounds_.width * scale),
249 Math.floor(this.imageBounds_.height * scale));
250
251 // A visible part of the image in image coordinates.
252 this.imageClipped_ = new Rect(this.imageBounds_);
253
254 // A visible part of the image in screen coordinates.
255 this.screenClipped_ = new Rect(this.screenBounds_);
256
257 // Adjust for the offset.
258 if (this.imageOnScreen_.left < 0) {
259 this.imageOnScreen_.left += this.clampOffsetX_(this.offsetX_) * scale;
260 this.imageClipped_.left = -this.imageOnScreen_.left / scale;
261 this.imageClipped_.width = this.screenBounds_.width / scale;
262 } else {
263 this.screenClipped_.left = this.imageOnScreen_.left;
264 this.screenClipped_.width = this.imageOnScreen_.width;
265 }
266
267 if (this.imageOnScreen_.top < 0) {
268 this.imageOnScreen_.top += this.clampOffsetY_(this.offsetY_) * scale;
269 this.imageClipped_.top = -this.imageOnScreen_.top / scale;
270 this.imageClipped_.height = this.screenBounds_.height / scale;
271 } else {
272 this.screenClipped_.top = this.imageOnScreen_.top;
273 this.screenClipped_.height = this.imageOnScreen_.height;
274 }
275 };
276
277 Viewport.prototype.repaint = function () {
278 if (this.repaintCallback_) this.repaintCallback_();
279 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/js/image_editor/image_util.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698