UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

1 lines 6.66 kB
{"version":3,"file":"StrokeLineCapProjections.mjs","names":[],"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"],"mappings":";;;;;;;;;;;;;;;;;AAmBA,IAAa,2BAAb,cAA8C,sBAAsB;CAUlE,YAAY,GAAO,GAAO,SAAwC;AAChE,QAAM,QAAQ;AACd,OAAK,IAAI,IAAI,MAAM,EAAE;AACrB,OAAK,IAAI,IAAI,MAAM,EAAE;;CAGvB,yBACE,MACA,IACA,YAAoB,KAAK,2BACzB;EACA,MAAM,SAAS,KAAK,iBAAiB,MAAM,GAAG;AAC9C,SAAO,KAAK,gBAAgB,qBAAqB,OAAO,EAAE,UAAU;;;;;;;;CAStE,cAAc;AACZ,SAAO,CACL,KAAK,oBAAoB,KAAK,GAAG,KAAK,GAAG,KAAK,0BAA0B,EACxE,KAAK,oBAAoB,KAAK,GAAG,KAAK,GAAG,CAAC,KAAK,0BAA0B,CAC1E;;;;;;;;CASH,eAAe;EACb,MAAM,cAAuB,EAAE;AAE/B,MAAI,CAAC,KAAK,UAAU,IAAI,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE;GAKzC,MAAM,aAAa,IAAI,MAAM,GAAG,EAAE,CAC/B,eAAe,KAAK,0BAA0B,CAC9C,SAAS,KAAK,oBAAoB;AACrC,eAAY,KACV,KAAK,UAAU,KAAK,EAAE,IAAI,WAAW,CAAC,EACtC,KAAK,UAAU,KAAK,EAAE,SAAS,WAAW,CAAC,CAC5C;QAED,aAAY,KACV,GAAG,IAAI,0BACL,KAAK,GACL,KAAK,GACL,KAAK,GACL,KAAK,QACN,CAAC,cAAc,CACjB;AAGH,SAAO;;;;;;;;CAST,gBAAgB;EACd,MAAM,cAAuB,EAAE;AAE/B,MAAI,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE;GAKrB,MAAM,aAAa,IAAI,MAAM,GAAG,EAAE,CAC/B,eAAe,KAAK,0BAA0B,CAC9C,SAAS,KAAK,oBAAoB;AACrC,eAAY,KAAK,KAAK,EAAE,IAAI,WAAW,EAAE,KAAK,EAAE,SAAS,WAAW,CAAC;SAChE;GACL,MAAM,uBAAuB,KAAK,yBAChC,KAAK,GACL,KAAK,GACL,KAAK,0BACN;GACD,MAAM,oBAAoB,KAAK,gBAC7B,cAAc,KAAK,iBAAiB,KAAK,GAAG,KAAK,EAAE,CAAC,EACpD,CAAC,KAAK,0BACP;GACD,MAAM,aAAa,KAAK,EAAE,IAAI,kBAAkB;AAChD,eAAY,KACV,WAAW,IAAI,qBAAqB,EACpC,WAAW,SAAS,qBAAqB,CAC1C;;AAGH,SAAO,YAAY,KAAK,MAAM,KAAK,UAAU,EAAE,CAAC;;CAGlD,gBAA0B;AACxB,UAAQ,KAAK,QAAQ,eAArB;GACE,KAAK,QACH,QAAO,KAAK,cAAc;GAC5B,KAAK,SACH,QAAO,KAAK,eAAe;GAC7B,QACE,QAAO,KAAK,aAAa;;;CAI/B,UAAgC;AAC9B,SAAO,KAAK,eAAe,CAAC,KAAK,WAAW;GAC1C,aAAa,KAAK;GAClB,gBAAgB;GACjB,EAAE"}