"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Shape = exports.shapes = void 0; const Global_1 = require("./Global"); const Util_1 = require("./Util"); const Factory_1 = require("./Factory"); const Node_1 = require("./Node"); const Validators_1 = require("./Validators"); const Global_2 = require("./Global"); const PointerEvents = require("./PointerEvents"); var HAS_SHADOW = 'hasShadow'; var SHADOW_RGBA = 'shadowRGBA'; var patternImage = 'patternImage'; var linearGradient = 'linearGradient'; var radialGradient = 'radialGradient'; let dummyContext; function getDummyContext() { if (dummyContext) { return dummyContext; } dummyContext = Util_1.Util.createCanvasElement().getContext('2d'); return dummyContext; } exports.shapes = {}; function _fillFunc(context) { const fillRule = this.attrs.fillRule; if (fillRule) { context.fill(fillRule); } else { context.fill(); } } function _strokeFunc(context) { context.stroke(); } function _fillFuncHit(context) { const fillRule = this.attrs.fillRule; if (fillRule) { context.fill(fillRule); } else { context.fill(); } } function _strokeFuncHit(context) { context.stroke(); } function _clearHasShadowCache() { this._clearCache(HAS_SHADOW); } function _clearGetShadowRGBACache() { this._clearCache(SHADOW_RGBA); } function _clearFillPatternCache() { this._clearCache(patternImage); } function _clearLinearGradientCache() { this._clearCache(linearGradient); } function _clearRadialGradientCache() { this._clearCache(radialGradient); } class Shape extends Node_1.Node { constructor(config) { super(config); let key; while (true) { key = Util_1.Util.getRandomColor(); if (key && !(key in exports.shapes)) { break; } } this.colorKey = key; exports.shapes[key] = this; } getContext() { Util_1.Util.warn('shape.getContext() method is deprecated. Please do not use it.'); return this.getLayer().getContext(); } getCanvas() { Util_1.Util.warn('shape.getCanvas() method is deprecated. Please do not use it.'); return this.getLayer().getCanvas(); } getSceneFunc() { return this.attrs.sceneFunc || this['_sceneFunc']; } getHitFunc() { return this.attrs.hitFunc || this['_hitFunc']; } hasShadow() { return this._getCache(HAS_SHADOW, this._hasShadow); } _hasShadow() { return (this.shadowEnabled() && this.shadowOpacity() !== 0 && !!(this.shadowColor() || this.shadowBlur() || this.shadowOffsetX() || this.shadowOffsetY())); } _getFillPattern() { return this._getCache(patternImage, this.__getFillPattern); } __getFillPattern() { if (this.fillPatternImage()) { var ctx = getDummyContext(); const pattern = ctx.createPattern(this.fillPatternImage(), this.fillPatternRepeat() || 'repeat'); if (pattern && pattern.setTransform) { const tr = new Util_1.Transform(); tr.translate(this.fillPatternX(), this.fillPatternY()); tr.rotate(Global_1.Konva.getAngle(this.fillPatternRotation())); tr.scale(this.fillPatternScaleX(), this.fillPatternScaleY()); tr.translate(-1 * this.fillPatternOffsetX(), -1 * this.fillPatternOffsetY()); const m = tr.getMatrix(); const matrix = typeof DOMMatrix === 'undefined' ? { a: m[0], b: m[1], c: m[2], d: m[3], e: m[4], f: m[5], } : new DOMMatrix(m); pattern.setTransform(matrix); } return pattern; } } _getLinearGradient() { return this._getCache(linearGradient, this.__getLinearGradient); } __getLinearGradient() { var colorStops = this.fillLinearGradientColorStops(); if (colorStops) { var ctx = getDummyContext(); var start = this.fillLinearGradientStartPoint(); var end = this.fillLinearGradientEndPoint(); var grd = ctx.createLinearGradient(start.x, start.y, end.x, end.y); for (var n = 0; n < colorStops.length; n += 2) { grd.addColorStop(colorStops[n], colorStops[n + 1]); } return grd; } } _getRadialGradient() { return this._getCache(radialGradient, this.__getRadialGradient); } __getRadialGradient() { var colorStops = this.fillRadialGradientColorStops(); if (colorStops) { var ctx = getDummyContext(); var start = this.fillRadialGradientStartPoint(); var end = this.fillRadialGradientEndPoint(); var grd = ctx.createRadialGradient(start.x, start.y, this.fillRadialGradientStartRadius(), end.x, end.y, this.fillRadialGradientEndRadius()); for (var n = 0; n < colorStops.length; n += 2) { grd.addColorStop(colorStops[n], colorStops[n + 1]); } return grd; } } getShadowRGBA() { return this._getCache(SHADOW_RGBA, this._getShadowRGBA); } _getShadowRGBA() { if (!this.hasShadow()) { return; } var rgba = Util_1.Util.colorToRGBA(this.shadowColor()); if (rgba) { return ('rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + rgba.a * (this.shadowOpacity() || 1) + ')'); } } hasFill() { return this._calculate('hasFill', [ 'fillEnabled', 'fill', 'fillPatternImage', 'fillLinearGradientColorStops', 'fillRadialGradientColorStops', ], () => { return (this.fillEnabled() && !!(this.fill() || this.fillPatternImage() || this.fillLinearGradientColorStops() || this.fillRadialGradientColorStops())); }); } hasStroke() { return this._calculate('hasStroke', [ 'strokeEnabled', 'strokeWidth', 'stroke', 'strokeLinearGradientColorStops', ], () => { return (this.strokeEnabled() && this.strokeWidth() && !!(this.stroke() || this.strokeLinearGradientColorStops())); }); } hasHitStroke() { const width = this.hitStrokeWidth(); if (width === 'auto') { return this.hasStroke(); } return this.strokeEnabled() && !!width; } intersects(point) { var stage = this.getStage(); if (!stage) { return false; } const bufferHitCanvas = stage.bufferHitCanvas; bufferHitCanvas.getContext().clear(); this.drawHit(bufferHitCanvas, undefined, true); const p = bufferHitCanvas.context.getImageData(Math.round(point.x), Math.round(point.y), 1, 1).data; return p[3] > 0; } destroy() { Node_1.Node.prototype.destroy.call(this); delete exports.shapes[this.colorKey]; delete this.colorKey; return this; } _useBufferCanvas(forceFill) { var _a; const perfectDrawEnabled = (_a = this.attrs.perfectDrawEnabled) !== null && _a !== void 0 ? _a : true; if (!perfectDrawEnabled) { return false; } const hasFill = forceFill || this.hasFill(); const hasStroke = this.hasStroke(); const isTransparent = this.getAbsoluteOpacity() !== 1; if (hasFill && hasStroke && isTransparent) { return true; } const hasShadow = this.hasShadow(); const strokeForShadow = this.shadowForStrokeEnabled(); if (hasFill && hasStroke && hasShadow && strokeForShadow) { return true; } return false; } setStrokeHitEnabled(val) { Util_1.Util.warn('strokeHitEnabled property is deprecated. Please use hitStrokeWidth instead.'); if (val) { this.hitStrokeWidth('auto'); } else { this.hitStrokeWidth(0); } } getStrokeHitEnabled() { if (this.hitStrokeWidth() === 0) { return false; } else { return true; } } getSelfRect() { var size = this.size(); return { x: this._centroid ? -size.width / 2 : 0, y: this._centroid ? -size.height / 2 : 0, width: size.width, height: size.height, }; } getClientRect(config = {}) { let hasCachedParent = false; let parent = this.getParent(); while (parent) { if (parent.isCached()) { hasCachedParent = true; break; } parent = parent.getParent(); } const skipTransform = config.skipTransform; const relativeTo = config.relativeTo || (hasCachedParent && this.getStage()) || undefined; const fillRect = this.getSelfRect(); const applyStroke = !config.skipStroke && this.hasStroke(); const strokeWidth = (applyStroke && this.strokeWidth()) || 0; const fillAndStrokeWidth = fillRect.width + strokeWidth; const fillAndStrokeHeight = fillRect.height + strokeWidth; const applyShadow = !config.skipShadow && this.hasShadow(); const shadowOffsetX = applyShadow ? this.shadowOffsetX() : 0; const shadowOffsetY = applyShadow ? this.shadowOffsetY() : 0; const preWidth = fillAndStrokeWidth + Math.abs(shadowOffsetX); const preHeight = fillAndStrokeHeight + Math.abs(shadowOffsetY); const blurRadius = (applyShadow && this.shadowBlur()) || 0; const width = preWidth + blurRadius * 2; const height = preHeight + blurRadius * 2; const rect = { width: width, height: height, x: -(strokeWidth / 2 + blurRadius) + Math.min(shadowOffsetX, 0) + fillRect.x, y: -(strokeWidth / 2 + blurRadius) + Math.min(shadowOffsetY, 0) + fillRect.y, }; if (!skipTransform) { return this._transformedRect(rect, relativeTo); } return rect; } drawScene(can, top, bufferCanvas) { var layer = this.getLayer(); var canvas = can || layer.getCanvas(), context = canvas.getContext(), cachedCanvas = this._getCanvasCache(), drawFunc = this.getSceneFunc(), hasShadow = this.hasShadow(), stage, bufferContext; var skipBuffer = canvas.isCache; var cachingSelf = top === this; if (!this.isVisible() && !cachingSelf) { return this; } if (cachedCanvas) { context.save(); var m = this.getAbsoluteTransform(top).getMatrix(); context.transform(m[0], m[1], m[2], m[3], m[4], m[5]); this._drawCachedSceneCanvas(context); context.restore(); return this; } if (!drawFunc) { return this; } context.save(); if (this._useBufferCanvas() && !skipBuffer) { stage = this.getStage(); const bc = bufferCanvas || stage.bufferCanvas; bufferContext = bc.getContext(); bufferContext.clear(); bufferContext.save(); bufferContext._applyLineJoin(this); var o = this.getAbsoluteTransform(top).getMatrix(); bufferContext.transform(o[0], o[1], o[2], o[3], o[4], o[5]); drawFunc.call(this, bufferContext, this); bufferContext.restore(); var ratio = bc.pixelRatio; if (hasShadow) { context._applyShadow(this); } context._applyOpacity(this); context._applyGlobalCompositeOperation(this); context.drawImage(bc._canvas, 0, 0, bc.width / ratio, bc.height / ratio); } else { context._applyLineJoin(this); if (!cachingSelf) { var o = this.getAbsoluteTransform(top).getMatrix(); context.transform(o[0], o[1], o[2], o[3], o[4], o[5]); context._applyOpacity(this); context._applyGlobalCompositeOperation(this); } if (hasShadow) { context._applyShadow(this); } drawFunc.call(this, context, this); } context.restore(); return this; } drawHit(can, top, skipDragCheck = false) { if (!this.shouldDrawHit(top, skipDragCheck)) { return this; } var layer = this.getLayer(), canvas = can || layer.hitCanvas, context = canvas && canvas.getContext(), drawFunc = this.hitFunc() || this.sceneFunc(), cachedCanvas = this._getCanvasCache(), cachedHitCanvas = cachedCanvas && cachedCanvas.hit; if (!this.colorKey) { Util_1.Util.warn('Looks like your canvas has a destroyed shape in it. Do not reuse shape after you destroyed it. If you want to reuse shape you should call remove() instead of destroy()'); } if (cachedHitCanvas) { context.save(); var m = this.getAbsoluteTransform(top).getMatrix(); context.transform(m[0], m[1], m[2], m[3], m[4], m[5]); this._drawCachedHitCanvas(context); context.restore(); return this; } if (!drawFunc) { return this; } context.save(); context._applyLineJoin(this); const selfCache = this === top; if (!selfCache) { var o = this.getAbsoluteTransform(top).getMatrix(); context.transform(o[0], o[1], o[2], o[3], o[4], o[5]); } drawFunc.call(this, context, this); context.restore(); return this; } drawHitFromCache(alphaThreshold = 0) { var cachedCanvas = this._getCanvasCache(), sceneCanvas = this._getCachedSceneCanvas(), hitCanvas = cachedCanvas.hit, hitContext = hitCanvas.getContext(), hitWidth = hitCanvas.getWidth(), hitHeight = hitCanvas.getHeight(), hitImageData, hitData, len, rgbColorKey, i, alpha; hitContext.clear(); hitContext.drawImage(sceneCanvas._canvas, 0, 0, hitWidth, hitHeight); try { hitImageData = hitContext.getImageData(0, 0, hitWidth, hitHeight); hitData = hitImageData.data; len = hitData.length; rgbColorKey = Util_1.Util._hexToRgb(this.colorKey); for (i = 0; i < len; i += 4) { alpha = hitData[i + 3]; if (alpha > alphaThreshold) { hitData[i] = rgbColorKey.r; hitData[i + 1] = rgbColorKey.g; hitData[i + 2] = rgbColorKey.b; hitData[i + 3] = 255; } else { hitData[i + 3] = 0; } } hitContext.putImageData(hitImageData, 0, 0); } catch (e) { Util_1.Util.error('Unable to draw hit graph from cached scene canvas. ' + e.message); } return this; } hasPointerCapture(pointerId) { return PointerEvents.hasPointerCapture(pointerId, this); } setPointerCapture(pointerId) { PointerEvents.setPointerCapture(pointerId, this); } releaseCapture(pointerId) { PointerEvents.releaseCapture(pointerId, this); } } exports.Shape = Shape; Shape.prototype._fillFunc = _fillFunc; Shape.prototype._strokeFunc = _strokeFunc; Shape.prototype._fillFuncHit = _fillFuncHit; Shape.prototype._strokeFuncHit = _strokeFuncHit; Shape.prototype._centroid = false; Shape.prototype.nodeType = 'Shape'; (0, Global_2._registerNode)(Shape); Shape.prototype.eventListeners = {}; Shape.prototype.on.call(Shape.prototype, 'shadowColorChange.konva shadowBlurChange.konva shadowOffsetChange.konva shadowOpacityChange.konva shadowEnabledChange.konva', _clearHasShadowCache); Shape.prototype.on.call(Shape.prototype, 'shadowColorChange.konva shadowOpacityChange.konva shadowEnabledChange.konva', _clearGetShadowRGBACache); Shape.prototype.on.call(Shape.prototype, 'fillPriorityChange.konva fillPatternImageChange.konva fillPatternRepeatChange.konva fillPatternScaleXChange.konva fillPatternScaleYChange.konva fillPatternOffsetXChange.konva fillPatternOffsetYChange.konva fillPatternXChange.konva fillPatternYChange.konva fillPatternRotationChange.konva', _clearFillPatternCache); Shape.prototype.on.call(Shape.prototype, 'fillPriorityChange.konva fillLinearGradientColorStopsChange.konva fillLinearGradientStartPointXChange.konva fillLinearGradientStartPointYChange.konva fillLinearGradientEndPointXChange.konva fillLinearGradientEndPointYChange.konva', _clearLinearGradientCache); Shape.prototype.on.call(Shape.prototype, 'fillPriorityChange.konva fillRadialGradientColorStopsChange.konva fillRadialGradientStartPointXChange.konva fillRadialGradientStartPointYChange.konva fillRadialGradientEndPointXChange.konva fillRadialGradientEndPointYChange.konva fillRadialGradientStartRadiusChange.konva fillRadialGradientEndRadiusChange.konva', _clearRadialGradientCache); Factory_1.Factory.addGetterSetter(Shape, 'stroke', undefined, (0, Validators_1.getStringOrGradientValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'strokeWidth', 2, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'fillAfterStrokeEnabled', false); Factory_1.Factory.addGetterSetter(Shape, 'hitStrokeWidth', 'auto', (0, Validators_1.getNumberOrAutoValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'strokeHitEnabled', true, (0, Validators_1.getBooleanValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'perfectDrawEnabled', true, (0, Validators_1.getBooleanValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'shadowForStrokeEnabled', true, (0, Validators_1.getBooleanValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'lineJoin'); Factory_1.Factory.addGetterSetter(Shape, 'lineCap'); Factory_1.Factory.addGetterSetter(Shape, 'sceneFunc'); Factory_1.Factory.addGetterSetter(Shape, 'hitFunc'); Factory_1.Factory.addGetterSetter(Shape, 'dash'); Factory_1.Factory.addGetterSetter(Shape, 'dashOffset', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'shadowColor', undefined, (0, Validators_1.getStringValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'shadowBlur', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'shadowOpacity', 1, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addComponentsGetterSetter(Shape, 'shadowOffset', ['x', 'y']); Factory_1.Factory.addGetterSetter(Shape, 'shadowOffsetX', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'shadowOffsetY', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'fillPatternImage'); Factory_1.Factory.addGetterSetter(Shape, 'fill', undefined, (0, Validators_1.getStringOrGradientValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'fillPatternX', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'fillPatternY', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'fillLinearGradientColorStops'); Factory_1.Factory.addGetterSetter(Shape, 'strokeLinearGradientColorStops'); Factory_1.Factory.addGetterSetter(Shape, 'fillRadialGradientStartRadius', 0); Factory_1.Factory.addGetterSetter(Shape, 'fillRadialGradientEndRadius', 0); Factory_1.Factory.addGetterSetter(Shape, 'fillRadialGradientColorStops'); Factory_1.Factory.addGetterSetter(Shape, 'fillPatternRepeat', 'repeat'); Factory_1.Factory.addGetterSetter(Shape, 'fillEnabled', true); Factory_1.Factory.addGetterSetter(Shape, 'strokeEnabled', true); Factory_1.Factory.addGetterSetter(Shape, 'shadowEnabled', true); Factory_1.Factory.addGetterSetter(Shape, 'dashEnabled', true); Factory_1.Factory.addGetterSetter(Shape, 'strokeScaleEnabled', true); Factory_1.Factory.addGetterSetter(Shape, 'fillPriority', 'color'); Factory_1.Factory.addComponentsGetterSetter(Shape, 'fillPatternOffset', ['x', 'y']); Factory_1.Factory.addGetterSetter(Shape, 'fillPatternOffsetX', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'fillPatternOffsetY', 0, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addComponentsGetterSetter(Shape, 'fillPatternScale', ['x', 'y']); Factory_1.Factory.addGetterSetter(Shape, 'fillPatternScaleX', 1, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addGetterSetter(Shape, 'fillPatternScaleY', 1, (0, Validators_1.getNumberValidator)()); Factory_1.Factory.addComponentsGetterSetter(Shape, 'fillLinearGradientStartPoint', [ 'x', 'y', ]); Factory_1.Factory.addComponentsGetterSetter(Shape, 'strokeLinearGradientStartPoint', [ 'x', 'y', ]); Factory_1.Factory.addGetterSetter(Shape, 'fillLinearGradientStartPointX', 0); Factory_1.Factory.addGetterSetter(Shape, 'strokeLinearGradientStartPointX', 0); Factory_1.Factory.addGetterSetter(Shape, 'fillLinearGradientStartPointY', 0); Factory_1.Factory.addGetterSetter(Shape, 'strokeLinearGradientStartPointY', 0); Factory_1.Factory.addComponentsGetterSetter(Shape, 'fillLinearGradientEndPoint', [ 'x', 'y', ]); Factory_1.Factory.addComponentsGetterSetter(Shape, 'strokeLinearGradientEndPoint', [ 'x', 'y', ]); Factory_1.Factory.addGetterSetter(Shape, 'fillLinearGradientEndPointX', 0); Factory_1.Factory.addGetterSetter(Shape, 'strokeLinearGradientEndPointX', 0); Factory_1.Factory.addGetterSetter(Shape, 'fillLinearGradientEndPointY', 0); Factory_1.Factory.addGetterSetter(Shape, 'strokeLinearGradientEndPointY', 0); Factory_1.Factory.addComponentsGetterSetter(Shape, 'fillRadialGradientStartPoint', [ 'x', 'y', ]); Factory_1.Factory.addGetterSetter(Shape, 'fillRadialGradientStartPointX', 0); Factory_1.Factory.addGetterSetter(Shape, 'fillRadialGradientStartPointY', 0); Factory_1.Factory.addComponentsGetterSetter(Shape, 'fillRadialGradientEndPoint', [ 'x', 'y', ]); Factory_1.Factory.addGetterSetter(Shape, 'fillRadialGradientEndPointX', 0); Factory_1.Factory.addGetterSetter(Shape, 'fillRadialGradientEndPointY', 0); Factory_1.Factory.addGetterSetter(Shape, 'fillPatternRotation', 0); Factory_1.Factory.addGetterSetter(Shape, 'fillRule', undefined, (0, Validators_1.getStringValidator)()); Factory_1.Factory.backCompat(Shape, { dashArray: 'dash', getDashArray: 'getDash', setDashArray: 'getDash', drawFunc: 'sceneFunc', getDrawFunc: 'getSceneFunc', setDrawFunc: 'setSceneFunc', drawHitFunc: 'hitFunc', getDrawHitFunc: 'getHitFunc', setDrawHitFunc: 'setHitFunc', });