{"version":3,"file":"SprayBrush.mjs","sources":["../../../src/brushes/SprayBrush.ts"],"sourcesContent":["import type { Point } from '../Point';\nimport { Group } from '../shapes/Group';\nimport { Shadow } from '../Shadow';\nimport { Rect } from '../shapes/Rect';\nimport { getRandomInt } from '../util/internals/getRandomInt';\nimport type { Canvas } from '../canvas/Canvas';\nimport { BaseBrush } from './BaseBrush';\nimport type { SprayBrushPoint } from './typedefs';\nimport { CENTER } from '../constants';\n\n/**\n *\n * @param rects\n * @returns\n */\nfunction getUniqueRects(rects: Rect[]) {\n  const uniqueRects: Record<string, boolean> = {};\n  const uniqueRectsArray: Rect[] = [];\n\n  for (let i = 0, key: string; i < rects.length; i++) {\n    key = `${rects[i].left}${rects[i].top}`;\n    if (!uniqueRects[key]) {\n      uniqueRects[key] = true;\n      uniqueRectsArray.push(rects[i]);\n    }\n  }\n\n  return uniqueRectsArray;\n}\n\nexport class SprayBrush extends BaseBrush {\n  /**\n   * Width of a spray\n   * @type Number\n   * @default\n   */\n  width = 10;\n\n  /**\n   * Density of a spray (number of dots per chunk)\n   * @type Number\n   * @default\n   */\n  density = 20;\n\n  /**\n   * Width of spray dots\n   * @type Number\n   * @default\n   */\n  dotWidth = 1;\n\n  /**\n   * Width variance of spray dots\n   * @type Number\n   * @default\n   */\n  dotWidthVariance = 1;\n\n  /**\n   * Whether opacity of a dot should be random\n   * @type Boolean\n   * @default\n   */\n  randomOpacity = false;\n\n  /**\n   * Whether overlapping dots (rectangles) should be removed (for performance reasons)\n   * @type Boolean\n   * @default\n   */\n  optimizeOverlapping = true;\n\n  private declare sprayChunks: SprayBrushPoint[][];\n\n  private declare sprayChunk: SprayBrushPoint[];\n\n  /**\n   * Constructor\n   * @param {Canvas} canvas\n   * @return {SprayBrush} Instance of a spray brush\n   */\n  constructor(canvas: Canvas) {\n    super(canvas);\n    this.sprayChunks = [];\n    this.sprayChunk = [];\n  }\n\n  /**\n   * Invoked on mouse down\n   * @param {Point} pointer\n   */\n  onMouseDown(pointer: Point) {\n    this.sprayChunks = [];\n    this.canvas.clearContext(this.canvas.contextTop);\n    this._setShadow();\n\n    this.addSprayChunk(pointer);\n    this.renderChunck(this.sprayChunk);\n  }\n\n  /**\n   * Invoked on mouse move\n   * @param {Point} pointer\n   */\n  onMouseMove(pointer: Point) {\n    if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {\n      return;\n    }\n    this.addSprayChunk(pointer);\n    this.renderChunck(this.sprayChunk);\n  }\n\n  /**\n   * Invoked on mouse up\n   */\n  onMouseUp() {\n    const originalRenderOnAddRemove = this.canvas.renderOnAddRemove;\n    this.canvas.renderOnAddRemove = false;\n\n    const rects: Rect[] = [];\n\n    for (let i = 0; i < this.sprayChunks.length; i++) {\n      const sprayChunk = this.sprayChunks[i];\n      for (let j = 0; j < sprayChunk.length; j++) {\n        const chunck = sprayChunk[j];\n        const rect = new Rect({\n          width: chunck.width,\n          height: chunck.width,\n          left: chunck.x + 1,\n          top: chunck.y + 1,\n          originX: CENTER,\n          originY: CENTER,\n          fill: this.color,\n        });\n        rects.push(rect);\n      }\n    }\n\n    const group = new Group(\n      this.optimizeOverlapping ? getUniqueRects(rects) : rects,\n      {\n        objectCaching: true,\n        subTargetCheck: false,\n        interactive: false,\n      },\n    );\n    this.shadow && group.set('shadow', new Shadow(this.shadow));\n    this.canvas.fire('before:path:created', { path: group });\n    this.canvas.add(group);\n    this.canvas.fire('path:created', { path: group });\n\n    this.canvas.clearContext(this.canvas.contextTop);\n    this._resetShadow();\n    this.canvas.renderOnAddRemove = originalRenderOnAddRemove;\n    this.canvas.requestRenderAll();\n  }\n\n  renderChunck(sprayChunck: SprayBrushPoint[]) {\n    const ctx = this.canvas.contextTop;\n    ctx.fillStyle = this.color;\n\n    this._saveAndTransform(ctx);\n\n    for (let i = 0; i < sprayChunck.length; i++) {\n      const point = sprayChunck[i];\n      ctx.globalAlpha = point.opacity;\n      ctx.fillRect(point.x, point.y, point.width, point.width);\n    }\n\n    ctx.restore();\n  }\n\n  /**\n   * Render all spray chunks\n   */\n  _render() {\n    const ctx = this.canvas.contextTop;\n    ctx.fillStyle = this.color;\n\n    this._saveAndTransform(ctx);\n\n    for (let i = 0; i < this.sprayChunks.length; i++) {\n      this.renderChunck(this.sprayChunks[i]);\n    }\n    ctx.restore();\n  }\n\n  /**\n   * @param {Point} pointer\n   */\n  addSprayChunk(pointer: Point) {\n    this.sprayChunk = [];\n    const radius = this.width / 2;\n\n    for (let i = 0; i < this.density; i++) {\n      this.sprayChunk.push({\n        x: getRandomInt(pointer.x - radius, pointer.x + radius),\n        y: getRandomInt(pointer.y - radius, pointer.y + radius),\n        width: this.dotWidthVariance\n          ? getRandomInt(\n              // bottom clamp width to 1\n              Math.max(1, this.dotWidth - this.dotWidthVariance),\n              this.dotWidth + this.dotWidthVariance,\n            )\n          : this.dotWidth,\n        opacity: this.randomOpacity ? getRandomInt(0, 100) / 100 : 1,\n      });\n    }\n\n    this.sprayChunks.push(this.sprayChunk);\n  }\n}\n"],"names":["getUniqueRects","rects","uniqueRects","uniqueRectsArray","i","key","length","concat","left","top","push","SprayBrush","BaseBrush","constructor","canvas","_defineProperty","sprayChunks","sprayChunk","onMouseDown","pointer","clearContext","contextTop","_setShadow","addSprayChunk","renderChunck","onMouseMove","limitedToCanvasSize","_isOutSideCanvas","onMouseUp","originalRenderOnAddRemove","renderOnAddRemove","j","chunck","rect","Rect","width","height","x","y","originX","CENTER","originY","fill","color","group","Group","optimizeOverlapping","objectCaching","subTargetCheck","interactive","shadow","set","Shadow","fire","path","add","_resetShadow","requestRenderAll","sprayChunck","ctx","fillStyle","_saveAndTransform","point","globalAlpha","opacity","fillRect","restore","_render","radius","density","getRandomInt","dotWidthVariance","Math","max","dotWidth","randomOpacity"],"mappings":"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"}