{"version":3,"file":"StrokeLineCapProjections.min.mjs","sources":["../../../../../src/util/misc/projectStroke/StrokeLineCapProjections.ts"],"sourcesContent":["import type { XY } from '../../../Point';\nimport { Point } from '../../../Point';\nimport { getOrthonormalVector, getUnitVector } from '../vectors';\nimport { StrokeLineJoinProjections } from './StrokeLineJoinProjections';\nimport { StrokeProjectionsBase } from './StrokeProjectionsBase';\nimport type { TProjection, TProjectStrokeOnPointsOptions } from './types';\n\n/**\n * class in charge of finding projections for each type of line cap for start/end of an open path\n * @see {@link [Open path projections at #8344](https://github.com/fabricjs/fabric.js/pull/8344#1-open-path)}\n *\n * Reference:\n * - MDN:\n *   - https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap\n *   - https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap\n * - Spec: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-linecap-dev\n * - Playground to understand how the line joins works: https://hypertolosana.github.io/efficient-webgl-stroking/index.html\n * - View the calculated projections for each of the control points: https://codesandbox.io/s/project-stroke-points-with-context-to-trace-b8jc4j?file=/src/index.js\n */\nexport class StrokeLineCapProjections extends StrokeProjectionsBase {\n  /**\n   * edge point\n   */\n  declare A: Point;\n  /**\n   * point next to edge point\n   */\n  declare T: Point;\n\n  constructor(A: XY, T: XY, options: TProjectStrokeOnPointsOptions) {\n    super(options);\n    this.A = new Point(A);\n    this.T = new Point(T);\n  }\n\n  calcOrthogonalProjection(\n    from: Point,\n    to: Point,\n    magnitude: number = this.strokeProjectionMagnitude,\n  ) {\n    const vector = this.createSideVector(from, to);\n    return this.scaleUnitVector(getOrthonormalVector(vector), magnitude);\n  }\n\n  /**\n   * OPEN PATH START/END - Line cap: Butt\n   * Calculation: to find the projections, just find the points orthogonal to the stroke\n   *\n   * @see https://github.com/fabricjs/fabric.js/pull/8344#1-1-butt\n   */\n  projectButt() {\n    return [\n      this.projectOrthogonally(this.A, this.T, this.strokeProjectionMagnitude),\n      this.projectOrthogonally(this.A, this.T, -this.strokeProjectionMagnitude),\n    ];\n  }\n\n  /**\n   * OPEN PATH START/END - Line cap: Round\n   * Calculation: same as stroke line join `round`\n   *\n   * @see https://github.com/fabricjs/fabric.js/pull/8344#1-2-round\n   */\n  projectRound() {\n    const projections: Point[] = [];\n\n    if (!this.isSkewed() && this.A.eq(this.T)) {\n      /* 1 point case without `skew`\n        When `strokeUniform` is true, scaling has no effect.\n        So we divide by scale, to remove its effect.\n      */\n      const projection = new Point(1, 1)\n        .scalarMultiply(this.strokeProjectionMagnitude)\n        .multiply(this.strokeUniformScalar);\n      projections.push(\n        this.applySkew(this.A.add(projection)),\n        this.applySkew(this.A.subtract(projection)),\n      );\n    } else {\n      projections.push(\n        ...new StrokeLineJoinProjections(\n          this.A,\n          this.T,\n          this.T,\n          this.options,\n        ).projectRound(),\n      );\n    }\n\n    return projections;\n  }\n\n  /**\n   * OPEN PATH START/END - Line cap: Square\n   * Calculation: project a rectangle of points on the stroke in the opposite direction of the vector `AT`\n   *\n   * @see https://github.com/fabricjs/fabric.js/pull/8344#1-3-square\n   */\n  projectSquare() {\n    const projections: Point[] = [];\n\n    if (this.A.eq(this.T)) {\n      /* 1 point case without `skew`\n        When `strokeUniform` is true, scaling has no effect.\n        So we divide by scale, to remove its effect.\n      */\n      const projection = new Point(1, 1)\n        .scalarMultiply(this.strokeProjectionMagnitude)\n        .multiply(this.strokeUniformScalar);\n      projections.push(this.A.add(projection), this.A.subtract(projection));\n    } else {\n      const orthogonalProjection = this.calcOrthogonalProjection(\n        this.A,\n        this.T,\n        this.strokeProjectionMagnitude,\n      );\n      const strokePointingOut = this.scaleUnitVector(\n        getUnitVector(this.createSideVector(this.A, this.T)),\n        -this.strokeProjectionMagnitude,\n      );\n      const projectedA = this.A.add(strokePointingOut);\n      projections.push(\n        projectedA.add(orthogonalProjection),\n        projectedA.subtract(orthogonalProjection),\n      );\n    }\n\n    return projections.map((p) => this.applySkew(p));\n  }\n\n  protected projectPoints() {\n    switch (this.options.strokeLineCap) {\n      case 'round':\n        return this.projectRound();\n      case 'square':\n        return this.projectSquare();\n      default:\n        return this.projectButt();\n    }\n  }\n\n  public project(): TProjection[] {\n    return this.projectPoints().map((point) => ({\n      originPoint: this.A,\n      projectedPoint: point,\n    }));\n  }\n}\n"],"names":["StrokeLineCapProjections","StrokeProjectionsBase","constructor","A","T","options","super","this","Point","calcOrthogonalProjection","from","to","magnitude","arguments","length","undefined","strokeProjectionMagnitude","vector","createSideVector","scaleUnitVector","getOrthonormalVector","projectButt","projectOrthogonally","projectRound","projections","isSkewed","eq","projection","scalarMultiply","multiply","strokeUniformScalar","push","applySkew","add","subtract","StrokeLineJoinProjections","projectSquare","orthogonalProjection","strokePointingOut","getUnitVector","projectedA","map","p","projectPoints","strokeLineCap","project","point","originPoint","projectedPoint"],"mappings":"oRAmBO,MAAMA,UAAiCC,EAU5CC,WAAAA,CAAYC,EAAOC,EAAOC,GACxBC,MAAMD,GACNE,KAAKJ,EAAI,IAAIK,EAAML,GACnBI,KAAKH,EAAI,IAAII,EAAMJ,EACrB,CAEAK,wBAAAA,CACEC,EACAC,GAEA,IADAC,EAAiBC,UAAAC,OAAAD,QAAAE,IAAAF,UAAAE,GAAAF,UAAG,GAAAN,KAAKS,0BAEzB,MAAMC,EAASV,KAAKW,iBAAiBR,EAAMC,GAC3C,OAAOJ,KAAKY,gBAAgBC,EAAqBH,GAASL,EAC5D,CAQAS,WAAAA,GACE,MAAO,CACLd,KAAKe,oBAAoBf,KAAKJ,EAAGI,KAAKH,EAAGG,KAAKS,2BAC9CT,KAAKe,oBAAoBf,KAAKJ,EAAGI,KAAKH,GAAIG,KAAKS,2BAEnD,CAQAO,YAAAA,GACE,MAAMC,EAAuB,GAE7B,IAAKjB,KAAKkB,YAAclB,KAAKJ,EAAEuB,GAAGnB,KAAKH,GAAI,CAKzC,MAAMuB,EAAa,IAAInB,EAAM,EAAG,GAC7BoB,eAAerB,KAAKS,2BACpBa,SAAStB,KAAKuB,qBACjBN,EAAYO,KACVxB,KAAKyB,UAAUzB,KAAKJ,EAAE8B,IAAIN,IAC1BpB,KAAKyB,UAAUzB,KAAKJ,EAAE+B,SAASP,IAEnC,MACEH,EAAYO,QACP,IAAII,EACL5B,KAAKJ,EACLI,KAAKH,EACLG,KAAKH,EACLG,KAAKF,SACLkB,gBAIN,OAAOC,CACT,CAQAY,aAAAA,GACE,MAAMZ,EAAuB,GAE7B,GAAIjB,KAAKJ,EAAEuB,GAAGnB,KAAKH,GAAI,CAKrB,MAAMuB,EAAa,IAAInB,EAAM,EAAG,GAC7BoB,eAAerB,KAAKS,2BACpBa,SAAStB,KAAKuB,qBACjBN,EAAYO,KAAKxB,KAAKJ,EAAE8B,IAAIN,GAAapB,KAAKJ,EAAE+B,SAASP,GAC3D,KAAO,CACL,MAAMU,EAAuB9B,KAAKE,yBAChCF,KAAKJ,EACLI,KAAKH,EACLG,KAAKS,2BAEDsB,EAAoB/B,KAAKY,gBAC7BoB,EAAchC,KAAKW,iBAAiBX,KAAKJ,EAAGI,KAAKH,KAChDG,KAAKS,2BAEFwB,EAAajC,KAAKJ,EAAE8B,IAAIK,GAC9Bd,EAAYO,KACVS,EAAWP,IAAII,GACfG,EAAWN,SAASG,GAExB,CAEA,OAAOb,EAAYiB,KAAKC,GAAMnC,KAAKyB,UAAUU,IAC/C,CAEUC,aAAAA,GACR,OAAQpC,KAAKF,QAAQuC,eACnB,IAAK,QACH,OAAOrC,KAAKgB,eACd,IAAK,SACH,OAAOhB,KAAK6B,gBACd,QACE,OAAO7B,KAAKc,cAElB,CAEOwB,OAAAA,GACL,OAAOtC,KAAKoC,gBAAgBF,KAAKK,IAAW,CAC1CC,YAAaxC,KAAKJ,EAClB6C,eAAgBF,KAEpB"}