| Index: third_party/google_input_tools/src/chrome/os/inputview/elements/content/gesturestroke.js
|
| diff --git a/third_party/google_input_tools/src/chrome/os/inputview/elements/content/gesturestroke.js b/third_party/google_input_tools/src/chrome/os/inputview/elements/content/gesturestroke.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f29d7fc9123d58bc4a66952d5249cef77c3bf010
|
| --- /dev/null
|
| +++ b/third_party/google_input_tools/src/chrome/os/inputview/elements/content/gesturestroke.js
|
| @@ -0,0 +1,309 @@
|
| +// Copyright 2016 The ChromeOS IME Authors. All Rights Reserved.
|
| +// limitations under the License.
|
| +// See the License for the specific language governing permissions and
|
| +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +// distributed under the License is distributed on an "AS-IS" BASIS,
|
| +// Unless required by applicable law or agreed to in writing, software
|
| +//
|
| +// http://www.apache.org/licenses/LICENSE-2.0
|
| +//
|
| +// You may obtain a copy of the License at
|
| +// you may not use this file except in compliance with the License.
|
| +// Licensed under the Apache License, Version 2.0 (the "License");
|
| +//
|
| +/**
|
| + * @fileoverview A single gesture typing stroke on the canvas.
|
| + */
|
| +goog.provide('i18n.input.chrome.inputview.elements.content.GestureStroke');
|
| +
|
| +goog.require('i18n.input.chrome.inputview.elements.content.Point');
|
| +
|
| +goog.scope(function() {
|
| +var Point = i18n.input.chrome.inputview.elements.content.Point;
|
| +
|
| +
|
| +
|
| +/**
|
| + * @constructor
|
| + */
|
| +i18n.input.chrome.inputview.elements.content.GestureStroke =
|
| + function() {
|
| + /**
|
| + * The list of points that make up this stroke.
|
| + *
|
| + * @private {!Array.<!Point>}
|
| + */
|
| + this.points_ = [];
|
| +
|
| + /**
|
| + * Whether or not this stroke is considered active. i.e. whether or not it
|
| + * should be considered for rendering and decoding.
|
| + *
|
| + * @private {boolean}
|
| + */
|
| + this.isActive_ = false;
|
| +
|
| + /**
|
| + * The time the first point was added to this stroke. Used to keep all points
|
| + * relative to the first point.
|
| + *
|
| + * @private {number}
|
| + */
|
| + this.firstTime_ = 0;
|
| +};
|
| +var GestureStroke =
|
| + i18n.input.chrome.inputview.elements.content.GestureStroke;
|
| +
|
| +
|
| +/**
|
| + * Rate at which the ttl should degrade for the fading stroke effect.
|
| + *
|
| + * @const {number}
|
| + * @private
|
| + */
|
| +GestureStroke.DEGRADATION_RATE_ = 7;
|
| +
|
| +
|
| +/**
|
| + * Distance threshold for when a stroke is considered active, in pixels.
|
| + * TODO(stevet): This is temporary and needs to be updated with a dynamic value
|
| + * that considers other parameters like the width of character keys.
|
| + *
|
| + * @const {number}
|
| + * @private
|
| + */
|
| +GestureStroke.ACTIVE_THRESHOLD_ = 40;
|
| +
|
| +
|
| +/**
|
| + * Starting red value.
|
| + *
|
| + * @const {number}
|
| + * @private
|
| + */
|
| +GestureStroke.STARTING_R_VALUE_ = 68;
|
| +
|
| +
|
| +/**
|
| + * Starting green value.
|
| + *
|
| + * @const {number}
|
| + * @private
|
| + */
|
| +GestureStroke.STARTING_G_VALUE_ = 132;
|
| +
|
| +
|
| +/**
|
| + * Starting blue value.
|
| + *
|
| + * @const {number}
|
| + * @private
|
| + */
|
| +GestureStroke.STARTING_B_VALUE_ = 244;
|
| +
|
| +
|
| +/**
|
| + * @const {number}
|
| + * @private
|
| + */
|
| +GestureStroke.STROKE_MAX_WIDTH_ = 9;
|
| +
|
| +
|
| +/**
|
| + * Returns a string that represents the color of the point based on the ttl in
|
| + * a format usable as a canvas stroke style.
|
| + *
|
| + * @param {number} ttl The time to live of the point.
|
| + * @return {string} The color to use for the point.
|
| + * @private
|
| + */
|
| +GestureStroke.calculateColor_ = function(ttl) {
|
| + // TODO(maxw): Use this percentage to fade the stroke color.
|
| + var remainingTtlPercentage = ttl / Point.STARTING_TTL;
|
| + var rValue = GestureStroke.STARTING_R_VALUE_;
|
| + var gValue = GestureStroke.STARTING_G_VALUE_;
|
| + var bValue = GestureStroke.STARTING_B_VALUE_;
|
| + return 'rgb(' + rValue + ', ' + gValue + ', ' + bValue + ')';
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Calculates the distance between two Points using the Pythagorean theorem.
|
| + * Note that goog.math.Coordinate provides a distance method, but requires that
|
| + * points are passed in as Coordinate objects. By defining a simple
|
| + * implementation here, we avoid the cost of creating Coordinate objects
|
| + * repeatedly.
|
| + *
|
| + * @param {!Point} first The first point.
|
| + * @param {!Point} second The second point.
|
| + * @return {number} The number of pixels between first and second.
|
| + * @private
|
| + */
|
| +GestureStroke.calculateDistance_ = function(first, second) {
|
| + var a = Math.abs(first.x - second.x);
|
| + var b = Math.abs(first.y - second.y);
|
| + return Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
|
| +};
|
| +
|
| +
|
| +/**
|
| + * 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
|
| + */
|
| +GestureStroke.calculateLineWidth_ = function(ttl) {
|
| + var ratio = ttl / Point.STARTING_TTL;
|
| + if (ratio < 0) {
|
| + ratio = 0;
|
| + }
|
| + // Reduce the max width proportionately with the current ratio.
|
| + return GestureStroke.STROKE_MAX_WIDTH_ * ratio;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Degrades all the points in this stroke.
|
| + *
|
| + * @return {boolean} Returns true if it was possible to degrade one or more
|
| + * points, otherwise it means that this stroke is now empty.
|
| + */
|
| +GestureStroke.prototype.degrade = function() {
|
| + var allEmpty = true;
|
| + for (var i = 0; i < this.points_.length; i++) {
|
| + if (this.points_[i].ttl > 0) {
|
| + this.points_[i].ttl -= GestureStroke.DEGRADATION_RATE_;
|
| + allEmpty = false;
|
| + }
|
| + }
|
| + return !allEmpty;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Draw the gesture trail for this stroke onto the canvas context.
|
| + *
|
| + * @param {!CanvasRenderingContext2D} context The drawing context to render to.
|
| + */
|
| +GestureStroke.prototype.draw = function(context) {
|
| + // Only start drawing active strokes. Note that TTL still updates even if a
|
| + // stroke is not yet active.
|
| + if (!this.isActive()) {
|
| + return;
|
| + }
|
| +
|
| + for (var i = 1; i < this.points_.length; i++) {
|
| + var first = this.points_[i - 1];
|
| + var second = this.points_[i];
|
| + // 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;
|
| + }
|
| +
|
| + context.beginPath();
|
| + context.moveTo(first.x, first.y);
|
| + context.lineTo(second.x, second.y);
|
| + context.strokeStyle = GestureStroke.calculateColor_(ttl);
|
| + context.fillStyle = 'none';
|
| + context.lineWidth = GestureStroke.calculateLineWidth_(ttl);
|
| + context.lineCap = 'round';
|
| + context.lineJoin = 'round';
|
| + context.stroke();
|
| + }
|
| +};
|
| +
|
| +
|
| +/**
|
| + * @param {number} i The index to look up.
|
| + * @return {number} The identifier of the point at index i.
|
| + */
|
| +GestureStroke.prototype.getIdentifierAt = function(i) {
|
| + return this.points_[i].identifier;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * @param {number} i The index to look up.
|
| + * @return {number} The time of the point at index i.
|
| + */
|
| +GestureStroke.prototype.getTimeAt = function(i) {
|
| + return this.points_[i].time;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * @return {!Array.<!Point>} The points stored in the stroke.
|
| + */
|
| +GestureStroke.prototype.getPoints = function() {
|
| + return this.points_;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Returns true iff this stroke is considered "active". This means that it has
|
| + * passed a certain threshold and should be considered for rendering and
|
| + * decoding.
|
| + *
|
| + * @return {boolean} Whether or not the stroke is active.
|
| + */
|
| +GestureStroke.prototype.isActive = function() {
|
| + // Once a stroke is active, it remains active.
|
| + if (this.isActive_) {
|
| + return this.isActive_;
|
| + }
|
| +
|
| + if (this.points_.length < 2) {
|
| + return false;
|
| + }
|
| +
|
| + // Calculate the distance between the first point and the latest one.
|
| + this.isActive_ = GestureStroke.calculateDistance_(
|
| + this.points_[0], this.points_[this.points_.length - 1]) >
|
| + GestureStroke.ACTIVE_THRESHOLD_;
|
| +
|
| + return this.isActive_;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * @return {boolean} Whether or not the stroke is degraded.
|
| + */
|
| +GestureStroke.prototype.isDegraded = function() {
|
| + var allPointsDegraded = true;
|
| + for (var i = 0; i < this.points_.length; i++) {
|
| + if (this.points_[i].ttl > 0) {
|
| + allPointsDegraded = false;
|
| + break;
|
| + }
|
| + }
|
| + return allPointsDegraded;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * @return {number} The length of the stroke, which is the number of points it
|
| + * contains.
|
| + */
|
| +GestureStroke.prototype.length = function() {
|
| + return this.points_.length;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Add a point to this stroke.
|
| + *
|
| + * @param {!Point} p The point to add to this stroke.
|
| + */
|
| +GestureStroke.prototype.pushPoint = function(p) {
|
| + if (this.points_.length == 0) {
|
| + this.firstTime_ = p.time;
|
| + }
|
| + // Convert the timestamp so it is relative to the first point, including
|
| + // setting the first point to zero.
|
| + p.time -= this.firstTime_;
|
| + this.points_.push(p);
|
| +};
|
| +}); // goog.scope
|
|
|