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

Unified Diff: chrome/browser/resources/file_manager/js/image_editor/image_buffer.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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/file_manager/js/image_editor/image_buffer.js
diff --git a/chrome/browser/resources/file_manager/js/image_editor/image_buffer.js b/chrome/browser/resources/file_manager/js/image_editor/image_buffer.js
index 874d3281105d498e94393aa8f567e6630c32bc34..75bb05e8c555aaa5e1b403c966358562e42fb47c 100644
--- a/chrome/browser/resources/file_manager/js/image_editor/image_buffer.js
+++ b/chrome/browser/resources/file_manager/js/image_editor/image_buffer.js
@@ -10,224 +10,22 @@
*/
function ImageBuffer(screenCanvas) {
this.screenCanvas_ = screenCanvas;
- this.screenContext_ = this.screenCanvas_.getContext("2d");
- this.scale_ = 1;
- this.offsetX_ = 0;
- this.offsetY_ = 0;
+ this.viewport_ = new Viewport(this.repaint.bind(this));
+ this.viewport_.setScreenSize(screenCanvas.width, screenCanvas.height);
- this.overlays_ = [];
+ this.content_ = new ImageBuffer.Content(
+ this.viewport_, screenCanvas.ownerDocument);
- this.setImageCanvas(this.createBlankCanvas(0, 0));
+ this.overlays_ = [];
+ this.addOverlay(new ImageBuffer.Margin(this.viewport_));
+ this.addOverlay(this.content_);
+ this.addOverlay(new ImageBuffer.Overview(this.viewport_, this.content_));
}
-/*
- * Viewport manipulation.
- */
-
-ImageBuffer.prototype.setScaleControl = function(scaleControl) {
- this.scaleControl_ = scaleControl;
-};
-
-ImageBuffer.prototype.getScale = function () { return this.scale_ };
-
-ImageBuffer.prototype.setScale = function (scale, notify) {
- if (this.scale_ == scale) return;
- this.scale_ = scale;
- if (notify && this.scaleControl_) this.scaleControl_.displayScale(scale);
-};
-
-ImageBuffer.prototype.getFittingScale = function() {
- var scaleX = this.screenCanvas_.width / this.imageCanvas_.width;
- var scaleY = this.screenCanvas_.height / this.imageCanvas_.height;
- return Math.min(scaleX, scaleY) * 0.85;
-};
-
-ImageBuffer.prototype.fitImage = function() {
- var scale = this.getFittingScale();
- if (this.scaleControl_) this.scaleControl_.setMinScale(scale);
- this.setScale(scale, true);
-};
-
-ImageBuffer.prototype.resizeScreen = function(width, height, keepFitting) {
- var wasFitting = this.getScale() == this.getFittingScale();
-
- this.screenCanvas_.width = width;
- this.screenCanvas_.height = height;
-
- var minScale = this.getFittingScale();
- if (this.scaleControl_) this.scaleControl_.setMinScale(minScale);
- if ((wasFitting && keepFitting) || this.getScale() < minScale) {
- this.setScale(minScale, true);
- }
- this.repaint();
-};
-
-ImageBuffer.prototype.getOffsetX = function () { return this.offsetX_; };
-
-ImageBuffer.prototype.getOffsetY = function () { return this.offsetY_; };
-
-ImageBuffer.prototype.setOffset = function(x, y, ignoreClipping) {
- if (!ignoreClipping) {
- var limitX = Math.max(0, -this.marginX_ / this.getScale());
- var limitY = Math.max(0, -this.marginY_ / this.getScale());
- x = ImageUtil.clip(-limitX, x, limitX);
- y = ImageUtil.clip(-limitY, y, limitY);
- }
- if (this.offsetX_ == x && this.offsetY_ == y) return;
- this.offsetX_ = x;
- this.offsetY_ = y;
-};
-
-ImageBuffer.prototype.setCenter = function(x, y, ignoreClipping) {
- this.setOffset(
- this.imageWhole_.width / 2 - x,
- this.imageWhole_.height / 2 - y,
- ignoreClipping);
-};
-
-/**
- * @return {Rect} The visible part of the image, in image coordinates.
- */
-ImageBuffer.prototype.getClippedImage = function() {
- return this.imageVisible_;
-};
-
-/**
- * @return {Rect} The visible part of the image, in screen coordinates.
- */
-ImageBuffer.prototype.getClippedScreen = function() {
- return this.screenVisible_;
-};
-
-/**
- * Returns a closure that can be called to pan the image.
- * Useful for implementing non-trivial variants of panning (overview etc).
- * @param {Number} originalX The x coordinate on the screen canvas that
- * corresponds to zero change to offsetX.
- * @param {Number} originalY The y coordinate on the screen canvas that
- * corresponds to zero change to offsetY.
- * @param {Function} scaleFunc returns the current image to screen scale.
- * @param {Function} hitFunc returns true if (x,y) is in the valid region.
- */
-ImageBuffer.prototype.createOffsetSetter_ = function (
- originalX, originalY, scaleFunc, hitFunc) {
- var self = this;
- var originalOffsetX = this.offsetX_;
- var originalOffsetY = this.offsetY_;
- if (!hitFunc) hitFunc = function() { return true; }
- if (!scaleFunc) scaleFunc = this.getScale.bind(this);
- return function(x, y) {
- if (hitFunc(x, y)) {
- var scale = scaleFunc();
- self.setOffset(
- originalOffsetX + (x - originalX) / scale,
- originalOffsetY + (y - originalY) / scale);
- self.repaint();
- }
- };
-};
-
-/**
- * @return {Boolean} True if the entire image is visible on the screen canvas.
- */
-ImageBuffer.prototype.isFullyVisible = function () {
- return this.marginX_ >= 0 && this.marginY_ >= 0;
-};
-
-ImageBuffer.prototype.updateViewPort = function () {
- var scale = this.getScale();
-
- this.screenWhole_ = new Rect(this.screenCanvas_);
- this.imageWhole_ = new Rect(this.imageCanvas_);
-
- // Image bounds in screen coordinates.
- this.imageOnScreen_ = {};
-
- this.imageOnScreen_.width = Math.floor(this.imageWhole_.width * scale);
- this.imageOnScreen_.height = Math.floor(this.imageWhole_.height * scale);
-
- this.marginX_ = Math.floor(
- (this.screenCanvas_.width - this.imageOnScreen_.width) / 2);
- this.marginY_ = Math.floor(
- (this.screenCanvas_.height - this.imageOnScreen_.height) / 2);
-
- this.imageOnScreen_.left = this.marginX_;
- this.imageOnScreen_.top = this.marginY_;
-
- this.imageVisible_ = new Rect(this.imageWhole_);
- this.screenVisible_ = new Rect(this.screenWhole_);
-
- if (this.marginX_ < 0) {
- this.imageOnScreen_.left +=
- ImageUtil.clip(this.marginX_, this.offsetX_ * scale, -this.marginX_);
- this.imageVisible_.left = -this.imageOnScreen_.left / scale;
- this.imageVisible_.width = this.screenCanvas_.width / scale;
- } else {
- this.screenVisible_.left = this.imageOnScreen_.left;
- this.screenVisible_.width = this.imageOnScreen_.width;
- }
-
- if (this.marginY_ < 0) {
- this.imageOnScreen_.top +=
- ImageUtil.clip(this.marginY_, this.offsetY_ * scale, -this.marginY_);
- this.imageVisible_.top = -this.imageOnScreen_.top / scale;
- this.imageVisible_.height = this.screenCanvas_.height / scale;
- } else {
- this.screenVisible_.top = this.imageOnScreen_.top;
- this.screenVisible_.height = this.imageOnScreen_.height;
- }
-
- this.updateOverlays();
-};
-
-/*
- * Coordinate conversion between the screen canvas and the image.
- */
-
-ImageBuffer.prototype.screenToImageSize = function(size) {
- return size / this.getScale();
-};
-
-ImageBuffer.prototype.screenToImageX = function(x) {
- return Math.round((x - this.imageOnScreen_.left) / this.getScale());
-};
-
-ImageBuffer.prototype.screenToImageY = function(y) {
- return Math.round((y - this.imageOnScreen_.top) / this.getScale());
-};
-
-ImageBuffer.prototype.screenToImageRect = function(rect) {
- return new Rect(
- this.screenToImageX(rect.left),
- this.screenToImageY(rect.top),
- this.screenToImageSize(rect.width),
- this.screenToImageSize(rect.height));
-};
-
-ImageBuffer.prototype.imageToScreenSize = function(size) {
- return size * this.getScale();
-};
-
-ImageBuffer.prototype.imageToScreenX = function(x) {
- return Math.round(this.imageOnScreen_.left + x * this.getScale());
-};
-
-ImageBuffer.prototype.imageToScreenY = function(y) {
- return Math.round(this.imageOnScreen_.top + y * this.getScale());
-};
-
-ImageBuffer.prototype.imageToScreenRect = function(rect) {
- return new Rect(
- this.imageToScreenX(rect.left),
- this.imageToScreenY(rect.top),
- this.imageToScreenSize(rect.width),
- this.imageToScreenSize(rect.height));
-};
+ImageBuffer.prototype.getViewport = function() { return this.viewport_ };
-/*
- * Content manipulation.
- */
+ImageBuffer.prototype.getContent = function() { return this.content_ };
/**
* Loads the new content.
@@ -241,123 +39,43 @@ ImageBuffer.prototype.load = function(source) {
image.onload = function(e) { self.load(e.target); };
image.src = source;
} else {
- this.imageCanvas_.width = source.width,
- this.imageCanvas_.height = source.height;
- this.drawImage(source);
-
- if (this.scaleControl_)
- this.scaleControl_.displayImageSize(
- this.imageCanvas_.width, this.imageCanvas_.height);
- this.fitImage();
+ this.content_.load(source);
this.repaint();
}
};
-ImageBuffer.prototype.getImageCanvas = function() { return this.imageCanvas_; };
-
-/**
- * Replaces the off-screen canvas.
- * To be used when the editor modifies the image dimensions.
- * @param {HTMLCanvasElement} canvas
- */
-ImageBuffer.prototype.setImageCanvas = function(canvas) {
- this.imageCanvas_ = canvas;
- this.imageContext_ = canvas.getContext("2d");
- if (this.scaleControl_)
- this.scaleControl_.displayImageSize(
- this.imageCanvas_.width, this.imageCanvas_.height);
-};
-
-/**
- * @return {HTMLCanvasElement} A new blank canvas of the required size.
- */
-ImageBuffer.prototype.createBlankCanvas = function (width, height) {
- var canvas = this.screenCanvas_.ownerDocument.createElement('canvas');
- canvas.width = width;
- canvas.height = height;
- return canvas;
-};
-
-/**
- * @return {HTMLCanvasElement} A new canvas with a copy of the content.
- */
-ImageBuffer.prototype.copyImageCanvas = function () {
- var canvas = this.createBlankCanvas(
- this.imageCanvas_.width, this.imageCanvas_.height);
- canvas.getContext('2d').drawImage(this.imageCanvas_, 0, 0);
- return canvas;
-};
+ImageBuffer.prototype.resizeScreen = function(width, height, keepFitting) {
+ this.screenCanvas_.width = width;
+ this.screenCanvas_.height = height;
-/**
- * @return {ImageData} A new ImageData object with a copy of the content.
- */
-ImageBuffer.prototype.copyImageData = function () {
- return this.imageContext_.getImageData(
- 0, 0, this.imageCanvas_.width, this.imageCanvas_.height);
-};
+ var wasFitting =
+ this.viewport_.getScale() == this.viewport_.getFittingScale();
-/**
- * @param {HTMLImageElement|HTMLCanvasElement} image
- */
-ImageBuffer.prototype.drawImage = function(image) {
- ImageUtil.trace.resetTimer('drawImage');
- this.imageContext_.drawImage(image, 0, 0);
- ImageUtil.trace.reportTimer('drawImage');
-};
+ this.viewport_.setScreenSize(width, height);
-/**
- * @param {ImageData} imageData
- */
-ImageBuffer.prototype.drawImageData = function (imageData) {
- ImageUtil.trace.resetTimer('putImageData');
- this.imageContext_.putImageData(imageData, 0, 0);
- ImageUtil.trace.reportTimer('putImageData');
+ var minScale = this.viewport_.getFittingScale();
+ if ((wasFitting && keepFitting) || this.viewport_.getScale() < minScale) {
+ this.viewport_.setScale(minScale, true);
+ }
+ this.repaint();
};
/**
* Paints the content on the screen canvas taking the current scale and offset
* into account.
*/
-ImageBuffer.prototype.repaint = function () {
- ImageUtil.trace.resetTimer('repaint');
-
- this.updateViewPort();
-
- this.screenContext_.save();
-
- this.screenContext_.fillStyle = '#F0F0F0';
- this.screenContext_.strokeStyle = '#000000';
-
- Rect.drawImage(this.screenContext_, this.imageCanvas_,
- this.imageOnScreen_, this.imageWhole_);
- Rect.fillBetween(this.screenContext_, this.imageOnScreen_,
- this.screenWhole_);
- Rect.stroke(this.screenContext_, this.imageOnScreen_);
-
- this.screenContext_.restore();
-
- this.drawOverlays(this.screenContext_);
-
- ImageUtil.trace.reportTimer('repaint');
+ImageBuffer.prototype.repaint = function (opt_fromOverlay) {
+ this.viewport_.update();
+ this.drawOverlays(this.screenCanvas_.getContext("2d"), opt_fromOverlay);
};
-/**
- * ImageBuffer.Overlay is a pluggable extension that modifies the outlook
- * and the behavior of the ImageBuffer instance.
- */
-ImageBuffer.Overlay = function() {};
-
-ImageBuffer.Overlay.prototype.getZIndex = function() { return 0 };
-
-ImageBuffer.Overlay.prototype.updateViewPort = function() {}
-
-ImageBuffer.Overlay.prototype.draw = function() {}
-
-ImageBuffer.Overlay.prototype.getCursorStyle = function() { return null };
-
-ImageBuffer.Overlay.prototype.onClick = function() { return false };
-
-ImageBuffer.Overlay.prototype.getDragHandler = function() { return null };
+ImageBuffer.prototype.repaintScreenRect = function (screenRect, imageRect) {
+ Rect.drawImage(
+ this.screenCanvas_.getContext('2d'),
+ this.getContent().getCanvas(),
+ screenRect || this.getViewport().imageToScreenRect(screenRect),
+ imageRect || this.getViewport().screenToImageRect(screenRect));
+};
/**
* @param {ImageBuffer.Overlay} overlay
@@ -386,21 +104,18 @@ ImageBuffer.prototype.removeOverlay = function (overlay) {
};
/**
- * Updates viewport configuration on all overlays.
- */
-ImageBuffer.prototype.updateOverlays = function (context) {
- for (var i = 0; i != this.overlays_.length; i++) {
- this.overlays_[i].updateViewPort(this);
- }
-}
-
-/**
* Draws overlays in the ascending Z-order.
+ * Skips overlays below opt_startFrom.
*/
-ImageBuffer.prototype.drawOverlays = function (context) {
+ImageBuffer.prototype.drawOverlays = function (context, opt_fromOverlay) {
+ var skip = true;
for (var i = 0; i != this.overlays_.length; i++) {
+ var overlay = this.overlays_[i];
+ if (!opt_fromOverlay || opt_fromOverlay == overlay) skip = false;
+ if (skip) continue;
+
context.save();
- this.overlays_[i].draw(context);
+ overlay.draw(context);
context.restore();
}
};
@@ -414,11 +129,6 @@ ImageBuffer.prototype.getCursorStyle = function (x, y, mouseDown) {
var style = this.overlays_[i].getCursorStyle(x, y, mouseDown);
if (style) return style;
}
-
- // Indicate that the image is draggable.
- if (!this.isFullyVisible() && this.screenVisible_.inside(x, y))
- return 'move';
-
return 'default';
};
@@ -442,116 +152,279 @@ ImageBuffer.prototype.getDragHandler = function (x, y) {
var handler = this.overlays_[i].getDragHandler(x, y);
if (handler) return handler;
}
+ return null;
+};
+
+/**
+ * ImageBuffer.Overlay is a pluggable extension that modifies the outlook
+ * and the behavior of the ImageBuffer instance.
+ */
+ImageBuffer.Overlay = function() {};
+
+ImageBuffer.Overlay.prototype.getZIndex = function() { return 0 };
+
+ImageBuffer.Overlay.prototype.draw = function() {};
+
+ImageBuffer.Overlay.prototype.getCursorStyle = function() { return null };
+
+ImageBuffer.Overlay.prototype.onClick = function() { return false };
+
+ImageBuffer.Overlay.prototype.getDragHandler = function() { return null };
+
+
+/**
+ * The margin overlay draws the image outline and paints the margins.
+ */
+ImageBuffer.Margin = function(viewport) {
+ this.viewport_ = viewport;
+};
+
+ImageBuffer.Margin.prototype = {__proto__: ImageBuffer.Overlay.prototype};
+
+// Draw below everything including the content.
+ImageBuffer.Margin.prototype.getZIndex = function() { return -2 };
+
+ImageBuffer.Margin.prototype.draw = function(context) {
+ context.save();
+ context.fillStyle = '#F0F0F0';
+ context.strokeStyle = '#000000';
+ Rect.fillBetween(context,
+ this.viewport_.getImageBoundsOnScreen(),
+ this.viewport_.getScreenBounds());
+ Rect.stroke(context, this.viewport_.getImageBoundsOnScreen());
+ context.restore();
+};
+
+/**
+ * The overlay containing the image.
+ */
+ImageBuffer.Content = function(viewport, document) {
+ this.viewport_ = viewport;
+ this.document_ = document;
+
+ this.generation_ = 0;
+
+ this.setCanvas(this.createBlankCanvas(0, 0));
+};
+
+ImageBuffer.Content.prototype = {__proto__: ImageBuffer.Overlay.prototype};
+
+// Draw below overlays with the default zIndex.
+ImageBuffer.Content.prototype.getZIndex = function() { return -1 };
+
+ImageBuffer.Content.prototype.draw = function(context) {
+ Rect.drawImage(
+ context, this.canvas_, this.viewport_.getImageBoundsOnScreen());
+};
+
+ImageBuffer.Content.prototype.getCursorStyle = function (x, y, mouseDown) {
+ // Indicate that the image is draggable.
+ if (this.viewport_.isClipped() &&
+ this.viewport_.getScreenClipped().inside(x, y))
+ return 'move';
+
+ return null;
+};
- if (!this.isFullyVisible() && this.screenVisible_.inside(x, y)) {
+ImageBuffer.Content.prototype.getDragHandler = function (x, y) {
+ var cursor = this.getCursorStyle(x, y);
+ if (cursor == 'move') {
// Return the handler that drags the entire image.
- return this.createOffsetSetter_(x, y, this.getScale.bind(this));
+ return this.viewport_.createOffsetSetter(x, y);
}
return null;
};
+ImageBuffer.Content.prototype.getCacheGeneration = function() {
+ return this.generation_;
+};
+
+ImageBuffer.Content.prototype.invalidateCaches = function() {
+ this.generation_++;
+};
+
+ImageBuffer.Content.prototype.getCanvas = function() { return this.canvas_ };
+
/**
- * Overview overlay draws the image thumbnail in the bottom right corner.
- * Indicates the currently visible part.
- * Supports panning by dragging.
+ * Replaces the off-screen canvas.
+ * To be used when the editor modifies the image dimensions.
+ * If the logical width/height are supplied they override the canvas dimensions
+ * and the canvas contents is scaled when displayed.
+ * @param {HTMLCanvasElement} canvas
+ * @param {Number} opt_width Logical width (=canvas.width by default)
+ * @param {Number} opt_height Logical height (=canvas.height by default)
*/
+ImageBuffer.Content.prototype.setCanvas = function(
+ canvas, opt_width, opt_height) {
+ this.canvas_ = canvas;
+ this.viewport_.setImageSize(opt_width || canvas.width,
+ opt_height || canvas.height);
-ImageBuffer.Overview = function() {};
+ this.invalidateCaches();
+};
-ImageBuffer.Overview.MAX_SIZE = 150;
-ImageBuffer.Overview.RIGHT = 7;
-ImageBuffer.Overview.BOTTOM = 50;
+/**
+ * @return {HTMLCanvasElement} A new blank canvas of the required size.
+ */
+ImageBuffer.Content.prototype.createBlankCanvas = function (width, height) {
+ var canvas = this.document_.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ return canvas;
+};
+
+/**
+ * @param {Number} opt_width Width of the copy, original width by default.
+ * @param {Number} opt_height Height of the copy, original height by default.
+ * @return {HTMLCanvasElement} A new canvas with a copy of the content.
+ */
+ImageBuffer.Content.prototype.copyCanvas = function (opt_width, opt_height) {
+ var canvas = this.createBlankCanvas(opt_width || this.canvas_.width,
+ opt_height || this.canvas_.height);
+ Rect.drawImage(canvas.getContext('2d'), this.canvas_);
+ return canvas;
+};
+
+/**
+ * @return {ImageData} A new ImageData object with a copy of the content.
+ */
+ImageBuffer.Content.prototype.copyImageData = function (opt_width, opt_height) {
+ return this.canvas_.getContext("2d").getImageData(
+ 0, 0, opt_width || this.canvas_.width, opt_height || this.canvas_.height);
+};
+
+/**
+ * @param {HTMLImageElement|HTMLCanvasElement} image
+ */
+ImageBuffer.Content.prototype.load = function(image) {
+ this.canvas_.width = image.width;
+ this.canvas_.height = image.height;
+
+ Rect.drawImage(this.canvas_.getContext("2d"), image);
+ this.invalidateCaches();
+
+ this.viewport_.setImageSize(image.width, image.height);
+ this.viewport_.fitImage();
+};
+
+/**
+ * @param {ImageData} imageData
+ */
+ImageBuffer.Content.prototype.drawImageData = function (imageData, x, y) {
+ this.canvas_.getContext("2d").putImageData(imageData, x, y);
+ this.invalidateCaches();
+};
+
+/**
+ * The overview overlay draws the image thumbnail in the bottom right corner.
+ * Indicates the currently visible part. Supports panning by dragging.
+ */
+ImageBuffer.Overview = function(viewport, content) {
+ this.viewport_ = viewport;
+ this.content_ = content;
+ this.contentGeneration_ = 0;
+};
ImageBuffer.Overview.prototype = {__proto__: ImageBuffer.Overlay.prototype};
-ImageBuffer.Overview.prototype.getZIndex = function() { return 100; }
+// Draw above everything.
+ImageBuffer.Overview.prototype.getZIndex = function() { return 100 };
-ImageBuffer.Overview.prototype.updateViewPort = function(buffer) {
- this.buffer_ = buffer;
+ImageBuffer.Overview.MAX_SIZE = 150;
+ImageBuffer.Overview.RIGHT = 7;
+ImageBuffer.Overview.BOTTOM = 50;
- this.whole_ = null;
- this.visible_ = null;
+ImageBuffer.Overview.prototype.update = function() {
+ var imageBounds = this.viewport_.getImageBounds();
- if (this.buffer_.isFullyVisible()) return;
+ if (this.contentGeneration_ != this.content_.getCacheGeneration()) {
+ this.contentGeneration_ = this.content_.getCacheGeneration();
- var screenWhole = this.buffer_.screenWhole_;
- var imageWhole = this.buffer_.imageWhole_;
- var imageVisible = this.buffer_.imageVisible_;
+ var aspect = imageBounds.width / imageBounds.height;
+ if (aspect > 1) {
+ this.bounds_ = new Rect(ImageBuffer.Overview.MAX_SIZE,
+ ImageBuffer.Overview.MAX_SIZE / aspect);
+ } else {
+ this.bounds_ = new Rect(ImageBuffer.Overview.MAX_SIZE * aspect,
+ ImageBuffer.Overview.MAX_SIZE);
+ }
- var aspect = imageWhole.width / imageWhole.height;
- if (aspect > 1) {
- this.whole_ = new Rect(ImageBuffer.Overview.MAX_SIZE,
- ImageBuffer.Overview.MAX_SIZE / aspect);
- } else {
- this.whole_ = new Rect(ImageBuffer.Overview.MAX_SIZE * aspect,
- ImageBuffer.Overview.MAX_SIZE);
+ this.canvas_ =
+ this.content_.copyCanvas(this.bounds_.width, this.bounds_.height);
}
- this.whole_ = this.whole_.moveTo(
- screenWhole.width - ImageBuffer.Overview.RIGHT - this.whole_.width,
- screenWhole.height - ImageBuffer.Overview.BOTTOM - this.whole_.height);
+ this.clipped_ = null;
+
+ if (this.viewport_.isClipped()) {
+ var screenBounds = this.viewport_.getScreenBounds();
- this.scale_ = this.whole_.width / imageWhole.width;
+ this.bounds_ = this.bounds_.moveTo(
+ screenBounds.width - ImageBuffer.Overview.RIGHT - this.bounds_.width,
+ screenBounds.height - ImageBuffer.Overview.BOTTOM -
+ this.bounds_.height);
- this.visible_ = imageVisible.
- scale(this.scale_).
- shift(this.whole_.left, this.whole_.top);
+ this.scale_ = this.bounds_.width / imageBounds.width;
+
+ this.clipped_ = this.viewport_.getImageClipped().
+ scale(this.scale_).
+ shift(this.bounds_.left, this.bounds_.top);
+ }
};
ImageBuffer.Overview.prototype.draw = function(context) {
- if (!this.visible_) return;
+ this.update();
+
+ if (!this.clipped_) return;
// Draw the thumbnail.
- Rect.drawImage(context, this.buffer_.imageCanvas_,
- this.whole_, this.buffer_.imageWhole_);
+ Rect.drawImage(context, this.canvas_, this.bounds_);
// Draw the thumbnail border.
context.strokeStyle = '#000000';
- Rect.stroke(context, this.whole_);
+ Rect.stroke(context, this.bounds_);
// Draw the shadow over the off-screen part of the thumbnail.
context.globalAlpha = 0.3;
context.fillStyle = '#000000';
- Rect.fillBetween(context, this.visible_, this.whole_);
+ Rect.fillBetween(context, this.clipped_, this.bounds_);
// Outline the on-screen part of the thumbnail.
context.strokeStyle = '#FFFFFF';
- Rect.stroke(context, this.visible_);
+ Rect.stroke(context, this.clipped_);
};
ImageBuffer.Overview.prototype.getCursorStyle = function(x, y) {
- if (!this.whole_ || !this.whole_.inside(x, y)) return null;
+ if (!this.bounds_ || !this.bounds_.inside(x, y)) return null;
// Indicate that the on-screen part is draggable.
- if (this.visible_.inside(x, y)) return 'move';
+ if (this.clipped_.inside(x, y)) return 'move';
- // Indicathe that the rest of the thumbnail is clickable.
+ // Indicate that the rest of the thumbnail is clickable.
return 'crosshair';
};
ImageBuffer.Overview.prototype.onClick = function(x, y) {
- if (!this.whole_ || !this.whole_.inside(x, y)) return false;
-
- if (this.visible_.inside(x, y)) return false;
-
- this.buffer_.setCenter(
- (x - this.whole_.left) / this.scale_,
- (y - this.whole_.top) / this.scale_);
- this.buffer_.repaint();
+ if (this.getCursorStyle(x, y) != 'crosshair') return false;
+ this.viewport_.setCenter(
+ (x - this.bounds_.left) / this.scale_,
+ (y - this.bounds_.top) / this.scale_);
+ this.viewport_.repaint();
return true;
};
ImageBuffer.Overview.prototype.getDragHandler = function(x, y) {
- if (!this.whole_ || !this.whole_.inside(x, y)) return null;
+ var cursor = this.getCursorStyle(x, y);
- if (this.visible_.inside(x, y)) {
+ if (cursor == 'move') {
var self = this;
function scale() { return -self.scale_;}
- function hit(x, y) { return self.whole_ && self.whole_.inside(x, y); }
- return this.buffer_.createOffsetSetter_(x, y, scale, hit);
- } else {
+ function hit(x, y) { return self.bounds_ && self.bounds_.inside(x, y); }
+ return this.viewport_.createOffsetSetter(x, y, scale, hit);
+ } else if (cursor == 'crosshair') {
// Force non-draggable behavior.
return function() {};
+ } else {
+ return null;
}
};

Powered by Google App Engine
This is Rietveld 408576698