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

Side by Side Diff: chrome/browser/resources/file_manager/js/media/media_util.js

Issue 12316118: Enabled Mosaic view on each volume. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased. Created 7 years, 9 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 /** 5 /**
6 * Loads a thumbnail using provided url. In CANVAS mode, loaded images 6 * Loads a thumbnail using provided url. In CANVAS mode, loaded images
7 * are attached as <canvas> element, while in IMAGE mode as <img>. 7 * are attached as <canvas> element, while in IMAGE mode as <img>.
8 * <canvas> renders faster than <img>, however has bigger memory overhead. 8 * <canvas> renders faster than <img>, however has bigger memory overhead.
9 * 9 *
10 * @param {string} url File URL. 10 * @param {string} url File URL.
11 * @param {ThumbnailLoader.LoaderType=} opt_loaderType Canvas or Image loader, 11 * @param {ThumbnailLoader.LoaderType=} opt_loaderType Canvas or Image loader,
12 * default: IMAGE. 12 * default: IMAGE.
13 * @param {Object=} opt_metadata Metadata object. 13 * @param {Object=} opt_metadata Metadata object.
14 * @param {string=} opt_mediaType Media type. 14 * @param {string=} opt_mediaType Media type.
15 * @param {ThumbnailLoader.UseEmbedded=} opt_useEmbedded If to use embedded
16 * jpeg thumbnail if available. Default: USE_EMBEDDED.
15 * @constructor 17 * @constructor
16 */ 18 */
17 function ThumbnailLoader(url, opt_loaderType, opt_metadata, opt_mediaType) { 19 function ThumbnailLoader(
20 url, opt_loaderType, opt_metadata, opt_mediaType, opt_useEmbedded) {
21 opt_useEmbedded = opt_useEmbedded || ThumbnailLoader.UseEmbedded.USE_EMBEDDED;
22
18 this.mediaType_ = opt_mediaType || FileType.getMediaType(url); 23 this.mediaType_ = opt_mediaType || FileType.getMediaType(url);
19 this.loaderType_ = opt_loaderType || ThumbnailLoader.LoaderType.IMAGE; 24 this.loaderType_ = opt_loaderType || ThumbnailLoader.LoaderType.IMAGE;
20 this.metadata_ = opt_metadata; 25 this.metadata_ = opt_metadata;
21 26
22 if (!opt_metadata) { 27 if (!opt_metadata) {
23 this.thumbnailUrl_ = url; // Use the URL directly. 28 this.thumbnailUrl_ = url; // Use the URL directly.
24 return; 29 return;
25 } 30 }
26 31
27 this.fallbackUrl_ = null; 32 this.fallbackUrl_ = null;
28 this.thumbnailUrl_ = null; 33 this.thumbnailUrl_ = null;
29 if (opt_metadata.drive) { 34 if (opt_metadata.drive) {
30 var apps = opt_metadata.drive.driveApps; 35 var apps = opt_metadata.drive.driveApps;
31 for (var i = 0; i < apps.length; ++i) { 36 for (var i = 0; i < apps.length; ++i) {
32 if (apps[i].docIcon && apps[i].isPrimary) { 37 if (apps[i].docIcon && apps[i].isPrimary) {
33 this.fallbackUrl_ = apps[i].docIcon; 38 this.fallbackUrl_ = apps[i].docIcon;
34 break; 39 break;
35 } 40 }
36 } 41 }
37 } 42 }
38 43
39 if (opt_metadata.thumbnail && opt_metadata.thumbnail.url) { 44 if (opt_metadata.thumbnail && opt_metadata.thumbnail.url &&
45 opt_useEmbedded == ThumbnailLoader.UseEmbedded.USE_EMBEDDED) {
40 this.thumbnailUrl_ = opt_metadata.thumbnail.url; 46 this.thumbnailUrl_ = opt_metadata.thumbnail.url;
41 this.transform_ = opt_metadata.thumbnail.transform; 47 this.transform_ = opt_metadata.thumbnail.transform;
42 } else if (FileType.isImage(url)) { 48 } else if (FileType.isImage(url)) {
43 this.thumbnailUrl_ = url; 49 this.thumbnailUrl_ = url;
44 this.transform_ = opt_metadata.media && opt_metadata.media.imageTransform; 50 this.transform_ = opt_metadata.media && opt_metadata.media.imageTransform;
45 } else if (this.fallbackUrl_) { 51 } else if (this.fallbackUrl_) {
46 // Use fallback as the primary thumbnail. 52 // Use fallback as the primary thumbnail.
47 this.thumbnailUrl_ = this.fallbackUrl_; 53 this.thumbnailUrl_ = this.fallbackUrl_;
48 this.fallbackUrl_ = null; 54 this.fallbackUrl_ = null;
49 } // else the generic thumbnail based on the media type will be used. 55 } // else the generic thumbnail based on the media type will be used.
50 } 56 }
51 57
52 /** 58 /**
53 * In percents (0.0 - 1.0), how much area can be cropped to fill an image 59 * In percents (0.0 - 1.0), how much area can be cropped to fill an image
54 * in a container, when loading a thumbnail in FillMode.AUTO mode. 60 * in a container, when loading a thumbnail in FillMode.AUTO mode.
55 * The specified 30% value allows to fill 16:9, 3:2 pictures in 4:3 element. 61 * The specified 30% value allows to fill 16:9, 3:2 pictures in 4:3 element.
56 * @type {number} 62 * @type {number}
57 */ 63 */
58 ThumbnailLoader.AUTO_FILL_THRESHOLD = 0.3; 64 ThumbnailLoader.AUTO_FILL_THRESHOLD = 0.3;
59 65
60 /** 66 /**
61 * Type of displaying a thumbnail within a box. 67 * Type of displaying a thumbnail within a box.
62 * @enum 68 * @enum {number}
63 */ 69 */
64 ThumbnailLoader.FillMode = { 70 ThumbnailLoader.FillMode = {
65 FILL: 0, // Fill whole box. Image may be cropped. 71 FILL: 0, // Fill whole box. Image may be cropped.
66 FIT: 1, // Keep aspect ratio, do not crop. 72 FIT: 1, // Keep aspect ratio, do not crop.
67 AUTO: 2 // Try to fill, but if incompatible aspect ratio, then fit. 73 AUTO: 2 // Try to fill, but if incompatible aspect ratio, then fit.
68 }; 74 };
69 75
70 /** 76 /**
71 * Optimization mode for downloading thumbnails. 77 * Optimization mode for downloading thumbnails.
72 * @enum 78 * @enum {number}
73 */ 79 */
74 ThumbnailLoader.OptimizationMode = { 80 ThumbnailLoader.OptimizationMode = {
75 NEVER_DISCARD: 0, // Never discards downloading. No optimization. 81 NEVER_DISCARD: 0, // Never discards downloading. No optimization.
76 DISCARD_DETACHED: 1 // Canceled if the container is not attached anymore. 82 DISCARD_DETACHED: 1 // Canceled if the container is not attached anymore.
77 }; 83 };
78 84
79 /** 85 /**
80 * Type of element to store the image. 86 * Type of element to store the image.
81 * @enum 87 * @enum {number}
82 */ 88 */
83 ThumbnailLoader.LoaderType = { 89 ThumbnailLoader.LoaderType = {
84 IMAGE: 0, 90 IMAGE: 0,
85 CANVAS: 1 91 CANVAS: 1
86 }; 92 };
87 93
88 /** 94 /**
95 * Whether to use the embedded thumbnail, or not. The embedded thumbnail may
96 * be small.
97 * @enum {number}
98 */
99 ThumbnailLoader.UseEmbedded = {
100 USE_EMBEDDED: 0,
101 NO_EMBEDDED: 1
102 };
103
104 /**
89 * Maximum thumbnail's width when generating from the full resolution image. 105 * Maximum thumbnail's width when generating from the full resolution image.
90 * @const 106 * @const
91 * @type {number} 107 * @type {number}
92 */ 108 */
93 ThumbnailLoader.THUMBNAIL_MAX_WIDTH = 500; 109 ThumbnailLoader.THUMBNAIL_MAX_WIDTH = 500;
94 110
95 /** 111 /**
96 * Maximum thumbnail's height when generating from the full resolution image. 112 * Maximum thumbnail's height when generating from the full resolution image.
97 * @const 113 * @const
98 * @type {number} 114 * @type {number}
(...skipping 17 matching lines...) Expand all
116 opt_optimizationMode = opt_optimizationMode || 132 opt_optimizationMode = opt_optimizationMode ||
117 ThumbnailLoader.OptimizationMode.NEVER_DISCARD; 133 ThumbnailLoader.OptimizationMode.NEVER_DISCARD;
118 134
119 if (!this.thumbnailUrl_) { 135 if (!this.thumbnailUrl_) {
120 // Relevant CSS rules are in file_types.css. 136 // Relevant CSS rules are in file_types.css.
121 box.setAttribute('generic-thumbnail', this.mediaType_); 137 box.setAttribute('generic-thumbnail', this.mediaType_);
122 if (opt_onGeneric) opt_onGeneric(); 138 if (opt_onGeneric) opt_onGeneric();
123 return; 139 return;
124 } 140 }
125 141
142 this.cancel();
126 this.canvasUpToDate_ = false; 143 this.canvasUpToDate_ = false;
127 this.image_ = new Image(); 144 this.image_ = new Image();
128 this.image_.onload = function() { 145 this.image_.onload = function() {
129 this.attachImage(box, fillMode); 146 this.attachImage(box, fillMode);
130 if (opt_onSuccess) 147 if (opt_onSuccess)
131 opt_onSuccess(this.image_, this.transform_); 148 opt_onSuccess(this.image_, this.transform_);
132 }.bind(this); 149 }.bind(this);
133 this.image_.onerror = function() { 150 this.image_.onerror = function() {
134 if (opt_onError) 151 if (opt_onError)
135 opt_onError(); 152 opt_onError();
(...skipping 12 matching lines...) Expand all
148 console.warn('Thumbnail already loaded: ' + this.thumbnailUrl_); 165 console.warn('Thumbnail already loaded: ' + this.thumbnailUrl_);
149 return; 166 return;
150 } 167 }
151 168
152 // TODO(mtomasz): Smarter calculation of the requested size. 169 // TODO(mtomasz): Smarter calculation of the requested size.
153 var wasAttached = box.ownerDocument.contains(box); 170 var wasAttached = box.ownerDocument.contains(box);
154 var modificationTime = this.metadata_ && 171 var modificationTime = this.metadata_ &&
155 this.metadata_.filesystem && 172 this.metadata_.filesystem &&
156 this.metadata_.filesystem.modificationTime && 173 this.metadata_.filesystem.modificationTime &&
157 this.metadata_.filesystem.modificationTime.getTime(); 174 this.metadata_.filesystem.modificationTime.getTime();
158 var taskId = util.loadImage( 175 this.taskId_ = util.loadImage(
159 this.image_, 176 this.image_,
160 this.thumbnailUrl_, 177 this.thumbnailUrl_,
161 { maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, 178 { maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH,
162 maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, 179 maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT,
163 cache: true, 180 cache: true,
164 timestamp: modificationTime }, 181 timestamp: modificationTime },
165 function() { 182 function() {
166 if (opt_optimizationMode == 183 if (opt_optimizationMode ==
167 ThumbnailLoader.OptimizationMode.DISCARD_DETACHED && 184 ThumbnailLoader.OptimizationMode.DISCARD_DETACHED &&
168 !box.ownerDocument.contains(box)) { 185 !box.ownerDocument.contains(box)) {
169 // If the container is not attached, then invalidate the download. 186 // If the container is not attached, then invalidate the download.
170 return false; 187 return false;
171 } 188 }
172 return true; 189 return true;
173 }); 190 });
174 191
175 if (!taskId) 192 if (!this.taskId_)
176 this.image_.classList.add('cached'); 193 this.image_.classList.add('cached');
177 }; 194 };
178 195
179 /** 196 /**
197 * Cancels loading the current image.
198 */
199 ThumbnailLoader.prototype.cancel = function() {
200 if (this.taskId_) {
201 this.image_.onload = function() {};
202 this.image_.onerror = function() {};
203 util.cancelLoadImage(this.taskId_);
204 }
205 };
206
207 /**
180 * @return {boolean} True if a valid image is loaded. 208 * @return {boolean} True if a valid image is loaded.
181 */ 209 */
182 ThumbnailLoader.prototype.hasValidImage = function() { 210 ThumbnailLoader.prototype.hasValidImage = function() {
183 return !!(this.image_ && this.image_.width && this.image_.height); 211 return !!(this.image_ && this.image_.width && this.image_.height);
184 }; 212 };
185 213
186 /** 214 /**
187 * @return {boolean} True if the image is rotated 90 degrees left or right. 215 * @return {boolean} True if the image is rotated 90 degrees left or right.
188 * @private 216 * @private
189 */ 217 */
(...skipping 20 matching lines...) Expand all
210 * 238 *
211 * @param {function(boolean)} callback Callback, parameter is true if the image 239 * @param {function(boolean)} callback Callback, parameter is true if the image
212 * has loaded successfully or a stock icon has been used. 240 * has loaded successfully or a stock icon has been used.
213 */ 241 */
214 ThumbnailLoader.prototype.loadDetachedImage = function(callback) { 242 ThumbnailLoader.prototype.loadDetachedImage = function(callback) {
215 if (!this.thumbnailUrl_) { 243 if (!this.thumbnailUrl_) {
216 callback(true); 244 callback(true);
217 return; 245 return;
218 } 246 }
219 247
248 this.cancel();
220 this.canvasUpToDate_ = false; 249 this.canvasUpToDate_ = false;
221 this.image_ = new Image(); 250 this.image_ = new Image();
222 this.image_.onload = callback.bind(null, true); 251 this.image_.onload = callback.bind(null, true);
223 this.image_.onerror = callback.bind(null, false); 252 this.image_.onerror = callback.bind(null, false);
224 253
225 // TODO(mtomasz): Smarter calculation of the requested size. 254 // TODO(mtomasz): Smarter calculation of the requested size.
226 var modificationTime = this.metadata_ && 255 var modificationTime = this.metadata_ &&
227 this.metadata_.filesystem && 256 this.metadata_.filesystem &&
228 this.metadata_.filesystem.modificationTime && 257 this.metadata_.filesystem.modificationTime &&
229 this.metadata_.filesystem.modificationTime.getTime(); 258 this.metadata_.filesystem.modificationTime.getTime();
230 var taskId = util.loadImage( 259 this.taskId_ = util.loadImage(
231 this.image_, 260 this.image_,
232 this.thumbnailUrl_, 261 this.thumbnailUrl_,
233 { maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, 262 { maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH,
234 maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, 263 maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT,
235 cache: true, 264 cache: true,
236 timestamp: modificationTime }); 265 timestamp: modificationTime });
237 266
238 if (!taskId) 267 if (!this.taskId_)
239 this.image_.classList.add('cached'); 268 this.image_.classList.add('cached');
240 }; 269 };
241 270
242 /** 271 /**
243 * Attach the image to a given element. 272 * Attach the image to a given element.
244 * @param {Element} container Parent element. 273 * @param {Element} container Parent element.
245 * @param {ThumbnailLoader.FillMode} fillMode Fill mode. 274 * @param {ThumbnailLoader.FillMode} fillMode Fill mode.
246 */ 275 */
247 ThumbnailLoader.prototype.attachImage = function(container, fillMode) { 276 ThumbnailLoader.prototype.attachImage = function(container, fillMode) {
248 if (!this.hasValidImage()) { 277 if (!this.hasValidImage()) {
(...skipping 18 matching lines...) Expand all
267 // Canvas will be attached. 296 // Canvas will be attached.
268 attachableMedia = this.canvas_; 297 attachableMedia = this.canvas_;
269 } else { 298 } else {
270 // Image will be attached. 299 // Image will be attached.
271 attachableMedia = this.image_; 300 attachableMedia = this.image_;
272 } 301 }
273 302
274 util.applyTransform(container, this.transform_); 303 util.applyTransform(container, this.transform_);
275 ThumbnailLoader.centerImage_( 304 ThumbnailLoader.centerImage_(
276 container, attachableMedia, fillMode, this.isRotated_()); 305 container, attachableMedia, fillMode, this.isRotated_());
277 if (this.image_.parentNode != container) { 306 if (attachableMedia.parentNode != container) {
278 container.textContent = ''; 307 container.textContent = '';
279 container.appendChild(attachableMedia); 308 container.appendChild(attachableMedia);
280 } 309 }
281 }; 310 };
282 311
283 /** 312 /**
284 * Update the image style to fit/fill the container. 313 * Update the image style to fit/fill the container.
285 * 314 *
286 * Using webkit center packing does not align the image properly, so we need 315 * Using webkit center packing does not align the image properly, so we need
287 * to wait until the image loads and its dimensions are known, then manually 316 * to wait until the image loads and its dimensions are known, then manually
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 380
352 function percent(fraction) { 381 function percent(fraction) {
353 return (fraction * 100).toFixed(2) + '%'; 382 return (fraction * 100).toFixed(2) + '%';
354 } 383 }
355 384
356 img.style.width = percent(fractionX); 385 img.style.width = percent(fractionX);
357 img.style.height = percent(fractionY); 386 img.style.height = percent(fractionY);
358 img.style.left = percent((1 - fractionX) / 2); 387 img.style.left = percent((1 - fractionX) / 2);
359 img.style.top = percent((1 - fractionY) / 2); 388 img.style.top = percent((1 - fractionY) / 2);
360 }; 389 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/js/file_tasks.js ('k') | chrome/browser/resources/file_manager/js/photo/gallery.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698