Index: third_party/google_input_tools/src/chrome/os/inputview/elements/content/gesturecanvasview.js |
diff --git a/third_party/google_input_tools/src/chrome/os/inputview/elements/content/gesturecanvasview.js b/third_party/google_input_tools/src/chrome/os/inputview/elements/content/gesturecanvasview.js |
index 9f081a138996e5a6f2b1aa6e337909b3c7c7802d..4661e2ca46c2592bf2711373ab0c46ff971247d8 100644 |
--- a/third_party/google_input_tools/src/chrome/os/inputview/elements/content/gesturecanvasview.js |
+++ b/third_party/google_input_tools/src/chrome/os/inputview/elements/content/gesturecanvasview.js |
@@ -12,6 +12,7 @@ |
// Licensed under the Apache License, Version 2.0 (the "License"); |
// |
goog.provide('i18n.input.chrome.inputview.elements.content.GestureCanvasView'); |
+goog.provide('i18n.input.chrome.inputview.elements.content.GestureCanvasView.Point'); |
goog.require('goog.async.Delay'); |
goog.require('goog.dom.TagName'); |
@@ -57,11 +58,11 @@ i18n.input.chrome.inputview.elements.content.GestureCanvasView = |
this.drawingContext_; |
/** |
- * Drag events whose points should be drawn on the canvas. |
+ * A list of list of gesture points to be rendered on the canvas as strokes. |
* |
- * @private {!Array} |
+ * @private {!Array.<Array>} |
*/ |
- this.dragEventList_ = []; |
+ this.strokeList_ = []; |
/** @private {!goog.async.Delay} */ |
this.animator_ = new goog.async.Delay(this.animateGestureTrail_, 0, this); |
@@ -72,6 +73,14 @@ goog.inherits(GestureCanvasView, i18n.input.chrome.inputview.elements.Element); |
/** |
+ * Rate at which the ttl should degrade for the fading stroke effect. |
+ * |
+ * @const {number} |
+ */ |
+GestureCanvasView.DEGRADATION_RATE = 5; |
+ |
+ |
+/** |
* Draw the gesture trail. |
* |
* @private |
@@ -81,27 +90,30 @@ GestureCanvasView.prototype.draw_ = function() { |
this.drawingContext_.clearRect( |
0, 0, this.drawingCanvas_.width, this.drawingCanvas_.height); |
- // Event positions come in relative to the top of the entire content area, so |
- // grab the canvas offset in order to calculate the correct position to draw |
- // the strokes. |
- var offset = goog.style.getPageOffset(this.drawingCanvas_); |
+ for (var i = 0; i < this.strokeList_.length; i++) { |
+ var pointList = this.strokeList_[i]; |
+ |
+ for (var j = 1; j < pointList.length; j++) { |
+ var first = pointList[j - 1]; |
+ var second = pointList[j]; |
+ // All rendering calculations are based on the second point in the segment |
+ // because there must be at least two points for something to be rendered. |
+ var ttl = second.ttl; |
+ if (ttl <= 0) { |
+ continue; |
+ } |
- // Iterate through all the points and draw them. |
- for (var i = 1; i < this.dragEventList_.length; i++) { |
- // TODO(stevet): The following is a basic implementation of the trail |
- // rendering. This should be later be updated to be more efficient and |
- // support effects like fading. |
- var first = this.dragEventList_[i - 1]; |
- var second = this.dragEventList_[i]; |
- this.drawingContext_.beginPath(); |
- this.drawingContext_.strokeStyle = '#00B4CC'; |
- this.drawingContext_.fillStyle = 'none'; |
- this.drawingContext_.lineWidth = 8; |
- this.drawingContext_.lineCap = 'round'; |
- this.drawingContext_.lineJoin = 'round'; |
- this.drawingContext_.moveTo(first.x - offset.x, first.y - offset.y); |
- this.drawingContext_.lineTo(second.x - offset.x, second.y - offset.y); |
- this.drawingContext_.stroke(); |
+ this.drawingContext_.beginPath(); |
+ this.drawingContext_.moveTo(first.x, first.y); |
+ this.drawingContext_.lineTo(second.x, second.y); |
+ // TODO(stevet): Use alpha and #00B4CC. |
+ this.drawingContext_.strokeStyle = this.calculateColor_(ttl); |
+ this.drawingContext_.fillStyle = 'none'; |
+ this.drawingContext_.lineWidth = this.calculateLineWidth_(ttl); |
+ this.drawingContext_.lineCap = 'round'; |
+ this.drawingContext_.lineJoin = 'round'; |
+ this.drawingContext_.stroke(); |
+ } |
} |
}; |
@@ -117,6 +129,8 @@ GestureCanvasView.prototype.createDom = function() { |
this.drawingCanvas_ = dom.createDom(TagName.CANVAS, Css.DRAWING_CANVAS); |
this.drawingContext_ = this.drawingCanvas_.getContext('2d'); |
dom.appendChild(elem, this.drawingCanvas_); |
+ |
+ this.animator_.start(); |
}; |
@@ -132,16 +146,18 @@ GestureCanvasView.prototype.resize = function(width, height) { |
/** |
- * Add a new point to the collection of points, and refresh the view. |
+ * Converts a drag event to a gesture Point and adds it to the collection of |
+ * points. |
* |
* @param {!i18n.input.chrome.inputview.events.DragEvent} e Drag event to draw. |
*/ |
-GestureCanvasView.prototype.addPointAndDraw = function(e) { |
- // Add to the collection. |
- this.dragEventList_.push(e); |
+GestureCanvasView.prototype.addPoint = function(e) { |
+ if (this.strokeList_.length == 0) { |
+ this.strokeList_.push([]); |
+ } |
- // Refresh the view. |
- this.draw_(); |
+ this.strokeList_[this.strokeList_.length - 1].push( |
+ this.createGesturePoint_(e)); |
}; |
@@ -149,17 +165,151 @@ GestureCanvasView.prototype.addPointAndDraw = function(e) { |
* Clear the view. |
*/ |
GestureCanvasView.prototype.clear = function() { |
- this.dragEventList_ = []; |
+ this.strokeList_ = []; |
this.draw_(); |
}; |
/** |
+ * Begins a new gesture. |
+ * |
+ * @param {!i18n.input.chrome.inputview.events.PointerEvent} e Drag event to |
+ * draw. |
+ */ |
+GestureCanvasView.prototype.startStroke = function(e) { |
+ // Always start a new array to separate previous strokes from this new one. |
+ this.strokeList_.push([]); |
+ |
+ this.strokeList_[this.strokeList_.length - 1].push( |
+ this.createGesturePoint_(e)); |
+}; |
+ |
+ |
+/** |
* The gesture trail animation function. |
* |
* @private |
*/ |
GestureCanvasView.prototype.animateGestureTrail_ = function() { |
- // TODO(stevet): Implement the gesture trail animation here. |
+ // TODO(stevet): This approximates drawing at 60fps. Refactor this and the |
+ // voice input code to use a common call to requestRenderFrame. |
+ var timeStep = 16; |
+ |
+ this.draw_(); |
+ this.degradeStrokes_(); |
+ this.animator_.start(timeStep); |
}; |
+ |
+ |
+/** |
+ * Calculates the line width of the point based on the ttl. |
+ * |
+ * @param {number} ttl The time to live of the point. |
+ * @return {number} The line width to use for the point. |
+ * @private |
+ */ |
+GestureCanvasView.prototype.calculateLineWidth_ = function(ttl) { |
+ var ratio = ttl / 255.0; |
+ if (ratio < 0) { |
+ ratio = 0; |
+ } |
+ return 9 * ratio; |
+}; |
+ |
+ |
+/** |
+ * Calculates the color of the point based on the ttl. |
+ * |
+ * @param {number} ttl The time to live of the point. |
+ * @return {string} The color to use for the point. |
+ * @private |
+ */ |
+GestureCanvasView.prototype.calculateColor_ = function(ttl) { |
+ var shade = 225 - ttl; |
+ if (shade < 0) { |
+ shade = 0; |
+ } |
+ return 'rgb(' + shade + ', ' + shade + ', ' + shade + ')'; |
+}; |
+ |
+ |
+/** |
+ * Returns a gesture point for a given event, with the correct coordinates. |
+ * |
+ * @param {!i18n.input.chrome.inputview.events.DragEvent| |
+ * i18n.input.chrome.inputview.events.PointerEvent} e The event to |
+ * convert. |
+ * @return {i18n.input.chrome.inputview.elements.content. |
+ * GestureCanvasView.Point} The converted gesture point. |
+ * @private |
+ */ |
+GestureCanvasView.prototype.createGesturePoint_ = function(e) { |
+ var offset = goog.style.getPageOffset(this.drawingCanvas_); |
+ return new |
+ i18n.input.chrome.inputview.elements.content.GestureCanvasView.Point( |
+ e.x - offset.x, e.y - offset.y); |
+}; |
+ |
+ |
+/** |
+ * Degrades the ttl of the points in all gesture strokes. |
+ * |
+ * @private |
+ */ |
+GestureCanvasView.prototype.degradeStrokes_ = function() { |
+ for (var i = 0; i < this.strokeList_.length; i++) { |
+ var all_empty = true; |
+ var pointList = this.strokeList_[i]; |
+ for (var j = 0; j < pointList.length; j++) { |
+ if (pointList[j].ttl > 0) { |
+ pointList[j].ttl -= GestureCanvasView.DEGRADATION_RATE; |
+ all_empty = false; |
+ } |
+ } |
+ |
+ // In the case where all points in the list are empty, dispose of the first. |
+ if (all_empty) { |
+ this.strokeList_.splice(i, 1); |
+ i--; |
+ } |
+ } |
+}; |
+ |
+ |
+/** |
+ * One point in the gesture stroke. |
+ * |
+ * This class is used for both rendering the gesture stroke, and also for |
+ * transmitting the stroke coordinates to the recognizer for decoding. |
+ * |
+ * @param {number} x The x coordinate. |
+ * @param {number} y The y coordinate. |
+ * @constructor |
+ */ |
+i18n.input.chrome.inputview.elements.content.GestureCanvasView.Point = |
+ function(x, y) { |
+ /** |
+ * The left offset relative to the canvas. |
+ * |
+ * @type {number} |
+ */ |
+ this.x = x; |
+ |
+ /** |
+ * The top offset relative to the canvas. |
+ * |
+ * @type {number} |
+ */ |
+ this.y = y; |
+ |
+ /** |
+ * The time-to-live value of the point, used to render the trail fading |
+ * effect. |
+ * |
+ * @type {number} |
+ */ |
+ this.ttl = 225; |
+}; |
+ |
+ |
}); // goog.scope |