UNPKG

@awayjs/graphics

Version:
1,019 lines (1,010 loc) 93 kB
import { __extends } from "tslib"; import { ArgumentError, RangeError, Point, Matrix, AssetBase, Rectangle, } from '@awayjs/core'; import { ImageSampler } from '@awayjs/stage'; import { EntityNode, PartitionBase, PickEntity } from '@awayjs/view'; import { Style, TriangleElements, LineElements, LineScaleMode, } from '@awayjs/renderer'; import { GraphicsPath } from './draw/GraphicsPath'; import { GraphicsFactoryFills } from './draw/GraphicsFactoryFills'; import { GraphicsFactoryStrokes } from './draw/GraphicsFactoryStrokes'; import { GraphicsFactoryHelper } from './draw/GraphicsFactoryHelper'; import { JointStyle } from './draw/JointStyle'; import { CapsStyle } from './draw/CapsStyle'; import { BitmapFillStyle } from './draw/fills/BitmapFillStyle'; import { GradientFillStyle } from './draw/fills/GradientFillStyle'; import { SolidFillStyle } from './draw/fills/SolidFillStyle'; import { GraphicsStrokeStyle } from './draw/GraphicsStrokeStyle'; import { GraphicsFillStyle } from './draw/GraphicsFillStyle'; import { Shape } from './renderables/Shape'; import { FillType } from './data/FillType'; import { PathSegment } from './data/PathSegment'; import { assert } from './data/utilities'; import { MaterialManager } from './managers/MaterialManager'; import { ManagedPool } from './ManagedPool'; import { Settings } from './Settings'; import { StyleUtils } from './flash/StyleUtils'; import { GraphicsPathCommand } from './draw/GraphicsPathCommand'; GraphicsFactoryFills.prepareWasm(); var Array_push = Array.prototype.push; var fromTwips = function (val) { return Math.round(val / 20); }; /** * * Graphics is a collection of Shapes, each of which contain the actual geometrical data such as vertices, * normals, uvs, etc. It also contains a reference to an animation class, which defines how the geometry moves. * A Graphics object is assigned to a Sprite, a scene graph occurence of the geometry, which in turn assigns * the SubGeometries to its respective TriangleGraphic objects. * * * * * @class Graphics */ var Graphics = /** @class */ (function (_super) { __extends(Graphics, _super); /** * Creates a new Graphics object. */ function Graphics() { var _this = _super.call(this) || this; _this._bitmapFillPool = {}; _this._queuedShapeTags = []; _this._shapes = []; _this._queued_fill_pathes = []; _this._queued_stroke_pathes = []; _this._current_position = new Point(); _this.tryOptimiseSigleImage = false; _this._lastPrebuildedShapes = []; _this._drawingDirty = false; _this.usages = 0; /*private*/ _this._clearCount = 0; _this._internalShapesId = []; _this._rFillPool = new ManagedPool(Shape, 100, false); _this._rStrokePool = new ManagedPool(Shape, 100, false); _this._poolingConfig = { fill: Settings.ALLOW_INTERNAL_POOL.FILLS, stroke: Settings.ALLOW_INTERNAL_POOL.STROKES, clearsCount: Settings.CLEARS_BEFORE_POOLING }; return _this; } Graphics.getShapeForBitmap = function (bitmap, rect) { var mat = MaterialManager.getMaterialForBitmap(bitmap); var style = mat.style; style.sampler = new ImageSampler(false, true, false); style.addSamplerAt(style.sampler, mat.getTextureAt(0)); return Shape.getShape(Shape.getTriangleElement(rect, false, true), mat, style); }; Graphics.getShapeForBitmapStyle = function (shapeStyle, flashBox) { var style = new Style(); var rect = new Rectangle(fromTwips(flashBox.xMin), fromTwips(flashBox.yMin), fromTwips(flashBox.xMax - flashBox.xMin), fromTwips(flashBox.yMax - flashBox.yMin)); var element = Shape.getTriangleElement(rect); element.usages++; var _a = shapeStyle.transform, a = _a.a, b = _a.b, c = _a.c, d = _a.d, tx = _a.tx, ty = _a.ty; var texture = shapeStyle.material.getTextureAt(0); var mat = MaterialManager.getMaterialForBitmap(shapeStyle.material.style.image); var bitmapFillStyle = new BitmapFillStyle(mat, new Matrix(a, b, c, d, tx, ty), shapeStyle.repeat, shapeStyle.smooth); var material = bitmapFillStyle.material; //enforce image smooth style var sampler = new ImageSampler(bitmapFillStyle.repeat, bitmapFillStyle.smooth, shapeStyle.smooth); material.style.sampler = sampler; material.animateUVs = true; style.addSamplerAt(sampler, texture); style.uvMatrix = bitmapFillStyle.getUVMatrix(); return Shape.getShape(element, material, style); }; Graphics.getGraphics = function () { if (Graphics._pool.length) return Graphics._pool.pop(); return new Graphics(); }; Graphics.clearPool = function () { Graphics._pool = []; }; Object.defineProperty(Graphics.prototype, "start", { get: function () { if (!this._start && this.sourceGraphics) { return this.sourceGraphics.start; } return this._start; }, set: function (v) { this._start = v; }, enumerable: false, configurable: true }); Object.defineProperty(Graphics.prototype, "end", { get: function () { if (!this._end && this.sourceGraphics) { return this.sourceGraphics.end; } return this._end; }, set: function (v) { this._end = v; }, enumerable: false, configurable: true }); Object.defineProperty(Graphics.prototype, "assetType", { get: function () { return Graphics.assetType; }, enumerable: false, configurable: true }); Object.defineProperty(Graphics.prototype, "count", { get: function () { return (this._shapes.length + this._queued_stroke_pathes.length + this._queued_fill_pathes.length + this._queuedShapeTags.length); }, enumerable: false, configurable: true }); Object.defineProperty(Graphics.prototype, "queued_stroke_pathes", { get: function () { return this._queued_stroke_pathes; }, set: function (value) { this._queued_stroke_pathes = value; }, enumerable: false, configurable: true }); Object.defineProperty(Graphics.prototype, "queued_fill_pathes", { get: function () { return this._queued_fill_pathes; }, set: function (value) { this._queued_fill_pathes = value; }, enumerable: false, configurable: true }); Graphics.prototype.add_queued_path = function (value, supressFill) { if (supressFill === void 0) { supressFill = false; } if (!value.style) { return; } var isLine = value.style.data_type === GraphicsStrokeStyle.data_type; if (!isLine) { this._drawingDirty = true; this._queued_fill_pathes.push(value); } else { this._queued_stroke_pathes.push(value); if (!supressFill) { this.endFill(); } } }; Object.defineProperty(Graphics.prototype, "internalPoolConfig", { get: function () { return this._poolingConfig; }, /* internal */ set: function (v) { this._poolingConfig.fill = typeof v === 'boolean' ? v : v.fill; this._poolingConfig.stroke = typeof v === 'boolean' ? v : v.stroke; if (!v) { this._rFillPool.enabled && this._rFillPool.clear(); this._rStrokePool.enabled && this._rStrokePool.clear(); this._rStrokePool.enabled = false; this._rStrokePool.enabled = false; } this._clearCount = 0; }, enumerable: false, configurable: true }); Graphics.prototype.popEmptyFillShape = function () { return this._rFillPool.pop(); }; Graphics.prototype.popEmptyStrokeShape = function () { return this._rStrokePool.pop(); }; /* internal */ Graphics.prototype.addShapeInternal = function (shape) { this.addShape(shape); this._internalShapesId.push(shape.id); }; /** * Adds a GraphicBase wrapping a Elements. * * @param elements */ Graphics.prototype.addShape = function (shape) { shape.usages++; var shapeIndex = this.getShapeIndex(shape); if (shapeIndex != -1) this.removeShapeAt(shapeIndex); this._shapes.push(shape); this.invalidate(); return shape; }; Graphics.prototype.removeShape = function (shape) { var shapeIndex = this.getShapeIndex(shape); if (shapeIndex == -1) throw new ArgumentError('Shape parameter is not a shape of the caller'); this.removeShapeAt(shapeIndex); }; Graphics.prototype.removeShapeAt = function (index) { if (index < 0 || index >= this._shapes.length) throw new RangeError('Index is out of range'); var shape = this._shapes.splice(index, 1)[0]; shape.usages--; if (!shape.usages) { if (!this.tryPoolShape(shape)) { shape.dispose(); } } this.invalidate(); }; Graphics.prototype.getShapeAt = function (index) { return this._shapes[index]; }; Graphics.prototype.getShapeIndex = function (shape) { return this._shapes.indexOf(shape); }; Graphics.prototype.applyTransformation = function (transform) { var len = this._shapes.length; for (var i = 0; i < len; ++i) { this._shapes[i].applyTransformation(transform); } }; Graphics.prototype.copyTo = function (graphics, cloneShapes) { if (cloneShapes === void 0) { cloneShapes = false; } if (this._drawingDirty) this.endFill(); graphics.sourceGraphics = this; graphics._addShapes(this._shapes, cloneShapes); }; Graphics.prototype.clone = function (cloneShapes) { if (cloneShapes === void 0) { cloneShapes = false; } var newInstance = Graphics.getGraphics(); this.copyTo(newInstance, cloneShapes); return newInstance; }; /** * Scales the geometry. * @param scale The amount by which to scale. */ Graphics.prototype.scale = function (scale) { var len = this._shapes.length; for (var i = 0; i < len; ++i) this._shapes[i].scale(scale); }; Graphics.prototype.tryPoolShape = function (shape) { // not works atm // text is bugged var canPooledTriangle = shape.elements.assetType === TriangleElements.assetType; var canPooledLine = shape.elements.assetType === LineElements.assetType; if (!canPooledLine && !canPooledTriangle) { return false; } var index = this._internalShapesId.indexOf(shape.id); if (index === -1) { return false; } if (canPooledTriangle) { return this._rFillPool.store(shape); } if (canPooledLine) { return this._rStrokePool.store(shape); } return false; }; Graphics.prototype.clear = function () { this._clearCount++; this._lastPrebuildedShapes.length = 0; var requireShapePool = (this._internalShapesId.length > 0 && this._clearCount >= this._poolingConfig.clearsCount); if (requireShapePool && (this._rStrokePool.enabled !== this._poolingConfig.stroke || this._rFillPool.enabled !== this._poolingConfig.fill)) { console.warn('[Graphics] To many clears, pooling shapes internally!', this.id, this._internalShapesId.length); this._rFillPool.enabled = this._poolingConfig.fill; this._rStrokePool.enabled = this._poolingConfig.stroke; } var shape; var len = this._shapes.length; for (var i = 0; i < len; i++) { shape = this._shapes[i]; shape.usages--; if (!shape.usages) { if (!this.tryPoolShape(shape)) { shape.dispose(); } } } this._internalShapesId.length = 0; this._shapes.length = 0; this.invalidate(); this._active_fill_path = null; this._active_stroke_path = null; this._queued_fill_pathes.length = 0; this._queued_stroke_pathes.length = 0; this._current_position.x = 0; this._current_position.y = 0; this._drawingDirty = false; this._lineStyle = null; this._fillStyle = null; }; /** * Clears all resources used by the Graphics object, including SubGeometries. */ Graphics.prototype.dispose = function () { this.clear(); if (this._bitmapFillPool) { for (var k in this._bitmapFillPool) { this._bitmapFillPool[k].fillStyle.material.dispose(); } this._bitmapFillPool = null; } this._bitmapFillPool = null; /* we can not release shapes for this, it was a store elements that can be reused then */ this._rFillPool.clear(); this._rStrokePool.clear(); this._internalShapesId.length = 0; this._clearCount = 0; Graphics._pool.push(this); }; /** * Scales the uv coordinates (tiling) * @param scaleU The amount by which to scale on the u axis. Default is 1; * @param scaleV The amount by which to scale on the v axis. Default is 1; */ Graphics.prototype.scaleUV = function (scaleU, scaleV) { if (scaleU === void 0) { scaleU = 1; } if (scaleV === void 0) { scaleV = 1; } var len = this._shapes.length; for (var i = 0; i < len; ++i) this._shapes[i].scaleUV(scaleU, scaleV); }; // public invalidateMaterials():void // { // var len:number = this._shapes.length; // for (var i:number = 0; i < len; ++i) // this._shapes[i].invalidateMaterial(); // } // public invalidateElements():void // { // var len:number = this._shapes.length; // for (var i:number = 0; i < len; ++i) // this._shapes[i].invalidateElements(); // } Graphics.prototype._acceptTraverser = function (traverser) { // this is important // not close shape when request bounds // otherwise it will corrupt rendering flow if (this._drawingDirty) { // need to drop shapes that was pre-built but not a closed (_endFillInternal(false)) // because shape was corrupted when a bounds calculation requested between commands for (var _i = 0, _a = this._lastPrebuildedShapes; _i < _a.length; _i++) { var s = _a[_i]; this.removeShape(s); } if (traverser instanceof PickEntity) { // build shape construct shapes but not close graphics this._endFillInternal(false); } else { this.endFill(); } } var len = this._shapes.length; for (var i = 0; i < len; i++) traverser.applyTraversable(this._shapes[i]); }; /** * Fills a drawing area with a bitmap image. The bitmap can be repeated or * tiled to fill the area. The fill remains in effect until you call the * <code>beginFill()</code>, <code>beginBitmapFill()</code>, * <code>beginGradientFill()</code>, or <code>beginShaderFill()</code> * method. Calling the <code>clear()</code> method clears the fill. * * <p>The application renders the fill whenever three or more points are * drawn, or when the <code>endFill()</code> method is called. </p> * * @param bitmap A transparent or opaque bitmap image that contains the bits * to be displayed. * @param matrix A matrix object(of the flash.geom.Matrix class), which you * can use to define transformations on the bitmap. For * example, you can use the following matrix to rotate a bitmap * by 45 degrees(pi/4 radians): * @param repeat If <code>true</code>, the bitmap image repeats in a tiled * pattern. If <code>false</code>, the bitmap image does not * repeat, and the edges of the bitmap are used for any fill * area that extends beyond the bitmap. * * <p>For example, consider the following bitmap(a 20 x * 20-pixel checkerboard pattern):</p> * * <p>When <code>repeat</code> is set to <code>true</code>(as * in the following example), the bitmap fill repeats the * bitmap:</p> * * <p>When <code>repeat</code> is set to <code>false</code>, * the bitmap fill uses the edge pixels for the fill area * outside the bitmap:</p> * @param smooth If <code>false</code>, upscaled bitmap images are rendered * by using a nearest-neighbor algorithm and look pixelated. If * <code>true</code>, upscaled bitmap images are rendered by * using a bilinear algorithm. Rendering by using the nearest * neighbor algorithm is faster. */ Graphics.prototype.beginBitmapFill = function (bitmap, matrix, repeat, smooth) { if (matrix === void 0) { matrix = null; } if (repeat === void 0) { repeat = true; } if (smooth === void 0) { smooth = Settings.SMOOTH_BITMAP_FILL_DEFAULT; } if (this._fillStyle) this.endFill(); if (!this._bitmapFillPool) { this._bitmapFillPool = {}; } var fill = this._bitmapFillPool[bitmap.id]; if (!fill) { fill = this._bitmapFillPool[bitmap.id] = new GraphicsFillStyle(new BitmapFillStyle(MaterialManager.getMaterialForBitmap(bitmap), matrix, repeat, smooth)); } else { fill.fillStyle.matrix = matrix; fill.fillStyle.repeat = repeat; fill.fillStyle.smooth = smooth; } this._fillStyle = fill; this._updateFillPath(); }; /** * Specifies a simple one-color fill that subsequent calls to other Graphics * methods(such as <code>lineTo()</code> or <code>drawCircle()</code>) use * when drawing. The fill remains in effect until you call the * <code>beginFill()</code>, <code>beginBitmapFill()</code>, * <code>beginGradientFill()</code>, or <code>beginShaderFill()</code> * method. Calling the <code>clear()</code> method clears the fill. * * <p>The application renders the fill whenever three or more points are * drawn, or when the <code>endFill()</code> method is called.</p> * * @param color The color of the fill(0xRRGGBB). * @param alpha The alpha value of the fill(0.0 to 1.0). */ Graphics.prototype.beginFill = function (color /*int*/, alpha) { if (alpha === void 0) { alpha = 1; } if (color == 0) color = 0x010101; if (this._fillStyle) this.endFill(); this._fillStyle = new GraphicsFillStyle(new SolidFillStyle(color, alpha)); this._updateFillPath(); }; /** * Specifies a gradient fill used by subsequent calls to other Graphics * methods(such as <code>lineTo()</code> or <code>drawCircle()</code>) for * the object. The fill remains in effect until you call the * <code>beginFill()</code>, <code>beginBitmapFill()</code>, * <code>beginGradientFill()</code>, or <code>beginShaderFill()</code> * method. Calling the <code>clear()</code> method clears the fill. * * <p>The application renders the fill whenever three or more points are * drawn, or when the <code>endFill()</code> method is called. </p> * * @param type A value from the GradientType class that * specifies which gradient type to use: * <code>GradientType.LINEAR</code> or * <code>GradientType.RADIAL</code>. * @param colors An array of RGB hexadecimal color values used * in the gradient; for example, red is 0xFF0000, * blue is 0x0000FF, and so on. You can specify * up to 15 colors. For each color, specify a * corresponding value in the alphas and ratios * parameters. * @param alphas An array of alpha values for the corresponding * colors in the colors array; valid values are 0 * to 1. If the value is less than 0, the default * is 0. If the value is greater than 1, the * default is 1. * @param ratios An array of color distribution ratios; valid * values are 0-255. This value defines the * percentage of the width where the color is * sampled at 100%. The value 0 represents the * left position in the gradient box, and 255 * represents the right position in the gradient * box. * @param matrix A transformation matrix as defined by the * flash.geom.Matrix class. The flash.geom.Matrix * class includes a * <code>createGradientBox()</code> method, which * lets you conveniently set up the matrix for use * with the <code>beginGradientFill()</code> * method. * @param spreadMethod A value from the SpreadMethod class that * specifies which spread method to use, either: * <code>SpreadMethod.PAD</code>, * <code>SpreadMethod.REFLECT</code>, or * <code>SpreadMethod.REPEAT</code>. * * <p>For example, consider a simple linear * gradient between two colors:</p> * * <p>This example uses * <code>SpreadMethod.PAD</code> for the spread * method, and the gradient fill looks like the * following:</p> * * <p>If you use <code>SpreadMethod.REFLECT</code> * for the spread method, the gradient fill looks * like the following:</p> * * <p>If you use <code>SpreadMethod.REPEAT</code> * for the spread method, the gradient fill looks * like the following:</p> * @param interpolationMethod A value from the InterpolationMethod class that * specifies which value to use: * <code>InterpolationMethod.LINEAR_RGB</code> or * <code>InterpolationMethod.RGB</code> * * <p>For example, consider a simple linear * gradient between two colors(with the * <code>spreadMethod</code> parameter set to * <code>SpreadMethod.REFLECT</code>). The * different interpolation methods affect the * appearance as follows: </p> * @param focalPointRatio A number that controls the location of the * focal point of the gradient. 0 means that the * focal point is in the center. 1 means that the * focal point is at one border of the gradient * circle. -1 means that the focal point is at the * other border of the gradient circle. A value * less than -1 or greater than 1 is rounded to -1 * or 1. For example, the following example shows * a <code>focalPointRatio</code> set to 0.75: * @throws ArgumentError If the <code>type</code> parameter is not valid. */ Graphics.prototype.beginGradientFill = function (type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPointRatio) { if (matrix === void 0) { matrix = null; } if (spreadMethod === void 0) { spreadMethod = 'pad'; } if (interpolationMethod === void 0) { interpolationMethod = 'rgb'; } if (focalPointRatio === void 0) { focalPointRatio = 0; } if (this._fillStyle) this.endFill(); this._fillStyle = new GraphicsFillStyle(new GradientFillStyle(type, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPointRatio)); this._updateFillPath(); }; /** * Copies all of drawing commands from the source Graphics object into the * calling Graphics object. * * @param sourceGraphics The Graphics object from which to copy the drawing * commands. */ Graphics.prototype.copyFrom = function (sourceGraphics) { sourceGraphics.copyTo(this); }; /** * Draws a cubic Bezier curve from the current drawing position to the * specified anchor point. Cubic Bezier curves consist of two anchor points * and two control points. The curve interpolates the two anchor points and * curves toward the two control points. * * The four points you use to draw a cubic Bezier curve with the * <code>cubicCurveTo()</code> method are as follows: * * <ul> * <li>The current drawing position is the first anchor point. </li> * <li>The anchorX and anchorY parameters specify the second anchor point. * </li> * <li>The <code>controlX1</code> and <code>controlY1</code> parameters * specify the first control point.</li> * <li>The <code>controlX2</code> and <code>controlY2</code> parameters * specify the second control point.</li> * </ul> * * If you call the <code>cubicCurveTo()</code> method before calling the * <code>moveTo()</code> method, your curve starts at position (0, 0). * * If the <code>cubicCurveTo()</code> method succeeds, the Flash runtime sets * the current drawing position to (<code>anchorX</code>, * <code>anchorY</code>). If the <code>cubicCurveTo()</code> method fails, * the current drawing position remains unchanged. * * If your movie clip contains content created with the Flash drawing tools, * the results of calls to the <code>cubicCurveTo()</code> method are drawn * underneath that content. * * @param controlX1 Specifies the horizontal position of the first control * point relative to the registration point of the parent * display object. * @param controlY1 Specifies the vertical position of the first control * point relative to the registration point of the parent * display object. * @param controlX2 Specifies the horizontal position of the second control * point relative to the registration point of the parent * display object. * @param controlY2 Specifies the vertical position of the second control * point relative to the registration point of the parent * display object. * @param anchorX Specifies the horizontal position of the anchor point * relative to the registration point of the parent display * object. * @param anchorY Specifies the vertical position of the anchor point * relative to the registration point of the parent display * object. */ Graphics.prototype.cubicCurveTo = function (controlX1, controlY1, controlX2, controlY2, anchorX, anchorY) { this._drawingDirty = true; if (this._active_fill_path) this._active_fill_path.cubicCurveTo(controlX1, controlY1, controlX2, controlY2, anchorX, anchorY); if (this._active_stroke_path) this._active_stroke_path.cubicCurveTo(controlX1, controlY1, controlX2, controlY2, anchorX, anchorY); this._current_position.x = anchorX; this._current_position.y = anchorY; this.invalidate(); }; /** * Draws a curve using the current line style from the current drawing * position to(anchorX, anchorY) and using the control point that * (<code>controlX</code>, <code>controlY</code>) specifies. The current * drawing position is then set to(<code>anchorX</code>, * <code>anchorY</code>). If the movie clip in which you are drawing contains * content created with the Flash drawing tools, calls to the * <code>curveTo()</code> method are drawn underneath this content. If you * call the <code>curveTo()</code> method before any calls to the * <code>moveTo()</code> method, the default of the current drawing position * is(0, 0). If any of the parameters are missing, this method fails and the * current drawing position is not changed. * * <p>The curve drawn is a quadratic Bezier curve. Quadratic Bezier curves * consist of two anchor points and one control point. The curve interpolates * the two anchor points and curves toward the control point. </p> * * @param controlX A number that specifies the horizontal position of the * control point relative to the registration point of the * parent display object. * @param controlY A number that specifies the vertical position of the * control point relative to the registration point of the * parent display object. * @param anchorX A number that specifies the horizontal position of the * next anchor point relative to the registration point of * the parent display object. * @param anchorY A number that specifies the vertical position of the next * anchor point relative to the registration point of the * parent display object. */ Graphics.prototype.curveTo = function (controlX, controlY, anchorX, anchorY) { this._drawingDirty = true; if (this._active_fill_path) this._active_fill_path.curveTo(controlX, controlY, anchorX, anchorY); if (this._active_stroke_path) this._active_stroke_path.curveTo(controlX, controlY, anchorX, anchorY); this._current_position.x = anchorX; this._current_position.y = anchorY; this.invalidate(); }; /** * Draws a circle. Set the line style, fill, or both before you call the * <code>drawCircle()</code> method, by calling the <code>linestyle()</code>, * <code>lineGradientStyle()</code>, <code>beginFill()</code>, * <code>beginGradientFill()</code>, or <code>beginBitmapFill()</code> * method. * * @param x The <i>x</i> location of the center of the circle relative * to the registration point of the parent display object(in * pixels). * @param y The <i>y</i> location of the center of the circle relative * to the registration point of the parent display object(in * pixels). * @param radius The radius of the circle(in pixels). */ Graphics.prototype.drawCircle = function (x, y, radius) { this._drawingDirty = true; //var radius2=radius*1.065; if (this._active_fill_path) { this._active_fill_path.moveTo(x, y); var r = radius; if (this._active_stroke_path) r -= this._active_stroke_path.style.thickness / 2; GraphicsFactoryHelper.drawElipse(x, y, r, r, this._active_fill_path.verts, 0, 360, 5, false); } if (this._active_stroke_path) GraphicsFactoryHelper.drawElipseStrokes(x, y, radius, radius, this._active_stroke_path, 0, 360, 2); this.invalidate(); }; /** * Draws an ellipse. Set the line style, fill, or both before you call the * <code>drawEllipse()</code> method, by calling the * <code>linestyle()</code>, <code>lineGradientStyle()</code>, * <code>beginFill()</code>, <code>beginGradientFill()</code>, or * <code>beginBitmapFill()</code> method. * * @param x The <i>x</i> location of the top-left of the bounding-box of * the ellipse relative to the registration point of the parent * display object(in pixels). * @param y The <i>y</i> location of the top left of the bounding-box of * the ellipse relative to the registration point of the parent * display object(in pixels). * @param width The width of the ellipse(in pixels). * @param height The height of the ellipse(in pixels). */ Graphics.prototype.drawEllipse = function (x, y, width, height) { this._drawingDirty = true; width /= 2; height /= 2; x += width; y += height; if (this._active_fill_path != null) { this._active_fill_path.moveTo(x, y); var w = width; var h = height; if (this._active_stroke_path != null) { w -= this._active_stroke_path.style.thickness / 2; h -= this._active_stroke_path.style.thickness / 2; } GraphicsFactoryHelper.drawElipse(x, y, w, h, this._active_fill_path.verts, 0, 360, 6, false); } if (this._active_stroke_path != null) { GraphicsFactoryHelper.drawElipseStrokes(x, y, width, height, this._active_stroke_path, 0, 360, 2); } this.invalidate(); }; /** * Submits a series of IGraphicsData instances for drawing. This method * accepts a Vector containing objects including paths, fills, and strokes * that implement the IGraphicsData interface. A Vector of IGraphicsData * instances can refer to a part of a shape, or a complex fully defined set * of data for rendering a complete shape. * * <p> Graphics paths can contain other graphics paths. If the * <code>graphicsData</code> Vector includes a path, that path and all its * sub-paths are rendered during this operation. </p> * */ Graphics.prototype.drawGraphicsData = function (graphicsData) { /* for (var i:number=0; i<graphicsData.length; i++){ //todo if(graphicsData[i].dataType=="beginFill"){ } else if(graphicsData[i].dataType=="endFill"){ } else if(graphicsData[i].dataType=="endFill"){ } else if(graphicsData[i].dataType=="Path"){ } } */ }; /** * Submits a series of commands for drawing. The <code>drawPath()</code> * method uses vector arrays to consolidate individual <code>moveTo()</code>, * <code>lineTo()</code>, and <code>curveTo()</code> drawing commands into a * single call. The <code>drawPath()</code> method parameters combine drawing * commands with x- and y-coordinate value pairs and a drawing direction. The * drawing commands are values from the GraphicsPathCommand class. The x- and * y-coordinate value pairs are Numbers in an array where each pair defines a * coordinate location. The drawing direction is a value from the * GraphicsPathWinding class. * * <p> Generally, drawings render faster with <code>drawPath()</code> than * with a series of individual <code>lineTo()</code> and * <code>curveTo()</code> methods. </p> * * <p> The <code>drawPath()</code> method uses a uses a floating computation * so rotation and scaling of shapes is more accurate and gives better * results. However, curves submitted using the <code>drawPath()</code> * method can have small sub-pixel alignment errors when used in conjunction * with the <code>lineTo()</code> and <code>curveTo()</code> methods. </p> * * <p> The <code>drawPath()</code> method also uses slightly different rules * for filling and drawing lines. They are: </p> * * <ul> * <li>When a fill is applied to rendering a path: * <ul> * <li>A sub-path of less than 3 points is not rendered.(But note that the * stroke rendering will still occur, consistent with the rules for strokes * below.)</li> * <li>A sub-path that isn't closed(the end point is not equal to the * begin point) is implicitly closed.</li> * </ul> * </li> * <li>When a stroke is applied to rendering a path: * <ul> * <li>The sub-paths can be composed of any number of points.</li> * <li>The sub-path is never implicitly closed.</li> * </ul> * </li> * </ul> * * @param winding Specifies the winding rule using a value defined in the * GraphicsPathWinding class. */ Graphics.prototype.drawPath = function (commands, data, winding) { this._drawingDirty = true; //shapeAJS.queuePath(allPaths[i], null); // segment.serializeAJS(shape, null, { x: 0, y: 0}); var commandsCount = commands.length; var dataPosition; if (this._active_fill_path) this._drawPathInternal(this._active_fill_path, commands, data, winding); if (this._active_stroke_path) this._drawPathInternal(this._active_stroke_path, commands, data, winding); this.invalidate(); }; Graphics.prototype._drawPathInternal = function (path, commands, data, winding) { var dataPosition = 0; for (var i = 0; i < commands.length; i++) { switch (commands[i]) { case GraphicsPathCommand.MOVE_TO: path.moveTo(data[dataPosition], data[dataPosition + 1]); dataPosition += 2; break; case GraphicsPathCommand.LINE_TO: path.lineTo(data[dataPosition], data[dataPosition + 1]); dataPosition += 2; break; case GraphicsPathCommand.CURVE_TO: path.curveTo(data[dataPosition], data[dataPosition + 1], data[dataPosition + 2], data[dataPosition + 3]); dataPosition += 4; break; case GraphicsPathCommand.NO_OP: default: } } }; /** * Draws a rectangle. Set the line style, fill, or both before you call the * <code>drawRect()</code> method, by calling the <code>linestyle()</code>, * <code>lineGradientStyle()</code>, <code>beginFill()</code>, * <code>beginGradientFill()</code>, or <code>beginBitmapFill()</code> * method. * * @param x A number indicating the horizontal position relative to the * registration point of the parent display object(in pixels). * @param y A number indicating the vertical position relative to the * registration point of the parent display object(in pixels). * @param width The width of the rectangle(in pixels). * @param height The height of the rectangle(in pixels). * @throws ArgumentError If the <code>width</code> or <code>height</code> * parameters are not a number * (<code>Number.NaN</code>). */ Graphics.prototype.drawRect = function (x, y, width, height) { this._drawingDirty = true; if (this._active_fill_path != null) { this._active_fill_path.moveTo(x, y); /* this._active_fill_path.lineTo(x+width, y); this._active_fill_path.lineTo(x+width, y+height); this._active_fill_path.lineTo(x, y+height); this._active_fill_path.lineTo(x, y); */ var w = width; var h = height; var t = 0; if (this._active_stroke_path != null) { t = this._active_stroke_path.style.thickness / 2; w -= this._active_stroke_path.style.thickness; h -= this._active_stroke_path.style.thickness; } GraphicsFactoryHelper.addTriangle(x + t, y + h + t, x + t, y + t, x + w + t, y + t, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + t, y + h + t, x + t + w, y + t, x + w + t, y + h + t, 0, this._active_fill_path.verts, false); } if (this._active_stroke_path != null) { this._active_stroke_path.moveTo(x, y); //var t:number=(<GraphicsStrokeStyle>this._active_stroke_path.style).thickness/2; /* eslint-disable */ // todo: respect Jointstyle here (?) /* GraphicsFactoryHelper.addTriangle(x-t, y+height+t, x-t, y-t, x+t, y+t, 0, this._active_stroke_path.verts, false); GraphicsFactoryHelper.addTriangle(x-t, y+height+t, x+t, y+height-t, x+t, y+t, 0, this._active_stroke_path.verts, false); GraphicsFactoryHelper.addTriangle(x-t, y-t, x+width+t, y-t, x+t, y+t, 0, this._active_stroke_path.verts, false); GraphicsFactoryHelper.addTriangle(x+t, y+t, x+width+t, y-t, x+width-t, y+t, 0, this._active_stroke_path.verts, false); GraphicsFactoryHelper.addTriangle(x+width-t, y+height-t, x+width-t, y+t, x+width+t, y+height+t, 0, this._active_stroke_path.verts, false); GraphicsFactoryHelper.addTriangle(x+width+t, y+height+t, x+width+t, y-t, x+width-t, y+t, 0, this._active_stroke_path.verts, false); GraphicsFactoryHelper.addTriangle(x-t, y+height+t, x+width+t, y+height+t, x+t, y+height-t, 0, this._active_stroke_path.verts, false); GraphicsFactoryHelper.addTriangle(x+t, y+height-t, x+width+t, y+height+t, x+width-t, y+height-t, 0, this._active_stroke_path.verts, false); */ /* eslint-enable */ this._active_stroke_path.lineTo(x + width, y); this._active_stroke_path.lineTo(x + width, y + height); this._active_stroke_path.lineTo(x, y + height); this._active_stroke_path.lineTo(x, y); } this.invalidate(); }; /** * Draws a rounded rectangle. Set the line style, fill, or both before you * call the <code>drawRoundRect()</code> method, by calling the * <code>linestyle()</code>, <code>lineGradientStyle()</code>, * <code>beginFill()</code>, <code>beginGradientFill()</code>, or * <code>beginBitmapFill()</code> method. * * @param x A number indicating the horizontal position relative * to the registration point of the parent display * object(in pixels). * @param y A number indicating the vertical position relative to * the registration point of the parent display object * (in pixels). * @param width The width of the round rectangle(in pixels). * @param height The height of the round rectangle(in pixels). * @param ellipseWidth The width of the ellipse used to draw the rounded * corners(in pixels). * @param ellipseHeight The height of the ellipse used to draw the rounded * corners(in pixels). Optional; if no value is * specified, the default value matches that provided * for the <code>ellipseWidth</code> parameter. * @throws ArgumentError If the <code>width</code>, <code>height</code>, * <code>ellipseWidth</code> or * <code>ellipseHeight</code> parameters are not a * number(<code>Number.NaN</code>). */ Graphics.prototype.drawRoundRect = function (x, y, width, height, ellipseWidth, ellipseHeight) { if (ellipseHeight === void 0) { ellipseHeight = NaN; } this._drawingDirty = true; if (isNaN(ellipseHeight)) { ellipseHeight = ellipseWidth; } var w = width; var h = height; var ew = ellipseWidth / 2; var eh = ellipseHeight / 2; var t = 0; if (this._active_fill_path != null) { this._active_fill_path.moveTo(x, y); if (this._active_stroke_path != null) { t = this._active_stroke_path.style.thickness / 2; w -= this._active_stroke_path.style.thickness; h -= this._active_stroke_path.style.thickness; } /* eslint-disable */ GraphicsFactoryHelper.addTriangle(x + t, y + h - eh, x + t, y + eh, x + w - t, y + eh, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + t, y + h - eh, x + w - t, y + eh, x + w - t, y + h - eh, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + ew, y + t, x + w - ew, y + eh, x + ew, y + eh, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + ew, y + t, x + w - ew, y + t, x + w - ew, y + eh, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + ew, y + h - eh, x + w - ew, y + h - t, x + ew, y + h - t, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + ew, y + h - eh, x + w - ew, y + h - eh, x + w - ew, y + h - t, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.drawElipse(x + ew, y + eh, ew - t, eh - t, this._active_fill_path.verts, 180, 270, 5, false); GraphicsFactoryHelper.drawElipse(x + w - ew, y + eh, ew - t, eh - t, this._active_fill_path.verts, 270, 360, 5, false); GraphicsFactoryHelper.drawElipse(x + w - ew, y + h - eh, ew - t, eh - t, this._active_fill_path.verts, 0, 90, 5, false); GraphicsFactoryHelper.drawElipse(x + ew, y + h - eh, ew - t, eh - t, this._active_fill_path.verts, 90, 180, 5, false); /* eslint-enable */ } if (this._active_stroke_path != null) { this._active_stroke_path.moveTo(x + ew, y); /* eslint-disable */ this._active_stroke_path.lineTo(x + w - ew, y); GraphicsFactoryHelper.drawElipseStrokes(x + w - ew, y + eh, ew, eh, this._active_stroke_path, 270, 360, 2); this._active_stroke_path.lineTo(x + w, y + h - eh); GraphicsFactoryHelper.drawElipseStrokes(x + w - ew, y + h - eh, ew, eh, this._active_stroke_path, 0, 90, 2); this._active_stroke_path.lineTo(x + ew, y + h); GraphicsFactoryHelper.drawElipseStrokes(x + ew, y + h - eh, ew, eh, this._active_stroke_path, 90, 180, 2); this._active_stroke_path.lineTo(x, y + eh); GraphicsFactoryHelper.drawElipseStrokes(x + ew, y + eh, ew, eh, this._active_stroke_path, 180, 270, 2); /* eslint-enable */ } this.invalidate(); }; Graphics.prototype.drawRoundRectComplex = function (x, y, width, height, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius) { var w = width; var h = height; var tl = topLeftRadius; var tr = topRightRadius; var bl = bottomLeftRadius; var br = bottomRightRadius; this._drawingDirty = true; var t = 0; if (this._active_fill_path != null) { this._active_fill_path.moveTo(x, y); if (this._active_stroke_path != null) { t = this._active_stroke_path.style.thickness / 2; w -= this._active_stroke_path.style.thickness; h -= this._active_stroke_path.style.thickness; } /* eslint-disable */ GraphicsFactoryHelper.addTriangle(x + tl, y + tl, x + w - tr, y + tr, x + w - br, y + h - br, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + tl, y + tl, x + w - br, y + h - br, x + bl, y + h - bl, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + t, y + tl, x + tl, y + tl, x + t, y + h - bl, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + tl, y + tl, x + t, y + h - bl, x + bl, y + h - bl, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + tl, y + t, x + tl, y + tl, x + w - tr, y + t, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + tl, y + tl, x + w - tr, y + tr, x + w - tr, y + t, 0, this._active_fill_path.verts, false); GraphicsFactoryHelper.addTriangle(x + w - t, y + tr, x + w - tr, y + tr, x + w - t, y + h - br, 0, this._active_fill_path.verts, false);