{"version":3,"file":"Shadow.min.mjs","names":[],"sources":["../../src/Shadow.ts"],"sourcesContent":["import { classRegistry } from './ClassRegistry';\nimport { Color } from './color/Color';\nimport { config } from './config';\nimport { reNum } from './parser/constants';\nimport { Point } from './Point';\nimport type { FabricObject } from './shapes/Object/FabricObject';\nimport type { TClassProperties } from './typedefs';\nimport { uid } from './util/internals/uid';\nimport { escapeXml } from './util/lang_string';\nimport { pickBy } from './util/misc/pick';\nimport { degreesToRadians } from './util/misc/radiansDegreesConversion';\nimport { toFixed } from './util/misc/toFixed';\nimport { rotateVector } from './util/misc/vectors';\n\n/**\n   * Regex matching shadow offsetX, offsetY and blur (ex: \"2px 2px 10px rgba(0,0,0,0.2)\", \"rgb(0,255,0) 2px 2px\")\n   * - (?:\\s|^): This part captures either a whitespace character (\\s) or the beginning of a line (^). It's non-capturing (due to (?:...)), meaning it doesn't create a capturing group.\n   * - (-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?: This captures the first component of the shadow, which is the horizontal offset. Breaking it down:\n   *   - (-?\\d+): Captures an optional minus sign followed by one or more digits (integer part of the number).\n   *   - (?:\\.\\d*)?: Optionally captures a decimal point followed by zero or more digits (decimal part of the number).\n   *   - (?:px)?: Optionally captures the \"px\" unit.\n   *   - (?:\\s?|$): Captures either an optional whitespace or the end of the line. This whole part is wrapped in a non-capturing group and marked as optional with ?.\n   * - (-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?: Similar to the previous step, this captures the vertical offset.\n\n(\\d+(?:\\.\\d*)?(?:px)?)?: This captures the blur radius. It's similar to the horizontal offset but without the optional minus sign.\n\n(?:\\s+(-?\\d+(?:\\.\\d*)?(?:px)?(?:\\s?|$))?){0,1}: This captures an optional part for the color. It allows for whitespace followed by a component with an optional minus sign, digits, decimal point, and \"px\" unit.\n\n(?:$|\\s): This captures either the end of the line or a whitespace character. It ensures that the match ends either at the end of the string or with a whitespace character.\n   */\n\nconst shadowOffsetRegex = '(-?\\\\d+(?:\\\\.\\\\d*)?(?:px)?(?:\\\\s?|$))?';\n\nconst reOffsetsAndBlur = new RegExp(\n  '(?:\\\\s|^)' +\n    shadowOffsetRegex +\n    shadowOffsetRegex +\n    '(' +\n    reNum +\n    '?(?:px)?)?(?:\\\\s?|$)(?:$|\\\\s)',\n);\n\nexport const shadowDefaultValues: Partial<TClassProperties<Shadow>> = {\n  color: 'rgb(0,0,0)',\n  blur: 0,\n  offsetX: 0,\n  offsetY: 0,\n  affectStroke: false,\n  includeDefaultValues: true,\n  nonScaling: false,\n};\n\nexport type SerializedShadowOptions = {\n  color: string;\n  blur: number;\n  offsetX: number;\n  offsetY: number;\n  affectStroke: boolean;\n  nonScaling: boolean;\n  type: string;\n};\n\nexport class Shadow {\n  /**\n   * Shadow color\n   * @type String\n   */\n  declare color: string;\n\n  /**\n   * Shadow blur\n   * @type Number\n   */\n  declare blur: number;\n\n  /**\n   * Shadow horizontal offset\n   * @type Number\n   */\n  declare offsetX: number;\n\n  /**\n   * Shadow vertical offset\n   * @type Number\n   */\n  declare offsetY: number;\n\n  /**\n   * Whether the shadow should affect stroke operations\n   * @type Boolean\n   */\n  declare affectStroke: boolean;\n\n  /**\n   * Indicates whether toObject should include default values\n   * @type Boolean\n   */\n  declare includeDefaultValues: boolean;\n\n  /**\n   * When `false`, the shadow will scale with the object.\n   * When `true`, the shadow's offsetX, offsetY, and blur will not be affected by the object's scale.\n   * default to false\n   * @type Boolean\n   */\n  declare nonScaling: boolean;\n\n  declare id: number | string;\n\n  static ownDefaults = shadowDefaultValues;\n\n  static type = 'shadow';\n\n  /**\n   * @see {@link http://fabric5.fabricjs.com/shadows|Shadow demo}\n   * @param {Object|String} [options] Options object with any of color, blur, offsetX, offsetY properties or string (e.g. \"rgba(0,0,0,0.2) 2px 2px 10px\")\n   */\n  constructor(options?: Partial<TClassProperties<Shadow>>);\n  constructor(svgAttribute: string);\n  constructor(arg0: string | Partial<TClassProperties<Shadow>> = {}) {\n    const options: Partial<TClassProperties<Shadow>> =\n      typeof arg0 === 'string' ? Shadow.parseShadow(arg0) : arg0;\n    Object.assign(this, Shadow.ownDefaults, options);\n    this.id = uid();\n  }\n\n  /**\n   * @param {String} value Shadow value to parse\n   * @return {Object} Shadow object with color, offsetX, offsetY and blur\n   */\n  static parseShadow(value: string) {\n    const shadowStr = value.trim(),\n      [, offsetX = 0, offsetY = 0, blur = 0] = (\n        reOffsetsAndBlur.exec(shadowStr) || []\n      ).map((value) => parseFloat(value) || 0),\n      color = (shadowStr.replace(reOffsetsAndBlur, '') || 'rgb(0,0,0)').trim();\n\n    return {\n      color,\n      offsetX,\n      offsetY,\n      blur,\n    };\n  }\n\n  /**\n   * Returns a string representation of an instance\n   * @see http://www.w3.org/TR/css-text-decor-3/#text-shadow\n   * @return {String} Returns CSS3 text-shadow declaration\n   */\n  toString() {\n    return [this.offsetX, this.offsetY, this.blur, this.color].join('px ');\n  }\n\n  /**\n   * Returns SVG representation of a shadow\n   * @param {FabricObject} object\n   * @return {String} SVG representation of a shadow\n   */\n  toSVG(object: FabricObject) {\n    const offset = rotateVector(\n        new Point(this.offsetX, this.offsetY),\n        degreesToRadians(-object.angle),\n      ),\n      BLUR_BOX = 20,\n      NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS,\n      color = new Color(this.color);\n    let fBoxX = 40,\n      fBoxY = 40;\n\n    if (object.width && object.height) {\n      //http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion\n      // we add some extra space to filter box to contain the blur ( 20 )\n      fBoxX =\n        toFixed(\n          (Math.abs(offset.x) + this.blur) / object.width,\n          NUM_FRACTION_DIGITS,\n        ) *\n          100 +\n        BLUR_BOX;\n      fBoxY =\n        toFixed(\n          (Math.abs(offset.y) + this.blur) / object.height,\n          NUM_FRACTION_DIGITS,\n        ) *\n          100 +\n        BLUR_BOX;\n    }\n    if (object.flipX) {\n      offset.x *= -1;\n    }\n    if (object.flipY) {\n      offset.y *= -1;\n    }\n\n    return `<filter id=\"SVGID_${escapeXml(this.id)}\" y=\"-${fBoxY}%\" height=\"${\n      100 + 2 * fBoxY\n    }%\" x=\"-${fBoxX}%\" width=\"${\n      100 + 2 * fBoxX\n    }%\" >\\n\\t<feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"${toFixed(\n      this.blur ? this.blur / 2 : 0,\n      NUM_FRACTION_DIGITS,\n    )}\"></feGaussianBlur>\\n\\t<feOffset dx=\"${toFixed(\n      offset.x,\n      NUM_FRACTION_DIGITS,\n    )}\" dy=\"${toFixed(\n      offset.y,\n      NUM_FRACTION_DIGITS,\n    )}\" result=\"oBlur\" ></feOffset>\\n\\t<feFlood flood-color=\"${color.toRgb()}\" flood-opacity=\"${color.getAlpha()}\"/>\\n\\t<feComposite in2=\"oBlur\" operator=\"in\" />\\n\\t<feMerge>\\n\\t\\t<feMergeNode></feMergeNode>\\n\\t\\t<feMergeNode in=\"SourceGraphic\"></feMergeNode>\\n\\t</feMerge>\\n</filter>\\n`;\n  }\n\n  /**\n   * Returns object representation of a shadow\n   * @return {Object} Object representation of a shadow instance\n   */\n  toObject() {\n    const data: SerializedShadowOptions = {\n      color: this.color,\n      blur: this.blur,\n      offsetX: this.offsetX,\n      offsetY: this.offsetY,\n      affectStroke: this.affectStroke,\n      nonScaling: this.nonScaling,\n      type: (this.constructor as typeof Shadow).type,\n    };\n    const defaults = Shadow.ownDefaults as SerializedShadowOptions;\n    return !this.includeDefaultValues\n      ? pickBy(data, (value, key) => value !== defaults[key])\n      : data;\n  }\n\n  static async fromObject(options: Partial<TClassProperties<Shadow>>) {\n    return new this(options);\n  }\n}\n\nclassRegistry.setClass(Shadow, 'shadow');\n"],"mappings":"mrBA+BA,MAAM,EAAoB,yCAEpB,EAAuB,OAC3B,YACE,EACA,EACA,IACA,EACA,gCAAA,CAuBJ,IAAa,EAAb,MAAa,CAAA,CAyDX,YAAY,EAAmD,EAAA,CAAA,CAC7D,IAAM,EACY,OAAT,GAAS,SAAW,EAAO,YAAY,EAAA,CAAQ,EACxD,OAAO,OAAO,KAAM,EAAO,YAAa,EAAA,CACxC,KAAK,GAAK,GAAA,CAOZ,OAAA,YAAmB,EAAA,CACjB,IAAM,EAAY,EAAM,MAAA,CAAA,EACnB,EAAU,EAAG,EAAU,EAAG,EAAO,IAClC,EAAiB,KAAK,EAAA,EAAc,EAAA,EACpC,IAAK,GAAU,WAAW,EAAA,EAAU,EAAA,CAGxC,MAAO,CACL,OAHS,EAAU,QAAQ,EAAkB,GAAA,EAAO,cAAc,MAAA,CAIlE,QAAA,EACA,QAAA,EACA,KAAA,EAAA,CASJ,UAAA,CACE,MAAO,CAAC,KAAK,QAAS,KAAK,QAAS,KAAK,KAAM,KAAK,MAAA,CAAO,KAAK,MAAA,CAQlE,MAAM,EAAA,CACJ,IAAM,EAAS,EACX,IAAI,EAAM,KAAK,QAAS,KAAK,QAAA,CAC7B,EAAA,CAAkB,EAAO,MAAA,CAAA,CAG3B,EAAsB,EAAO,oBAC7B,EAAQ,IAAI,EAAM,KAAK,MAAA,CACrB,EAAQ,GACV,EAAQ,GA2BV,OAzBI,EAAO,OAAS,EAAO,SAGzB,EAKI,IAJF,GACG,KAAK,IAAI,EAAO,EAAA,CAAK,KAAK,MAAQ,EAAO,MAC1C,EAAA,CAZO,GAgBX,EAKI,IAJF,GACG,KAAK,IAAI,EAAO,EAAA,CAAK,KAAK,MAAQ,EAAO,OAC1C,EAAA,CAnBO,IAwBT,EAAO,QACT,EAAO,GAAA,IAEL,EAAO,QACT,EAAO,GAAA,IAGF,qBAAqB,EAAU,KAAK,GAAA,CAAA,QAAY,EAAA,aACrD,IAAM,EAAI,EAAA,SACF,EAAA,YACR,IAAM,EAAI,EAAA,yDAC8C,EACxD,KAAK,KAAO,KAAK,KAAO,EAAI,EAC5B,EAAA,CAAA,uCACuC,EACvC,EAAO,EACP,EAAA,CAAA,QACQ,EACR,EAAO,EACP,EAAA,CAAA,yDACyD,EAAM,OAAA,CAAA,mBAA2B,EAAM,UAAA,CAAA,+KAOpG,UAAA,CACE,IAAM,EAAgC,CACpC,MAAO,KAAK,MACZ,KAAM,KAAK,KACX,QAAS,KAAK,QACd,QAAS,KAAK,QACd,aAAc,KAAK,aACnB,WAAY,KAAK,WACjB,KAAO,KAAK,YAA8B,KAAA,CAEtC,EAAW,EAAO,YACxB,OAAQ,KAAK,qBAET,EADA,EAAO,GAAO,EAAO,IAAQ,IAAU,EAAS,GAAA,CAItD,aAAA,WAAwB,EAAA,CACtB,OAAO,IAAI,KAAK,EAAA,GAAA,EAAA,EA3HX,cAnE6D,CACpE,MAAO,aACP,KAAM,EACN,QAAS,EACT,QAAS,EACT,aAAA,CAAc,EACd,qBAAA,CAAsB,EACtB,WAAA,CAAY,EAAA,CAAA,CAAA,EAAA,EA8DL,OAAO,SAAA,CA6HhB,EAAc,SAAS,EAAQ,SAAA,CAAA,OAAA,KAAA"}