1 line
12 KiB
Plaintext
1 line
12 KiB
Plaintext
|
|
{"version":3,"file":"PencilBrush.mjs","names":[],"sources":["../../../src/brushes/PencilBrush.ts"],"sourcesContent":["import type { ModifierKey, TEvent } from '../EventTypeDefs';\nimport type { Point } from '../Point';\nimport { Shadow } from '../Shadow';\nimport { Path } from '../shapes/Path';\nimport { getSmoothPathFromPoints, joinPath } from '../util/path';\nimport type { Canvas } from '../canvas/Canvas';\nimport { BaseBrush } from './BaseBrush';\nimport type { TSimplePathData } from '../util/path/typedefs';\n\n/**\n * @private\n * @param {TSimplePathData} pathData SVG path commands\n * @returns {boolean}\n */\nfunction isEmptySVGPath(pathData: TSimplePathData): boolean {\n return joinPath(pathData) === 'M 0 0 Q 0 0 0 0 L 0 0';\n}\n\nexport class PencilBrush extends BaseBrush {\n /**\n * Discard points that are less than `decimate` pixel distant from each other\n * @type Number\n * @default 0.4\n */\n decimate = 0.4;\n\n /**\n * Draws a straight line between last recorded point to current pointer\n * Used for `shift` functionality\n *\n * @type boolean\n * @default false\n */\n drawStraightLine = false;\n\n /**\n * The event modifier key that makes the brush draw a straight line.\n * If `null` or 'none' or any other string that is not a modifier key the feature is disabled.\n * @type {ModifierKey | undefined | null}\n */\n straightLineKey: ModifierKey | undefined | null = 'shiftKey';\n\n declare protected _points: Point[];\n declare protected _hasStraightLine: boolean;\n declare protected oldEnd?: Point;\n\n constructor(canvas: Canvas) {\n super(canvas);\n this._points = [];\n this._hasStraightLine = false;\n }\n\n needsFullRender() {\n return super.needsFullRender() || this._hasStraightLine;\n }\n\n static drawSegment(ctx: CanvasRenderingContext2D, p1: Point, p2: Point) {\n const midPoint = p1.midPointFrom(p2);\n ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y);\n return midPoint;\n }\n\n /**\n * Invoked on mouse down\n * @param {Point} pointer\n */\n onMouseDown(pointer: Point, { e }: TEvent) {\n if (!this.canvas._isMainEvent(e)) {\n return;\n }\n this.drawStraightLine = !!this.straightLineKey && e[this.straightLineKey];\n this._prepareForDrawing(pointer);\n // capture coordinates immediately\n // this allows to draw dots (when movement never occurs)\n this._addPoint(pointer);\n this._render();\n }\n\n /**\n * Invoked on mouse move\n * @param {Point} pointer\n */\n onMouseMove(pointer: Point, { e }: TEvent) {\n if (!this.canvas._isMainEvent(e)) {\n return;\n }\n this.drawStraightLine = !!this.straightLineKey && e[this.straightLineKey];\n if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n return;\n }\n if (this._addPoint(pointer) && this._points.length > 1) {\n if (this.needsFullRender()) {\n // redraw curve\n // clear top canvas\n this.canvas.clearContext(this.canvas.contextTop);\n this._render();\n } else {\n const points = this._points,\n length = points.length,\n ctx = this.canvas.contextTop;\n // draw the curve update\n this._saveAndTransform(ctx);\n if (this.oldEnd) {\n ctx.beginPath();\n ctx.moveTo(this.oldEnd.x, this.oldEnd.y);\n }\n this.oldEnd = PencilBrush.drawSegment(\n ctx,\n points[length - 2],\n points[length - 1],\n );\n ctx.stroke();\n ctx.restore();\n }\n }\n }\n\n /**\n * Invoked on mouse up\n */\n onMouseUp({ e }: TEvent) {\n if (!this.canvas._isMainEvent(e)) {\n return true;\n }\n this.drawStraightLine = false;\n this.oldEnd = undefined;\n this._finalizeAndAddPath();\n\n return false;\n }\n\n /**\n * @private\n * @param {Point} pointer Actual mouse position related to the canvas.\n */\n _prepareForDrawing(pointer: Point) {\n this._reset();\n this._addPoint(pointer);\n this.canvas.contextTop.moveTo(pointer.x, p
|