103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)'use strict'; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Loads a thumbnail using provided url. In CANVAS mode, loaded images 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * are attached as <canvas> element, while in IMAGE mode as <img>. 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * <canvas> renders faster than <img>, however has bigger memory overhead. 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {FileEntry} entry File entry. 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {ThumbnailLoader.LoaderType=} opt_loaderType Canvas or Image loader, 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * default: IMAGE. 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object=} opt_metadata Metadata object. 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {string=} opt_mediaType Media type. 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {ThumbnailLoader.UseEmbedded=} opt_useEmbedded If to use embedded 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * jpeg thumbnail if available. Default: USE_EMBEDDED. 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * @param {number=} opt_priority Priority, the highest is 0. default: 2. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function ThumbnailLoader(entry, opt_loaderType, opt_metadata, opt_mediaType, 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) opt_useEmbedded, opt_priority) { 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) opt_useEmbedded = opt_useEmbedded || ThumbnailLoader.UseEmbedded.USE_EMBEDDED; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.mediaType_ = opt_mediaType || FileType.getMediaType(entry); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.loaderType_ = opt_loaderType || ThumbnailLoader.LoaderType.IMAGE; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.metadata_ = opt_metadata; 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) this.priority_ = (opt_priority !== undefined) ? opt_priority : 2; 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.transform_ = null; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opt_metadata) { 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.thumbnailUrl_ = entry.toURL(); // Use the URL directly. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fallbackUrl_ = null; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.thumbnailUrl_ = null; 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (opt_metadata.external && opt_metadata.external.customIconUrl) 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.fallbackUrl_ = opt_metadata.external.customIconUrl; 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Fetch the rotation from the external properties (if available). 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var externalTransform; 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (opt_metadata.external && 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci opt_metadata.external.imageRotation !== undefined) { 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci externalTransform = { 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scaleX: 1, 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scaleY: 1, 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci rotate90: opt_metadata.external.imageRotation / 90 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) }; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (((opt_metadata.thumbnail && opt_metadata.thumbnail.url) || 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (opt_metadata.external && opt_metadata.external.thumbnailUrl)) && 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) opt_useEmbedded === ThumbnailLoader.UseEmbedded.USE_EMBEDDED) { 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the thumbnail generated from the local cache (metadata.thumbnail.url) 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // is available, use it. If not, use the one passed from the external 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // provider (metadata.external.thumbnailUrl). 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.thumbnailUrl_ = 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (opt_metadata.thumbnail && opt_metadata.thumbnail.url) || 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (opt_metadata.external && opt_metadata.external.thumbnailUrl); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.transform_ = externalTransform !== undefined ? externalTransform : 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (opt_metadata.thumbnail && opt_metadata.thumbnail.transform); 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (FileType.isImage(entry)) { 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.thumbnailUrl_ = entry.toURL(); 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.transform_ = externalTransform !== undefined ? externalTransform : 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) opt_metadata.media && opt_metadata.media.imageTransform; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (this.fallbackUrl_) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use fallback as the primary thumbnail. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.thumbnailUrl_ = this.fallbackUrl_; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fallbackUrl_ = null; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } // else the generic thumbnail based on the media type will be used. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * In percents (0.0 - 1.0), how much area can be cropped to fill an image 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * in a container, when loading a thumbnail in FillMode.AUTO mode. 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The specified 30% value allows to fill 16:9, 3:2 pictures in 4:3 element. 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @type {number} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.AUTO_FILL_THRESHOLD = 0.3; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Type of displaying a thumbnail within a box. 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @enum {number} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.FillMode = { 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FILL: 0, // Fill whole box. Image may be cropped. 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FIT: 1, // Keep aspect ratio, do not crop. 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OVER_FILL: 2, // Fill whole box with possible stretching. 917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AUTO: 3 // Try to fill, but if incompatible aspect ratio, then fit. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Optimization mode for downloading thumbnails. 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @enum {number} 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.OptimizationMode = { 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NEVER_DISCARD: 0, // Never discards downloading. No optimization. 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISCARD_DETACHED: 1 // Canceled if the container is not attached anymore. 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Type of element to store the image. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @enum {number} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.LoaderType = { 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IMAGE: 0, 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CANVAS: 1 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Whether to use the embedded thumbnail, or not. The embedded thumbnail may 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * be small. 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @enum {number} 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.UseEmbedded = { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) USE_EMBEDDED: 0, 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NO_EMBEDDED: 1 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Maximum thumbnail's width when generating from the full resolution image. 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @const 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @type {number} 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.THUMBNAIL_MAX_WIDTH = 500; 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Maximum thumbnail's height when generating from the full resolution image. 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @const 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @type {number} 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.THUMBNAIL_MAX_HEIGHT = 500; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Loads and attaches an image. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} box Container element. 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {ThumbnailLoader.FillMode} fillMode Fill mode. 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {ThumbnailLoader.OptimizationMode=} opt_optimizationMode Optimization 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * for downloading thumbnails. By default optimizations are disabled. 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {function(Image, Object)=} opt_onSuccess Success callback, 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * accepts the image and the transform. 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {function()=} opt_onError Error callback. 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {function()=} opt_onGeneric Callback for generic image used. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.prototype.load = function(box, fillMode, opt_optimizationMode, 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) opt_onSuccess, opt_onError, opt_onGeneric) { 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) opt_optimizationMode = opt_optimizationMode || 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ThumbnailLoader.OptimizationMode.NEVER_DISCARD; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.thumbnailUrl_) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Relevant CSS rules are in file_types.css. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) box.setAttribute('generic-thumbnail', this.mediaType_); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_onGeneric) opt_onGeneric(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.cancel(); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.canvasUpToDate_ = false; 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_ = new Image(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.image_.onload = function() { 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.attachImage(box, fillMode); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_onSuccess) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opt_onSuccess(this.image_, this.transform_); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }.bind(this); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.image_.onerror = function() { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_onError) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opt_onError(); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.fallbackUrl_) { 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.thumbnailUrl_ = this.fallbackUrl_; 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.fallbackUrl_ = null; 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.load(box, fillMode, opt_optimizationMode, opt_onSuccess); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) box.setAttribute('generic-thumbnail', this.mediaType_); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }.bind(this); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.image_.src) { 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) console.warn('Thumbnail already loaded: ' + this.thumbnailUrl_); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(mtomasz): Smarter calculation of the requested size. 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var wasAttached = box.ownerDocument.contains(box); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var modificationTime = this.metadata_ && 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.metadata_.filesystem && 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.metadata_.filesystem.modificationTime && 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.metadata_.filesystem.modificationTime.getTime(); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.taskId_ = util.loadImage( 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_, 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.thumbnailUrl_, 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cache: true, 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) priority: this.priority_, 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timestamp: modificationTime }, 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) function() { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (opt_optimizationMode == 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ThumbnailLoader.OptimizationMode.DISCARD_DETACHED && 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !box.ownerDocument.contains(box)) { 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the container is not attached, then invalidate the download. 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Cancels loading the current image. 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.prototype.cancel = function() { 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.taskId_) { 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_.onload = function() {}; 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_.onerror = function() {}; 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) util.cancelLoadImage(this.taskId_); 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.taskId_ = null; 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if a valid image is loaded. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ThumbnailLoader.prototype.hasValidImage = function() { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !!(this.image_ && this.image_.width && this.image_.height); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if the image is rotated 90 degrees left or right. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ThumbnailLoader.prototype.isRotated_ = function() { 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return this.transform_ && (this.transform_.rotate90 % 2 === 1); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} Image width (corrected for rotation). 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ThumbnailLoader.prototype.getWidth = function() { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.isRotated_() ? this.image_.height : this.image_.width; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} Image height (corrected for rotation). 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ThumbnailLoader.prototype.getHeight = function() { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.isRotated_() ? this.image_.width : this.image_.height; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Load an image but do not attach it. 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function(boolean)} callback Callback, parameter is true if the image 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * has loaded successfully or a stock icon has been used. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ThumbnailLoader.prototype.loadDetachedImage = function(callback) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.thumbnailUrl_) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback(true); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.cancel(); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.canvasUpToDate_ = false; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.image_ = new Image(); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.image_.onload = callback.bind(null, true); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.image_.onerror = callback.bind(null, false); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(mtomasz): Smarter calculation of the requested size. 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var modificationTime = this.metadata_ && 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.metadata_.filesystem && 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.metadata_.filesystem.modificationTime && 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.metadata_.filesystem.modificationTime.getTime(); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.taskId_ = util.loadImage( 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.image_, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.thumbnailUrl_, 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cache: true, 28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) priority: this.priority_, 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timestamp: modificationTime }); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Renders the thumbnail into either canvas or an image element. 2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @private 2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ThumbnailLoader.prototype.renderMedia_ = function() { 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (this.loaderType_ !== ThumbnailLoader.LoaderType.CANVAS) 2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!this.canvas_) 2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.canvas_ = document.createElement('canvas'); 2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Copy the image to a canvas if the canvas is outdated. 2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!this.canvasUpToDate_) { 2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.canvas_.width = this.image_.width; 2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.canvas_.height = this.image_.height; 2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) var context = this.canvas_.getContext('2d'); 3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) context.drawImage(this.image_, 0, 0); 3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.canvasUpToDate_ = true; 3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Attach the image to a given element. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Element} container Parent element. 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {ThumbnailLoader.FillMode} fillMode Fill mode. 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.prototype.attachImage = function(container, fillMode) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.hasValidImage()) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container.setAttribute('generic-thumbnail', this.mediaType_); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.renderMedia_(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) util.applyTransform(container, this.transform_); 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) var attachableMedia = this.loaderType_ === ThumbnailLoader.LoaderType.CANVAS ? 3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.canvas_ : this.image_; 3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ThumbnailLoader.centerImage_( 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) container, attachableMedia, fillMode, this.isRotated_()); 3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (attachableMedia.parentNode !== container) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container.textContent = ''; 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) container.appendChild(attachableMedia); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!this.taskId_) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) attachableMedia.classList.add('cached'); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Gets the loaded image. 3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * TODO(mtomasz): Apply transformations. 3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * 3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {Image|HTMLCanvasElement} Either image or a canvas object. 3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ThumbnailLoader.prototype.getImage = function() { 3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.renderMedia_(); 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return this.loaderType_ === ThumbnailLoader.LoaderType.CANVAS ? this.canvas_ : 3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.image_; 3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Update the image style to fit/fill the container. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Using webkit center packing does not align the image properly, so we need 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to wait until the image loads and its dimensions are known, then manually 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * position it at the center. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} box Containing element. 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Image|HTMLCanvasElement} img Element containing an image. 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {ThumbnailLoader.FillMode} fillMode Fill mode. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} rotate True if the image should be rotated 90 degrees. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThumbnailLoader.centerImage_ = function(box, img, fillMode, rotate) { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var imageWidth = img.width; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var imageHeight = img.height; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var fractionX; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var fractionY; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var boxWidth = box.clientWidth; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var boxHeight = box.clientHeight; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var fill; 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (fillMode) { 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ThumbnailLoader.FillMode.FILL: 3717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case ThumbnailLoader.FillMode.OVER_FILL: 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fill = true; 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ThumbnailLoader.FillMode.FIT: 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fill = false; 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ThumbnailLoader.FillMode.AUTO: 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var imageRatio = imageWidth / imageHeight; 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var boxRatio = 1.0; 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (boxWidth && boxHeight) 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) boxRatio = boxWidth / boxHeight; 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Cropped area in percents. 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var ratioFactor = boxRatio / imageRatio; 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fill = (ratioFactor >= 1.0 - ThumbnailLoader.AUTO_FILL_THRESHOLD) && 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (ratioFactor <= 1.0 + ThumbnailLoader.AUTO_FILL_THRESHOLD); 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (boxWidth && boxHeight) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we know the box size we can position the image correctly even 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in a non-square box. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var fitScaleX = (rotate ? boxHeight : boxWidth) / imageWidth; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var fitScaleY = (rotate ? boxWidth : boxHeight) / imageHeight; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var scale = fill ? 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Math.max(fitScaleX, fitScaleY) : 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Math.min(fitScaleX, fitScaleY); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (fillMode !== ThumbnailLoader.FillMode.OVER_FILL) 4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scale = Math.min(scale, 1); // Never overscale. 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fractionX = imageWidth * scale / boxWidth; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fractionY = imageHeight * scale / boxHeight; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We do not know the box size so we assume it is square. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute the image position based only on the image dimensions. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First try vertical fit or horizontal fill. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fractionX = imageWidth / imageHeight; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fractionY = 1; 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((fractionX < 1) === !!fill) { // Vertical fill or horizontal fit. 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fractionY = 1 / fractionX; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fractionX = 1; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function percent(fraction) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (fraction * 100).toFixed(2) + '%'; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) img.style.width = percent(fractionX); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) img.style.height = percent(fractionY); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) img.style.left = percent((1 - fractionX) / 2); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) img.style.top = percent((1 - fractionY) / 2); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 425