http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/transitionbase.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/fx/transitionbase.js b/externs/GCL/externs/goog/fx/transitionbase.js new file mode 100644 index 0000000..0a2c184 --- /dev/null +++ b/externs/GCL/externs/goog/fx/transitionbase.js @@ -0,0 +1,236 @@ +// Copyright 2011 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview An abstract base class for transitions. This is a simple + * interface that allows for playing, pausing and stopping an animation. It adds + * a simple event model, and animation status. + */ +goog.provide('goog.fx.TransitionBase'); +goog.provide('goog.fx.TransitionBase.State'); + +goog.require('goog.events.EventTarget'); +goog.require('goog.fx.Transition'); // Unreferenced: interface + + + +/** + * Constructor for a transition object. + * + * @constructor + * @implements {goog.fx.Transition} + * @extends {goog.events.EventTarget} + */ +goog.fx.TransitionBase = function() { + goog.fx.TransitionBase.base(this, 'constructor'); + + /** + * The internal state of the animation. + * @type {goog.fx.TransitionBase.State} + * @private + */ + this.state_ = goog.fx.TransitionBase.State.STOPPED; + + /** + * Timestamp for when the animation was started. + * @type {?number} + * @protected + */ + this.startTime = null; + + /** + * Timestamp for when the animation finished or was stopped. + * @type {?number} + * @protected + */ + this.endTime = null; +}; +goog.inherits(goog.fx.TransitionBase, goog.events.EventTarget); + + +/** + * Enum for the possible states of an animation. + * @enum {number} + */ +goog.fx.TransitionBase.State = { + STOPPED: 0, + PAUSED: -1, + PLAYING: 1 +}; + + +/** + * Plays the animation. + * + * @param {boolean=} opt_restart Optional parameter to restart the animation. + * @return {boolean} True iff the animation was started. + * @override + */ +goog.fx.TransitionBase.prototype.play = goog.abstractMethod; + + +/** + * Stops the animation. + * + * @param {boolean=} opt_gotoEnd Optional boolean parameter to go the the end of + * the animation. + * @override + */ +goog.fx.TransitionBase.prototype.stop = goog.abstractMethod; + + +/** + * Pauses the animation. + */ +goog.fx.TransitionBase.prototype.pause = goog.abstractMethod; + + +/** + * Returns the current state of the animation. + * @return {goog.fx.TransitionBase.State} State of the animation. + */ +goog.fx.TransitionBase.prototype.getStateInternal = function() { + return this.state_; +}; + + +/** + * Sets the current state of the animation to playing. + * @protected + */ +goog.fx.TransitionBase.prototype.setStatePlaying = function() { + this.state_ = goog.fx.TransitionBase.State.PLAYING; +}; + + +/** + * Sets the current state of the animation to paused. + * @protected + */ +goog.fx.TransitionBase.prototype.setStatePaused = function() { + this.state_ = goog.fx.TransitionBase.State.PAUSED; +}; + + +/** + * Sets the current state of the animation to stopped. + * @protected + */ +goog.fx.TransitionBase.prototype.setStateStopped = function() { + this.state_ = goog.fx.TransitionBase.State.STOPPED; +}; + + +/** + * @return {boolean} True iff the current state of the animation is playing. + */ +goog.fx.TransitionBase.prototype.isPlaying = function() { + return this.state_ == goog.fx.TransitionBase.State.PLAYING; +}; + + +/** + * @return {boolean} True iff the current state of the animation is paused. + */ +goog.fx.TransitionBase.prototype.isPaused = function() { + return this.state_ == goog.fx.TransitionBase.State.PAUSED; +}; + + +/** + * @return {boolean} True iff the current state of the animation is stopped. + */ +goog.fx.TransitionBase.prototype.isStopped = function() { + return this.state_ == goog.fx.TransitionBase.State.STOPPED; +}; + + +/** + * Dispatches the BEGIN event. Sub classes should override this instead + * of listening to the event, and call this instead of dispatching the event. + * @protected + */ +goog.fx.TransitionBase.prototype.onBegin = function() { + this.dispatchAnimationEvent(goog.fx.Transition.EventType.BEGIN); +}; + + +/** + * Dispatches the END event. Sub classes should override this instead + * of listening to the event, and call this instead of dispatching the event. + * @protected + */ +goog.fx.TransitionBase.prototype.onEnd = function() { + this.dispatchAnimationEvent(goog.fx.Transition.EventType.END); +}; + + +/** + * Dispatches the FINISH event. Sub classes should override this instead + * of listening to the event, and call this instead of dispatching the event. + * @protected + */ +goog.fx.TransitionBase.prototype.onFinish = function() { + this.dispatchAnimationEvent(goog.fx.Transition.EventType.FINISH); +}; + + +/** + * Dispatches the PAUSE event. Sub classes should override this instead + * of listening to the event, and call this instead of dispatching the event. + * @protected + */ +goog.fx.TransitionBase.prototype.onPause = function() { + this.dispatchAnimationEvent(goog.fx.Transition.EventType.PAUSE); +}; + + +/** + * Dispatches the PLAY event. Sub classes should override this instead + * of listening to the event, and call this instead of dispatching the event. + * @protected + */ +goog.fx.TransitionBase.prototype.onPlay = function() { + this.dispatchAnimationEvent(goog.fx.Transition.EventType.PLAY); +}; + + +/** + * Dispatches the RESUME event. Sub classes should override this instead + * of listening to the event, and call this instead of dispatching the event. + * @protected + */ +goog.fx.TransitionBase.prototype.onResume = function() { + this.dispatchAnimationEvent(goog.fx.Transition.EventType.RESUME); +}; + + +/** + * Dispatches the STOP event. Sub classes should override this instead + * of listening to the event, and call this instead of dispatching the event. + * @protected + */ +goog.fx.TransitionBase.prototype.onStop = function() { + this.dispatchAnimationEvent(goog.fx.Transition.EventType.STOP); +}; + + +/** + * Dispatches an event object for the current animation. + * @param {string} type Event type that will be dispatched. + * @protected + */ +goog.fx.TransitionBase.prototype.dispatchAnimationEvent = function(type) { + this.dispatchEvent(type); +};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/abstractgraphics.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/graphics/abstractgraphics.js b/externs/GCL/externs/goog/graphics/abstractgraphics.js new file mode 100644 index 0000000..0ae1776 --- /dev/null +++ b/externs/GCL/externs/goog/graphics/abstractgraphics.js @@ -0,0 +1,454 @@ +// Copyright 2007 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview Graphics utility functions and factory methods. + * @author [email protected] (Erik Arvidsson) + */ + + +goog.provide('goog.graphics.AbstractGraphics'); + +goog.require('goog.dom'); +goog.require('goog.graphics.Path'); +goog.require('goog.math.Coordinate'); +goog.require('goog.math.Size'); +goog.require('goog.style'); +goog.require('goog.ui.Component'); + + + +/** + * Base class for the different graphics. You should never construct objects + * of this class. Instead us goog.graphics.createGraphics + * @param {number|string} width The width in pixels or percent. + * @param {number|string} height The height in pixels or percent. + * @param {?number=} opt_coordWidth Optional coordinate system width - if + * omitted or null, defaults to same as width. + * @param {?number=} opt_coordHeight Optional coordinate system height - if + * omitted or null, defaults to same as height. + * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the + * document we want to render in. + * @constructor + * @extends {goog.ui.Component} + */ +goog.graphics.AbstractGraphics = function(width, height, + opt_coordWidth, opt_coordHeight, + opt_domHelper) { + goog.ui.Component.call(this, opt_domHelper); + + /** + * Width of graphics in pixels or percentage points. + * @type {number|string} + * @protected + */ + this.width = width; + + /** + * Height of graphics in pixels or precentage points. + * @type {number|string} + * @protected + */ + this.height = height; + + /** + * Width of coordinate system in units. + * @type {?number} + * @protected + */ + this.coordWidth = opt_coordWidth || null; + + /** + * Height of coordinate system in units. + * @type {?number} + * @protected + */ + this.coordHeight = opt_coordHeight || null; +}; +goog.inherits(goog.graphics.AbstractGraphics, goog.ui.Component); + + +/** + * The root level group element. + * @type {goog.graphics.GroupElement?} + * @protected + */ +goog.graphics.AbstractGraphics.prototype.canvasElement = null; + + +/** + * Left coordinate of the view box + * @type {number} + * @protected + */ +goog.graphics.AbstractGraphics.prototype.coordLeft = 0; + + +/** + * Top coordinate of the view box + * @type {number} + * @protected + */ +goog.graphics.AbstractGraphics.prototype.coordTop = 0; + + +/** + * @return {goog.graphics.GroupElement} The root level canvas element. + */ +goog.graphics.AbstractGraphics.prototype.getCanvasElement = function() { + return this.canvasElement; +}; + + +/** + * Changes the coordinate size. + * @param {number} coordWidth The coordinate width. + * @param {number} coordHeight The coordinate height. + */ +goog.graphics.AbstractGraphics.prototype.setCoordSize = function(coordWidth, + coordHeight) { + this.coordWidth = coordWidth; + this.coordHeight = coordHeight; +}; + + +/** + * @return {goog.math.Size} The coordinate size. + */ +goog.graphics.AbstractGraphics.prototype.getCoordSize = function() { + if (this.coordWidth) { + return new goog.math.Size(this.coordWidth, + /** @type {number} */ (this.coordHeight)); + } else { + return this.getPixelSize(); + } +}; + + +/** + * Changes the coordinate system position. + * @param {number} left The coordinate system left bound. + * @param {number} top The coordinate system top bound. + */ +goog.graphics.AbstractGraphics.prototype.setCoordOrigin = goog.abstractMethod; + + +/** + * @return {!goog.math.Coordinate} The coordinate system position. + */ +goog.graphics.AbstractGraphics.prototype.getCoordOrigin = function() { + return new goog.math.Coordinate(this.coordLeft, this.coordTop); +}; + + +/** + * Change the size of the canvas. + * @param {number} pixelWidth The width in pixels. + * @param {number} pixelHeight The height in pixels. + */ +goog.graphics.AbstractGraphics.prototype.setSize = goog.abstractMethod; + + +/** + * @return {goog.math.Size} The size of canvas. + * @deprecated Use getPixelSize. + */ +goog.graphics.AbstractGraphics.prototype.getSize = function() { + return this.getPixelSize(); +}; + + +/** + * @return {goog.math.Size?} Returns the number of pixels spanned by the + * surface, or null if the size could not be computed due to the size being + * specified in percentage points and the component not being in the + * document. + */ +goog.graphics.AbstractGraphics.prototype.getPixelSize = function() { + if (this.isInDocument()) { + return goog.style.getSize(this.getElement()); + } + if (goog.isNumber(this.width) && goog.isNumber(this.height)) { + return new goog.math.Size(this.width, this.height); + } + return null; +}; + + +/** + * @return {number} Returns the number of pixels per unit in the x direction. + */ +goog.graphics.AbstractGraphics.prototype.getPixelScaleX = function() { + var pixelSize = this.getPixelSize(); + return pixelSize ? pixelSize.width / this.getCoordSize().width : 0; +}; + + +/** + * @return {number} Returns the number of pixels per unit in the y direction. + */ +goog.graphics.AbstractGraphics.prototype.getPixelScaleY = function() { + var pixelSize = this.getPixelSize(); + return pixelSize ? pixelSize.height / this.getCoordSize().height : 0; +}; + + +/** + * Remove all drawing elements from the graphics. + */ +goog.graphics.AbstractGraphics.prototype.clear = goog.abstractMethod; + + +/** + * Remove a single drawing element from the surface. The default implementation + * assumes a DOM based drawing surface. + * @param {goog.graphics.Element} element The element to remove. + */ +goog.graphics.AbstractGraphics.prototype.removeElement = function(element) { + goog.dom.removeNode(element.getElement()); +}; + + +/** + * Sets the fill for the given element. + * @param {goog.graphics.StrokeAndFillElement} element The element wrapper. + * @param {goog.graphics.Fill?} fill The fill object. + */ +goog.graphics.AbstractGraphics.prototype.setElementFill = goog.abstractMethod; + + +/** + * Sets the stroke for the given element. + * @param {goog.graphics.StrokeAndFillElement} element The element wrapper. + * @param {goog.graphics.Stroke?} stroke The stroke object. + */ +goog.graphics.AbstractGraphics.prototype.setElementStroke = goog.abstractMethod; + + +/** + * Set the transformation of an element. + * + * If a more general affine transform is needed than this provides + * (e.g. skew and scale) then use setElementAffineTransform. + * @param {goog.graphics.Element} element The element wrapper. + * @param {number} x The x coordinate of the translation transform. + * @param {number} y The y coordinate of the translation transform. + * @param {number} angle The angle of the rotation transform. + * @param {number} centerX The horizontal center of the rotation transform. + * @param {number} centerY The vertical center of the rotation transform. + */ +goog.graphics.AbstractGraphics.prototype.setElementTransform = + goog.abstractMethod; + + +/** + * Set the affine transform of an element. + * @param {!goog.graphics.Element} element The element wrapper. + * @param {!goog.graphics.AffineTransform} affineTransform The + * transformation applied to this element. + */ +goog.graphics.AbstractGraphics.prototype.setElementAffineTransform = + goog.abstractMethod; + + +/** + * Draw a circle + * + * @param {number} cx Center X coordinate. + * @param {number} cy Center Y coordinate. + * @param {number} r Radius length. + * @param {goog.graphics.Stroke?} stroke Stroke object describing the + * stroke. + * @param {goog.graphics.Fill?} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to + * append to. If not specified, appends to the main canvas. + * + * @return {goog.graphics.EllipseElement} The newly created element. + */ +goog.graphics.AbstractGraphics.prototype.drawCircle = function( + cx, cy, r, stroke, fill, opt_group) { + return this.drawEllipse(cx, cy, r, r, stroke, fill, opt_group); +}; + + +/** + * Draw an ellipse + * + * @param {number} cx Center X coordinate. + * @param {number} cy Center Y coordinate. + * @param {number} rx Radius length for the x-axis. + * @param {number} ry Radius length for the y-axis. + * @param {goog.graphics.Stroke?} stroke Stroke object describing the + * stroke. + * @param {goog.graphics.Fill?} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to + * append to. If not specified, appends to the main canvas. + * + * @return {goog.graphics.EllipseElement} The newly created element. + */ +goog.graphics.AbstractGraphics.prototype.drawEllipse = goog.abstractMethod; + + +/** + * Draw a rectangle + * + * @param {number} x X coordinate (left). + * @param {number} y Y coordinate (top). + * @param {number} width Width of rectangle. + * @param {number} height Height of rectangle. + * @param {goog.graphics.Stroke?} stroke Stroke object describing the + * stroke. + * @param {goog.graphics.Fill?} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to + * append to. If not specified, appends to the main canvas. + * + * @return {goog.graphics.RectElement} The newly created element. + */ +goog.graphics.AbstractGraphics.prototype.drawRect = goog.abstractMethod; + + +/** + * Draw a text string within a rectangle (drawing is horizontal) + * + * @param {string} text The text to draw. + * @param {number} x X coordinate (left). + * @param {number} y Y coordinate (top). + * @param {number} width Width of rectangle. + * @param {number} height Height of rectangle. + * @param {string} align Horizontal alignment: left (default), center, right. + * @param {string} vAlign Vertical alignment: top (default), center, bottom. + * @param {goog.graphics.Font} font Font describing the font properties. + * @param {goog.graphics.Stroke?} stroke Stroke object describing the + * stroke. + * @param {goog.graphics.Fill?} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to + * append to. If not specified, appends to the main canvas. + * + * @return {goog.graphics.TextElement} The newly created element. + */ +goog.graphics.AbstractGraphics.prototype.drawText = function( + text, x, y, width, height, align, vAlign, font, stroke, fill, opt_group) { + var baseline = font.size / 2; // Baseline is middle of line + var textY; + if (vAlign == 'bottom') { + textY = y + height - baseline; + } else if (vAlign == 'center') { + textY = y + height / 2; + } else { + textY = y + baseline; + } + + return this.drawTextOnLine(text, x, textY, x + width, textY, align, + font, stroke, fill, opt_group); +}; + + +/** + * Draw a text string vertically centered on a given line. + * + * @param {string} text The text to draw. + * @param {number} x1 X coordinate of start of line. + * @param {number} y1 Y coordinate of start of line. + * @param {number} x2 X coordinate of end of line. + * @param {number} y2 Y coordinate of end of line. + * @param {string} align Horizontal alingnment: left (default), center, right. + * @param {goog.graphics.Font} font Font describing the font properties. + * @param {goog.graphics.Stroke?} stroke Stroke object describing the + * stroke. + * @param {goog.graphics.Fill?} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to + * append to. If not specified, appends to the main canvas. + * + * @return {goog.graphics.TextElement} The newly created element. + */ +goog.graphics.AbstractGraphics.prototype.drawTextOnLine = goog.abstractMethod; + + +/** + * Draw a path. + * + * @param {!goog.graphics.Path} path The path object to draw. + * @param {goog.graphics.Stroke?} stroke Stroke object describing the + * stroke. + * @param {goog.graphics.Fill?} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to + * append to. If not specified, appends to the main canvas. + * + * @return {goog.graphics.PathElement} The newly created element. + */ +goog.graphics.AbstractGraphics.prototype.drawPath = goog.abstractMethod; + + +/** + * Create an empty group of drawing elements. + * + * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to + * append to. If not specified, appends to the main canvas. + * + * @return {goog.graphics.GroupElement} The newly created group. + */ +goog.graphics.AbstractGraphics.prototype.createGroup = goog.abstractMethod; + + +/** + * Create an empty path. + * + * @return {!goog.graphics.Path} The path. + * @deprecated Use {@code new goog.graphics.Path()}. + */ +goog.graphics.AbstractGraphics.prototype.createPath = function() { + return new goog.graphics.Path(); +}; + + +/** + * Measure and return the width (in pixels) of a given text string. + * Text measurement is needed to make sure a text can fit in the allocated + * area. The way text length is measured is by writing it into a div that is + * after the visible area, measure the div width, and immediatly erase the + * written value. + * + * @param {string} text The text string to measure. + * @param {goog.graphics.Font} font The font object describing the font style. + * + * @return {number} The width in pixels of the text strings. + */ +goog.graphics.AbstractGraphics.prototype.getTextWidth = goog.abstractMethod; + + +/** + * @return {boolean} Whether the underlying element can be cloned resulting in + * an accurate reproduction of the graphics contents. + */ +goog.graphics.AbstractGraphics.prototype.isDomClonable = function() { + return false; +}; + + +/** + * Start preventing redraws - useful for chaining large numbers of changes + * together. Not guaranteed to do anything - i.e. only use this for + * optimization of a single code path. + */ +goog.graphics.AbstractGraphics.prototype.suspend = function() { +}; + + +/** + * Stop preventing redraws. If any redraws had been prevented, a redraw will + * be done now. + */ +goog.graphics.AbstractGraphics.prototype.resume = function() { +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/affinetransform.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/graphics/affinetransform.js b/externs/GCL/externs/goog/graphics/affinetransform.js new file mode 100644 index 0000000..ec328f2 --- /dev/null +++ b/externs/GCL/externs/goog/graphics/affinetransform.js @@ -0,0 +1,588 @@ +// Copyright 2008 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview Provides an object representation of an AffineTransform and + * methods for working with it. + */ + + +goog.provide('goog.graphics.AffineTransform'); + +goog.require('goog.math'); + + + +/** + * Creates a 2D affine transform. An affine transform performs a linear + * mapping from 2D coordinates to other 2D coordinates that preserves the + * "straightness" and "parallelness" of lines. + * + * Such a coordinate transformation can be represented by a 3 row by 3 column + * matrix with an implied last row of [ 0 0 1 ]. This matrix transforms source + * coordinates (x,y) into destination coordinates (x',y') by considering them + * to be a column vector and multiplying the coordinate vector by the matrix + * according to the following process: + * <pre> + * [ x'] [ m00 m01 m02 ] [ x ] [ m00x + m01y + m02 ] + * [ y'] = [ m10 m11 m12 ] [ y ] = [ m10x + m11y + m12 ] + * [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ] + * </pre> + * + * This class is optimized for speed and minimizes calculations based on its + * knowledge of the underlying matrix (as opposed to say simply performing + * matrix multiplication). + * + * @param {number=} opt_m00 The m00 coordinate of the transform. + * @param {number=} opt_m10 The m10 coordinate of the transform. + * @param {number=} opt_m01 The m01 coordinate of the transform. + * @param {number=} opt_m11 The m11 coordinate of the transform. + * @param {number=} opt_m02 The m02 coordinate of the transform. + * @param {number=} opt_m12 The m12 coordinate of the transform. + * @constructor + * @final + */ +goog.graphics.AffineTransform = function(opt_m00, opt_m10, opt_m01, + opt_m11, opt_m02, opt_m12) { + if (arguments.length == 6) { + this.setTransform(/** @type {number} */ (opt_m00), + /** @type {number} */ (opt_m10), + /** @type {number} */ (opt_m01), + /** @type {number} */ (opt_m11), + /** @type {number} */ (opt_m02), + /** @type {number} */ (opt_m12)); + } else if (arguments.length != 0) { + throw Error('Insufficient matrix parameters'); + } else { + this.m00_ = this.m11_ = 1; + this.m10_ = this.m01_ = this.m02_ = this.m12_ = 0; + } +}; + + +/** + * @return {boolean} Whether this transform is the identity transform. + */ +goog.graphics.AffineTransform.prototype.isIdentity = function() { + return this.m00_ == 1 && this.m10_ == 0 && this.m01_ == 0 && + this.m11_ == 1 && this.m02_ == 0 && this.m12_ == 0; +}; + + +/** + * @return {!goog.graphics.AffineTransform} A copy of this transform. + */ +goog.graphics.AffineTransform.prototype.clone = function() { + return new goog.graphics.AffineTransform(this.m00_, this.m10_, this.m01_, + this.m11_, this.m02_, this.m12_); +}; + + +/** + * Sets this transform to the matrix specified by the 6 values. + * + * @param {number} m00 The m00 coordinate of the transform. + * @param {number} m10 The m10 coordinate of the transform. + * @param {number} m01 The m01 coordinate of the transform. + * @param {number} m11 The m11 coordinate of the transform. + * @param {number} m02 The m02 coordinate of the transform. + * @param {number} m12 The m12 coordinate of the transform. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.setTransform = function(m00, m10, m01, + m11, m02, m12) { + if (!goog.isNumber(m00) || !goog.isNumber(m10) || !goog.isNumber(m01) || + !goog.isNumber(m11) || !goog.isNumber(m02) || !goog.isNumber(m12)) { + throw Error('Invalid transform parameters'); + } + this.m00_ = m00; + this.m10_ = m10; + this.m01_ = m01; + this.m11_ = m11; + this.m02_ = m02; + this.m12_ = m12; + return this; +}; + + +/** + * Sets this transform to be identical to the given transform. + * + * @param {!goog.graphics.AffineTransform} tx The transform to copy. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.copyFrom = function(tx) { + this.m00_ = tx.m00_; + this.m10_ = tx.m10_; + this.m01_ = tx.m01_; + this.m11_ = tx.m11_; + this.m02_ = tx.m02_; + this.m12_ = tx.m12_; + return this; +}; + + +/** + * Concatenates this transform with a scaling transformation. + * + * @param {number} sx The x-axis scaling factor. + * @param {number} sy The y-axis scaling factor. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.scale = function(sx, sy) { + this.m00_ *= sx; + this.m10_ *= sx; + this.m01_ *= sy; + this.m11_ *= sy; + return this; +}; + + +/** + * Pre-concatenates this transform with a scaling transformation, + * i.e. calculates the following matrix product: + * + * <pre> + * [sx 0 0] [m00 m01 m02] + * [ 0 sy 0] [m10 m11 m12] + * [ 0 0 1] [ 0 0 1] + * </pre> + * + * @param {number} sx The x-axis scaling factor. + * @param {number} sy The y-axis scaling factor. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.preScale = function(sx, sy) { + this.m00_ *= sx; + this.m01_ *= sx; + this.m02_ *= sx; + this.m10_ *= sy; + this.m11_ *= sy; + this.m12_ *= sy; + return this; +}; + + +/** + * Concatenates this transform with a translate transformation. + * + * @param {number} dx The distance to translate in the x direction. + * @param {number} dy The distance to translate in the y direction. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.translate = function(dx, dy) { + this.m02_ += dx * this.m00_ + dy * this.m01_; + this.m12_ += dx * this.m10_ + dy * this.m11_; + return this; +}; + + +/** + * Pre-concatenates this transform with a translate transformation, + * i.e. calculates the following matrix product: + * + * <pre> + * [1 0 dx] [m00 m01 m02] + * [0 1 dy] [m10 m11 m12] + * [0 0 1] [ 0 0 1] + * </pre> + * + * @param {number} dx The distance to translate in the x direction. + * @param {number} dy The distance to translate in the y direction. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.preTranslate = function(dx, dy) { + this.m02_ += dx; + this.m12_ += dy; + return this; +}; + + +/** + * Concatenates this transform with a rotation transformation around an anchor + * point. + * + * @param {number} theta The angle of rotation measured in radians. + * @param {number} x The x coordinate of the anchor point. + * @param {number} y The y coordinate of the anchor point. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.rotate = function(theta, x, y) { + return this.concatenate( + goog.graphics.AffineTransform.getRotateInstance(theta, x, y)); +}; + + +/** + * Pre-concatenates this transform with a rotation transformation around an + * anchor point. + * + * @param {number} theta The angle of rotation measured in radians. + * @param {number} x The x coordinate of the anchor point. + * @param {number} y The y coordinate of the anchor point. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.preRotate = function(theta, x, y) { + return this.preConcatenate( + goog.graphics.AffineTransform.getRotateInstance(theta, x, y)); +}; + + +/** + * Concatenates this transform with a shear transformation. + * + * @param {number} shx The x shear factor. + * @param {number} shy The y shear factor. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.shear = function(shx, shy) { + var m00 = this.m00_; + var m10 = this.m10_; + this.m00_ += shy * this.m01_; + this.m10_ += shy * this.m11_; + this.m01_ += shx * m00; + this.m11_ += shx * m10; + return this; +}; + + +/** + * Pre-concatenates this transform with a shear transformation. + * i.e. calculates the following matrix product: + * + * <pre> + * [ 1 shx 0] [m00 m01 m02] + * [shy 1 0] [m10 m11 m12] + * [ 0 0 1] [ 0 0 1] + * </pre> + * + * @param {number} shx The x shear factor. + * @param {number} shy The y shear factor. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.preShear = function(shx, shy) { + var m00 = this.m00_; + var m01 = this.m01_; + var m02 = this.m02_; + this.m00_ += shx * this.m10_; + this.m01_ += shx * this.m11_; + this.m02_ += shx * this.m12_; + this.m10_ += shy * m00; + this.m11_ += shy * m01; + this.m12_ += shy * m02; + return this; +}; + + +/** + * @return {string} A string representation of this transform. The format of + * of the string is compatible with SVG matrix notation, i.e. + * "matrix(a,b,c,d,e,f)". + * @override + */ +goog.graphics.AffineTransform.prototype.toString = function() { + return 'matrix(' + + [this.m00_, this.m10_, this.m01_, this.m11_, this.m02_, this.m12_].join( + ',') + + ')'; +}; + + +/** + * @return {number} The scaling factor in the x-direction (m00). + */ +goog.graphics.AffineTransform.prototype.getScaleX = function() { + return this.m00_; +}; + + +/** + * @return {number} The scaling factor in the y-direction (m11). + */ +goog.graphics.AffineTransform.prototype.getScaleY = function() { + return this.m11_; +}; + + +/** + * @return {number} The translation in the x-direction (m02). + */ +goog.graphics.AffineTransform.prototype.getTranslateX = function() { + return this.m02_; +}; + + +/** + * @return {number} The translation in the y-direction (m12). + */ +goog.graphics.AffineTransform.prototype.getTranslateY = function() { + return this.m12_; +}; + + +/** + * @return {number} The shear factor in the x-direction (m01). + */ +goog.graphics.AffineTransform.prototype.getShearX = function() { + return this.m01_; +}; + + +/** + * @return {number} The shear factor in the y-direction (m10). + */ +goog.graphics.AffineTransform.prototype.getShearY = function() { + return this.m10_; +}; + + +/** + * Concatenates an affine transform to this transform. + * + * @param {!goog.graphics.AffineTransform} tx The transform to concatenate. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.concatenate = function(tx) { + var m0 = this.m00_; + var m1 = this.m01_; + this.m00_ = tx.m00_ * m0 + tx.m10_ * m1; + this.m01_ = tx.m01_ * m0 + tx.m11_ * m1; + this.m02_ += tx.m02_ * m0 + tx.m12_ * m1; + + m0 = this.m10_; + m1 = this.m11_; + this.m10_ = tx.m00_ * m0 + tx.m10_ * m1; + this.m11_ = tx.m01_ * m0 + tx.m11_ * m1; + this.m12_ += tx.m02_ * m0 + tx.m12_ * m1; + return this; +}; + + +/** + * Pre-concatenates an affine transform to this transform. + * + * @param {!goog.graphics.AffineTransform} tx The transform to preconcatenate. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.preConcatenate = function(tx) { + var m0 = this.m00_; + var m1 = this.m10_; + this.m00_ = tx.m00_ * m0 + tx.m01_ * m1; + this.m10_ = tx.m10_ * m0 + tx.m11_ * m1; + + m0 = this.m01_; + m1 = this.m11_; + this.m01_ = tx.m00_ * m0 + tx.m01_ * m1; + this.m11_ = tx.m10_ * m0 + tx.m11_ * m1; + + m0 = this.m02_; + m1 = this.m12_; + this.m02_ = tx.m00_ * m0 + tx.m01_ * m1 + tx.m02_; + this.m12_ = tx.m10_ * m0 + tx.m11_ * m1 + tx.m12_; + return this; +}; + + +/** + * Transforms an array of coordinates by this transform and stores the result + * into a destination array. + * + * @param {!Array<number>} src The array containing the source points + * as x, y value pairs. + * @param {number} srcOff The offset to the first point to be transformed. + * @param {!Array<number>} dst The array into which to store the transformed + * point pairs. + * @param {number} dstOff The offset of the location of the first transformed + * point in the destination array. + * @param {number} numPts The number of points to tranform. + */ +goog.graphics.AffineTransform.prototype.transform = function(src, srcOff, dst, + dstOff, numPts) { + var i = srcOff; + var j = dstOff; + var srcEnd = srcOff + 2 * numPts; + while (i < srcEnd) { + var x = src[i++]; + var y = src[i++]; + dst[j++] = x * this.m00_ + y * this.m01_ + this.m02_; + dst[j++] = x * this.m10_ + y * this.m11_ + this.m12_; + } +}; + + +/** + * @return {number} The determinant of this transform. + */ +goog.graphics.AffineTransform.prototype.getDeterminant = function() { + return this.m00_ * this.m11_ - this.m01_ * this.m10_; +}; + + +/** + * Returns whether the transform is invertible. A transform is not invertible + * if the determinant is 0 or any value is non-finite or NaN. + * + * @return {boolean} Whether the transform is invertible. + */ +goog.graphics.AffineTransform.prototype.isInvertible = function() { + var det = this.getDeterminant(); + return goog.math.isFiniteNumber(det) && + goog.math.isFiniteNumber(this.m02_) && + goog.math.isFiniteNumber(this.m12_) && + det != 0; +}; + + +/** + * @return {!goog.graphics.AffineTransform} An AffineTransform object + * representing the inverse transformation. + */ +goog.graphics.AffineTransform.prototype.createInverse = function() { + var det = this.getDeterminant(); + return new goog.graphics.AffineTransform( + this.m11_ / det, + -this.m10_ / det, + -this.m01_ / det, + this.m00_ / det, + (this.m01_ * this.m12_ - this.m11_ * this.m02_) / det, + (this.m10_ * this.m02_ - this.m00_ * this.m12_) / det); +}; + + +/** + * Creates a transform representing a scaling transformation. + * + * @param {number} sx The x-axis scaling factor. + * @param {number} sy The y-axis scaling factor. + * @return {!goog.graphics.AffineTransform} A transform representing a scaling + * transformation. + */ +goog.graphics.AffineTransform.getScaleInstance = function(sx, sy) { + return new goog.graphics.AffineTransform().setToScale(sx, sy); +}; + + +/** + * Creates a transform representing a translation transformation. + * + * @param {number} dx The distance to translate in the x direction. + * @param {number} dy The distance to translate in the y direction. + * @return {!goog.graphics.AffineTransform} A transform representing a + * translation transformation. + */ +goog.graphics.AffineTransform.getTranslateInstance = function(dx, dy) { + return new goog.graphics.AffineTransform().setToTranslation(dx, dy); +}; + + +/** + * Creates a transform representing a shearing transformation. + * + * @param {number} shx The x-axis shear factor. + * @param {number} shy The y-axis shear factor. + * @return {!goog.graphics.AffineTransform} A transform representing a shearing + * transformation. + */ +goog.graphics.AffineTransform.getShearInstance = function(shx, shy) { + return new goog.graphics.AffineTransform().setToShear(shx, shy); +}; + + +/** + * Creates a transform representing a rotation transformation. + * + * @param {number} theta The angle of rotation measured in radians. + * @param {number} x The x coordinate of the anchor point. + * @param {number} y The y coordinate of the anchor point. + * @return {!goog.graphics.AffineTransform} A transform representing a rotation + * transformation. + */ +goog.graphics.AffineTransform.getRotateInstance = function(theta, x, y) { + return new goog.graphics.AffineTransform().setToRotation(theta, x, y); +}; + + +/** + * Sets this transform to a scaling transformation. + * + * @param {number} sx The x-axis scaling factor. + * @param {number} sy The y-axis scaling factor. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.setToScale = function(sx, sy) { + return this.setTransform(sx, 0, 0, sy, 0, 0); +}; + + +/** + * Sets this transform to a translation transformation. + * + * @param {number} dx The distance to translate in the x direction. + * @param {number} dy The distance to translate in the y direction. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.setToTranslation = function(dx, dy) { + return this.setTransform(1, 0, 0, 1, dx, dy); +}; + + +/** + * Sets this transform to a shearing transformation. + * + * @param {number} shx The x-axis shear factor. + * @param {number} shy The y-axis shear factor. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.setToShear = function(shx, shy) { + return this.setTransform(1, shy, shx, 1, 0, 0); +}; + + +/** + * Sets this transform to a rotation transformation. + * + * @param {number} theta The angle of rotation measured in radians. + * @param {number} x The x coordinate of the anchor point. + * @param {number} y The y coordinate of the anchor point. + * @return {!goog.graphics.AffineTransform} This affine transform. + */ +goog.graphics.AffineTransform.prototype.setToRotation = function(theta, x, y) { + var cos = Math.cos(theta); + var sin = Math.sin(theta); + return this.setTransform(cos, sin, -sin, cos, + x - x * cos + y * sin, y - x * sin - y * cos); +}; + + +/** + * Compares two affine transforms for equality. + * + * @param {goog.graphics.AffineTransform} tx The other affine transform. + * @return {boolean} whether the two transforms are equal. + */ +goog.graphics.AffineTransform.prototype.equals = function(tx) { + if (this == tx) { + return true; + } + if (!tx) { + return false; + } + return this.m00_ == tx.m00_ && + this.m01_ == tx.m01_ && + this.m02_ == tx.m02_ && + this.m10_ == tx.m10_ && + this.m11_ == tx.m11_ && + this.m12_ == tx.m12_; +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/canvaselement.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/graphics/canvaselement.js b/externs/GCL/externs/goog/graphics/canvaselement.js new file mode 100644 index 0000000..6c400db --- /dev/null +++ b/externs/GCL/externs/goog/graphics/canvaselement.js @@ -0,0 +1,812 @@ +// Copyright 2007 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview Objects representing shapes drawn on a canvas. + * @author [email protected] (Robby Walker) + */ + +goog.provide('goog.graphics.CanvasEllipseElement'); +goog.provide('goog.graphics.CanvasGroupElement'); +goog.provide('goog.graphics.CanvasImageElement'); +goog.provide('goog.graphics.CanvasPathElement'); +goog.provide('goog.graphics.CanvasRectElement'); +goog.provide('goog.graphics.CanvasTextElement'); + + +goog.require('goog.array'); +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.dom.safe'); +goog.require('goog.graphics.EllipseElement'); +goog.require('goog.graphics.GroupElement'); +goog.require('goog.graphics.ImageElement'); +goog.require('goog.graphics.Path'); +goog.require('goog.graphics.PathElement'); +goog.require('goog.graphics.RectElement'); +goog.require('goog.graphics.TextElement'); +goog.require('goog.html.SafeHtml'); +goog.require('goog.html.uncheckedconversions'); +goog.require('goog.math'); +goog.require('goog.string'); +goog.require('goog.string.Const'); + + + +/** + * Object representing a group of objects in a canvas. + * This is an implementation of the goog.graphics.GroupElement interface. + * You should not construct objects from this constructor. The graphics + * will return the object for you. + * @param {goog.graphics.CanvasGraphics} graphics The graphics creating + * this element. + * @constructor + * @extends {goog.graphics.GroupElement} + * @deprecated goog.graphics is deprecated. It existed to abstract over browser + * differences before the canvas tag was widely supported. See + * http://en.wikipedia.org/wiki/Canvas_element for details. + * @final + */ +goog.graphics.CanvasGroupElement = function(graphics) { + goog.graphics.GroupElement.call(this, null, graphics); + + + /** + * Children contained by this group. + * @type {Array<goog.graphics.Element>} + * @private + */ + this.children_ = []; +}; +goog.inherits(goog.graphics.CanvasGroupElement, goog.graphics.GroupElement); + + +/** + * Remove all drawing elements from the group. + * @override + */ +goog.graphics.CanvasGroupElement.prototype.clear = function() { + if (this.children_.length) { + this.children_.length = 0; + this.getGraphics().redraw(); + } +}; + + +/** + * Set the size of the group element. + * @param {number|string} width The width of the group element. + * @param {number|string} height The height of the group element. + * @override + */ +goog.graphics.CanvasGroupElement.prototype.setSize = function(width, height) { + // Do nothing. +}; + + +/** + * Append a child to the group. Does not draw it + * @param {goog.graphics.Element} element The child to append. + */ +goog.graphics.CanvasGroupElement.prototype.appendChild = function(element) { + this.children_.push(element); +}; + + +/** + * Draw the group. + * @param {CanvasRenderingContext2D} ctx The context to draw the element in. + */ +goog.graphics.CanvasGroupElement.prototype.draw = function(ctx) { + for (var i = 0, len = this.children_.length; i < len; i++) { + this.getGraphics().drawElement(this.children_[i]); + } +}; + + + +/** + * Thin wrapper for canvas ellipse elements. + * This is an implementation of the goog.graphics.EllipseElement interface. + * You should not construct objects from this constructor. The graphics + * will return the object for you. + * @param {Element} element The DOM element to wrap. + * @param {goog.graphics.CanvasGraphics} graphics The graphics creating + * this element. + * @param {number} cx Center X coordinate. + * @param {number} cy Center Y coordinate. + * @param {number} rx Radius length for the x-axis. + * @param {number} ry Radius length for the y-axis. + * @param {goog.graphics.Stroke} stroke The stroke to use for this element. + * @param {goog.graphics.Fill} fill The fill to use for this element. + * @constructor + * @extends {goog.graphics.EllipseElement} + * @final + */ +goog.graphics.CanvasEllipseElement = function(element, graphics, + cx, cy, rx, ry, stroke, fill) { + goog.graphics.EllipseElement.call(this, element, graphics, stroke, fill); + + /** + * X coordinate of the ellipse center. + * @type {number} + * @private + */ + this.cx_ = cx; + + + /** + * Y coordinate of the ellipse center. + * @type {number} + * @private + */ + this.cy_ = cy; + + + /** + * Radius length for the x-axis. + * @type {number} + * @private + */ + this.rx_ = rx; + + + /** + * Radius length for the y-axis. + * @type {number} + * @private + */ + this.ry_ = ry; + + + /** + * Internal path approximating an ellipse. + * @type {goog.graphics.Path} + * @private + */ + this.path_ = new goog.graphics.Path(); + this.setUpPath_(); + + /** + * Internal path element that actually does the drawing. + * @type {goog.graphics.CanvasPathElement} + * @private + */ + this.pathElement_ = new goog.graphics.CanvasPathElement(null, graphics, + this.path_, stroke, fill); +}; +goog.inherits(goog.graphics.CanvasEllipseElement, goog.graphics.EllipseElement); + + +/** + * Sets up the path. + * @private + */ +goog.graphics.CanvasEllipseElement.prototype.setUpPath_ = function() { + this.path_.clear(); + this.path_.moveTo(this.cx_ + goog.math.angleDx(0, this.rx_), + this.cy_ + goog.math.angleDy(0, this.ry_)); + this.path_.arcTo(this.rx_, this.ry_, 0, 360); + this.path_.close(); +}; + + +/** + * Update the center point of the ellipse. + * @param {number} cx Center X coordinate. + * @param {number} cy Center Y coordinate. + * @override + */ +goog.graphics.CanvasEllipseElement.prototype.setCenter = function(cx, cy) { + this.cx_ = cx; + this.cy_ = cy; + this.setUpPath_(); + this.pathElement_.setPath(/** @type {!goog.graphics.Path} */ (this.path_)); +}; + + +/** + * Update the radius of the ellipse. + * @param {number} rx Center X coordinate. + * @param {number} ry Center Y coordinate. + * @override + */ +goog.graphics.CanvasEllipseElement.prototype.setRadius = function(rx, ry) { + this.rx_ = rx; + this.ry_ = ry; + this.setUpPath_(); + this.pathElement_.setPath(/** @type {!goog.graphics.Path} */ (this.path_)); +}; + + +/** + * Draw the ellipse. Should be treated as package scope. + * @param {CanvasRenderingContext2D} ctx The context to draw the element in. + */ +goog.graphics.CanvasEllipseElement.prototype.draw = function(ctx) { + this.pathElement_.draw(ctx); +}; + + + +/** + * Thin wrapper for canvas rectangle elements. + * This is an implementation of the goog.graphics.RectElement interface. + * You should not construct objects from this constructor. The graphics + * will return the object for you. + * @param {Element} element The DOM element to wrap. + * @param {goog.graphics.CanvasGraphics} graphics The graphics creating + * this element. + * @param {number} x X coordinate (left). + * @param {number} y Y coordinate (top). + * @param {number} w Width of rectangle. + * @param {number} h Height of rectangle. + * @param {goog.graphics.Stroke} stroke The stroke to use for this element. + * @param {goog.graphics.Fill} fill The fill to use for this element. + * @constructor + * @extends {goog.graphics.RectElement} + * @final + */ +goog.graphics.CanvasRectElement = function(element, graphics, x, y, w, h, + stroke, fill) { + goog.graphics.RectElement.call(this, element, graphics, stroke, fill); + + /** + * X coordinate of the top left corner. + * @type {number} + * @private + */ + this.x_ = x; + + + /** + * Y coordinate of the top left corner. + * @type {number} + * @private + */ + this.y_ = y; + + + /** + * Width of the rectangle. + * @type {number} + * @private + */ + this.w_ = w; + + + /** + * Height of the rectangle. + * @type {number} + * @private + */ + this.h_ = h; +}; +goog.inherits(goog.graphics.CanvasRectElement, goog.graphics.RectElement); + + +/** + * Update the position of the rectangle. + * @param {number} x X coordinate (left). + * @param {number} y Y coordinate (top). + * @override + */ +goog.graphics.CanvasRectElement.prototype.setPosition = function(x, y) { + this.x_ = x; + this.y_ = y; + if (this.drawn_) { + this.getGraphics().redraw(); + } +}; + + +/** + * Whether the rectangle has been drawn yet. + * @type {boolean} + * @private + */ +goog.graphics.CanvasRectElement.prototype.drawn_ = false; + + +/** + * Update the size of the rectangle. + * @param {number} width Width of rectangle. + * @param {number} height Height of rectangle. + * @override + */ +goog.graphics.CanvasRectElement.prototype.setSize = function(width, height) { + this.w_ = width; + this.h_ = height; + if (this.drawn_) { + this.getGraphics().redraw(); + } +}; + + +/** + * Draw the rectangle. Should be treated as package scope. + * @param {CanvasRenderingContext2D} ctx The context to draw the element in. + */ +goog.graphics.CanvasRectElement.prototype.draw = function(ctx) { + this.drawn_ = true; + ctx.beginPath(); + ctx.moveTo(this.x_, this.y_); + ctx.lineTo(this.x_, this.y_ + this.h_); + ctx.lineTo(this.x_ + this.w_, this.y_ + this.h_); + ctx.lineTo(this.x_ + this.w_, this.y_); + ctx.closePath(); +}; + + + +/** + * Thin wrapper for canvas path elements. + * This is an implementation of the goog.graphics.PathElement interface. + * You should not construct objects from this constructor. The graphics + * will return the object for you. + * @param {Element} element The DOM element to wrap. + * @param {goog.graphics.CanvasGraphics} graphics The graphics creating + * this element. + * @param {!goog.graphics.Path} path The path object to draw. + * @param {goog.graphics.Stroke} stroke The stroke to use for this element. + * @param {goog.graphics.Fill} fill The fill to use for this element. + * @constructor + * @extends {goog.graphics.PathElement} + * @final + */ +goog.graphics.CanvasPathElement = function(element, graphics, path, stroke, + fill) { + goog.graphics.PathElement.call(this, element, graphics, stroke, fill); + + this.setPath(path); +}; +goog.inherits(goog.graphics.CanvasPathElement, goog.graphics.PathElement); + + +/** + * Whether the shape has been drawn yet. + * @type {boolean} + * @private + */ +goog.graphics.CanvasPathElement.prototype.drawn_ = false; + + +/** + * The path to draw. + * @type {goog.graphics.Path} + * @private + */ +goog.graphics.CanvasPathElement.prototype.path_; + + +/** + * Update the underlying path. + * @param {!goog.graphics.Path} path The path object to draw. + * @override + */ +goog.graphics.CanvasPathElement.prototype.setPath = function(path) { + this.path_ = path.isSimple() ? path : + goog.graphics.Path.createSimplifiedPath(path); + if (this.drawn_) { + this.getGraphics().redraw(); + } +}; + + +/** + * Draw the path. Should be treated as package scope. + * @param {CanvasRenderingContext2D} ctx The context to draw the element in. + * @suppress {deprecated} goog.graphics is deprecated. + */ +goog.graphics.CanvasPathElement.prototype.draw = function(ctx) { + this.drawn_ = true; + + ctx.beginPath(); + this.path_.forEachSegment(function(segment, args) { + switch (segment) { + case goog.graphics.Path.Segment.MOVETO: + ctx.moveTo(args[0], args[1]); + break; + case goog.graphics.Path.Segment.LINETO: + for (var i = 0; i < args.length; i += 2) { + ctx.lineTo(args[i], args[i + 1]); + } + break; + case goog.graphics.Path.Segment.CURVETO: + for (var i = 0; i < args.length; i += 6) { + ctx.bezierCurveTo(args[i], args[i + 1], args[i + 2], + args[i + 3], args[i + 4], args[i + 5]); + } + break; + case goog.graphics.Path.Segment.ARCTO: + throw Error('Canvas paths cannot contain arcs'); + case goog.graphics.Path.Segment.CLOSE: + ctx.closePath(); + break; + } + }); +}; + + + +/** + * Thin wrapper for canvas text elements. + * This is an implementation of the goog.graphics.TextElement interface. + * You should not construct objects from this constructor. The graphics + * will return the object for you. + * @param {!goog.graphics.CanvasGraphics} graphics The graphics creating + * this element. + * @param {string} text The text to draw. + * @param {number} x1 X coordinate of start of line. + * @param {number} y1 Y coordinate of start of line. + * @param {number} x2 X coordinate of end of line. + * @param {number} y2 Y coordinate of end of line. + * @param {?string} align Horizontal alignment: left (default), center, right. + * @param {!goog.graphics.Font} font Font describing the font properties. + * @param {goog.graphics.Stroke} stroke The stroke to use for this element. + * @param {goog.graphics.Fill} fill The fill to use for this element. + * @constructor + * @extends {goog.graphics.TextElement} + * @final + */ +goog.graphics.CanvasTextElement = function(graphics, text, x1, y1, x2, y2, + align, font, stroke, fill) { + var element = goog.dom.createDom(goog.dom.TagName.DIV, { + 'style': 'display:table;position:absolute;padding:0;margin:0;border:0' + }); + goog.graphics.TextElement.call(this, element, graphics, stroke, fill); + + /** + * The text to draw. + * @type {string} + * @private + */ + this.text_ = text; + + /** + * X coordinate of the start of the line the text is drawn on. + * @type {number} + * @private + */ + this.x1_ = x1; + + /** + * Y coordinate of the start of the line the text is drawn on. + * @type {number} + * @private + */ + this.y1_ = y1; + + /** + * X coordinate of the end of the line the text is drawn on. + * @type {number} + * @private + */ + this.x2_ = x2; + + /** + * Y coordinate of the end of the line the text is drawn on. + * @type {number} + * @private + */ + this.y2_ = y2; + + /** + * Horizontal alignment: left (default), center, right. + * @type {string} + * @private + */ + this.align_ = align || 'left'; + + /** + * Font object describing the font properties. + * @type {goog.graphics.Font} + * @private + */ + this.font_ = font; + + /** + * The inner element that contains the text. + * @type {Element} + * @private + */ + this.innerElement_ = goog.dom.createDom(goog.dom.TagName.DIV, { + 'style': 'display:table-cell;padding: 0;margin: 0;border: 0' + }); + + this.updateStyle_(); + this.updateText_(); + + // Append to the DOM. + graphics.getElement().appendChild(element); + element.appendChild(this.innerElement_); +}; +goog.inherits(goog.graphics.CanvasTextElement, goog.graphics.TextElement); + + +/** + * Update the displayed text of the element. + * @param {string} text The text to draw. + * @override + */ +goog.graphics.CanvasTextElement.prototype.setText = function(text) { + this.text_ = text; + this.updateText_(); +}; + + +/** + * Sets the fill for this element. + * @param {goog.graphics.Fill} fill The fill object. + * @override + */ +goog.graphics.CanvasTextElement.prototype.setFill = function(fill) { + this.fill = fill; + var element = this.getElement(); + if (element) { + element.style.color = fill.getColor() || fill.getColor1(); + } +}; + + +/** + * Sets the stroke for this element. + * @param {goog.graphics.Stroke} stroke The stroke object. + * @override + */ +goog.graphics.CanvasTextElement.prototype.setStroke = function(stroke) { + // Ignore stroke +}; + + +/** + * Draw the text. Should be treated as package scope. + * @param {CanvasRenderingContext2D} ctx The context to draw the element in. + */ +goog.graphics.CanvasTextElement.prototype.draw = function(ctx) { + // Do nothing - the text is already drawn. +}; + + +/** + * Update the styles of the DIVs. + * @private + */ +goog.graphics.CanvasTextElement.prototype.updateStyle_ = function() { + var x1 = this.x1_; + var x2 = this.x2_; + var y1 = this.y1_; + var y2 = this.y2_; + var align = this.align_; + var font = this.font_; + var style = this.getElement().style; + var scaleX = this.getGraphics().getPixelScaleX(); + var scaleY = this.getGraphics().getPixelScaleY(); + + if (x1 == x2) { + // Special case vertical text + style.lineHeight = '90%'; + + this.innerElement_.style.verticalAlign = align == 'center' ? 'middle' : + align == 'left' ? (y1 < y2 ? 'top' : 'bottom') : + y1 < y2 ? 'bottom' : 'top'; + style.textAlign = 'center'; + + var w = font.size * scaleX; + style.top = Math.round(Math.min(y1, y2) * scaleY) + 'px'; + style.left = Math.round((x1 - w / 2) * scaleX) + 'px'; + style.width = Math.round(w) + 'px'; + style.height = Math.abs(y1 - y2) * scaleY + 'px'; + + style.fontSize = font.size * 0.6 * scaleY + 'pt'; + } else { + style.lineHeight = '100%'; + this.innerElement_.style.verticalAlign = 'top'; + style.textAlign = align; + + style.top = Math.round(((y1 + y2) / 2 - font.size * 2 / 3) * scaleY) + 'px'; + style.left = Math.round(x1 * scaleX) + 'px'; + style.width = Math.round(Math.abs(x2 - x1) * scaleX) + 'px'; + style.height = 'auto'; + + style.fontSize = font.size * scaleY + 'pt'; + } + + style.fontWeight = font.bold ? 'bold' : 'normal'; + style.fontStyle = font.italic ? 'italic' : 'normal'; + style.fontFamily = font.family; + + var fill = this.getFill(); + style.color = fill.getColor() || fill.getColor1(); +}; + + +/** + * Update the text content. + * @private + */ +goog.graphics.CanvasTextElement.prototype.updateText_ = function() { + if (this.x1_ == this.x2_) { + // Special case vertical text + var html = + goog.array.map( + this.text_.split(''), + function(entry) { return goog.string.htmlEscape(entry); }) + .join('<br>'); + // Creating a SafeHtml for each character would be quite expensive, and it's + // obvious that this is safe, so an unchecked conversion is appropriate. + var safeHtml = goog.html.uncheckedconversions + .safeHtmlFromStringKnownToSatisfyTypeContract( + goog.string.Const.from('Concatenate escaped chars and <br>'), + html); + goog.dom.safe.setInnerHtml( + /** @type {!Element} */ (this.innerElement_), safeHtml); + } else { + goog.dom.safe.setInnerHtml( + /** @type {!Element} */ (this.innerElement_), + goog.html.SafeHtml.htmlEscape(this.text_)); + } +}; + + + +/** + * Thin wrapper for canvas image elements. + * This is an implementation of the goog.graphics.ImageElement interface. + * You should not construct objects from this constructor. The graphics + * will return the object for you. + * @param {Element} element The DOM element to wrap. + * @param {goog.graphics.CanvasGraphics} graphics The graphics creating + * this element. + * @param {number} x X coordinate (left). + * @param {number} y Y coordinate (top). + * @param {number} w Width of rectangle. + * @param {number} h Height of rectangle. + * @param {string} src Source of the image. + * @constructor + * @extends {goog.graphics.ImageElement} + * @final + */ +goog.graphics.CanvasImageElement = function(element, graphics, x, y, w, h, + src) { + goog.graphics.ImageElement.call(this, element, graphics); + + /** + * X coordinate of the top left corner. + * @type {number} + * @private + */ + this.x_ = x; + + + /** + * Y coordinate of the top left corner. + * @type {number} + * @private + */ + this.y_ = y; + + + /** + * Width of the rectangle. + * @type {number} + * @private + */ + this.w_ = w; + + + /** + * Height of the rectangle. + * @type {number} + * @private + */ + this.h_ = h; + + + /** + * URL of the image source. + * @type {string} + * @private + */ + this.src_ = src; +}; +goog.inherits(goog.graphics.CanvasImageElement, goog.graphics.ImageElement); + + +/** + * Whether the image has been drawn yet. + * @type {boolean} + * @private + */ +goog.graphics.CanvasImageElement.prototype.drawn_ = false; + + +/** + * Update the position of the image. + * @param {number} x X coordinate (left). + * @param {number} y Y coordinate (top). + * @override + */ +goog.graphics.CanvasImageElement.prototype.setPosition = function(x, y) { + this.x_ = x; + this.y_ = y; + if (this.drawn_) { + this.getGraphics().redraw(); + } +}; + + +/** + * Update the size of the image. + * @param {number} width Width of rectangle. + * @param {number} height Height of rectangle. + * @override + */ +goog.graphics.CanvasImageElement.prototype.setSize = function(width, height) { + this.w_ = width; + this.h_ = height; + if (this.drawn_) { + this.getGraphics().redraw(); + } +}; + + +/** + * Update the source of the image. + * @param {string} src Source of the image. + * @override + */ +goog.graphics.CanvasImageElement.prototype.setSource = function(src) { + this.src_ = src; + if (this.drawn_) { + // TODO(robbyw): Probably need to reload the image here. + this.getGraphics().redraw(); + } +}; + + +/** + * Draw the image. Should be treated as package scope. + * @param {CanvasRenderingContext2D} ctx The context to draw the element in. + */ +goog.graphics.CanvasImageElement.prototype.draw = function(ctx) { + if (this.img_) { + if (this.w_ && this.h_) { + // If the image is already loaded, draw it. + ctx.drawImage(this.img_, this.x_, this.y_, this.w_, this.h_); + } + this.drawn_ = true; + + } else { + // Otherwise, load it. + var img = new Image(); + img.onload = goog.bind(this.handleImageLoad_, this, img); + // TODO(robbyw): Handle image load errors. + img.src = this.src_; + } +}; + + +/** + * Handle an image load. + * @param {Element} img The image element that finished loading. + * @private + */ +goog.graphics.CanvasImageElement.prototype.handleImageLoad_ = function(img) { + this.img_ = img; + + // TODO(robbyw): Add a small delay to catch batched images + this.getGraphics().redraw(); +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/canvasgraphics.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/graphics/canvasgraphics.js b/externs/GCL/externs/goog/graphics/canvasgraphics.js new file mode 100644 index 0000000..2c55938 --- /dev/null +++ b/externs/GCL/externs/goog/graphics/canvasgraphics.js @@ -0,0 +1,670 @@ +// Copyright 2007 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview CanvasGraphics sub class that uses the canvas tag for drawing. + * @author [email protected] (Robby Walker) + */ + + +goog.provide('goog.graphics.CanvasGraphics'); + + +goog.require('goog.dom.TagName'); +goog.require('goog.events.EventType'); +goog.require('goog.graphics.AbstractGraphics'); +goog.require('goog.graphics.CanvasEllipseElement'); +goog.require('goog.graphics.CanvasGroupElement'); +goog.require('goog.graphics.CanvasImageElement'); +goog.require('goog.graphics.CanvasPathElement'); +goog.require('goog.graphics.CanvasRectElement'); +goog.require('goog.graphics.CanvasTextElement'); +goog.require('goog.graphics.SolidFill'); +goog.require('goog.math.Size'); +goog.require('goog.style'); + + + +/** + * A Graphics implementation for drawing using canvas. + * @param {string|number} width The (non-zero) width in pixels. Strings + * expressing percentages of parent with (e.g. '80%') are also accepted. + * @param {string|number} height The (non-zero) height in pixels. Strings + * expressing percentages of parent with (e.g. '80%') are also accepted. + * @param {?number=} opt_coordWidth The coordinate width - if + * omitted or null, defaults to same as width. + * @param {?number=} opt_coordHeight The coordinate height - if + * omitted or null, defaults to same as height. + * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the + * document we want to render in. + * @constructor + * @extends {goog.graphics.AbstractGraphics} + * @deprecated goog.graphics is deprecated. It existed to abstract over browser + * differences before the canvas tag was widely supported. See + * http://en.wikipedia.org/wiki/Canvas_element for details. + */ +goog.graphics.CanvasGraphics = function(width, height, + opt_coordWidth, opt_coordHeight, + opt_domHelper) { + goog.graphics.AbstractGraphics.call(this, width, height, + opt_coordWidth, opt_coordHeight, + opt_domHelper); +}; +goog.inherits(goog.graphics.CanvasGraphics, goog.graphics.AbstractGraphics); + + +/** + * Sets the fill for the given element. + * @param {goog.graphics.StrokeAndFillElement} element The element + * wrapper. + * @param {goog.graphics.Fill} fill The fill object. + * @override + */ +goog.graphics.CanvasGraphics.prototype.setElementFill = function(element, + fill) { + this.redraw(); +}; + + +/** + * Sets the stroke for the given element. + * @param {goog.graphics.StrokeAndFillElement} element The element + * wrapper. + * @param {goog.graphics.Stroke} stroke The stroke object. + * @override + */ +goog.graphics.CanvasGraphics.prototype.setElementStroke = function( + element, stroke) { + this.redraw(); +}; + + +/** + * Set the translation and rotation of an element. + * + * If a more general affine transform is needed than this provides + * (e.g. skew and scale) then use setElementAffineTransform. + * @param {goog.graphics.Element} element The element wrapper. + * @param {number} x The x coordinate of the translation transform. + * @param {number} y The y coordinate of the translation transform. + * @param {number} angle The angle of the rotation transform. + * @param {number} centerX The horizontal center of the rotation transform. + * @param {number} centerY The vertical center of the rotation transform. + * @override + */ +goog.graphics.CanvasGraphics.prototype.setElementTransform = function(element, + x, y, angle, centerX, centerY) { + this.redraw(); +}; + + +/** + * Set the transformation of an element. + * + * Note that in this implementation this method just calls this.redraw() + * and the affineTransform param is unused. + * @param {!goog.graphics.Element} element The element wrapper. + * @param {!goog.graphics.AffineTransform} affineTransform The + * transformation applied to this element. + * @override + */ +goog.graphics.CanvasGraphics.prototype.setElementAffineTransform = + function(element, affineTransform) { + this.redraw(); +}; + + +/** + * Push an element transform on to the transform stack. + * @param {goog.graphics.Element} element The transformed element. + */ +goog.graphics.CanvasGraphics.prototype.pushElementTransform = function( + element) { + var ctx = this.getContext(); + ctx.save(); + + var transform = element.getTransform(); + + // TODO(robbyw): Test for unsupported transforms i.e. skews. + var tx = transform.getTranslateX(); + var ty = transform.getTranslateY(); + if (tx || ty) { + ctx.translate(tx, ty); + } + + var sinTheta = transform.getShearY(); + if (sinTheta) { + ctx.rotate(Math.asin(sinTheta)); + } +}; + + +/** + * Pop an element transform off of the transform stack. + */ +goog.graphics.CanvasGraphics.prototype.popElementTransform = function() { + this.getContext().restore(); +}; + + +/** + * Creates the DOM representation of the graphics area. + * @override + */ +goog.graphics.CanvasGraphics.prototype.createDom = function() { + var element = this.dom_.createDom(goog.dom.TagName.DIV, + {'style': 'position:relative;overflow:hidden'}); + this.setElementInternal(element); + + this.canvas_ = this.dom_.createDom(goog.dom.TagName.CANVAS); + element.appendChild(this.canvas_); + + /** + * The main canvas element. + * @type {goog.graphics.CanvasGroupElement} + */ + this.canvasElement = new goog.graphics.CanvasGroupElement(this); + + this.lastGroup_ = this.canvasElement; + this.redrawTimeout_ = 0; + + this.updateSize(); +}; + + +/** + * Clears the drawing context object in response to actions that make the old + * context invalid - namely resize of the canvas element. + * @private + */ +goog.graphics.CanvasGraphics.prototype.clearContext_ = function() { + this.context_ = null; +}; + + +/** + * Returns the drawing context. + * @return {Object} The canvas element rendering context. + */ +goog.graphics.CanvasGraphics.prototype.getContext = function() { + if (!this.getElement()) { + this.createDom(); + } + if (!this.context_) { + this.context_ = this.canvas_.getContext('2d'); + this.context_.save(); + } + return this.context_; +}; + + +/** + * Changes the coordinate system position. + * @param {number} left The coordinate system left bound. + * @param {number} top The coordinate system top bound. + * @override + */ +goog.graphics.CanvasGraphics.prototype.setCoordOrigin = function(left, top) { + this.coordLeft = left; + this.coordTop = top; + this.redraw(); +}; + + +/** + * Changes the coordinate size. + * @param {number} coordWidth The coordinate width. + * @param {number} coordHeight The coordinate height. + * @override + */ +goog.graphics.CanvasGraphics.prototype.setCoordSize = function(coordWidth, + coordHeight) { + goog.graphics.CanvasGraphics.superClass_.setCoordSize.apply(this, arguments); + this.redraw(); +}; + + +/** + * Change the size of the canvas. + * @param {number} pixelWidth The width in pixels. + * @param {number} pixelHeight The height in pixels. + * @override + */ +goog.graphics.CanvasGraphics.prototype.setSize = function(pixelWidth, + pixelHeight) { + this.width = pixelWidth; + this.height = pixelHeight; + + this.updateSize(); + this.redraw(); +}; + + +/** @override */ +goog.graphics.CanvasGraphics.prototype.getPixelSize = function() { + // goog.style.getSize does not work for Canvas elements. We + // have to compute the size manually if it is percentage based. + var width = this.width; + var height = this.height; + var computeWidth = goog.isString(width) && width.indexOf('%') != -1; + var computeHeight = goog.isString(height) && height.indexOf('%') != -1; + + if (!this.isInDocument() && (computeWidth || computeHeight)) { + return null; + } + + var parent; + var parentSize; + + if (computeWidth) { + parent = /** @type {Element} */ (this.getElement().parentNode); + parentSize = goog.style.getSize(parent); + width = parseFloat(/** @type {string} */ (width)) * parentSize.width / 100; + } + + if (computeHeight) { + parent = parent || /** @type {Element} */ (this.getElement().parentNode); + parentSize = parentSize || goog.style.getSize(parent); + height = parseFloat(/** @type {string} */ (height)) * parentSize.height / + 100; + } + + return new goog.math.Size(/** @type {number} */ (width), + /** @type {number} */ (height)); +}; + + +/** + * Update the size of the canvas. + */ +goog.graphics.CanvasGraphics.prototype.updateSize = function() { + goog.style.setSize(this.getElement(), this.width, this.height); + + var pixels = this.getPixelSize(); + if (pixels) { + goog.style.setSize(this.canvas_, + /** @type {number} */ (pixels.width), + /** @type {number} */ (pixels.height)); + this.canvas_.width = pixels.width; + this.canvas_.height = pixels.height; + this.clearContext_(); + } +}; + + +/** + * Reset the canvas. + */ +goog.graphics.CanvasGraphics.prototype.reset = function() { + var ctx = this.getContext(); + ctx.restore(); + var size = this.getPixelSize(); + if (size.width && size.height) { + ctx.clearRect(0, 0, size.width, size.height); + } + ctx.save(); +}; + + +/** + * Remove all drawing elements from the graphics. + * @override + */ +goog.graphics.CanvasGraphics.prototype.clear = function() { + this.reset(); + this.canvasElement.clear(); + var el = this.getElement(); + + // Remove all children (text nodes) except the canvas (which is at index 0) + while (el.childNodes.length > 1) { + el.removeChild(el.lastChild); + } +}; + + +/** + * Redraw the entire canvas. + */ +goog.graphics.CanvasGraphics.prototype.redraw = function() { + if (this.preventRedraw_) { + this.needsRedraw_ = true; + return; + } + + if (this.isInDocument()) { + this.reset(); + + if (this.coordWidth) { + var pixels = this.getPixelSize(); + this.getContext().scale(pixels.width / this.coordWidth, + pixels.height / this.coordHeight); + } + if (this.coordLeft || this.coordTop) { + this.getContext().translate(-this.coordLeft, -this.coordTop); + } + this.pushElementTransform(this.canvasElement); + this.canvasElement.draw(this.context_); + this.popElementTransform(); + } +}; + + +/** + * Draw an element, including any stroke or fill. + * @param {goog.graphics.Element} element The element to draw. + */ +goog.graphics.CanvasGraphics.prototype.drawElement = function(element) { + if (element instanceof goog.graphics.CanvasTextElement) { + // Don't draw text since that is not implemented using canvas. + return; + } + + var ctx = this.getContext(); + this.pushElementTransform(element); + + if (!element.getFill || !element.getStroke) { + // Draw without stroke or fill (e.g. the element is an image or group). + element.draw(ctx); + this.popElementTransform(); + return; + } + + var fill = element.getFill(); + if (fill) { + if (fill instanceof goog.graphics.SolidFill) { + if (fill.getOpacity() != 0) { + ctx.globalAlpha = fill.getOpacity(); + ctx.fillStyle = fill.getColor(); + element.draw(ctx); + ctx.fill(); + ctx.globalAlpha = 1; + } + } else { // (fill instanceof goog.graphics.LinearGradient) + var linearGradient = ctx.createLinearGradient(fill.getX1(), fill.getY1(), + fill.getX2(), fill.getY2()); + linearGradient.addColorStop(0.0, fill.getColor1()); + linearGradient.addColorStop(1.0, fill.getColor2()); + + ctx.fillStyle = linearGradient; + element.draw(ctx); + ctx.fill(); + } + } + + var stroke = element.getStroke(); + if (stroke) { + element.draw(ctx); + ctx.strokeStyle = stroke.getColor(); + + var width = stroke.getWidth(); + if (goog.isString(width) && width.indexOf('px') != -1) { + width = parseFloat(width) / this.getPixelScaleX(); + } + ctx.lineWidth = width; + + ctx.stroke(); + } + + this.popElementTransform(); +}; + + +/** + * Append an element. + * + * @param {goog.graphics.Element} element The element to draw. + * @param {goog.graphics.GroupElement|undefined} group The group to draw + * it in. If null or undefined, defaults to the root group. + * @protected + */ +goog.graphics.CanvasGraphics.prototype.append = function(element, group) { + group = group || this.canvasElement; + group.appendChild(element); + + if (this.isDrawable(group)) { + this.drawElement(element); + } +}; + + +/** + * Draw an ellipse. + * + * @param {number} cx Center X coordinate. + * @param {number} cy Center Y coordinate. + * @param {number} rx Radius length for the x-axis. + * @param {number} ry Radius length for the y-axis. + * @param {goog.graphics.Stroke} stroke Stroke object describing the + * stroke. + * @param {goog.graphics.Fill} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper + * element to append to. If not specified, appends to the main canvas. + * + * @return {!goog.graphics.EllipseElement} The newly created element. + * @override + */ +goog.graphics.CanvasGraphics.prototype.drawEllipse = function(cx, cy, rx, ry, + stroke, fill, opt_group) { + var element = new goog.graphics.CanvasEllipseElement(null, this, + cx, cy, rx, ry, stroke, fill); + this.append(element, opt_group); + return element; +}; + + +/** + * Draw a rectangle. + * + * @param {number} x X coordinate (left). + * @param {number} y Y coordinate (top). + * @param {number} width Width of rectangle. + * @param {number} height Height of rectangle. + * @param {goog.graphics.Stroke} stroke Stroke object describing the + * stroke. + * @param {goog.graphics.Fill} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper + * element to append to. If not specified, appends to the main canvas. + * + * @return {!goog.graphics.RectElement} The newly created element. + * @override + */ +goog.graphics.CanvasGraphics.prototype.drawRect = function(x, y, width, height, + stroke, fill, opt_group) { + var element = new goog.graphics.CanvasRectElement(null, this, + x, y, width, height, stroke, fill); + this.append(element, opt_group); + return element; +}; + + +/** + * Draw an image. + * + * @param {number} x X coordinate (left). + * @param {number} y Y coordinate (top). + * @param {number} width Width of image. + * @param {number} height Height of image. + * @param {string} src Source of the image. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper + * element to append to. If not specified, appends to the main canvas. + * + * @return {!goog.graphics.ImageElement} The newly created element. + */ +goog.graphics.CanvasGraphics.prototype.drawImage = function(x, y, width, height, + src, opt_group) { + var element = new goog.graphics.CanvasImageElement(null, this, x, y, width, + height, src); + this.append(element, opt_group); + return element; +}; + + +/** + * Draw a text string vertically centered on a given line. + * + * @param {string} text The text to draw. + * @param {number} x1 X coordinate of start of line. + * @param {number} y1 Y coordinate of start of line. + * @param {number} x2 X coordinate of end of line. + * @param {number} y2 Y coordinate of end of line. + * @param {?string} align Horizontal alignment: left (default), center, right. + * @param {goog.graphics.Font} font Font describing the font properties. + * @param {goog.graphics.Stroke} stroke Stroke object describing the stroke. + * @param {goog.graphics.Fill} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper + * element to append to. If not specified, appends to the main canvas. + * + * @return {!goog.graphics.TextElement} The newly created element. + * @override + */ +goog.graphics.CanvasGraphics.prototype.drawTextOnLine = function( + text, x1, y1, x2, y2, align, font, stroke, fill, opt_group) { + var element = new goog.graphics.CanvasTextElement(this, + text, x1, y1, x2, y2, align, /** @type {!goog.graphics.Font} */ (font), + stroke, fill); + this.append(element, opt_group); + return element; +}; + + +/** + * Draw a path. + * @param {!goog.graphics.Path} path The path object to draw. + * @param {goog.graphics.Stroke} stroke Stroke object describing the stroke. + * @param {goog.graphics.Fill} fill Fill object describing the fill. + * @param {goog.graphics.GroupElement=} opt_group The group wrapper + * element to append to. If not specified, appends to the main canvas. + * + * @return {!goog.graphics.PathElement} The newly created element. + * @override + */ +goog.graphics.CanvasGraphics.prototype.drawPath = function(path, stroke, fill, + opt_group) { + var element = new goog.graphics.CanvasPathElement(null, this, + path, stroke, fill); + this.append(element, opt_group); + return element; +}; + + +/** + * @param {goog.graphics.GroupElement} group The group to possibly + * draw to. + * @return {boolean} Whether drawing can occur now. + */ +goog.graphics.CanvasGraphics.prototype.isDrawable = function(group) { + return this.isInDocument() && !this.redrawTimeout_ && + !this.isRedrawRequired(group); +}; + + +/** + * Returns true if drawing to the given group means a redraw is required. + * @param {goog.graphics.GroupElement} group The group to draw to. + * @return {boolean} Whether drawing to this group should force a redraw. + */ +goog.graphics.CanvasGraphics.prototype.isRedrawRequired = function(group) { + // TODO(robbyw): Moving up to any parent of lastGroup should not force redraw. + return group != this.canvasElement && group != this.lastGroup_; +}; + + +/** + * Create an empty group of drawing elements. + * + * @param {goog.graphics.GroupElement=} opt_group The group wrapper + * element to append to. If not specified, appends to the main canvas. + * + * @return {!goog.graphics.CanvasGroupElement} The newly created group. + * @override + */ +goog.graphics.CanvasGraphics.prototype.createGroup = function(opt_group) { + var group = new goog.graphics.CanvasGroupElement(this); + + opt_group = opt_group || this.canvasElement; + + // TODO(robbyw): Moving up to any parent group should not force redraw. + if (opt_group == this.canvasElement || opt_group == this.lastGroup_) { + this.lastGroup_ = group; + } + + this.append(group, opt_group); + + return group; +}; + + +/** + * Measure and return the width (in pixels) of a given text string. + * Text measurement is needed to make sure a text can fit in the allocated + * area. The way text length is measured is by writing it into a div that is + * after the visible area, measure the div width, and immediatly erase the + * written value. + * + * @param {string} text The text string to measure. + * @param {goog.graphics.Font} font The font object describing the font style. + * @override + */ +goog.graphics.CanvasGraphics.prototype.getTextWidth = goog.abstractMethod; + + +/** + * Disposes of the component by removing event handlers, detacing DOM nodes from + * the document body, and removing references to them. + * @override + * @protected + */ +goog.graphics.CanvasGraphics.prototype.disposeInternal = function() { + this.context_ = null; + goog.graphics.CanvasGraphics.superClass_.disposeInternal.call(this); +}; + + +/** @override */ +goog.graphics.CanvasGraphics.prototype.enterDocument = function() { + var oldPixelSize = this.getPixelSize(); + goog.graphics.CanvasGraphics.superClass_.enterDocument.call(this); + if (!oldPixelSize) { + this.updateSize(); + this.dispatchEvent(goog.events.EventType.RESIZE); + } + this.redraw(); +}; + + +/** + * Start preventing redraws - useful for chaining large numbers of changes + * together. Not guaranteed to do anything - i.e. only use this for + * optimization of a single code path. + * @override + */ +goog.graphics.CanvasGraphics.prototype.suspend = function() { + this.preventRedraw_ = true; +}; + + +/** + * Stop preventing redraws. If any redraws had been prevented, a redraw will + * be done now. + * @override + */ +goog.graphics.CanvasGraphics.prototype.resume = function() { + this.preventRedraw_ = false; + + if (this.needsRedraw_) { + this.redraw(); + this.needsRedraw_ = false; + } +};
