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

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: 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
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.update();
21 }
22
23 /**
24 * Viewport modification.
25 */
26
SeRya 2011/08/08 13:26:44 New line should not be here. The argument should b
Vladislav Kaznacheev 2011/08/08 13:47:51 Initialized in the constructor. As for the comme
27 Viewport.prototype.setScaleControl = function(scaleControl) {
28 this.scaleControl_ = scaleControl;
29 };
30
31 Viewport.prototype.setImageSize = function(width, height) {
32 this.imageBounds_ = new Rect(width, height);
33 if (this.scaleControl_) this.scaleControl_.displayImageSize(width, height);
34 this.invalidateCaches();
35 };
36
37 Viewport.prototype.setScreenSize = function(width, height) {
38 this.screenBounds_ = new Rect(width, height);
39 if (this.scaleControl_)
40 this.scaleControl_.setMinScale(this.getFittingScale());
41 this.invalidateCaches();
42 };
43
44 Viewport.prototype.getScale = function () { return this.scale_ };
SeRya 2011/08/08 13:26:44 Space before ().
Vladislav Kaznacheev 2011/08/08 13:47:51 Done.
45
46 Viewport.prototype.setScale = function (scale, notify) {
SeRya 2011/08/08 13:26:44 Space before ()
Vladislav Kaznacheev 2011/08/08 13:47:51 Done.
47 if (this.scale_ == scale) return;
48 this.scale_ = scale;
49 if (notify && this.scaleControl_) this.scaleControl_.displayScale(scale);
50 this.invalidateCaches();
51 };
52
53 Viewport.prototype.getFittingScale = function() {
54 var scaleX = this.screenBounds_.width / this.imageBounds_.width;
55 var scaleY = this.screenBounds_.height / this.imageBounds_.height;
56 return Math.min(scaleX, scaleY) * 0.85;
57 };
58
59 Viewport.prototype.fitImage = function() {
60 var scale = this.getFittingScale();
61 if (this.scaleControl_) this.scaleControl_.setMinScale(scale);
62 this.setScale(scale, true);
63 };
64
65 Viewport.prototype.getOffsetX = function () { return this.offsetX_ };
66
67 Viewport.prototype.getOffsetY = function () { return this.offsetY_ };
68
69 Viewport.prototype.setOffset = function(x, y, ignoreClipping) {
70 if (!ignoreClipping) {
71 x = this.clampOffsetX_(x);
72 y = this.clampOffsetY_(y);
73 }
74 if (this.offsetX_ == x && this.offsetY_ == y) return;
75 this.offsetX_ = x;
76 this.offsetY_ = y;
77 this.invalidateCaches();
78 };
79
80 Viewport.prototype.setCenter = function(x, y, ignoreClipping) {
81 this.setOffset(
82 this.imageBounds_.width / 2 - x,
83 this.imageBounds_.height / 2 - y,
84 ignoreClipping);
85 };
86
87 /**
88 * Return a closure that can be called to pan the image.
89 * Useful for implementing non-trivial variants of panning (overview etc).
90 * @param {Number} originalX The x coordinate on the screen canvas that
91 * corresponds to zero change to offsetX.
92 * @param {Number} originalY The y coordinate on the screen canvas that
93 * corresponds to zero change to offsetY.
94 * @param {Function} scaleFunc returns the current image to screen scale.
95 * @param {Function} hitFunc returns true if (x,y) is in the valid region.
96 */
97 Viewport.prototype.createOffsetSetter = function (
98 originalX, originalY, scaleFunc, hitFunc) {
99 var originalOffsetX = this.offsetX_;
100 var originalOffsetY = this.offsetY_;
101 if (!hitFunc) hitFunc = function() { return true };
102 if (!scaleFunc) scaleFunc = this.getScale.bind(this);
103
104 var self = this;
105 return function(x, y) {
106 if (hitFunc(x, y)) {
107 var scale = scaleFunc();
108 self.setOffset(
109 originalOffsetX + (x - originalX) / scale,
110 originalOffsetY + (y - originalY) / scale);
111 self.repaint();
112 }
113 };
114 };
115
116 /**
117 * Access to the current viewport state.
SeRya 2011/08/08 13:26:44 It's not a JS Doc comment and dont need to comply
Vladislav Kaznacheev 2011/08/08 13:47:51 Done.
118 */
119
120 /**
121 * @return {Rect} The image bounds in image coordinates.
122 */
123 Viewport.prototype.getImageBounds = function() { return this.imageBounds_ };
124
125 /**
126 * @return {Rect} The screen bounds in screen coordinates.
127 */
128 Viewport.prototype.getScreenBounds = function() { return this.screenBounds_ };
129
130 /**
131 * @return {Rect} The visible part of the image, in image coordinates.
132 */
133 Viewport.prototype.getImageClipped = function() { return this.imageClipped_ };
134
135 /**
136 * @return {Rect} The visible part of the image, in screen coordinates.
137 */
138 Viewport.prototype.getScreenClipped = function() { return this.screenClipped_ };
139
140 /**
141 * A counter that is incremented with each viewport state change.
142 * Clients that cache anything that depends on the viewport state should keep
143 * track of this counter.
144 */
145 Viewport.prototype.getCacheGeneration = function() { return this.generation_ };
146
147 /**
148 * Called on evert view port state change (even if repaint has not been called).
149 */
150 Viewport.prototype.invalidateCaches = function() { this.generation_++ };
151
152 /**
153 * @return {Rect} The image bounds in screen coordinates.
154 */
155 Viewport.prototype.getImageBoundsOnScreen = function() {
156 return this.imageOnScreen_;
157 };
158
159 /*
SeRya 2011/08/08 13:26:44 /** ?
Vladislav Kaznacheev 2011/08/08 13:47:51 Also a section comment. On 2011/08/08 13:26:44, Se
160 * Conversion between the screen and image coordinate spaces.
161 */
162 Viewport.prototype.screenToImageSize = function(size) {
163 return size / this.getScale();
164 };
165
166 Viewport.prototype.screenToImageX = function(x) {
167 return Math.round((x - this.imageOnScreen_.left) / this.getScale());
168 };
169
170 Viewport.prototype.screenToImageY = function(y) {
171 return Math.round((y - this.imageOnScreen_.top) / this.getScale());
172 };
173
174 Viewport.prototype.screenToImageRect = function(rect) {
175 return new Rect(
176 this.screenToImageX(rect.left),
177 this.screenToImageY(rect.top),
178 this.screenToImageSize(rect.width),
179 this.screenToImageSize(rect.height));
180 };
181
182 Viewport.prototype.imageToScreenSize = function(size) {
183 return size * this.getScale();
184 };
185
186 Viewport.prototype.imageToScreenX = function(x) {
187 return Math.round(this.imageOnScreen_.left + x * this.getScale());
188 };
189
190 Viewport.prototype.imageToScreenY = function(y) {
191 return Math.round(this.imageOnScreen_.top + y * this.getScale());
192 };
193
194 Viewport.prototype.imageToScreenRect = function(rect) {
195 return new Rect(
196 this.imageToScreenX(rect.left),
197 this.imageToScreenY(rect.top),
198 this.imageToScreenSize(rect.width),
199 this.imageToScreenSize(rect.height));
200 };
201
202 /**
203 * @return {Boolean} True if some part of the image is clipped by the screen.
204 */
205 Viewport.prototype.isClipped = function () {
206 return this.getMarginX_() < 0 || this.getMarginY_() < 0;
207 };
208
209 /**
210 * Horizontal margin. Negative if the image is clipped horizontally.
211 */
212 Viewport.prototype.getMarginX_ = function() {
213 return Math.floor(
214 (this.screenBounds_.width - this.imageBounds_.width * this.scale_) / 2);
215 };
216
217 /**
218 * Vertical margin. Negative if the image is clipped vertically.
219 */
220 Viewport.prototype.getMarginY_ = function() {
221 return Math.floor(
222 (this.screenBounds_.height - this.imageBounds_.height * this.scale_) / 2);
223 };
224
225 Viewport.prototype.clampOffsetX_ = function(x) {
226 var limit = Math.max(0, -this.getMarginX_() / this.getScale());
227 return ImageUtil.clamp(-limit, x, limit);
228 };
229
230 Viewport.prototype.clampOffsetY_ = function(y) {
231 var limit = Math.max(0, -this.getMarginY_() / this.getScale());
232 return ImageUtil.clamp(-limit, y, limit);
233 };
234
235 /**
236 * Recalculate the viewport parameters.
237 */
238 Viewport.prototype.update = function() {
239 var scale = this.getScale();
240
241 // Image bounds in screen coordinates.
242 this.imageOnScreen_ = new Rect(
243 this.getMarginX_(),
244 this.getMarginY_(),
245 Math.floor(this.imageBounds_.width * scale),
246 Math.floor(this.imageBounds_.height * scale));
247
248 // A visible part of the image in image coordinates.
249 this.imageClipped_ = new Rect(this.imageBounds_);
250
251 // A visible part of the image in screen coordinates.
252 this.screenClipped_ = new Rect(this.screenBounds_);
253
254 // Adjust for the offset.
255 if (this.imageOnScreen_.left < 0) {
256 this.imageOnScreen_.left += this.clampOffsetX_(this.offsetX_) * scale;
257 this.imageClipped_.left = -this.imageOnScreen_.left / scale;
258 this.imageClipped_.width = this.screenBounds_.width / scale;
259 } else {
260 this.screenClipped_.left = this.imageOnScreen_.left;
261 this.screenClipped_.width = this.imageOnScreen_.width;
262 }
263
264 if (this.imageOnScreen_.top < 0) {
265 this.imageOnScreen_.top += this.clampOffsetY_(this.offsetY_) * scale;
266 this.imageClipped_.top = -this.imageOnScreen_.top / scale;
267 this.imageClipped_.height = this.screenBounds_.height / scale;
268 } else {
269 this.screenClipped_.top = this.imageOnScreen_.top;
270 this.screenClipped_.height = this.imageOnScreen_.height;
271 }
272 };
273
274 Viewport.prototype.repaint = function () {
275 if (this.repaintCallback_) this.repaintCallback_();
276 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698