fabric 7.3.1 → 7.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -27
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/defineProperty.mjs +1 -1
- package/{dist-extensions/_virtual/_@oxc-project_runtime@0.122.0 → dist/_virtual/_@oxc-project_runtime@0.126.0}/helpers/toPrimitive.mjs +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/toPropertyKey.mjs +1 -1
- package/{dist-extensions/_virtual/_@oxc-project_runtime@0.122.0 → dist/_virtual/_@oxc-project_runtime@0.126.0}/helpers/typeof.mjs +1 -1
- package/dist/index.js +88 -66
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +35 -35
- package/dist/index.min.js.map +1 -1
- package/dist/index.min.mjs +37 -37
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +88 -66
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.cjs +83 -62
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +83 -62
- package/dist/index.node.mjs.map +1 -1
- package/dist/package.min.mjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/src/Collection.min.mjs +1 -1
- package/dist/src/Collection.mjs +1 -1
- package/dist/src/LayoutManager/LayoutManager.min.mjs +1 -1
- package/dist/src/LayoutManager/LayoutManager.mjs +1 -1
- package/dist/src/LayoutManager/LayoutStrategies/ClipPathLayout.min.mjs +1 -1
- package/dist/src/LayoutManager/LayoutStrategies/ClipPathLayout.mjs +1 -1
- package/dist/src/LayoutManager/LayoutStrategies/FitContentLayout.min.mjs +1 -1
- package/dist/src/LayoutManager/LayoutStrategies/FitContentLayout.mjs +1 -1
- package/dist/src/LayoutManager/LayoutStrategies/FixedLayout.min.mjs +1 -1
- package/dist/src/LayoutManager/LayoutStrategies/FixedLayout.mjs +1 -1
- package/dist/src/LayoutManager/LayoutStrategies/LayoutStrategy.min.mjs +1 -1
- package/dist/src/LayoutManager/LayoutStrategies/LayoutStrategy.mjs +1 -1
- package/dist/src/Observable.min.mjs +1 -1
- package/dist/src/Observable.mjs +1 -1
- package/dist/src/Pattern/Pattern.min.mjs +1 -1
- package/dist/src/Pattern/Pattern.mjs +1 -1
- package/dist/src/Shadow.min.mjs +1 -1
- package/dist/src/Shadow.mjs +1 -1
- package/dist/src/brushes/BaseBrush.min.mjs +1 -1
- package/dist/src/brushes/BaseBrush.mjs +1 -1
- package/dist/src/brushes/CircleBrush.min.mjs +1 -1
- package/dist/src/brushes/CircleBrush.mjs +1 -1
- package/dist/src/brushes/PencilBrush.min.mjs +1 -1
- package/dist/src/brushes/PencilBrush.mjs +1 -1
- package/dist/src/brushes/SprayBrush.min.mjs +1 -1
- package/dist/src/brushes/SprayBrush.mjs +1 -1
- package/dist/src/cache.min.mjs +1 -1
- package/dist/src/cache.mjs +1 -1
- package/dist/src/canvas/Canvas.min.mjs +1 -1
- package/dist/src/canvas/Canvas.mjs +1 -1
- package/dist/src/canvas/DOMManagers/CanvasDOMManager.min.mjs +1 -1
- package/dist/src/canvas/DOMManagers/CanvasDOMManager.mjs +1 -1
- package/dist/src/canvas/DOMManagers/StaticCanvasDOMManager.min.mjs +1 -1
- package/dist/src/canvas/DOMManagers/StaticCanvasDOMManager.mjs +1 -1
- package/dist/src/canvas/SelectableCanvas.min.mjs +1 -1
- package/dist/src/canvas/SelectableCanvas.mjs +1 -1
- package/dist/src/canvas/StaticCanvas.d.ts +1 -1
- package/dist/src/canvas/StaticCanvas.d.ts.map +1 -1
- package/dist/src/canvas/StaticCanvas.min.mjs +5 -5
- package/dist/src/canvas/StaticCanvas.min.mjs.map +1 -1
- package/dist/src/canvas/StaticCanvas.mjs +4 -4
- package/dist/src/canvas/StaticCanvas.mjs.map +1 -1
- package/dist/src/canvas/TextEditingManager.min.mjs +1 -1
- package/dist/src/canvas/TextEditingManager.mjs +1 -1
- package/dist/src/color/Color.min.mjs +1 -1
- package/dist/src/color/Color.mjs +1 -1
- package/dist/src/config.min.mjs +1 -1
- package/dist/src/config.mjs +1 -1
- package/dist/src/controls/Control.min.mjs +1 -1
- package/dist/src/controls/Control.mjs +1 -1
- package/dist/src/filters/BaseFilter.min.mjs +1 -1
- package/dist/src/filters/BaseFilter.mjs +1 -1
- package/dist/src/filters/BlendColor.min.mjs +1 -1
- package/dist/src/filters/BlendColor.mjs +1 -1
- package/dist/src/filters/BlendImage.min.mjs +1 -1
- package/dist/src/filters/BlendImage.mjs +1 -1
- package/dist/src/filters/Blur.min.mjs +1 -1
- package/dist/src/filters/Blur.mjs +1 -1
- package/dist/src/filters/Brightness.min.mjs +1 -1
- package/dist/src/filters/Brightness.mjs +1 -1
- package/dist/src/filters/Canvas2dFilterBackend.min.mjs +1 -1
- package/dist/src/filters/Canvas2dFilterBackend.mjs +1 -1
- package/dist/src/filters/ColorMatrix.min.mjs +1 -1
- package/dist/src/filters/ColorMatrix.mjs +1 -1
- package/dist/src/filters/ColorMatrixFilters.min.mjs +1 -1
- package/dist/src/filters/ColorMatrixFilters.mjs +1 -1
- package/dist/src/filters/Composed.min.mjs +1 -1
- package/dist/src/filters/Composed.mjs +1 -1
- package/dist/src/filters/Contrast.min.mjs +1 -1
- package/dist/src/filters/Contrast.mjs +1 -1
- package/dist/src/filters/Convolute.min.mjs +1 -1
- package/dist/src/filters/Convolute.min.mjs.map +1 -1
- package/dist/src/filters/Convolute.mjs +1 -1
- package/dist/src/filters/Gamma.min.mjs +1 -1
- package/dist/src/filters/Gamma.mjs +1 -1
- package/dist/src/filters/Grayscale.min.mjs +1 -1
- package/dist/src/filters/Grayscale.mjs +1 -1
- package/dist/src/filters/HueRotation.min.mjs +1 -1
- package/dist/src/filters/HueRotation.mjs +1 -1
- package/dist/src/filters/Invert.min.mjs +1 -1
- package/dist/src/filters/Invert.mjs +1 -1
- package/dist/src/filters/Noise.min.mjs +1 -1
- package/dist/src/filters/Noise.mjs +1 -1
- package/dist/src/filters/Pixelate.min.mjs +1 -1
- package/dist/src/filters/Pixelate.mjs +1 -1
- package/dist/src/filters/RemoveColor.min.mjs +1 -1
- package/dist/src/filters/RemoveColor.mjs +1 -1
- package/dist/src/filters/Resize.min.mjs +2 -2
- package/dist/src/filters/Resize.min.mjs.map +1 -1
- package/dist/src/filters/Resize.mjs +2 -2
- package/dist/src/filters/Resize.mjs.map +1 -1
- package/dist/src/filters/Saturation.min.mjs +1 -1
- package/dist/src/filters/Saturation.mjs +1 -1
- package/dist/src/filters/Vibrance.min.mjs +1 -1
- package/dist/src/filters/Vibrance.mjs +1 -1
- package/dist/src/filters/WebGLFilterBackend.min.mjs +1 -1
- package/dist/src/filters/WebGLFilterBackend.mjs +1 -1
- package/dist/src/gradient/Gradient.d.ts.map +1 -1
- package/dist/src/gradient/Gradient.min.mjs +4 -4
- package/dist/src/gradient/Gradient.min.mjs.map +1 -1
- package/dist/src/gradient/Gradient.mjs +6 -2
- package/dist/src/gradient/Gradient.mjs.map +1 -1
- package/dist/src/gradient/typedefs.d.ts +7 -7
- package/dist/src/parser/applyViewboxTransform.d.ts.map +1 -1
- package/dist/src/parser/applyViewboxTransform.min.mjs +1 -1
- package/dist/src/parser/applyViewboxTransform.min.mjs.map +1 -1
- package/dist/src/parser/applyViewboxTransform.mjs +2 -4
- package/dist/src/parser/applyViewboxTransform.mjs.map +1 -1
- package/dist/src/shapes/ActiveSelection.min.mjs +1 -1
- package/dist/src/shapes/ActiveSelection.mjs +1 -1
- package/dist/src/shapes/Circle.min.mjs +2 -2
- package/dist/src/shapes/Circle.min.mjs.map +1 -1
- package/dist/src/shapes/Circle.mjs +1 -1
- package/dist/src/shapes/Ellipse.min.mjs +1 -1
- package/dist/src/shapes/Ellipse.mjs +1 -1
- package/dist/src/shapes/Group.min.mjs +1 -1
- package/dist/src/shapes/Group.mjs +1 -1
- package/dist/src/shapes/IText/DraggableTextDelegate.min.mjs +1 -1
- package/dist/src/shapes/IText/DraggableTextDelegate.mjs +1 -1
- package/dist/src/shapes/IText/IText.d.ts.map +1 -1
- package/dist/src/shapes/IText/IText.min.mjs +1 -1
- package/dist/src/shapes/IText/IText.min.mjs.map +1 -1
- package/dist/src/shapes/IText/IText.mjs +3 -3
- package/dist/src/shapes/IText/IText.mjs.map +1 -1
- package/dist/src/shapes/IText/ITextBehavior.min.mjs +1 -1
- package/dist/src/shapes/IText/ITextBehavior.mjs +1 -1
- package/dist/src/shapes/IText/ITextClickBehavior.min.mjs +1 -1
- package/dist/src/shapes/IText/ITextClickBehavior.mjs +1 -1
- package/dist/src/shapes/Image.min.mjs +1 -1
- package/dist/src/shapes/Image.mjs +1 -1
- package/dist/src/shapes/Line.min.mjs +1 -1
- package/dist/src/shapes/Line.mjs +1 -1
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs +2 -2
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs.map +1 -1
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs +11 -26
- package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs.map +1 -1
- package/dist/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
- package/dist/src/shapes/Object/InteractiveObject.min.mjs +1 -1
- package/dist/src/shapes/Object/InteractiveObject.min.mjs.map +1 -1
- package/dist/src/shapes/Object/InteractiveObject.mjs +7 -6
- package/dist/src/shapes/Object/InteractiveObject.mjs.map +1 -1
- package/dist/src/shapes/Object/Object.min.mjs +1 -1
- package/dist/src/shapes/Object/Object.mjs +1 -1
- package/dist/src/shapes/Object/ObjectGeometry.d.ts.map +1 -1
- package/dist/src/shapes/Object/ObjectGeometry.min.mjs +1 -1
- package/dist/src/shapes/Object/ObjectGeometry.min.mjs.map +1 -1
- package/dist/src/shapes/Object/ObjectGeometry.mjs +6 -2
- package/dist/src/shapes/Object/ObjectGeometry.mjs.map +1 -1
- package/dist/src/shapes/Object/types/FabricObjectProps.d.ts +1 -1
- package/dist/src/shapes/Path.min.mjs +1 -1
- package/dist/src/shapes/Path.mjs +1 -1
- package/dist/src/shapes/Polygon.min.mjs +1 -1
- package/dist/src/shapes/Polygon.mjs +1 -1
- package/dist/src/shapes/Polyline.min.mjs +1 -1
- package/dist/src/shapes/Polyline.mjs +1 -1
- package/dist/src/shapes/Rect.min.mjs +1 -1
- package/dist/src/shapes/Rect.mjs +1 -1
- package/dist/src/shapes/Text/StyledText.min.mjs +1 -1
- package/dist/src/shapes/Text/StyledText.mjs +1 -1
- package/dist/src/shapes/Text/Text.d.ts +4 -4
- package/dist/src/shapes/Text/Text.min.mjs +1 -1
- package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
- package/dist/src/shapes/Text/Text.mjs +3 -3
- package/dist/src/shapes/Text/Text.mjs.map +1 -1
- package/dist/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
- package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs +2 -2
- package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs.map +1 -1
- package/dist/src/shapes/Text/TextSVGExportMixin.mjs +14 -7
- package/dist/src/shapes/Text/TextSVGExportMixin.mjs.map +1 -1
- package/dist/src/shapes/Textbox.d.ts.map +1 -1
- package/dist/src/shapes/Textbox.min.mjs +2 -2
- package/dist/src/shapes/Textbox.min.mjs.map +1 -1
- package/dist/src/shapes/Textbox.mjs +2 -3
- package/dist/src/shapes/Textbox.mjs.map +1 -1
- package/dist/src/shapes/Triangle.min.mjs +1 -1
- package/dist/src/shapes/Triangle.mjs +1 -1
- package/dist/src/util/animation/AnimationBase.min.mjs +1 -1
- package/dist/src/util/animation/AnimationBase.mjs +1 -1
- package/dist/src/util/animation/easing.min.mjs +1 -1
- package/dist/src/util/animation/easing.min.mjs.map +1 -1
- package/dist/src/util/animation/easing.mjs +1 -1
- package/dist/src/util/animation/easing.mjs.map +1 -1
- package/dist/src/util/internals/applyCanvasTransform.d.ts +1 -1
- package/dist/src/util/internals/applyCanvasTransform.min.mjs.map +1 -1
- package/dist/src/util/internals/applyCanvasTransform.mjs +1 -1
- package/dist/src/util/internals/applyCanvasTransform.mjs.map +1 -1
- package/dist/src/util/internals/svgExportCheck.d.ts +4 -0
- package/dist/src/util/internals/svgExportCheck.d.ts.map +1 -0
- package/dist/src/util/internals/svgExportCheck.min.mjs +2 -0
- package/dist/src/util/internals/svgExportCheck.min.mjs.map +1 -0
- package/dist/src/util/internals/svgExportCheck.mjs +12 -0
- package/dist/src/util/internals/svgExportCheck.mjs.map +1 -0
- package/dist/src/util/misc/matrix.d.ts +14 -0
- package/dist/src/util/misc/matrix.d.ts.map +1 -1
- package/dist/src/util/misc/matrix.min.mjs +1 -1
- package/dist/src/util/misc/matrix.min.mjs.map +1 -1
- package/dist/src/util/misc/matrix.mjs +15 -1
- package/dist/src/util/misc/matrix.mjs.map +1 -1
- package/dist/src/util/misc/mergeClipPaths.d.ts +1 -1
- package/dist/src/util/misc/mergeClipPaths.min.mjs.map +1 -1
- package/dist/src/util/misc/mergeClipPaths.mjs +1 -1
- package/dist/src/util/misc/mergeClipPaths.mjs.map +1 -1
- package/dist/src/util/misc/objectEnlive.min.mjs.map +1 -1
- package/dist/src/util/misc/objectEnlive.mjs +1 -1
- package/dist/src/util/misc/objectEnlive.mjs.map +1 -1
- package/dist/src/util/misc/projectStroke/StrokeLineJoinProjections.min.mjs +1 -1
- package/dist/src/util/misc/projectStroke/StrokeLineJoinProjections.min.mjs.map +1 -1
- package/dist/src/util/misc/projectStroke/StrokeLineJoinProjections.mjs +1 -1
- package/dist/src/util/misc/svgParsing.d.ts +2 -2
- package/dist/src/util/misc/svgParsing.d.ts.map +1 -1
- package/dist/src/util/misc/svgParsing.min.mjs +1 -1
- package/dist/src/util/misc/svgParsing.min.mjs.map +1 -1
- package/dist/src/util/misc/svgParsing.mjs +8 -3
- package/dist/src/util/misc/svgParsing.mjs.map +1 -1
- package/dist/src/util/path/index.d.ts.map +1 -1
- package/dist/src/util/path/index.min.mjs +1 -1
- package/dist/src/util/path/index.min.mjs.map +1 -1
- package/dist/src/util/path/index.mjs +2 -1
- package/dist/src/util/path/index.mjs.map +1 -1
- package/dist/src/util/path/regex.min.mjs.map +1 -1
- package/dist/src/util/path/regex.mjs +1 -1
- package/dist/src/util/path/regex.mjs.map +1 -1
- package/dist-extensions/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/defineProperty.mjs +1 -1
- package/{dist/_virtual/_@oxc-project_runtime@0.122.0 → dist-extensions/_virtual/_@oxc-project_runtime@0.126.0}/helpers/toPrimitive.mjs +1 -1
- package/dist-extensions/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/toPropertyKey.mjs +1 -1
- package/{dist/_virtual/_@oxc-project_runtime@0.122.0 → dist-extensions/_virtual/_@oxc-project_runtime@0.126.0}/helpers/typeof.mjs +1 -1
- package/dist-extensions/aligning_guidelines/index.mjs +1 -1
- package/dist-extensions/cropping_controls/croppingHandlers.mjs +1 -7
- package/dist-extensions/cropping_controls/croppingHandlers.mjs.map +1 -1
- package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -1
- package/dist-extensions/fabric-extensions.min.js +1 -1
- package/dist-extensions/fabric-extensions.min.js.map +1 -1
- package/dist-extensions/src/canvas/StaticCanvas.d.ts +1 -1
- package/dist-extensions/src/canvas/StaticCanvas.d.ts.map +1 -1
- package/dist-extensions/src/gradient/Gradient.d.ts.map +1 -1
- package/dist-extensions/src/gradient/typedefs.d.ts +7 -7
- package/dist-extensions/src/parser/applyViewboxTransform.d.ts.map +1 -1
- package/dist-extensions/src/shapes/IText/IText.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Object/ObjectGeometry.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Object/types/FabricObjectProps.d.ts +1 -1
- package/dist-extensions/src/shapes/Text/Text.d.ts +4 -4
- package/dist-extensions/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
- package/dist-extensions/src/util/internals/applyCanvasTransform.d.ts +1 -1
- package/dist-extensions/src/util/internals/svgExportCheck.d.ts +4 -0
- package/dist-extensions/src/util/internals/svgExportCheck.d.ts.map +1 -0
- package/dist-extensions/src/util/misc/matrix.d.ts +14 -0
- package/dist-extensions/src/util/misc/matrix.d.ts.map +1 -1
- package/dist-extensions/src/util/misc/mergeClipPaths.d.ts +1 -1
- package/dist-extensions/src/util/misc/svgParsing.d.ts +2 -2
- package/dist-extensions/src/util/misc/svgParsing.d.ts.map +1 -1
- package/dist-extensions/src/util/path/index.d.ts.map +1 -1
- package/extensions/cropping_controls/croppingHandlers.ts +13 -19
- package/package.json +10 -10
- package/src/LayoutManager/README.md +3 -3
- package/src/canvas/StaticCanvas.spec.ts +19 -0
- package/src/canvas/StaticCanvas.ts +7 -3
- package/src/filters/Resize.ts +1 -1
- package/src/gradient/Gradient.spec.ts +60 -1
- package/src/gradient/Gradient.ts +9 -2
- package/src/gradient/typedefs.ts +7 -7
- package/src/parser/applyViewboxTransform.ts +2 -4
- package/src/shapes/IText/IText.ts +1 -2
- package/src/shapes/IText/ITextBehavior.test.ts +6 -6
- package/src/shapes/Object/FabricObject.spec.ts +3 -2
- package/src/shapes/Object/FabricObjectSVGExportMixin.ts +47 -37
- package/src/shapes/Object/InteractiveObject.ts +13 -3
- package/src/shapes/Object/Object-interactivity.spec.ts +126 -7
- package/src/shapes/Object/ObjectGeometry.spec.ts +10 -1
- package/src/shapes/Object/ObjectGeometry.ts +10 -3
- package/src/shapes/Object/objectSvgExport.spec.ts +27 -0
- package/src/shapes/Object/types/FabricObjectProps.ts +1 -1
- package/src/shapes/Text/Text.spec.ts +25 -0
- package/src/shapes/Text/Text.ts +5 -5
- package/src/shapes/Text/TextSVGExportMixin.ts +25 -11
- package/src/shapes/Textbox.ts +1 -2
- package/src/util/animation/animations.spec.ts +1 -1
- package/src/util/animation/easing.ts +1 -1
- package/src/util/internals/applyCanvasTransform.ts +1 -1
- package/src/util/internals/svgExportCheck.ts +20 -0
- package/src/util/misc/matrix.spec.ts +52 -0
- package/src/util/misc/matrix.ts +16 -0
- package/src/util/misc/mergeClipPaths.ts +1 -1
- package/src/util/misc/objectEnlive.ts +1 -1
- package/src/util/misc/svgParsing.ts +22 -10
- package/src/util/path/index.ts +3 -2
- package/src/util/path/regex.ts +1 -1
- package/src/util/typeAssertions.spec.ts +1 -1
- /package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/defineProperty.min.mjs +0 -0
- /package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/toPrimitive.min.mjs +0 -0
- /package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/toPropertyKey.min.mjs +0 -0
- /package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/typeof.min.mjs +0 -0
|
@@ -3,7 +3,7 @@ import type { StaticCanvas } from '../../canvas/StaticCanvas';
|
|
|
3
3
|
* Set the transform of the passed context to the same of a specific Canvas or StaticCanvas.
|
|
4
4
|
* setTransform is used since this utility will RESET the ctx transform to the basic value
|
|
5
5
|
* of retina scaling and viewport transform
|
|
6
|
-
* It is not meant to be added to other transforms, it is used internally to
|
|
6
|
+
* It is not meant to be added to other transforms, it is used internally to prepare canvases to draw
|
|
7
7
|
* @param ctx
|
|
8
8
|
* @param canvas
|
|
9
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applyCanvasTransform.min.mjs","names":[],"sources":["../../../../src/util/internals/applyCanvasTransform.ts"],"sourcesContent":["import type { StaticCanvas } from '../../canvas/StaticCanvas';\n\n/**\n * Set the transform of the passed context to the same of a specific Canvas or StaticCanvas.\n * setTransform is used since this utility will RESET the ctx transform to the basic value\n * of retina scaling and viewport transform\n * It is not meant to be added to other transforms, it is used internally to
|
|
1
|
+
{"version":3,"file":"applyCanvasTransform.min.mjs","names":[],"sources":["../../../../src/util/internals/applyCanvasTransform.ts"],"sourcesContent":["import type { StaticCanvas } from '../../canvas/StaticCanvas';\n\n/**\n * Set the transform of the passed context to the same of a specific Canvas or StaticCanvas.\n * setTransform is used since this utility will RESET the ctx transform to the basic value\n * of retina scaling and viewport transform\n * It is not meant to be added to other transforms, it is used internally to prepare canvases to draw\n * @param ctx\n * @param canvas\n */\nexport const applyCanvasTransform = (\n ctx: CanvasRenderingContext2D,\n canvas: StaticCanvas,\n) => {\n const scale = canvas.getRetinaScaling();\n ctx.setTransform(scale, 0, 0, scale, 0, 0);\n const v = canvas.viewportTransform;\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n};\n"],"mappings":"AAUA,MAAa,GACX,EACA,IAAA,CAEA,IAAM,EAAQ,EAAO,kBAAA,CACrB,EAAI,aAAa,EAAO,EAAG,EAAG,EAAO,EAAG,EAAA,CACxC,IAAM,EAAI,EAAO,kBACjB,EAAI,UAAU,EAAE,GAAI,EAAE,GAAI,EAAE,GAAI,EAAE,GAAI,EAAE,GAAI,EAAE,GAAA,EAAA,OAAA,KAAA"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Set the transform of the passed context to the same of a specific Canvas or StaticCanvas.
|
|
4
4
|
* setTransform is used since this utility will RESET the ctx transform to the basic value
|
|
5
5
|
* of retina scaling and viewport transform
|
|
6
|
-
* It is not meant to be added to other transforms, it is used internally to
|
|
6
|
+
* It is not meant to be added to other transforms, it is used internally to prepare canvases to draw
|
|
7
7
|
* @param ctx
|
|
8
8
|
* @param canvas
|
|
9
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applyCanvasTransform.mjs","names":[],"sources":["../../../../src/util/internals/applyCanvasTransform.ts"],"sourcesContent":["import type { StaticCanvas } from '../../canvas/StaticCanvas';\n\n/**\n * Set the transform of the passed context to the same of a specific Canvas or StaticCanvas.\n * setTransform is used since this utility will RESET the ctx transform to the basic value\n * of retina scaling and viewport transform\n * It is not meant to be added to other transforms, it is used internally to
|
|
1
|
+
{"version":3,"file":"applyCanvasTransform.mjs","names":[],"sources":["../../../../src/util/internals/applyCanvasTransform.ts"],"sourcesContent":["import type { StaticCanvas } from '../../canvas/StaticCanvas';\n\n/**\n * Set the transform of the passed context to the same of a specific Canvas or StaticCanvas.\n * setTransform is used since this utility will RESET the ctx transform to the basic value\n * of retina scaling and viewport transform\n * It is not meant to be added to other transforms, it is used internally to prepare canvases to draw\n * @param ctx\n * @param canvas\n */\nexport const applyCanvasTransform = (\n ctx: CanvasRenderingContext2D,\n canvas: StaticCanvas,\n) => {\n const scale = canvas.getRetinaScaling();\n ctx.setTransform(scale, 0, 0, scale, 0, 0);\n const v = canvas.viewportTransform;\n ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n};\n"],"mappings":";;;;;;;;;AAUA,MAAa,wBACX,KACA,WACG;CACH,MAAM,QAAQ,OAAO,kBAAkB;AACvC,KAAI,aAAa,OAAO,GAAG,GAAG,OAAO,GAAG,EAAE;CAC1C,MAAM,IAAI,OAAO;AACjB,KAAI,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const isSafeSvgStyleValue: (value: unknown) => value is string;
|
|
2
|
+
export declare const getSafeSvgStyleNumber: (value: unknown, fallback?: string) => string;
|
|
3
|
+
export declare const getSafeSvgStyleToken: (value: unknown, fallback?: string) => string;
|
|
4
|
+
//# sourceMappingURL=svgExportCheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svgExportCheck.d.ts","sourceRoot":"","sources":["../../../../src/util/internals/svgExportCheck.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAGvB,CAAC;AAExC,eAAO,MAAM,qBAAqB,GAChC,OAAO,OAAO,EACd,iBAAa,KACZ,MAGF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,EAAE,iBAAa,KAAG,MACO,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=new RegExp(String.raw`[\0-\x1F\x7F;<>\\]|\/\*|\*\/|url\s*\(|expression\s*\(|(?:java|vb)script\s*:|data\s*:|@import\b`,`iu`),t=t=>typeof t==`string`&&t.trim().length>0&&!e.test(t),n=(e,t=``)=>{let n=Number(e);return Number.isFinite(n)?`${n}`:t},r=(e,n=``)=>typeof e==`string`&&t(e)?e:n;export{n as getSafeSvgStyleNumber,r as getSafeSvgStyleToken,t as isSafeSvgStyleValue};
|
|
2
|
+
//# sourceMappingURL=svgExportCheck.min.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svgExportCheck.min.mjs","names":[],"sources":["../../../../src/util/internals/svgExportCheck.ts"],"sourcesContent":["const unsafeSvgStyleValueRegex = new RegExp(\n String.raw`[\\0-\\x1F\\x7F;<>\\\\]|\\/\\*|\\*\\/|url\\s*\\(|expression\\s*\\(|(?:java|vb)script\\s*:|data\\s*:|@import\\b`,\n 'iu',\n);\n\nexport const isSafeSvgStyleValue = (value: unknown): value is string =>\n typeof value === 'string' &&\n value.trim().length > 0 &&\n !unsafeSvgStyleValueRegex.test(value);\n\nexport const getSafeSvgStyleNumber = (\n value: unknown,\n fallback = '',\n): string => {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? `${numeric}` : fallback;\n};\n\nexport const getSafeSvgStyleToken = (value: unknown, fallback = ''): string =>\n typeof value === 'string' && isSafeSvgStyleValue(value) ? value : fallback;\n"],"mappings":"AAAA,MAAM,EAA2B,IAAI,OACnC,OAAO,GAAG,iGACV,KAAA,CAGW,EAAuB,GACjB,OAAV,GAAU,UACjB,EAAM,MAAA,CAAO,OAAS,GAAA,CACrB,EAAyB,KAAK,EAAA,CAEpB,GACX,EACA,EAAW,KAAA,CAEX,IAAM,EAAU,OAAO,EAAA,CACvB,OAAO,OAAO,SAAS,EAAA,CAAW,GAAG,IAAY,GAGtC,GAAwB,EAAgB,EAAW,KAC7C,OAAV,GAAU,UAAY,EAAoB,EAAA,CAAS,EAAQ,EAAA,OAAA,KAAA,sBAAA,KAAA,qBAAA,KAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/util/internals/svgExportCheck.ts
|
|
2
|
+
const unsafeSvgStyleValueRegex = new RegExp(String.raw`[\0-\x1F\x7F;<>\\]|\/\*|\*\/|url\s*\(|expression\s*\(|(?:java|vb)script\s*:|data\s*:|@import\b`, "iu");
|
|
3
|
+
const isSafeSvgStyleValue = (value) => typeof value === "string" && value.trim().length > 0 && !unsafeSvgStyleValueRegex.test(value);
|
|
4
|
+
const getSafeSvgStyleNumber = (value, fallback = "") => {
|
|
5
|
+
const numeric = Number(value);
|
|
6
|
+
return Number.isFinite(numeric) ? `${numeric}` : fallback;
|
|
7
|
+
};
|
|
8
|
+
const getSafeSvgStyleToken = (value, fallback = "") => typeof value === "string" && isSafeSvgStyleValue(value) ? value : fallback;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { getSafeSvgStyleNumber, getSafeSvgStyleToken, isSafeSvgStyleValue };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=svgExportCheck.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svgExportCheck.mjs","names":[],"sources":["../../../../src/util/internals/svgExportCheck.ts"],"sourcesContent":["const unsafeSvgStyleValueRegex = new RegExp(\n String.raw`[\\0-\\x1F\\x7F;<>\\\\]|\\/\\*|\\*\\/|url\\s*\\(|expression\\s*\\(|(?:java|vb)script\\s*:|data\\s*:|@import\\b`,\n 'iu',\n);\n\nexport const isSafeSvgStyleValue = (value: unknown): value is string =>\n typeof value === 'string' &&\n value.trim().length > 0 &&\n !unsafeSvgStyleValueRegex.test(value);\n\nexport const getSafeSvgStyleNumber = (\n value: unknown,\n fallback = '',\n): string => {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? `${numeric}` : fallback;\n};\n\nexport const getSafeSvgStyleToken = (value: unknown, fallback = ''): string =>\n typeof value === 'string' && isSafeSvgStyleValue(value) ? value : fallback;\n"],"mappings":";AAAA,MAAM,2BAA2B,IAAI,OACnC,OAAO,GAAG,kGACV,KACD;AAED,MAAa,uBAAuB,UAClC,OAAO,UAAU,YACjB,MAAM,MAAM,CAAC,SAAS,KACtB,CAAC,yBAAyB,KAAK,MAAM;AAEvC,MAAa,yBACX,OACA,WAAW,OACA;CACX,MAAM,UAAU,OAAO,MAAM;AAC7B,QAAO,OAAO,SAAS,QAAQ,GAAG,GAAG,YAAY;;AAGnD,MAAa,wBAAwB,OAAgB,WAAW,OAC9D,OAAO,UAAU,YAAY,oBAAoB,MAAM,GAAG,QAAQ"}
|
|
@@ -53,6 +53,20 @@ export declare const multiplyTransformMatrices: (a: TMat2D, b: TMat2D, is2x2?: b
|
|
|
53
53
|
*/
|
|
54
54
|
export declare const multiplyTransformMatrixArray: (matrices: (TMat2D | undefined | null | false)[], is2x2?: boolean) => TMat2D;
|
|
55
55
|
export declare const calcPlaneRotation: ([a, b]: TMat2D) => TRadian;
|
|
56
|
+
/**
|
|
57
|
+
* Returns the uniform scale (zoom) magnitude of a 2D affine matrix,
|
|
58
|
+
* computed as the length of the image of the unit X basis vector.
|
|
59
|
+
*/
|
|
60
|
+
export declare const calcPlaneZoom: ([a, b]: TMat2D) => number;
|
|
61
|
+
/**
|
|
62
|
+
* Returns the Y-axis scale magnitude of a 2D affine matrix,
|
|
63
|
+
* computed as the length of the image of the unit Y basis vector.
|
|
64
|
+
* We do not support non uniform zooming on the viewport but to make things work
|
|
65
|
+
* we need to have a function that can return the value on Y axis.
|
|
66
|
+
* Bug reports and features will be planned with zoom being just a number
|
|
67
|
+
* that is the same for both axis
|
|
68
|
+
*/
|
|
69
|
+
export declare const calcPlaneScaleY: ([, , c, d]: TMat2D) => number;
|
|
56
70
|
/**
|
|
57
71
|
* Decomposes standard 2x3 matrix into transform components
|
|
58
72
|
* @param {TMat2D} a transformMatrix
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matrix.d.ts","sourceRoot":"","sources":["../../../../src/util/misc/matrix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAK/D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,oBAAoB,GACnD,iBAAiB,GACjB,gBAAgB,CAAC;AAEnB,MAAM,MAAM,eAAe,GAAG,QAAQ,CACpC,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,OAAO,CAAC,CAC5C,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,YACW,CAAC;AAExD;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GACzB,GAAG,EAAE,EACL,GAAG,MAAM,EACT,eAAe,OAAO,KACrB,KAAgD,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,MAAM,KAAG,MAO3C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GACpC,GAAG,MAAM,EACT,GAAG,MAAM,EACT,QAAQ,OAAO,KACd,MAQU,CAAC;AAEd;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,GACvC,UAAU,CAAC,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,KAAK,CAAC,EAAE,EAC/C,QAAQ,OAAO,WAQM,CAAC;AAExB,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,KAC1B,OAAO,CAAC;AAE9B;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,KAAG,eAevC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,GAAI,GAAG,MAAM,EAAE,UAAK,KAAG,MAOxD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,KAAS,EAAE,GAAE,iBAAsB,EACrC,EAAE,CAAK,EAAE,CAAK,EAAE,GAAE,OAAO,CAAC,EAAE,CAAM,GACjC,MAAM,CAYR;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,GAAI,GAAG,MAAM,EAAE,IAAG,MAAU,KAAG,MAO5D,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,WACP,CAAC;AAEpC,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,YACN,CAAC;AAErC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAAI,WAAW,OAAO,KAAG,MAOtD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAAI,WAAW,OAAO,KAAG,MAOtD,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAAI,iDAOlC,gBAAgB,WAYlB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,GAAI,SAAS,kBAAkB,KAAG,MAW3D,CAAC"}
|
|
1
|
+
{"version":3,"file":"matrix.d.ts","sourceRoot":"","sources":["../../../../src/util/misc/matrix.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{iMatrix as e}from"../../constants.min.mjs";import{cos as t}from"./cos.min.mjs";import{sin as n}from"./sin.min.mjs";import{Point as r}from"../../Point.min.mjs";import{degreesToRadians as i,radiansToDegrees as a}from"./radiansDegreesConversion.min.mjs";const o=t=>t.every((t,n)=>t===e[n]),s=(e,t,n)=>new r(e).transform(t,n),c=e=>{let t=1/(e[0]*e[3]-e[1]*e[2]),n=[t*e[3],-t*e[1],-t*e[2],t*e[0],0,0],{x:i,y:a}=new r(e[4],e[5]).transform(n,!0);return n[4]=-i,n[5]=-a,n},l=(e,t,n)=>[e[0]*t[0]+e[2]*t[1],e[1]*t[0]+e[3]*t[1],e[0]*t[2]+e[2]*t[3],e[1]*t[2]+e[3]*t[3],n?0:e[0]*t[4]+e[2]*t[5]+e[4],n?0:e[1]*t[4]+e[3]*t[5]+e[5]],u=(t,n)=>t.reduceRight((e,t)=>t&&e?l(t,e,n):t||e,void 0)||e.concat(),d=([e,t])=>Math.atan2(t,e),f=e=>{let t=d(e),n=e[0]**2+e[1]**2,r=Math.sqrt(n),i=(e[0]*e[3]-e[2]*e[1])/r,o=Math.atan2(e[0]*e[2]+e[1]*e[3],n);return{angle:a(t),scaleX:r,scaleY:i,skewX:a(o),skewY:0,translateX:e[4]||0,translateY:e[5]||0}},
|
|
1
|
+
import{iMatrix as e}from"../../constants.min.mjs";import{cos as t}from"./cos.min.mjs";import{sin as n}from"./sin.min.mjs";import{Point as r}from"../../Point.min.mjs";import{degreesToRadians as i,radiansToDegrees as a}from"./radiansDegreesConversion.min.mjs";const o=t=>t.every((t,n)=>t===e[n]),s=(e,t,n)=>new r(e).transform(t,n),c=e=>{let t=1/(e[0]*e[3]-e[1]*e[2]),n=[t*e[3],-t*e[1],-t*e[2],t*e[0],0,0],{x:i,y:a}=new r(e[4],e[5]).transform(n,!0);return n[4]=-i,n[5]=-a,n},l=(e,t,n)=>[e[0]*t[0]+e[2]*t[1],e[1]*t[0]+e[3]*t[1],e[0]*t[2]+e[2]*t[3],e[1]*t[2]+e[3]*t[3],n?0:e[0]*t[4]+e[2]*t[5]+e[4],n?0:e[1]*t[4]+e[3]*t[5]+e[5]],u=(t,n)=>t.reduceRight((e,t)=>t&&e?l(t,e,n):t||e,void 0)||e.concat(),d=([e,t])=>Math.atan2(t,e),f=([e,t])=>Math.sqrt(e*e+t*t),p=([,,e,t])=>Math.sqrt(e*e+t*t),m=e=>{let t=d(e),n=e[0]**2+e[1]**2,r=Math.sqrt(n),i=(e[0]*e[3]-e[2]*e[1])/r,o=Math.atan2(e[0]*e[2]+e[1]*e[3],n);return{angle:a(t),scaleX:r,scaleY:i,skewX:a(o),skewY:0,translateX:e[4]||0,translateY:e[5]||0}},h=(e,t=0)=>[1,0,0,1,e,t];function g({angle:e=0}={},{x:r=0,y:a=0}={}){let o=i(e),s=t(o),c=n(o);return[s,c,-c,s,r?r-(s*r-c*a):0,a?a-(c*r+s*a):0]}const _=(e,t=e)=>[e,0,0,t,0,0],v=e=>Math.tan(i(e)),y=e=>[1,0,v(e),1,0,0],b=e=>[1,v(e),0,1,0,0],x=({scaleX:e=1,scaleY:t=1,flipX:n=!1,flipY:r=!1,skewX:i=0,skewY:a=0})=>{let o=_(n?-e:e,r?-t:t);return i&&(o=l(o,y(i),!0)),a&&(o=l(o,b(a),!0)),o},S=e=>{let{translateX:t=0,translateY:n=0,angle:r=0}=e,i=h(t,n);r&&(i=l(i,g({angle:r})));let a=x(e);return o(a)||(i=l(i,a)),i};export{x as calcDimensionsMatrix,d as calcPlaneRotation,p as calcPlaneScaleY,f as calcPlaneZoom,S as composeMatrix,g as createRotateMatrix,_ as createScaleMatrix,y as createSkewXMatrix,b as createSkewYMatrix,h as createTranslateMatrix,c as invertTransform,o as isIdentityMatrix,l as multiplyTransformMatrices,u as multiplyTransformMatrixArray,m as qrDecompose,s as transformPoint};
|
|
2
2
|
//# sourceMappingURL=matrix.min.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matrix.min.mjs","names":[],"sources":["../../../../src/util/misc/matrix.ts"],"sourcesContent":["import { iMatrix } from '../../constants';\nimport type { XY } from '../../Point';\nimport { Point } from '../../Point';\nimport type { TDegree, TRadian, TMat2D } from '../../typedefs';\nimport { cos } from './cos';\nimport { degreesToRadians, radiansToDegrees } from './radiansDegreesConversion';\nimport { sin } from './sin';\n\nexport type TRotateMatrixArgs = {\n angle?: TDegree;\n};\n\nexport type TTranslateMatrixArgs = {\n translateX?: number;\n translateY?: number;\n};\n\nexport type TScaleMatrixArgs = {\n scaleX?: number;\n scaleY?: number;\n flipX?: boolean;\n flipY?: boolean;\n skewX?: TDegree;\n skewY?: TDegree;\n};\n\nexport type TComposeMatrixArgs = TTranslateMatrixArgs &\n TRotateMatrixArgs &\n TScaleMatrixArgs;\n\nexport type TQrDecomposeOut = Required<\n Omit<TComposeMatrixArgs, 'flipX' | 'flipY'>\n>;\n\nexport const isIdentityMatrix = (mat: TMat2D) =>\n mat.every((value, index) => value === iMatrix[index]);\n\n/**\n * Apply transform t to point p\n * @deprecated use {@link Point#transform}\n * @param {Point | XY} p The point to transform\n * @param {Array} t The transform\n * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n * @return {Point} The transformed point\n */\nexport const transformPoint = (\n p: XY,\n t: TMat2D,\n ignoreOffset?: boolean,\n): Point => new Point(p).transform(t, ignoreOffset);\n\n/**\n * Invert transformation t\n * @param {Array} t The transform\n * @return {Array} The inverted transform\n */\nexport const invertTransform = (t: TMat2D): TMat2D => {\n const a = 1 / (t[0] * t[3] - t[1] * t[2]),\n r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0] as TMat2D,\n { x, y } = new Point(t[4], t[5]).transform(r, true);\n r[4] = -x;\n r[5] = -y;\n return r;\n};\n\n/**\n * Multiply matrix A by matrix B to nest transformations\n * @param {TMat2D} a First transformMatrix\n * @param {TMat2D} b Second transformMatrix\n * @param {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\n * @return {TMat2D} The product of the two transform matrices\n */\nexport const multiplyTransformMatrices = (\n a: TMat2D,\n b: TMat2D,\n is2x2?: boolean,\n): TMat2D =>\n [\n a[0] * b[0] + a[2] * b[1],\n a[1] * b[0] + a[3] * b[1],\n a[0] * b[2] + a[2] * b[3],\n a[1] * b[2] + a[3] * b[3],\n is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],\n is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5],\n ] as TMat2D;\n\n/**\n * Multiplies the matrices array such that a matrix defines the plane for the rest of the matrices **after** it\n *\n * `multiplyTransformMatrixArray([A, B, C, D])` is equivalent to `A(B(C(D)))`\n *\n * @param matrices an array of matrices\n * @param [is2x2] flag to multiply matrices as 2x2 matrices\n * @returns the multiplication product\n */\nexport const multiplyTransformMatrixArray = (\n matrices: (TMat2D | undefined | null | false)[],\n is2x2?: boolean,\n) =>\n matrices.reduceRight(\n (product: TMat2D, curr) =>\n curr && product\n ? multiplyTransformMatrices(curr, product, is2x2)\n : curr || product,\n undefined as unknown as TMat2D,\n ) || iMatrix.concat();\n\nexport const calcPlaneRotation = ([a, b]: TMat2D) =>\n Math.atan2(b, a) as TRadian;\n\n/**\n * Decomposes standard 2x3 matrix into transform components\n * @param {TMat2D} a transformMatrix\n * @return {Object} Components of transform\n */\nexport const qrDecompose = (a: TMat2D): TQrDecomposeOut => {\n const angle = calcPlaneRotation(a),\n denom = Math.pow(a[0], 2) + Math.pow(a[1], 2),\n scaleX = Math.sqrt(denom),\n scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,\n skewX = Math.atan2(a[0] * a[2] + a[1] * a[3], denom);\n return {\n angle: radiansToDegrees(angle),\n scaleX,\n scaleY,\n skewX: radiansToDegrees(skewX),\n skewY: 0 as TDegree,\n translateX: a[4] || 0,\n translateY: a[5] || 0,\n };\n};\n\n/**\n * Generate a translation matrix\n *\n * A translation matrix in the form of\n * [ 1 0 x ]\n * [ 0 1 y ]\n * [ 0 0 1 ]\n *\n * See {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#translate} for more details\n *\n * @param {number} x translation on X axis\n * @param {number} [y] translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createTranslateMatrix = (x: number, y = 0): TMat2D => [\n 1,\n 0,\n 0,\n 1,\n x,\n y,\n];\n\n/**\n * Generate a rotation matrix around around a point (x,y), defaulting to (0,0)\n *\n * A matrix in the form of\n * [cos(a) -sin(a) -x*cos(a)+y*sin(a)+x]\n * [sin(a) cos(a) -x*sin(a)-y*cos(a)+y]\n * [0 0 1 ]\n *\n *\n * @param {TDegree} angle rotation in degrees\n * @param {XY} [pivotPoint] pivot point to rotate around\n * @returns {TMat2D} matrix\n */\nexport function createRotateMatrix(\n { angle = 0 }: TRotateMatrixArgs = {},\n { x = 0, y = 0 }: Partial<XY> = {},\n): TMat2D {\n const angleRadiant = degreesToRadians(angle),\n cosValue = cos(angleRadiant),\n sinValue = sin(angleRadiant);\n return [\n cosValue,\n sinValue,\n -sinValue,\n cosValue,\n x ? x - (cosValue * x - sinValue * y) : 0,\n y ? y - (sinValue * x + cosValue * y) : 0,\n ];\n}\n\n/**\n * Generate a scale matrix around the point (0,0)\n *\n * A matrix in the form of\n * [x 0 0]\n * [0 y 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#scale}\n *\n * @param {number} x scale on X axis\n * @param {number} [y] scale on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createScaleMatrix = (x: number, y: number = x): TMat2D => [\n x,\n 0,\n 0,\n y,\n 0,\n 0,\n];\n\nexport const angleToSkew = (angle: TDegree) =>\n Math.tan(degreesToRadians(angle));\n\nexport const skewToAngle = (value: TRadian) =>\n radiansToDegrees(Math.atan(value));\n\n/**\n * Generate a skew matrix for the X axis\n *\n * A matrix in the form of\n * [1 x 0]\n * [0 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewx}\n *\n * @param {TDegree} skewValue translation on X axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewXMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n 0,\n angleToSkew(skewValue),\n 1,\n 0,\n 0,\n];\n\n/**\n * Generate a skew matrix for the Y axis\n *\n * A matrix in the form of\n * [1 0 0]\n * [y 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewy}\n *\n * @param {TDegree} skewValue translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewYMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n angleToSkew(skewValue),\n 0,\n 1,\n 0,\n 0,\n];\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet.\n * is called DimensionsTransformMatrix because those properties are the one that influence\n * the size of the resulting box of the object.\n * @param {Object} options\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @return {Number[]} transform matrix\n */\nexport const calcDimensionsMatrix = ({\n scaleX = 1,\n scaleY = 1,\n flipX = false,\n flipY = false,\n skewX = 0 as TDegree,\n skewY = 0 as TDegree,\n}: TScaleMatrixArgs) => {\n let matrix = createScaleMatrix(\n flipX ? -scaleX : scaleX,\n flipY ? -scaleY : scaleY,\n );\n if (skewX) {\n matrix = multiplyTransformMatrices(matrix, createSkewXMatrix(skewX), true);\n }\n if (skewY) {\n matrix = multiplyTransformMatrices(matrix, createSkewYMatrix(skewY), true);\n }\n return matrix;\n};\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet\n * Before changing this function look at: src/benchmarks/calcTransformMatrix.mjs\n * @param {Object} options\n * @param {Number} [options.angle]\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @param {Number} [options.translateX]\n * @param {Number} [options.translateY]\n * @return {Number[]} transform matrix\n */\nexport const composeMatrix = (options: TComposeMatrixArgs): TMat2D => {\n const { translateX = 0, translateY = 0, angle = 0 as TDegree } = options;\n let matrix = createTranslateMatrix(translateX, translateY);\n if (angle) {\n matrix = multiplyTransformMatrices(matrix, createRotateMatrix({ angle }));\n }\n const scaleMatrix = calcDimensionsMatrix(options);\n if (!isIdentityMatrix(scaleMatrix)) {\n matrix = multiplyTransformMatrices(matrix, scaleMatrix);\n }\n return matrix;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"matrix.min.mjs","names":[],"sources":["../../../../src/util/misc/matrix.ts"],"sourcesContent":["import { iMatrix } from '../../constants';\nimport type { XY } from '../../Point';\nimport { Point } from '../../Point';\nimport type { TDegree, TRadian, TMat2D } from '../../typedefs';\nimport { cos } from './cos';\nimport { degreesToRadians, radiansToDegrees } from './radiansDegreesConversion';\nimport { sin } from './sin';\n\nexport type TRotateMatrixArgs = {\n angle?: TDegree;\n};\n\nexport type TTranslateMatrixArgs = {\n translateX?: number;\n translateY?: number;\n};\n\nexport type TScaleMatrixArgs = {\n scaleX?: number;\n scaleY?: number;\n flipX?: boolean;\n flipY?: boolean;\n skewX?: TDegree;\n skewY?: TDegree;\n};\n\nexport type TComposeMatrixArgs = TTranslateMatrixArgs &\n TRotateMatrixArgs &\n TScaleMatrixArgs;\n\nexport type TQrDecomposeOut = Required<\n Omit<TComposeMatrixArgs, 'flipX' | 'flipY'>\n>;\n\nexport const isIdentityMatrix = (mat: TMat2D) =>\n mat.every((value, index) => value === iMatrix[index]);\n\n/**\n * Apply transform t to point p\n * @deprecated use {@link Point#transform}\n * @param {Point | XY} p The point to transform\n * @param {Array} t The transform\n * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n * @return {Point} The transformed point\n */\nexport const transformPoint = (\n p: XY,\n t: TMat2D,\n ignoreOffset?: boolean,\n): Point => new Point(p).transform(t, ignoreOffset);\n\n/**\n * Invert transformation t\n * @param {Array} t The transform\n * @return {Array} The inverted transform\n */\nexport const invertTransform = (t: TMat2D): TMat2D => {\n const a = 1 / (t[0] * t[3] - t[1] * t[2]),\n r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0] as TMat2D,\n { x, y } = new Point(t[4], t[5]).transform(r, true);\n r[4] = -x;\n r[5] = -y;\n return r;\n};\n\n/**\n * Multiply matrix A by matrix B to nest transformations\n * @param {TMat2D} a First transformMatrix\n * @param {TMat2D} b Second transformMatrix\n * @param {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\n * @return {TMat2D} The product of the two transform matrices\n */\nexport const multiplyTransformMatrices = (\n a: TMat2D,\n b: TMat2D,\n is2x2?: boolean,\n): TMat2D =>\n [\n a[0] * b[0] + a[2] * b[1],\n a[1] * b[0] + a[3] * b[1],\n a[0] * b[2] + a[2] * b[3],\n a[1] * b[2] + a[3] * b[3],\n is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],\n is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5],\n ] as TMat2D;\n\n/**\n * Multiplies the matrices array such that a matrix defines the plane for the rest of the matrices **after** it\n *\n * `multiplyTransformMatrixArray([A, B, C, D])` is equivalent to `A(B(C(D)))`\n *\n * @param matrices an array of matrices\n * @param [is2x2] flag to multiply matrices as 2x2 matrices\n * @returns the multiplication product\n */\nexport const multiplyTransformMatrixArray = (\n matrices: (TMat2D | undefined | null | false)[],\n is2x2?: boolean,\n) =>\n matrices.reduceRight(\n (product: TMat2D, curr) =>\n curr && product\n ? multiplyTransformMatrices(curr, product, is2x2)\n : curr || product,\n undefined as unknown as TMat2D,\n ) || iMatrix.concat();\n\nexport const calcPlaneRotation = ([a, b]: TMat2D) =>\n Math.atan2(b, a) as TRadian;\n\n/**\n * Returns the uniform scale (zoom) magnitude of a 2D affine matrix,\n * computed as the length of the image of the unit X basis vector.\n */\nexport const calcPlaneZoom = ([a, b]: TMat2D) => Math.sqrt(a * a + b * b);\n\n/**\n * Returns the Y-axis scale magnitude of a 2D affine matrix,\n * computed as the length of the image of the unit Y basis vector.\n * We do not support non uniform zooming on the viewport but to make things work\n * we need to have a function that can return the value on Y axis.\n * Bug reports and features will be planned with zoom being just a number\n * that is the same for both axis\n */\nexport const calcPlaneScaleY = ([, , c, d]: TMat2D) => Math.sqrt(c * c + d * d);\n\n/**\n * Decomposes standard 2x3 matrix into transform components\n * @param {TMat2D} a transformMatrix\n * @return {Object} Components of transform\n */\nexport const qrDecompose = (a: TMat2D): TQrDecomposeOut => {\n const angle = calcPlaneRotation(a),\n denom = Math.pow(a[0], 2) + Math.pow(a[1], 2),\n scaleX = Math.sqrt(denom),\n scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,\n skewX = Math.atan2(a[0] * a[2] + a[1] * a[3], denom);\n return {\n angle: radiansToDegrees(angle),\n scaleX,\n scaleY,\n skewX: radiansToDegrees(skewX),\n skewY: 0 as TDegree,\n translateX: a[4] || 0,\n translateY: a[5] || 0,\n };\n};\n\n/**\n * Generate a translation matrix\n *\n * A translation matrix in the form of\n * [ 1 0 x ]\n * [ 0 1 y ]\n * [ 0 0 1 ]\n *\n * See {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#translate} for more details\n *\n * @param {number} x translation on X axis\n * @param {number} [y] translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createTranslateMatrix = (x: number, y = 0): TMat2D => [\n 1,\n 0,\n 0,\n 1,\n x,\n y,\n];\n\n/**\n * Generate a rotation matrix around around a point (x,y), defaulting to (0,0)\n *\n * A matrix in the form of\n * [cos(a) -sin(a) -x*cos(a)+y*sin(a)+x]\n * [sin(a) cos(a) -x*sin(a)-y*cos(a)+y]\n * [0 0 1 ]\n *\n *\n * @param {TDegree} angle rotation in degrees\n * @param {XY} [pivotPoint] pivot point to rotate around\n * @returns {TMat2D} matrix\n */\nexport function createRotateMatrix(\n { angle = 0 }: TRotateMatrixArgs = {},\n { x = 0, y = 0 }: Partial<XY> = {},\n): TMat2D {\n const angleRadiant = degreesToRadians(angle),\n cosValue = cos(angleRadiant),\n sinValue = sin(angleRadiant);\n return [\n cosValue,\n sinValue,\n -sinValue,\n cosValue,\n x ? x - (cosValue * x - sinValue * y) : 0,\n y ? y - (sinValue * x + cosValue * y) : 0,\n ];\n}\n\n/**\n * Generate a scale matrix around the point (0,0)\n *\n * A matrix in the form of\n * [x 0 0]\n * [0 y 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#scale}\n *\n * @param {number} x scale on X axis\n * @param {number} [y] scale on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createScaleMatrix = (x: number, y: number = x): TMat2D => [\n x,\n 0,\n 0,\n y,\n 0,\n 0,\n];\n\nexport const angleToSkew = (angle: TDegree) =>\n Math.tan(degreesToRadians(angle));\n\nexport const skewToAngle = (value: TRadian) =>\n radiansToDegrees(Math.atan(value));\n\n/**\n * Generate a skew matrix for the X axis\n *\n * A matrix in the form of\n * [1 x 0]\n * [0 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewx}\n *\n * @param {TDegree} skewValue translation on X axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewXMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n 0,\n angleToSkew(skewValue),\n 1,\n 0,\n 0,\n];\n\n/**\n * Generate a skew matrix for the Y axis\n *\n * A matrix in the form of\n * [1 0 0]\n * [y 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewy}\n *\n * @param {TDegree} skewValue translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewYMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n angleToSkew(skewValue),\n 0,\n 1,\n 0,\n 0,\n];\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet.\n * is called DimensionsTransformMatrix because those properties are the one that influence\n * the size of the resulting box of the object.\n * @param {Object} options\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @return {Number[]} transform matrix\n */\nexport const calcDimensionsMatrix = ({\n scaleX = 1,\n scaleY = 1,\n flipX = false,\n flipY = false,\n skewX = 0 as TDegree,\n skewY = 0 as TDegree,\n}: TScaleMatrixArgs) => {\n let matrix = createScaleMatrix(\n flipX ? -scaleX : scaleX,\n flipY ? -scaleY : scaleY,\n );\n if (skewX) {\n matrix = multiplyTransformMatrices(matrix, createSkewXMatrix(skewX), true);\n }\n if (skewY) {\n matrix = multiplyTransformMatrices(matrix, createSkewYMatrix(skewY), true);\n }\n return matrix;\n};\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet\n * Before changing this function look at: src/benchmarks/calcTransformMatrix.mjs\n * @param {Object} options\n * @param {Number} [options.angle]\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @param {Number} [options.translateX]\n * @param {Number} [options.translateY]\n * @return {Number[]} transform matrix\n */\nexport const composeMatrix = (options: TComposeMatrixArgs): TMat2D => {\n const { translateX = 0, translateY = 0, angle = 0 as TDegree } = options;\n let matrix = createTranslateMatrix(translateX, translateY);\n if (angle) {\n matrix = multiplyTransformMatrices(matrix, createRotateMatrix({ angle }));\n }\n const scaleMatrix = calcDimensionsMatrix(options);\n if (!isIdentityMatrix(scaleMatrix)) {\n matrix = multiplyTransformMatrices(matrix, scaleMatrix);\n }\n return matrix;\n};\n"],"mappings":"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"}
|
|
@@ -59,6 +59,20 @@ const multiplyTransformMatrices = (a, b, is2x2) => [
|
|
|
59
59
|
const multiplyTransformMatrixArray = (matrices, is2x2) => matrices.reduceRight((product, curr) => curr && product ? multiplyTransformMatrices(curr, product, is2x2) : curr || product, void 0) || iMatrix.concat();
|
|
60
60
|
const calcPlaneRotation = ([a, b]) => Math.atan2(b, a);
|
|
61
61
|
/**
|
|
62
|
+
* Returns the uniform scale (zoom) magnitude of a 2D affine matrix,
|
|
63
|
+
* computed as the length of the image of the unit X basis vector.
|
|
64
|
+
*/
|
|
65
|
+
const calcPlaneZoom = ([a, b]) => Math.sqrt(a * a + b * b);
|
|
66
|
+
/**
|
|
67
|
+
* Returns the Y-axis scale magnitude of a 2D affine matrix,
|
|
68
|
+
* computed as the length of the image of the unit Y basis vector.
|
|
69
|
+
* We do not support non uniform zooming on the viewport but to make things work
|
|
70
|
+
* we need to have a function that can return the value on Y axis.
|
|
71
|
+
* Bug reports and features will be planned with zoom being just a number
|
|
72
|
+
* that is the same for both axis
|
|
73
|
+
*/
|
|
74
|
+
const calcPlaneScaleY = ([, , c, d]) => Math.sqrt(c * c + d * d);
|
|
75
|
+
/**
|
|
62
76
|
* Decomposes standard 2x3 matrix into transform components
|
|
63
77
|
* @param {TMat2D} a transformMatrix
|
|
64
78
|
* @return {Object} Components of transform
|
|
@@ -233,6 +247,6 @@ const composeMatrix = (options) => {
|
|
|
233
247
|
return matrix;
|
|
234
248
|
};
|
|
235
249
|
//#endregion
|
|
236
|
-
export { calcDimensionsMatrix, calcPlaneRotation, composeMatrix, createRotateMatrix, createScaleMatrix, createSkewXMatrix, createSkewYMatrix, createTranslateMatrix, invertTransform, isIdentityMatrix, multiplyTransformMatrices, multiplyTransformMatrixArray, qrDecompose, transformPoint };
|
|
250
|
+
export { calcDimensionsMatrix, calcPlaneRotation, calcPlaneScaleY, calcPlaneZoom, composeMatrix, createRotateMatrix, createScaleMatrix, createSkewXMatrix, createSkewYMatrix, createTranslateMatrix, invertTransform, isIdentityMatrix, multiplyTransformMatrices, multiplyTransformMatrixArray, qrDecompose, transformPoint };
|
|
237
251
|
|
|
238
252
|
//# sourceMappingURL=matrix.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matrix.mjs","names":[],"sources":["../../../../src/util/misc/matrix.ts"],"sourcesContent":["import { iMatrix } from '../../constants';\nimport type { XY } from '../../Point';\nimport { Point } from '../../Point';\nimport type { TDegree, TRadian, TMat2D } from '../../typedefs';\nimport { cos } from './cos';\nimport { degreesToRadians, radiansToDegrees } from './radiansDegreesConversion';\nimport { sin } from './sin';\n\nexport type TRotateMatrixArgs = {\n angle?: TDegree;\n};\n\nexport type TTranslateMatrixArgs = {\n translateX?: number;\n translateY?: number;\n};\n\nexport type TScaleMatrixArgs = {\n scaleX?: number;\n scaleY?: number;\n flipX?: boolean;\n flipY?: boolean;\n skewX?: TDegree;\n skewY?: TDegree;\n};\n\nexport type TComposeMatrixArgs = TTranslateMatrixArgs &\n TRotateMatrixArgs &\n TScaleMatrixArgs;\n\nexport type TQrDecomposeOut = Required<\n Omit<TComposeMatrixArgs, 'flipX' | 'flipY'>\n>;\n\nexport const isIdentityMatrix = (mat: TMat2D) =>\n mat.every((value, index) => value === iMatrix[index]);\n\n/**\n * Apply transform t to point p\n * @deprecated use {@link Point#transform}\n * @param {Point | XY} p The point to transform\n * @param {Array} t The transform\n * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n * @return {Point} The transformed point\n */\nexport const transformPoint = (\n p: XY,\n t: TMat2D,\n ignoreOffset?: boolean,\n): Point => new Point(p).transform(t, ignoreOffset);\n\n/**\n * Invert transformation t\n * @param {Array} t The transform\n * @return {Array} The inverted transform\n */\nexport const invertTransform = (t: TMat2D): TMat2D => {\n const a = 1 / (t[0] * t[3] - t[1] * t[2]),\n r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0] as TMat2D,\n { x, y } = new Point(t[4], t[5]).transform(r, true);\n r[4] = -x;\n r[5] = -y;\n return r;\n};\n\n/**\n * Multiply matrix A by matrix B to nest transformations\n * @param {TMat2D} a First transformMatrix\n * @param {TMat2D} b Second transformMatrix\n * @param {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\n * @return {TMat2D} The product of the two transform matrices\n */\nexport const multiplyTransformMatrices = (\n a: TMat2D,\n b: TMat2D,\n is2x2?: boolean,\n): TMat2D =>\n [\n a[0] * b[0] + a[2] * b[1],\n a[1] * b[0] + a[3] * b[1],\n a[0] * b[2] + a[2] * b[3],\n a[1] * b[2] + a[3] * b[3],\n is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],\n is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5],\n ] as TMat2D;\n\n/**\n * Multiplies the matrices array such that a matrix defines the plane for the rest of the matrices **after** it\n *\n * `multiplyTransformMatrixArray([A, B, C, D])` is equivalent to `A(B(C(D)))`\n *\n * @param matrices an array of matrices\n * @param [is2x2] flag to multiply matrices as 2x2 matrices\n * @returns the multiplication product\n */\nexport const multiplyTransformMatrixArray = (\n matrices: (TMat2D | undefined | null | false)[],\n is2x2?: boolean,\n) =>\n matrices.reduceRight(\n (product: TMat2D, curr) =>\n curr && product\n ? multiplyTransformMatrices(curr, product, is2x2)\n : curr || product,\n undefined as unknown as TMat2D,\n ) || iMatrix.concat();\n\nexport const calcPlaneRotation = ([a, b]: TMat2D) =>\n Math.atan2(b, a) as TRadian;\n\n/**\n * Decomposes standard 2x3 matrix into transform components\n * @param {TMat2D} a transformMatrix\n * @return {Object} Components of transform\n */\nexport const qrDecompose = (a: TMat2D): TQrDecomposeOut => {\n const angle = calcPlaneRotation(a),\n denom = Math.pow(a[0], 2) + Math.pow(a[1], 2),\n scaleX = Math.sqrt(denom),\n scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,\n skewX = Math.atan2(a[0] * a[2] + a[1] * a[3], denom);\n return {\n angle: radiansToDegrees(angle),\n scaleX,\n scaleY,\n skewX: radiansToDegrees(skewX),\n skewY: 0 as TDegree,\n translateX: a[4] || 0,\n translateY: a[5] || 0,\n };\n};\n\n/**\n * Generate a translation matrix\n *\n * A translation matrix in the form of\n * [ 1 0 x ]\n * [ 0 1 y ]\n * [ 0 0 1 ]\n *\n * See {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#translate} for more details\n *\n * @param {number} x translation on X axis\n * @param {number} [y] translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createTranslateMatrix = (x: number, y = 0): TMat2D => [\n 1,\n 0,\n 0,\n 1,\n x,\n y,\n];\n\n/**\n * Generate a rotation matrix around around a point (x,y), defaulting to (0,0)\n *\n * A matrix in the form of\n * [cos(a) -sin(a) -x*cos(a)+y*sin(a)+x]\n * [sin(a) cos(a) -x*sin(a)-y*cos(a)+y]\n * [0 0 1 ]\n *\n *\n * @param {TDegree} angle rotation in degrees\n * @param {XY} [pivotPoint] pivot point to rotate around\n * @returns {TMat2D} matrix\n */\nexport function createRotateMatrix(\n { angle = 0 }: TRotateMatrixArgs = {},\n { x = 0, y = 0 }: Partial<XY> = {},\n): TMat2D {\n const angleRadiant = degreesToRadians(angle),\n cosValue = cos(angleRadiant),\n sinValue = sin(angleRadiant);\n return [\n cosValue,\n sinValue,\n -sinValue,\n cosValue,\n x ? x - (cosValue * x - sinValue * y) : 0,\n y ? y - (sinValue * x + cosValue * y) : 0,\n ];\n}\n\n/**\n * Generate a scale matrix around the point (0,0)\n *\n * A matrix in the form of\n * [x 0 0]\n * [0 y 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#scale}\n *\n * @param {number} x scale on X axis\n * @param {number} [y] scale on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createScaleMatrix = (x: number, y: number = x): TMat2D => [\n x,\n 0,\n 0,\n y,\n 0,\n 0,\n];\n\nexport const angleToSkew = (angle: TDegree) =>\n Math.tan(degreesToRadians(angle));\n\nexport const skewToAngle = (value: TRadian) =>\n radiansToDegrees(Math.atan(value));\n\n/**\n * Generate a skew matrix for the X axis\n *\n * A matrix in the form of\n * [1 x 0]\n * [0 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewx}\n *\n * @param {TDegree} skewValue translation on X axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewXMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n 0,\n angleToSkew(skewValue),\n 1,\n 0,\n 0,\n];\n\n/**\n * Generate a skew matrix for the Y axis\n *\n * A matrix in the form of\n * [1 0 0]\n * [y 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewy}\n *\n * @param {TDegree} skewValue translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewYMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n angleToSkew(skewValue),\n 0,\n 1,\n 0,\n 0,\n];\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet.\n * is called DimensionsTransformMatrix because those properties are the one that influence\n * the size of the resulting box of the object.\n * @param {Object} options\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @return {Number[]} transform matrix\n */\nexport const calcDimensionsMatrix = ({\n scaleX = 1,\n scaleY = 1,\n flipX = false,\n flipY = false,\n skewX = 0 as TDegree,\n skewY = 0 as TDegree,\n}: TScaleMatrixArgs) => {\n let matrix = createScaleMatrix(\n flipX ? -scaleX : scaleX,\n flipY ? -scaleY : scaleY,\n );\n if (skewX) {\n matrix = multiplyTransformMatrices(matrix, createSkewXMatrix(skewX), true);\n }\n if (skewY) {\n matrix = multiplyTransformMatrices(matrix, createSkewYMatrix(skewY), true);\n }\n return matrix;\n};\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet\n * Before changing this function look at: src/benchmarks/calcTransformMatrix.mjs\n * @param {Object} options\n * @param {Number} [options.angle]\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @param {Number} [options.translateX]\n * @param {Number} [options.translateY]\n * @return {Number[]} transform matrix\n */\nexport const composeMatrix = (options: TComposeMatrixArgs): TMat2D => {\n const { translateX = 0, translateY = 0, angle = 0 as TDegree } = options;\n let matrix = createTranslateMatrix(translateX, translateY);\n if (angle) {\n matrix = multiplyTransformMatrices(matrix, createRotateMatrix({ angle }));\n }\n const scaleMatrix = calcDimensionsMatrix(options);\n if (!isIdentityMatrix(scaleMatrix)) {\n matrix = multiplyTransformMatrices(matrix, scaleMatrix);\n }\n return matrix;\n};\n"],"mappings":";;;;;;AAkCA,MAAa,oBAAoB,QAC/B,IAAI,OAAO,OAAO,UAAU,UAAU,QAAQ,OAAO;;;;;;;;;AAUvD,MAAa,kBACX,GACA,GACA,iBACU,IAAI,MAAM,EAAE,CAAC,UAAU,GAAG,aAAa;;;;;;AAOnD,MAAa,mBAAmB,MAAsB;CACpD,MAAM,IAAI,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KACpC,IAAI;EAAC,IAAI,EAAE;EAAI,CAAC,IAAI,EAAE;EAAI,CAAC,IAAI,EAAE;EAAI,IAAI,EAAE;EAAI;EAAG;EAAE,EACpD,EAAE,GAAG,MAAM,IAAI,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,UAAU,GAAG,KAAK;AACrD,GAAE,KAAK,CAAC;AACR,GAAE,KAAK,CAAC;AACR,QAAO;;;;;;;;;AAUT,MAAa,6BACX,GACA,GACA,UAEA;CACE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;CACvB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;CACvB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;CACvB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;CACvB,QAAQ,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;CAC1C,QAAQ,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;CAC3C;;;;;;;;;;AAWH,MAAa,gCACX,UACA,UAEA,SAAS,aACN,SAAiB,SAChB,QAAQ,UACJ,0BAA0B,MAAM,SAAS,MAAM,GAC/C,QAAQ,SACd,KAAA,EACD,IAAI,QAAQ,QAAQ;AAEvB,MAAa,qBAAqB,CAAC,GAAG,OACpC,KAAK,MAAM,GAAG,EAAE;;;;;;AAOlB,MAAa,eAAe,MAA+B;CACzD,MAAM,QAAQ,kBAAkB,EAAE,EAChC,QAAQ,KAAK,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,IAAI,EAAE,EAC7C,SAAS,KAAK,KAAK,MAAM,EACzB,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,QACvC,QAAQ,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,MAAM;AACtD,QAAO;EACL,OAAO,iBAAiB,MAAM;EAC9B;EACA;EACA,OAAO,iBAAiB,MAAM;EAC9B,OAAO;EACP,YAAY,EAAE,MAAM;EACpB,YAAY,EAAE,MAAM;EACrB;;;;;;;;;;;;;;;;AAiBH,MAAa,yBAAyB,GAAW,IAAI,MAAc;CACjE;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;;;;;;;;;AAeD,SAAgB,mBACd,EAAE,QAAQ,MAAyB,EAAE,EACrC,EAAE,IAAI,GAAG,IAAI,MAAmB,EAAE,EAC1B;CACR,MAAM,eAAe,iBAAiB,MAAM,EAC1C,WAAW,IAAI,aAAa,EAC5B,WAAW,IAAI,aAAa;AAC9B,QAAO;EACL;EACA;EACA,CAAC;EACD;EACA,IAAI,KAAK,WAAW,IAAI,WAAW,KAAK;EACxC,IAAI,KAAK,WAAW,IAAI,WAAW,KAAK;EACzC;;;;;;;;;;;;;;;;AAiBH,MAAa,qBAAqB,GAAW,IAAY,MAAc;CACrE;CACA;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,eAAe,UAC1B,KAAK,IAAI,iBAAiB,MAAM,CAAC;;;;;;;;;;;;;;AAkBnC,MAAa,qBAAqB,cAA+B;CAC/D;CACA;CACA,YAAY,UAAU;CACtB;CACA;CACA;CACD;;;;;;;;;;;;;;AAeD,MAAa,qBAAqB,cAA+B;CAC/D;CACA,YAAY,UAAU;CACtB;CACA;CACA;CACA;CACD;;;;;;;;;;;;;;;;AAiBD,MAAa,wBAAwB,EACnC,SAAS,GACT,SAAS,GACT,QAAQ,OACR,QAAQ,OACR,QAAQ,GACR,QAAQ,QACc;CACtB,IAAI,SAAS,kBACX,QAAQ,CAAC,SAAS,QAClB,QAAQ,CAAC,SAAS,OACnB;AACD,KAAI,MACF,UAAS,0BAA0B,QAAQ,kBAAkB,MAAM,EAAE,KAAK;AAE5E,KAAI,MACF,UAAS,0BAA0B,QAAQ,kBAAkB,MAAM,EAAE,KAAK;AAE5E,QAAO;;;;;;;;;;;;;;;;;;;AAoBT,MAAa,iBAAiB,YAAwC;CACpE,MAAM,EAAE,aAAa,GAAG,aAAa,GAAG,QAAQ,MAAiB;CACjE,IAAI,SAAS,sBAAsB,YAAY,WAAW;AAC1D,KAAI,MACF,UAAS,0BAA0B,QAAQ,mBAAmB,EAAE,OAAO,CAAC,CAAC;CAE3E,MAAM,cAAc,qBAAqB,QAAQ;AACjD,KAAI,CAAC,iBAAiB,YAAY,CAChC,UAAS,0BAA0B,QAAQ,YAAY;AAEzD,QAAO"}
|
|
1
|
+
{"version":3,"file":"matrix.mjs","names":[],"sources":["../../../../src/util/misc/matrix.ts"],"sourcesContent":["import { iMatrix } from '../../constants';\nimport type { XY } from '../../Point';\nimport { Point } from '../../Point';\nimport type { TDegree, TRadian, TMat2D } from '../../typedefs';\nimport { cos } from './cos';\nimport { degreesToRadians, radiansToDegrees } from './radiansDegreesConversion';\nimport { sin } from './sin';\n\nexport type TRotateMatrixArgs = {\n angle?: TDegree;\n};\n\nexport type TTranslateMatrixArgs = {\n translateX?: number;\n translateY?: number;\n};\n\nexport type TScaleMatrixArgs = {\n scaleX?: number;\n scaleY?: number;\n flipX?: boolean;\n flipY?: boolean;\n skewX?: TDegree;\n skewY?: TDegree;\n};\n\nexport type TComposeMatrixArgs = TTranslateMatrixArgs &\n TRotateMatrixArgs &\n TScaleMatrixArgs;\n\nexport type TQrDecomposeOut = Required<\n Omit<TComposeMatrixArgs, 'flipX' | 'flipY'>\n>;\n\nexport const isIdentityMatrix = (mat: TMat2D) =>\n mat.every((value, index) => value === iMatrix[index]);\n\n/**\n * Apply transform t to point p\n * @deprecated use {@link Point#transform}\n * @param {Point | XY} p The point to transform\n * @param {Array} t The transform\n * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied\n * @return {Point} The transformed point\n */\nexport const transformPoint = (\n p: XY,\n t: TMat2D,\n ignoreOffset?: boolean,\n): Point => new Point(p).transform(t, ignoreOffset);\n\n/**\n * Invert transformation t\n * @param {Array} t The transform\n * @return {Array} The inverted transform\n */\nexport const invertTransform = (t: TMat2D): TMat2D => {\n const a = 1 / (t[0] * t[3] - t[1] * t[2]),\n r = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0] as TMat2D,\n { x, y } = new Point(t[4], t[5]).transform(r, true);\n r[4] = -x;\n r[5] = -y;\n return r;\n};\n\n/**\n * Multiply matrix A by matrix B to nest transformations\n * @param {TMat2D} a First transformMatrix\n * @param {TMat2D} b Second transformMatrix\n * @param {Boolean} is2x2 flag to multiply matrices as 2x2 matrices\n * @return {TMat2D} The product of the two transform matrices\n */\nexport const multiplyTransformMatrices = (\n a: TMat2D,\n b: TMat2D,\n is2x2?: boolean,\n): TMat2D =>\n [\n a[0] * b[0] + a[2] * b[1],\n a[1] * b[0] + a[3] * b[1],\n a[0] * b[2] + a[2] * b[3],\n a[1] * b[2] + a[3] * b[3],\n is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],\n is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5],\n ] as TMat2D;\n\n/**\n * Multiplies the matrices array such that a matrix defines the plane for the rest of the matrices **after** it\n *\n * `multiplyTransformMatrixArray([A, B, C, D])` is equivalent to `A(B(C(D)))`\n *\n * @param matrices an array of matrices\n * @param [is2x2] flag to multiply matrices as 2x2 matrices\n * @returns the multiplication product\n */\nexport const multiplyTransformMatrixArray = (\n matrices: (TMat2D | undefined | null | false)[],\n is2x2?: boolean,\n) =>\n matrices.reduceRight(\n (product: TMat2D, curr) =>\n curr && product\n ? multiplyTransformMatrices(curr, product, is2x2)\n : curr || product,\n undefined as unknown as TMat2D,\n ) || iMatrix.concat();\n\nexport const calcPlaneRotation = ([a, b]: TMat2D) =>\n Math.atan2(b, a) as TRadian;\n\n/**\n * Returns the uniform scale (zoom) magnitude of a 2D affine matrix,\n * computed as the length of the image of the unit X basis vector.\n */\nexport const calcPlaneZoom = ([a, b]: TMat2D) => Math.sqrt(a * a + b * b);\n\n/**\n * Returns the Y-axis scale magnitude of a 2D affine matrix,\n * computed as the length of the image of the unit Y basis vector.\n * We do not support non uniform zooming on the viewport but to make things work\n * we need to have a function that can return the value on Y axis.\n * Bug reports and features will be planned with zoom being just a number\n * that is the same for both axis\n */\nexport const calcPlaneScaleY = ([, , c, d]: TMat2D) => Math.sqrt(c * c + d * d);\n\n/**\n * Decomposes standard 2x3 matrix into transform components\n * @param {TMat2D} a transformMatrix\n * @return {Object} Components of transform\n */\nexport const qrDecompose = (a: TMat2D): TQrDecomposeOut => {\n const angle = calcPlaneRotation(a),\n denom = Math.pow(a[0], 2) + Math.pow(a[1], 2),\n scaleX = Math.sqrt(denom),\n scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,\n skewX = Math.atan2(a[0] * a[2] + a[1] * a[3], denom);\n return {\n angle: radiansToDegrees(angle),\n scaleX,\n scaleY,\n skewX: radiansToDegrees(skewX),\n skewY: 0 as TDegree,\n translateX: a[4] || 0,\n translateY: a[5] || 0,\n };\n};\n\n/**\n * Generate a translation matrix\n *\n * A translation matrix in the form of\n * [ 1 0 x ]\n * [ 0 1 y ]\n * [ 0 0 1 ]\n *\n * See {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#translate} for more details\n *\n * @param {number} x translation on X axis\n * @param {number} [y] translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createTranslateMatrix = (x: number, y = 0): TMat2D => [\n 1,\n 0,\n 0,\n 1,\n x,\n y,\n];\n\n/**\n * Generate a rotation matrix around around a point (x,y), defaulting to (0,0)\n *\n * A matrix in the form of\n * [cos(a) -sin(a) -x*cos(a)+y*sin(a)+x]\n * [sin(a) cos(a) -x*sin(a)-y*cos(a)+y]\n * [0 0 1 ]\n *\n *\n * @param {TDegree} angle rotation in degrees\n * @param {XY} [pivotPoint] pivot point to rotate around\n * @returns {TMat2D} matrix\n */\nexport function createRotateMatrix(\n { angle = 0 }: TRotateMatrixArgs = {},\n { x = 0, y = 0 }: Partial<XY> = {},\n): TMat2D {\n const angleRadiant = degreesToRadians(angle),\n cosValue = cos(angleRadiant),\n sinValue = sin(angleRadiant);\n return [\n cosValue,\n sinValue,\n -sinValue,\n cosValue,\n x ? x - (cosValue * x - sinValue * y) : 0,\n y ? y - (sinValue * x + cosValue * y) : 0,\n ];\n}\n\n/**\n * Generate a scale matrix around the point (0,0)\n *\n * A matrix in the form of\n * [x 0 0]\n * [0 y 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#scale}\n *\n * @param {number} x scale on X axis\n * @param {number} [y] scale on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createScaleMatrix = (x: number, y: number = x): TMat2D => [\n x,\n 0,\n 0,\n y,\n 0,\n 0,\n];\n\nexport const angleToSkew = (angle: TDegree) =>\n Math.tan(degreesToRadians(angle));\n\nexport const skewToAngle = (value: TRadian) =>\n radiansToDegrees(Math.atan(value));\n\n/**\n * Generate a skew matrix for the X axis\n *\n * A matrix in the form of\n * [1 x 0]\n * [0 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewx}\n *\n * @param {TDegree} skewValue translation on X axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewXMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n 0,\n angleToSkew(skewValue),\n 1,\n 0,\n 0,\n];\n\n/**\n * Generate a skew matrix for the Y axis\n *\n * A matrix in the form of\n * [1 0 0]\n * [y 1 0]\n * [0 0 1]\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewy}\n *\n * @param {TDegree} skewValue translation on Y axis\n * @returns {TMat2D} matrix\n */\nexport const createSkewYMatrix = (skewValue: TDegree): TMat2D => [\n 1,\n angleToSkew(skewValue),\n 0,\n 1,\n 0,\n 0,\n];\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet.\n * is called DimensionsTransformMatrix because those properties are the one that influence\n * the size of the resulting box of the object.\n * @param {Object} options\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @return {Number[]} transform matrix\n */\nexport const calcDimensionsMatrix = ({\n scaleX = 1,\n scaleY = 1,\n flipX = false,\n flipY = false,\n skewX = 0 as TDegree,\n skewY = 0 as TDegree,\n}: TScaleMatrixArgs) => {\n let matrix = createScaleMatrix(\n flipX ? -scaleX : scaleX,\n flipY ? -scaleY : scaleY,\n );\n if (skewX) {\n matrix = multiplyTransformMatrices(matrix, createSkewXMatrix(skewX), true);\n }\n if (skewY) {\n matrix = multiplyTransformMatrices(matrix, createSkewYMatrix(skewY), true);\n }\n return matrix;\n};\n\n/**\n * Returns a transform matrix starting from an object of the same kind of\n * the one returned from qrDecompose, useful also if you want to calculate some\n * transformations from an object that is not enlived yet\n * Before changing this function look at: src/benchmarks/calcTransformMatrix.mjs\n * @param {Object} options\n * @param {Number} [options.angle]\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Boolean} [options.flipX]\n * @param {Boolean} [options.flipY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @param {Number} [options.translateX]\n * @param {Number} [options.translateY]\n * @return {Number[]} transform matrix\n */\nexport const composeMatrix = (options: TComposeMatrixArgs): TMat2D => {\n const { translateX = 0, translateY = 0, angle = 0 as TDegree } = options;\n let matrix = createTranslateMatrix(translateX, translateY);\n if (angle) {\n matrix = multiplyTransformMatrices(matrix, createRotateMatrix({ angle }));\n }\n const scaleMatrix = calcDimensionsMatrix(options);\n if (!isIdentityMatrix(scaleMatrix)) {\n matrix = multiplyTransformMatrices(matrix, scaleMatrix);\n }\n return matrix;\n};\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { Group } from '../../shapes/Group';
|
|
|
4
4
|
* Merges 2 clip paths into one visually equal clip path
|
|
5
5
|
*
|
|
6
6
|
* **IMPORTANT**:\
|
|
7
|
-
* Does **NOT** clone the arguments, clone them
|
|
7
|
+
* Does **NOT** clone the arguments, clone them prior if necessary.
|
|
8
8
|
*
|
|
9
9
|
* Creates a wrapper (group) that contains one clip path and is clipped by the other so content is kept where both overlap.
|
|
10
10
|
* Use this method if both the clip paths may have nested clip paths of their own, so assigning one to the other's clip path property is not possible.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeClipPaths.min.mjs","names":[],"sources":["../../../../src/util/misc/mergeClipPaths.ts"],"sourcesContent":["import type { FabricObject } from '../../shapes/Object/FabricObject';\nimport { sendObjectToPlane } from './planeChange';\nimport { Group } from '../../shapes/Group';\n/**\n * Merges 2 clip paths into one visually equal clip path\n *\n * **IMPORTANT**:\\\n * Does **NOT** clone the arguments, clone them
|
|
1
|
+
{"version":3,"file":"mergeClipPaths.min.mjs","names":[],"sources":["../../../../src/util/misc/mergeClipPaths.ts"],"sourcesContent":["import type { FabricObject } from '../../shapes/Object/FabricObject';\nimport { sendObjectToPlane } from './planeChange';\nimport { Group } from '../../shapes/Group';\n/**\n * Merges 2 clip paths into one visually equal clip path\n *\n * **IMPORTANT**:\\\n * Does **NOT** clone the arguments, clone them prior if necessary.\n *\n * Creates a wrapper (group) that contains one clip path and is clipped by the other so content is kept where both overlap.\n * Use this method if both the clip paths may have nested clip paths of their own, so assigning one to the other's clip path property is not possible.\n *\n * In order to handle the `inverted` property we follow logic described in the following cases:\\\n * **(1)** both clip paths are inverted - the clip paths pass the inverted prop to the wrapper and loose it themselves.\\\n * **(2)** one is inverted and the other isn't - the wrapper shouldn't become inverted and the inverted clip path must clip the non inverted one to produce an identical visual effect.\\\n * **(3)** both clip paths are not inverted - wrapper and clip paths remain unchanged.\n *\n * @param {fabric.Object} c1\n * @param {fabric.Object} c2\n * @returns {fabric.Object} merged clip path\n */\nexport const mergeClipPaths = (c1: FabricObject, c2: FabricObject) => {\n let a = c1,\n b = c2;\n if (a.inverted && !b.inverted) {\n // case (2)\n a = c2;\n b = c1;\n }\n // `b` becomes `a`'s clip path so we transform `b` to `a` coordinate plane\n sendObjectToPlane(b, b.group?.calcTransformMatrix(), a.calcTransformMatrix());\n // assign the `inverted` prop to the wrapping group\n const inverted = a.inverted && b.inverted;\n if (inverted) {\n // case (1)\n a.inverted = b.inverted = false;\n }\n return new Group([a], { clipPath: b, inverted });\n};\n"],"mappings":"6GAqBA,MAAa,GAAkB,EAAkB,IAAA,CAAA,IAAA,EAC/C,IAAI,EAAI,EACN,EAAI,EACF,EAAE,UAAA,CAAa,EAAE,WAEnB,EAAI,EACJ,EAAI,GAGN,EAAkB,GAAA,EAAG,EAAE,QAAA,KAAA,IAAA,GAAA,EAAO,qBAAA,CAAuB,EAAE,qBAAA,CAAA,CAEvD,IAAM,EAAW,EAAE,UAAY,EAAE,SAKjC,OAJI,IAEF,EAAE,SAAW,EAAE,SAAA,CAAW,GAErB,IAAI,EAAM,CAAC,EAAA,CAAI,CAAE,SAAU,EAAG,SAAA,EAAA,CAAA,EAAA,OAAA,KAAA"}
|
|
@@ -5,7 +5,7 @@ import { Group } from "../../shapes/Group.mjs";
|
|
|
5
5
|
* Merges 2 clip paths into one visually equal clip path
|
|
6
6
|
*
|
|
7
7
|
* **IMPORTANT**:\
|
|
8
|
-
* Does **NOT** clone the arguments, clone them
|
|
8
|
+
* Does **NOT** clone the arguments, clone them prior if necessary.
|
|
9
9
|
*
|
|
10
10
|
* Creates a wrapper (group) that contains one clip path and is clipped by the other so content is kept where both overlap.
|
|
11
11
|
* Use this method if both the clip paths may have nested clip paths of their own, so assigning one to the other's clip path property is not possible.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeClipPaths.mjs","names":[],"sources":["../../../../src/util/misc/mergeClipPaths.ts"],"sourcesContent":["import type { FabricObject } from '../../shapes/Object/FabricObject';\nimport { sendObjectToPlane } from './planeChange';\nimport { Group } from '../../shapes/Group';\n/**\n * Merges 2 clip paths into one visually equal clip path\n *\n * **IMPORTANT**:\\\n * Does **NOT** clone the arguments, clone them
|
|
1
|
+
{"version":3,"file":"mergeClipPaths.mjs","names":[],"sources":["../../../../src/util/misc/mergeClipPaths.ts"],"sourcesContent":["import type { FabricObject } from '../../shapes/Object/FabricObject';\nimport { sendObjectToPlane } from './planeChange';\nimport { Group } from '../../shapes/Group';\n/**\n * Merges 2 clip paths into one visually equal clip path\n *\n * **IMPORTANT**:\\\n * Does **NOT** clone the arguments, clone them prior if necessary.\n *\n * Creates a wrapper (group) that contains one clip path and is clipped by the other so content is kept where both overlap.\n * Use this method if both the clip paths may have nested clip paths of their own, so assigning one to the other's clip path property is not possible.\n *\n * In order to handle the `inverted` property we follow logic described in the following cases:\\\n * **(1)** both clip paths are inverted - the clip paths pass the inverted prop to the wrapper and loose it themselves.\\\n * **(2)** one is inverted and the other isn't - the wrapper shouldn't become inverted and the inverted clip path must clip the non inverted one to produce an identical visual effect.\\\n * **(3)** both clip paths are not inverted - wrapper and clip paths remain unchanged.\n *\n * @param {fabric.Object} c1\n * @param {fabric.Object} c2\n * @returns {fabric.Object} merged clip path\n */\nexport const mergeClipPaths = (c1: FabricObject, c2: FabricObject) => {\n let a = c1,\n b = c2;\n if (a.inverted && !b.inverted) {\n // case (2)\n a = c2;\n b = c1;\n }\n // `b` becomes `a`'s clip path so we transform `b` to `a` coordinate plane\n sendObjectToPlane(b, b.group?.calcTransformMatrix(), a.calcTransformMatrix());\n // assign the `inverted` prop to the wrapping group\n const inverted = a.inverted && b.inverted;\n if (inverted) {\n // case (1)\n a.inverted = b.inverted = false;\n }\n return new Group([a], { clipPath: b, inverted });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,kBAAkB,IAAkB,OAAqB;;CACpE,IAAI,IAAI,IACN,IAAI;AACN,KAAI,EAAE,YAAY,CAAC,EAAE,UAAU;AAE7B,MAAI;AACJ,MAAI;;AAGN,mBAAkB,IAAA,WAAG,EAAE,WAAA,QAAA,aAAA,KAAA,IAAA,KAAA,IAAA,SAAO,qBAAqB,EAAE,EAAE,qBAAqB,CAAC;CAE7E,MAAM,WAAW,EAAE,YAAY,EAAE;AACjC,KAAI,SAEF,GAAE,WAAW,EAAE,WAAW;AAE5B,QAAO,IAAI,MAAM,CAAC,EAAE,EAAE;EAAE,UAAU;EAAG;EAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objectEnlive.min.mjs","names":[],"sources":["../../../../src/util/misc/objectEnlive.ts"],"sourcesContent":["import { noop } from '../../constants';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport type {\n Abortable,\n Constructor,\n TCrossOrigin,\n TFiller,\n} from '../../typedefs';\nimport { createImage } from './dom';\nimport { classRegistry } from '../../ClassRegistry';\nimport type { BaseFilter } from '../../filters/BaseFilter';\nimport type { FabricObject as BaseFabricObject } from '../../shapes/Object/Object';\nimport { FabricError, SignalAbortedError } from '../internals/console';\nimport type { Shadow } from '../../Shadow';\n\nexport type LoadImageOptions = Abortable & {\n /**\n * cors value for the image loading, default to anonymous\n */\n crossOrigin?: TCrossOrigin;\n};\n\n/**\n * Loads image element from given url and resolve it, or catch.\n * @param {String} url URL representing an image\n * @param {LoadImageOptions} [options] image loading options\n * @returns {Promise<HTMLImageElement>} the loaded image.\n */\nexport const loadImage = (\n url: string,\n { signal, crossOrigin = null }: LoadImageOptions = {},\n) =>\n new Promise<HTMLImageElement>(function (resolve, reject) {\n if (signal && signal.aborted) {\n return reject(new SignalAbortedError('loadImage'));\n }\n const img = createImage();\n let abort: EventListenerOrEventListenerObject;\n if (signal) {\n abort = function (err: Event) {\n img.src = '';\n reject(err);\n };\n signal.addEventListener('abort', abort, { once: true });\n }\n const done = function () {\n img.onload = img.onerror = null;\n abort && signal?.removeEventListener('abort', abort);\n resolve(img);\n };\n if (!url) {\n done();\n return;\n }\n img.onload = done;\n img.onerror = function () {\n abort && signal?.removeEventListener('abort', abort);\n reject(new FabricError(`Error loading ${img.src}`));\n };\n crossOrigin && (img.crossOrigin = crossOrigin);\n img.src = url;\n });\n\nexport type EnlivenObjectOptions = Abortable & {\n /**\n * Method for further parsing of object elements,\n * called after each fabric object created.\n */\n reviver?: <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n >(\n serializedObj: Record<string, any>,\n instance: T | undefined,\n error?: FabricError,\n ) => void | Promise<T>;\n};\n\n/**\n * @TODO type this correctly.\n * Creates corresponding fabric instances from their object representations\n * @param {Object[]} objects Objects to enliven\n * @param {EnlivenObjectOptions} [options]\n * @param {(serializedObj: object, instance: FabricObject) => any} [options.reviver] Method for further parsing of object elements,\n * called after each fabric object created.\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<FabricObject[]>}\n */\nexport const enlivenObjects = <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n>(\n objects: any[],\n { signal, reviver = noop }: EnlivenObjectOptions = {},\n) =>\n new Promise<T[]>((resolve, reject) => {\n const instances: T[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n Promise.allSettled(\n objects.map((obj) =>\n classRegistry\n .getClass<\n Constructor<T> & {\n fromObject(options: any, context: Abortable): Promise<T>;\n }\n >(obj.type)\n .fromObject(obj, { signal }),\n ),\n )\n .then(async (elementsResult) => {\n for (const [index, result] of elementsResult.entries()) {\n if (result.status === 'fulfilled') {\n await reviver(objects[index], result.value);\n instances.push(result.value);\n }\n if (result.status === 'rejected') {\n const fallback = await reviver(\n objects[index],\n undefined,\n result.reason,\n );\n if (fallback) {\n instances.push(fallback as T);\n }\n }\n }\n resolve(instances);\n })\n .catch((error) => {\n // cleanup\n instances.forEach((instance) => {\n (instance as FabricObject).dispose &&\n (instance as FabricObject).dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n\n/**\n * Creates corresponding fabric instances residing in an object, e.g. `clipPath`\n * @param {Object} object with properties to enlive ( fill, stroke, clipPath, path )\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<Record<string, FabricObject | TFiller | null>>} the input object with enlived values\n */\nexport const enlivenObjectEnlivables = <\n R = Record<string, FabricObject | TFiller | null>,\n>(\n serializedObject: any,\n { signal }: Abortable = {},\n) =>\n new Promise<R>((resolve, reject) => {\n const instances: (FabricObject | TFiller | Shadow)[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n // enlive every possible property\n const promises = Object.values(serializedObject).map((value: any) => {\n if (!value) {\n return value;\n }\n /**\n * clipPath or shadow or gradient or text on a path or a pattern,\n * or the backgroundImage or overlayImage of canvas\n * If we have a type and there is a
|
|
1
|
+
{"version":3,"file":"objectEnlive.min.mjs","names":[],"sources":["../../../../src/util/misc/objectEnlive.ts"],"sourcesContent":["import { noop } from '../../constants';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport type {\n Abortable,\n Constructor,\n TCrossOrigin,\n TFiller,\n} from '../../typedefs';\nimport { createImage } from './dom';\nimport { classRegistry } from '../../ClassRegistry';\nimport type { BaseFilter } from '../../filters/BaseFilter';\nimport type { FabricObject as BaseFabricObject } from '../../shapes/Object/Object';\nimport { FabricError, SignalAbortedError } from '../internals/console';\nimport type { Shadow } from '../../Shadow';\n\nexport type LoadImageOptions = Abortable & {\n /**\n * cors value for the image loading, default to anonymous\n */\n crossOrigin?: TCrossOrigin;\n};\n\n/**\n * Loads image element from given url and resolve it, or catch.\n * @param {String} url URL representing an image\n * @param {LoadImageOptions} [options] image loading options\n * @returns {Promise<HTMLImageElement>} the loaded image.\n */\nexport const loadImage = (\n url: string,\n { signal, crossOrigin = null }: LoadImageOptions = {},\n) =>\n new Promise<HTMLImageElement>(function (resolve, reject) {\n if (signal && signal.aborted) {\n return reject(new SignalAbortedError('loadImage'));\n }\n const img = createImage();\n let abort: EventListenerOrEventListenerObject;\n if (signal) {\n abort = function (err: Event) {\n img.src = '';\n reject(err);\n };\n signal.addEventListener('abort', abort, { once: true });\n }\n const done = function () {\n img.onload = img.onerror = null;\n abort && signal?.removeEventListener('abort', abort);\n resolve(img);\n };\n if (!url) {\n done();\n return;\n }\n img.onload = done;\n img.onerror = function () {\n abort && signal?.removeEventListener('abort', abort);\n reject(new FabricError(`Error loading ${img.src}`));\n };\n crossOrigin && (img.crossOrigin = crossOrigin);\n img.src = url;\n });\n\nexport type EnlivenObjectOptions = Abortable & {\n /**\n * Method for further parsing of object elements,\n * called after each fabric object created.\n */\n reviver?: <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n >(\n serializedObj: Record<string, any>,\n instance: T | undefined,\n error?: FabricError,\n ) => void | Promise<T>;\n};\n\n/**\n * @TODO type this correctly.\n * Creates corresponding fabric instances from their object representations\n * @param {Object[]} objects Objects to enliven\n * @param {EnlivenObjectOptions} [options]\n * @param {(serializedObj: object, instance: FabricObject) => any} [options.reviver] Method for further parsing of object elements,\n * called after each fabric object created.\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<FabricObject[]>}\n */\nexport const enlivenObjects = <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n>(\n objects: any[],\n { signal, reviver = noop }: EnlivenObjectOptions = {},\n) =>\n new Promise<T[]>((resolve, reject) => {\n const instances: T[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n Promise.allSettled(\n objects.map((obj) =>\n classRegistry\n .getClass<\n Constructor<T> & {\n fromObject(options: any, context: Abortable): Promise<T>;\n }\n >(obj.type)\n .fromObject(obj, { signal }),\n ),\n )\n .then(async (elementsResult) => {\n for (const [index, result] of elementsResult.entries()) {\n if (result.status === 'fulfilled') {\n await reviver(objects[index], result.value);\n instances.push(result.value);\n }\n if (result.status === 'rejected') {\n const fallback = await reviver(\n objects[index],\n undefined,\n result.reason,\n );\n if (fallback) {\n instances.push(fallback as T);\n }\n }\n }\n resolve(instances);\n })\n .catch((error) => {\n // cleanup\n instances.forEach((instance) => {\n (instance as FabricObject).dispose &&\n (instance as FabricObject).dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n\n/**\n * Creates corresponding fabric instances residing in an object, e.g. `clipPath`\n * @param {Object} object with properties to enlive ( fill, stroke, clipPath, path )\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<Record<string, FabricObject | TFiller | null>>} the input object with enlived values\n */\nexport const enlivenObjectEnlivables = <\n R = Record<string, FabricObject | TFiller | null>,\n>(\n serializedObject: any,\n { signal }: Abortable = {},\n) =>\n new Promise<R>((resolve, reject) => {\n const instances: (FabricObject | TFiller | Shadow)[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n // enlive every possible property\n const promises = Object.values(serializedObject).map((value: any) => {\n if (!value) {\n return value;\n }\n /**\n * clipPath or shadow or gradient or text on a path or a pattern,\n * or the backgroundImage or overlayImage of canvas\n * If we have a type and there is a class registered for it, we enlive it.\n * If there is no class registered for it we return the value as is\n * */\n if (value.type && classRegistry.has(value.type)) {\n return enlivenObjects<FabricObject | Shadow | TFiller>([value], {\n signal,\n }).then(([enlived]) => {\n instances.push(enlived);\n return enlived;\n });\n }\n return value;\n });\n const keys = Object.keys(serializedObject);\n Promise.all(promises)\n .then((enlived) => {\n return enlived.reduce((acc, instance, index) => {\n acc[keys[index]] = instance;\n return acc;\n }, {});\n })\n .then(resolve)\n .catch((error) => {\n // cleanup\n instances.forEach((instance: any) => {\n instance.dispose && instance.dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n"],"mappings":"0OA4BA,MAAa,GACX,EAAA,CACE,OAAA,EAAQ,YAAA,EAAc,MAA2B,EAAA,GAEnD,IAAI,QAA0B,SAAU,EAAS,EAAA,CAC/C,GAAI,GAAU,EAAO,QACnB,OAAO,EAAO,IAAI,EAAmB,YAAA,CAAA,CAEvC,IAAM,EAAM,GAAA,CACR,EACA,IACF,EAAQ,SAAU,EAAA,CAChB,EAAI,IAAM,GACV,EAAO,EAAA,EAET,EAAO,iBAAiB,QAAS,EAAO,CAAE,KAAA,CAAM,EAAA,CAAA,EAElD,IAAM,EAAO,UAAA,CACX,EAAI,OAAS,EAAI,QAAU,KAC3B,IAAA,GAAA,MAAS,EAAQ,oBAAoB,QAAS,EAAA,EAC9C,EAAQ,EAAA,EAEL,GAIL,EAAI,OAAS,EACb,EAAI,QAAU,UAAA,CACZ,IAAA,GAAA,MAAS,EAAQ,oBAAoB,QAAS,EAAA,EAC9C,EAAO,IAAI,EAAY,iBAAiB,EAAI,MAAA,CAAA,EAE9C,IAAgB,EAAI,YAAc,GAClC,EAAI,IAAM,GATR,GAAA,EAAA,CAyCO,GAQX,EAAA,CACE,OAAA,EAAQ,QAAA,EAAU,GAA+B,EAAA,GAEnD,IAAI,SAAc,EAAS,IAAA,CACzB,IAAM,EAAiB,EAAA,CACvB,GAAU,EAAO,iBAAiB,QAAS,EAAQ,CAAE,KAAA,CAAM,EAAA,CAAA,CAC3D,QAAQ,WACN,EAAQ,IAAK,GACX,EACG,SAIC,EAAI,KAAA,CACL,WAAW,EAAK,CAAE,OAAA,EAAA,CAAA,CAAA,CAAA,CAGtB,KAAK,KAAO,IAAA,CACX,IAAK,GAAA,CAAO,EAAO,KAAW,EAAe,SAAA,CAK3C,GAJI,EAAO,SAAW,cAAX,MACH,EAAQ,EAAQ,GAAQ,EAAO,MAAA,CACrC,EAAU,KAAK,EAAO,MAAA,EAEpB,EAAO,SAAW,WAAY,CAChC,IAAM,EAAA,MAAiB,EACrB,EAAQ,GAAA,IACR,GACA,EAAO,OAAA,CAEL,GACF,EAAU,KAAK,EAAA,CAIrB,EAAQ,EAAA,EAAA,CAET,MAAO,GAAA,CAEN,EAAU,QAAS,GAAA,CAChB,EAA0B,SACxB,EAA0B,SAAA,EAAA,CAE/B,EAAO,EAAA,EAAA,CAER,YAAA,CACC,GAAU,EAAO,oBAAoB,QAAS,EAAA,EAAA,EAAA,CAWzC,GAGX,EAAA,CACE,OAAA,GAAsB,EAAA,GAExB,IAAI,SAAY,EAAS,IAAA,CACvB,IAAM,EAAiD,EAAA,CACvD,GAAU,EAAO,iBAAiB,QAAS,EAAQ,CAAE,KAAA,CAAM,EAAA,CAAA,CAE3D,IAAM,EAAW,OAAO,OAAO,EAAA,CAAkB,IAAK,GAC/C,GASD,EAAM,MAAQ,EAAc,IAAI,EAAM,KAAA,CACjC,EAAgD,CAAC,EAAA,CAAQ,CAC9D,OAAA,EAAA,CAAA,CACC,MAAA,CAAO,MACR,EAAU,KAAK,EAAA,CACR,GAAA,CAbF,EAAA,CAkBL,EAAO,OAAO,KAAK,EAAA,CACzB,QAAQ,IAAI,EAAA,CACT,KAAM,GACE,EAAQ,QAAQ,EAAK,EAAU,KACpC,EAAI,EAAK,IAAU,EACZ,GACN,EAAA,CAAA,CAAA,CAEJ,KAAK,EAAA,CACL,MAAO,GAAA,CAEN,EAAU,QAAS,GAAA,CACjB,EAAS,SAAW,EAAS,SAAA,EAAA,CAE/B,EAAO,EAAA,EAAA,CAER,YAAA,CACC,GAAU,EAAO,oBAAoB,QAAS,EAAA,EAAA,EAAA,CAAA,OAAA,KAAA,wBAAA,KAAA,eAAA,KAAA"}
|
|
@@ -86,7 +86,7 @@ const enlivenObjectEnlivables = (serializedObject, { signal } = {}) => new Promi
|
|
|
86
86
|
/**
|
|
87
87
|
* clipPath or shadow or gradient or text on a path or a pattern,
|
|
88
88
|
* or the backgroundImage or overlayImage of canvas
|
|
89
|
-
* If we have a type and there is a
|
|
89
|
+
* If we have a type and there is a class registered for it, we enlive it.
|
|
90
90
|
* If there is no class registered for it we return the value as is
|
|
91
91
|
* */
|
|
92
92
|
if (value.type && classRegistry.has(value.type)) return enlivenObjects([value], { signal }).then(([enlived]) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objectEnlive.mjs","names":[],"sources":["../../../../src/util/misc/objectEnlive.ts"],"sourcesContent":["import { noop } from '../../constants';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport type {\n Abortable,\n Constructor,\n TCrossOrigin,\n TFiller,\n} from '../../typedefs';\nimport { createImage } from './dom';\nimport { classRegistry } from '../../ClassRegistry';\nimport type { BaseFilter } from '../../filters/BaseFilter';\nimport type { FabricObject as BaseFabricObject } from '../../shapes/Object/Object';\nimport { FabricError, SignalAbortedError } from '../internals/console';\nimport type { Shadow } from '../../Shadow';\n\nexport type LoadImageOptions = Abortable & {\n /**\n * cors value for the image loading, default to anonymous\n */\n crossOrigin?: TCrossOrigin;\n};\n\n/**\n * Loads image element from given url and resolve it, or catch.\n * @param {String} url URL representing an image\n * @param {LoadImageOptions} [options] image loading options\n * @returns {Promise<HTMLImageElement>} the loaded image.\n */\nexport const loadImage = (\n url: string,\n { signal, crossOrigin = null }: LoadImageOptions = {},\n) =>\n new Promise<HTMLImageElement>(function (resolve, reject) {\n if (signal && signal.aborted) {\n return reject(new SignalAbortedError('loadImage'));\n }\n const img = createImage();\n let abort: EventListenerOrEventListenerObject;\n if (signal) {\n abort = function (err: Event) {\n img.src = '';\n reject(err);\n };\n signal.addEventListener('abort', abort, { once: true });\n }\n const done = function () {\n img.onload = img.onerror = null;\n abort && signal?.removeEventListener('abort', abort);\n resolve(img);\n };\n if (!url) {\n done();\n return;\n }\n img.onload = done;\n img.onerror = function () {\n abort && signal?.removeEventListener('abort', abort);\n reject(new FabricError(`Error loading ${img.src}`));\n };\n crossOrigin && (img.crossOrigin = crossOrigin);\n img.src = url;\n });\n\nexport type EnlivenObjectOptions = Abortable & {\n /**\n * Method for further parsing of object elements,\n * called after each fabric object created.\n */\n reviver?: <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n >(\n serializedObj: Record<string, any>,\n instance: T | undefined,\n error?: FabricError,\n ) => void | Promise<T>;\n};\n\n/**\n * @TODO type this correctly.\n * Creates corresponding fabric instances from their object representations\n * @param {Object[]} objects Objects to enliven\n * @param {EnlivenObjectOptions} [options]\n * @param {(serializedObj: object, instance: FabricObject) => any} [options.reviver] Method for further parsing of object elements,\n * called after each fabric object created.\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<FabricObject[]>}\n */\nexport const enlivenObjects = <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n>(\n objects: any[],\n { signal, reviver = noop }: EnlivenObjectOptions = {},\n) =>\n new Promise<T[]>((resolve, reject) => {\n const instances: T[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n Promise.allSettled(\n objects.map((obj) =>\n classRegistry\n .getClass<\n Constructor<T> & {\n fromObject(options: any, context: Abortable): Promise<T>;\n }\n >(obj.type)\n .fromObject(obj, { signal }),\n ),\n )\n .then(async (elementsResult) => {\n for (const [index, result] of elementsResult.entries()) {\n if (result.status === 'fulfilled') {\n await reviver(objects[index], result.value);\n instances.push(result.value);\n }\n if (result.status === 'rejected') {\n const fallback = await reviver(\n objects[index],\n undefined,\n result.reason,\n );\n if (fallback) {\n instances.push(fallback as T);\n }\n }\n }\n resolve(instances);\n })\n .catch((error) => {\n // cleanup\n instances.forEach((instance) => {\n (instance as FabricObject).dispose &&\n (instance as FabricObject).dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n\n/**\n * Creates corresponding fabric instances residing in an object, e.g. `clipPath`\n * @param {Object} object with properties to enlive ( fill, stroke, clipPath, path )\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<Record<string, FabricObject | TFiller | null>>} the input object with enlived values\n */\nexport const enlivenObjectEnlivables = <\n R = Record<string, FabricObject | TFiller | null>,\n>(\n serializedObject: any,\n { signal }: Abortable = {},\n) =>\n new Promise<R>((resolve, reject) => {\n const instances: (FabricObject | TFiller | Shadow)[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n // enlive every possible property\n const promises = Object.values(serializedObject).map((value: any) => {\n if (!value) {\n return value;\n }\n /**\n * clipPath or shadow or gradient or text on a path or a pattern,\n * or the backgroundImage or overlayImage of canvas\n * If we have a type and there is a
|
|
1
|
+
{"version":3,"file":"objectEnlive.mjs","names":[],"sources":["../../../../src/util/misc/objectEnlive.ts"],"sourcesContent":["import { noop } from '../../constants';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport type {\n Abortable,\n Constructor,\n TCrossOrigin,\n TFiller,\n} from '../../typedefs';\nimport { createImage } from './dom';\nimport { classRegistry } from '../../ClassRegistry';\nimport type { BaseFilter } from '../../filters/BaseFilter';\nimport type { FabricObject as BaseFabricObject } from '../../shapes/Object/Object';\nimport { FabricError, SignalAbortedError } from '../internals/console';\nimport type { Shadow } from '../../Shadow';\n\nexport type LoadImageOptions = Abortable & {\n /**\n * cors value for the image loading, default to anonymous\n */\n crossOrigin?: TCrossOrigin;\n};\n\n/**\n * Loads image element from given url and resolve it, or catch.\n * @param {String} url URL representing an image\n * @param {LoadImageOptions} [options] image loading options\n * @returns {Promise<HTMLImageElement>} the loaded image.\n */\nexport const loadImage = (\n url: string,\n { signal, crossOrigin = null }: LoadImageOptions = {},\n) =>\n new Promise<HTMLImageElement>(function (resolve, reject) {\n if (signal && signal.aborted) {\n return reject(new SignalAbortedError('loadImage'));\n }\n const img = createImage();\n let abort: EventListenerOrEventListenerObject;\n if (signal) {\n abort = function (err: Event) {\n img.src = '';\n reject(err);\n };\n signal.addEventListener('abort', abort, { once: true });\n }\n const done = function () {\n img.onload = img.onerror = null;\n abort && signal?.removeEventListener('abort', abort);\n resolve(img);\n };\n if (!url) {\n done();\n return;\n }\n img.onload = done;\n img.onerror = function () {\n abort && signal?.removeEventListener('abort', abort);\n reject(new FabricError(`Error loading ${img.src}`));\n };\n crossOrigin && (img.crossOrigin = crossOrigin);\n img.src = url;\n });\n\nexport type EnlivenObjectOptions = Abortable & {\n /**\n * Method for further parsing of object elements,\n * called after each fabric object created.\n */\n reviver?: <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n >(\n serializedObj: Record<string, any>,\n instance: T | undefined,\n error?: FabricError,\n ) => void | Promise<T>;\n};\n\n/**\n * @TODO type this correctly.\n * Creates corresponding fabric instances from their object representations\n * @param {Object[]} objects Objects to enliven\n * @param {EnlivenObjectOptions} [options]\n * @param {(serializedObj: object, instance: FabricObject) => any} [options.reviver] Method for further parsing of object elements,\n * called after each fabric object created.\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<FabricObject[]>}\n */\nexport const enlivenObjects = <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n>(\n objects: any[],\n { signal, reviver = noop }: EnlivenObjectOptions = {},\n) =>\n new Promise<T[]>((resolve, reject) => {\n const instances: T[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n Promise.allSettled(\n objects.map((obj) =>\n classRegistry\n .getClass<\n Constructor<T> & {\n fromObject(options: any, context: Abortable): Promise<T>;\n }\n >(obj.type)\n .fromObject(obj, { signal }),\n ),\n )\n .then(async (elementsResult) => {\n for (const [index, result] of elementsResult.entries()) {\n if (result.status === 'fulfilled') {\n await reviver(objects[index], result.value);\n instances.push(result.value);\n }\n if (result.status === 'rejected') {\n const fallback = await reviver(\n objects[index],\n undefined,\n result.reason,\n );\n if (fallback) {\n instances.push(fallback as T);\n }\n }\n }\n resolve(instances);\n })\n .catch((error) => {\n // cleanup\n instances.forEach((instance) => {\n (instance as FabricObject).dispose &&\n (instance as FabricObject).dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n\n/**\n * Creates corresponding fabric instances residing in an object, e.g. `clipPath`\n * @param {Object} object with properties to enlive ( fill, stroke, clipPath, path )\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<Record<string, FabricObject | TFiller | null>>} the input object with enlived values\n */\nexport const enlivenObjectEnlivables = <\n R = Record<string, FabricObject | TFiller | null>,\n>(\n serializedObject: any,\n { signal }: Abortable = {},\n) =>\n new Promise<R>((resolve, reject) => {\n const instances: (FabricObject | TFiller | Shadow)[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n // enlive every possible property\n const promises = Object.values(serializedObject).map((value: any) => {\n if (!value) {\n return value;\n }\n /**\n * clipPath or shadow or gradient or text on a path or a pattern,\n * or the backgroundImage or overlayImage of canvas\n * If we have a type and there is a class registered for it, we enlive it.\n * If there is no class registered for it we return the value as is\n * */\n if (value.type && classRegistry.has(value.type)) {\n return enlivenObjects<FabricObject | Shadow | TFiller>([value], {\n signal,\n }).then(([enlived]) => {\n instances.push(enlived);\n return enlived;\n });\n }\n return value;\n });\n const keys = Object.keys(serializedObject);\n Promise.all(promises)\n .then((enlived) => {\n return enlived.reduce((acc, instance, index) => {\n acc[keys[index]] = instance;\n return acc;\n }, {});\n })\n .then(resolve)\n .catch((error) => {\n // cleanup\n instances.forEach((instance: any) => {\n instance.dispose && instance.dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{_defineProperty as e}from"../../../../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import{_defineProperty as e}from"../../../../_virtual/_@oxc-project_runtime@0.126.0/helpers/defineProperty.min.mjs";import{halfPI as t,twoMathPi as n}from"../../../constants.min.mjs";import{Point as r}from"../../../Point.min.mjs";import{degreesToRadians as i}from"../radiansDegreesConversion.min.mjs";import{calcAngleBetweenVectors as a,calcVectorRotation as o,crossProduct as s,getOrthonormalVector as c,getUnitVector as l,isBetweenVectors as u,magnitude as d,rotateVector as f}from"../vectors.min.mjs";import{StrokeProjectionsBase as p}from"./StrokeProjectionsBase.min.mjs";const m=new r;var h=class h extends p{static getOrthogonalRotationFactor(e,n){let r=n?a(e,n):o(e);return Math.abs(r)<t?-1:1}constructor(t,n,i,o){super(o),e(this,`AB`,void 0),e(this,`AC`,void 0),e(this,`alpha`,void 0),e(this,`bisector`,void 0),this.A=new r(t),this.B=new r(n),this.C=new r(i),this.AB=this.createSideVector(this.A,this.B),this.AC=this.createSideVector(this.A,this.C),this.alpha=a(this.AB,this.AC),this.bisector=l(f(this.AB.eq(m)?this.AC:this.AB,this.alpha/2))}calcOrthogonalProjection(e,t,n=this.strokeProjectionMagnitude){let r=c(this.createSideVector(e,t)),i=h.getOrthogonalRotationFactor(r,this.bisector);return this.scaleUnitVector(r,n*i)}projectBevel(){let e=[];return(this.alpha%n===0?[this.B]:[this.B,this.C]).forEach(t=>{e.push(this.projectOrthogonally(this.A,t)),e.push(this.projectOrthogonally(this.A,t,-this.strokeProjectionMagnitude))}),e}projectMiter(){let e=[],t=Math.abs(this.alpha),n=1/Math.sin(t/2),r=this.scaleUnitVector(this.bisector,-this.strokeProjectionMagnitude*n),i=this.options.strokeUniform?d(this.scaleUnitVector(this.bisector,this.options.strokeMiterLimit)):this.options.strokeMiterLimit;return d(r)/this.strokeProjectionMagnitude<=i&&e.push(this.applySkew(this.A.add(r))),e.push(...this.projectBevel()),e}projectRoundNoSkew(e,t){let n=[],i=new r(h.getOrthogonalRotationFactor(this.bisector),h.getOrthogonalRotationFactor(new r(this.bisector.y,this.bisector.x)));return[new r(1,0).scalarMultiply(this.strokeProjectionMagnitude).multiply(this.strokeUniformScalar).multiply(i),new r(0,1).scalarMultiply(this.strokeProjectionMagnitude).multiply(this.strokeUniformScalar).multiply(i)].forEach(r=>{u(r,e,t)&&n.push(this.A.add(r))}),n}projectRoundWithSkew(e,t){let n=[],{skewX:a,skewY:o,scaleX:s,scaleY:c,strokeUniform:l}=this.options,d=new r(Math.tan(i(a)),Math.tan(i(o))),f=this.strokeProjectionMagnitude,p=l?f/c/Math.sqrt(1/c**2+1/s**2*d.y**2):f/Math.sqrt(1+d.y**2),m=new r(Math.sqrt(Math.max(f**2-p**2,0)),p),h=l?f/Math.sqrt(1+d.x**2*(1/c)**2/(1/s+1/s*d.x*d.y)**2):f/Math.sqrt(1+d.x**2/(1+d.x*d.y)**2),g=new r(h,Math.sqrt(Math.max(f**2-h**2,0)));return[g,g.scalarMultiply(-1),m,m.scalarMultiply(-1)].map(e=>this.applySkew(l?e.multiply(this.strokeUniformScalar):e)).forEach(r=>{u(r,e,t)&&n.push(this.applySkew(this.A).add(r))}),n}projectRound(){let e=[];e.push(...this.projectBevel());let t=this.alpha%n===0,r=this.applySkew(this.A),i=e[t?0:2].subtract(r),a=e[+!!t].subtract(r),o=s(i,t?this.applySkew(this.AB.scalarMultiply(-1)):this.applySkew(this.bisector.multiply(this.strokeUniformScalar).scalarMultiply(-1)))>0,c=o?i:a,l=o?a:i;return this.isSkewed()?e.push(...this.projectRoundWithSkew(c,l)):e.push(...this.projectRoundNoSkew(c,l)),e}projectPoints(){switch(this.options.strokeLineJoin){case`miter`:return this.projectMiter();case`round`:return this.projectRound();default:return this.projectBevel()}}project(){return this.projectPoints().map(e=>({originPoint:this.A,projectedPoint:e,angle:this.alpha,bisector:this.bisector}))}};export{h as StrokeLineJoinProjections};
|
|
2
2
|
//# sourceMappingURL=StrokeLineJoinProjections.min.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StrokeLineJoinProjections.min.mjs","names":[],"sources":["../../../../../src/util/misc/projectStroke/StrokeLineJoinProjections.ts"],"sourcesContent":["import type { XY } from '../../../Point';\nimport { Point } from '../../../Point';\nimport { halfPI, twoMathPi } from '../../../constants';\nimport type { TRadian } from '../../../typedefs';\nimport { degreesToRadians } from '../radiansDegreesConversion';\nimport {\n calcAngleBetweenVectors,\n calcVectorRotation,\n crossProduct,\n getOrthonormalVector,\n getUnitVector,\n isBetweenVectors,\n magnitude,\n rotateVector,\n} from '../vectors';\nimport { StrokeProjectionsBase } from './StrokeProjectionsBase';\nimport type { TProjection, TProjectStrokeOnPointsOptions } from './types';\n\nconst zeroVector = new Point();\n\n/**\n * class in charge of finding projections for each type of line join\n * @see {@link [Closed path projections at #8344](https://github.com/fabricjs/fabric.js/pull/8344#2-closed-path)}\n *\n * - MDN:\n * - https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin\n * - https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin\n * - Spec: https://svgwg.org/svg2-draft/painting.html#StrokeLinejoinProperty\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 *\n */\nexport class StrokeLineJoinProjections extends StrokeProjectionsBase {\n /**\n * The point being projected (the angle ∠BAC)\n */\n declare A: Point;\n /**\n * The point before A\n */\n declare B: Point;\n /**\n * The point after A\n */\n declare C: Point;\n /**\n * The AB vector\n */\n AB: Point;\n /**\n * The AC vector\n */\n AC: Point;\n /**\n * The angle of A (∠BAC)\n */\n alpha: TRadian;\n /**\n * The bisector of A (∠BAC)\n */\n bisector: Point;\n\n static getOrthogonalRotationFactor(vector1: Point, vector2?: Point) {\n const angle = vector2\n ? calcAngleBetweenVectors(vector1, vector2)\n : calcVectorRotation(vector1);\n return Math.abs(angle) < halfPI ? -1 : 1;\n }\n\n constructor(A: XY, B: XY, C: XY, options: TProjectStrokeOnPointsOptions) {\n super(options);\n this.A = new Point(A);\n this.B = new Point(B);\n this.C = new Point(C);\n this.AB = this.createSideVector(this.A, this.B);\n this.AC = this.createSideVector(this.A, this.C);\n this.alpha = calcAngleBetweenVectors(this.AB, this.AC);\n this.bisector = getUnitVector(\n // if AC is also the zero vector nothing will be projected\n // in that case the next point will handle the projection\n rotateVector(this.AB.eq(zeroVector) ? this.AC : this.AB, this.alpha / 2),\n );\n }\n\n calcOrthogonalProjection(\n from: Point,\n to: Point,\n magnitude: number = this.strokeProjectionMagnitude,\n ) {\n const vector = this.createSideVector(from, to);\n const orthogonalProjection = getOrthonormalVector(vector);\n const correctSide = StrokeLineJoinProjections.getOrthogonalRotationFactor(\n orthogonalProjection,\n this.bisector,\n );\n return this.scaleUnitVector(orthogonalProjection, magnitude * correctSide);\n }\n\n /**\n * BEVEL\n * Calculation: the projection points are formed by the vector orthogonal to the vertex.\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-2-bevel\n */\n projectBevel() {\n const projections: Point[] = [];\n // if `alpha` equals 0 or 2*PI, the projections are the same for `B` and `C`\n (this.alpha % twoMathPi === 0 ? [this.B] : [this.B, this.C]).forEach(\n (to) => {\n projections.push(this.projectOrthogonally(this.A, to));\n projections.push(\n this.projectOrthogonally(this.A, to, -this.strokeProjectionMagnitude),\n );\n },\n );\n return projections;\n }\n\n /**\n * MITER\n * Calculation: the corner is formed by extending the outer edges of the stroke\n * at the tangents of the path segments until they intersect.\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-1-miter\n */\n projectMiter() {\n const projections: Point[] = [],\n alpha = Math.abs(this.alpha),\n hypotUnitScalar = 1 / Math.sin(alpha / 2),\n miterVector = this.scaleUnitVector(\n this.bisector,\n -this.strokeProjectionMagnitude * hypotUnitScalar,\n );\n\n // When two line segments meet at a sharp angle, it is possible for the join to extend,\n // far beyond the thickness of the line stroking the path. The stroke-miterlimit imposes\n // a limit on the extent of the line join.\n // MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit\n // When the stroke is uniform, scaling changes the arrangement of points, this changes the miter-limit\n const strokeMiterLimit = this.options.strokeUniform\n ? magnitude(\n this.scaleUnitVector(this.bisector, this.options.strokeMiterLimit),\n )\n : this.options.strokeMiterLimit;\n\n if (\n magnitude(miterVector) / this.strokeProjectionMagnitude <=\n strokeMiterLimit\n ) {\n projections.push(this.applySkew(this.A.add(miterVector)));\n }\n /* when the miter-limit is reached, the stroke line join becomes of type bevel.\n We always need two orthogonal projections which are basically bevel-type projections,\n so regardless of whether the miter-limit was reached or not, we include these projections.\n */\n projections.push(...this.projectBevel());\n\n return projections;\n }\n\n /**\n * ROUND (without skew)\n * Calculation: the projections are the two vectors parallel to X and Y axes\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-3-1-round-without-skew\n */\n private projectRoundNoSkew(startCircle: Point, endCircle: Point) {\n const projections: Point[] = [],\n // correctSide is used to only consider projecting for the outer side\n correctSide = new Point(\n StrokeLineJoinProjections.getOrthogonalRotationFactor(this.bisector),\n StrokeLineJoinProjections.getOrthogonalRotationFactor(\n new Point(this.bisector.y, this.bisector.x),\n ),\n ),\n radiusOnAxisX = new Point(1, 0)\n .scalarMultiply(this.strokeProjectionMagnitude)\n .multiply(this.strokeUniformScalar)\n .multiply(correctSide),\n radiusOnAxisY = new Point(0, 1)\n .scalarMultiply(this.strokeProjectionMagnitude)\n .multiply(this.strokeUniformScalar)\n .multiply(correctSide);\n\n [radiusOnAxisX, radiusOnAxisY].forEach((vector) => {\n if (isBetweenVectors(vector, startCircle, endCircle)) {\n projections.push(this.A.add(vector));\n }\n });\n return projections;\n }\n\n /**\n * ROUND (with skew)\n * Calculation: the projections are the points furthest from the vertex in\n * the direction of the X and Y axes after distortion.\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-3-2-round-skew\n */\n private projectRoundWithSkew(startCircle: Point, endCircle: Point) {\n const projections: Point[] = [];\n\n const { skewX, skewY, scaleX, scaleY, strokeUniform } = this.options,\n shearing = new Point(\n Math.tan(degreesToRadians(skewX)),\n Math.tan(degreesToRadians(skewY)),\n );\n // The points furthest from the vertex in the direction of the X and Y axes after distortion\n const circleRadius = this.strokeProjectionMagnitude,\n newY = strokeUniform\n ? circleRadius /\n scaleY /\n Math.sqrt(1 / scaleY ** 2 + (1 / scaleX ** 2) * shearing.y ** 2)\n : circleRadius / Math.sqrt(1 + shearing.y ** 2),\n furthestY = new Point(\n // Safe guard due to floating point precision. In some situations the square root\n // was returning NaN because of a negative number close to zero.\n Math.sqrt(Math.max(circleRadius ** 2 - newY ** 2, 0)),\n newY,\n ),\n newX = strokeUniform\n ? circleRadius /\n Math.sqrt(\n 1 +\n (shearing.x ** 2 * (1 / scaleY) ** 2) /\n (1 / scaleX + (1 / scaleX) * shearing.x * shearing.y) ** 2,\n )\n : circleRadius /\n Math.sqrt(1 + shearing.x ** 2 / (1 + shearing.x * shearing.y) ** 2),\n furthestX = new Point(\n newX,\n Math.sqrt(Math.max(circleRadius ** 2 - newX ** 2, 0)),\n );\n\n [\n furthestX,\n furthestX.scalarMultiply(-1),\n furthestY,\n furthestY.scalarMultiply(-1),\n ]\n // We need to skew the vector here as this information is used to check if\n // it is between the start and end of the circle segment\n .map((vector) =>\n this.applySkew(\n strokeUniform ? vector.multiply(this.strokeUniformScalar) : vector,\n ),\n )\n .forEach((vector) => {\n if (isBetweenVectors(vector, startCircle, endCircle)) {\n projections.push(this.applySkew(this.A).add(vector));\n }\n });\n\n return projections;\n }\n\n projectRound() {\n const projections: Point[] = [];\n /* Include the start and end points of the circle segment, so that only\n the projections contained within it are included */\n // add the orthogonal projections (start and end points of circle segment)\n projections.push(...this.projectBevel());\n // let's determines which one of the orthogonal projection is the beginning and end of the circle segment.\n // when `alpha` equals 0 or 2*PI, we have a straight line, so the way to find the start/end is different.\n const isStraightLine = this.alpha % twoMathPi === 0,\n // change the origin of the projections to point A\n // so that the cross product calculation is correct\n newOrigin = this.applySkew(this.A),\n proj0 = projections[isStraightLine ? 0 : 2].subtract(newOrigin),\n proj1 = projections[isStraightLine ? 1 : 0].subtract(newOrigin),\n // when `isStraightLine` === true, we compare with the vector opposite AB, otherwise we compare with the bisector.\n comparisonVector = isStraightLine\n ? this.applySkew(this.AB.scalarMultiply(-1))\n : this.applySkew(\n this.bisector.multiply(this.strokeUniformScalar).scalarMultiply(-1),\n ),\n // the beginning of the circle segment is always to the right of the comparison vector (cross product > 0)\n isProj0Start = crossProduct(proj0, comparisonVector) > 0,\n startCircle = isProj0Start ? proj0 : proj1,\n endCircle = isProj0Start ? proj1 : proj0;\n if (!this.isSkewed()) {\n projections.push(...this.projectRoundNoSkew(startCircle, endCircle));\n } else {\n projections.push(...this.projectRoundWithSkew(startCircle, endCircle));\n }\n return projections;\n }\n\n /**\n * Project stroke width on points returning projections for each point as follows:\n * - `miter`: 1 point corresponding to the outer boundary. If the miter limit is exceeded, it will be 2 points (becomes bevel)\n * - `bevel`: 2 points corresponding to the bevel possible boundaries, orthogonal to the stroke.\n * - `round`: same as `bevel` when it has no skew, with skew are 4 points.\n */\n protected projectPoints() {\n switch (this.options.strokeLineJoin) {\n case 'miter':\n return this.projectMiter();\n case 'round':\n return this.projectRound();\n default:\n return this.projectBevel();\n }\n }\n\n public project(): TProjection[] {\n return this.projectPoints().map((point) => ({\n originPoint: this.A,\n projectedPoint: point,\n angle: this.alpha,\n bisector: this.bisector,\n }));\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StrokeLineJoinProjections.min.mjs","names":[],"sources":["../../../../../src/util/misc/projectStroke/StrokeLineJoinProjections.ts"],"sourcesContent":["import type { XY } from '../../../Point';\nimport { Point } from '../../../Point';\nimport { halfPI, twoMathPi } from '../../../constants';\nimport type { TRadian } from '../../../typedefs';\nimport { degreesToRadians } from '../radiansDegreesConversion';\nimport {\n calcAngleBetweenVectors,\n calcVectorRotation,\n crossProduct,\n getOrthonormalVector,\n getUnitVector,\n isBetweenVectors,\n magnitude,\n rotateVector,\n} from '../vectors';\nimport { StrokeProjectionsBase } from './StrokeProjectionsBase';\nimport type { TProjection, TProjectStrokeOnPointsOptions } from './types';\n\nconst zeroVector = new Point();\n\n/**\n * class in charge of finding projections for each type of line join\n * @see {@link [Closed path projections at #8344](https://github.com/fabricjs/fabric.js/pull/8344#2-closed-path)}\n *\n * - MDN:\n * - https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin\n * - https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin\n * - Spec: https://svgwg.org/svg2-draft/painting.html#StrokeLinejoinProperty\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 *\n */\nexport class StrokeLineJoinProjections extends StrokeProjectionsBase {\n /**\n * The point being projected (the angle ∠BAC)\n */\n declare A: Point;\n /**\n * The point before A\n */\n declare B: Point;\n /**\n * The point after A\n */\n declare C: Point;\n /**\n * The AB vector\n */\n AB: Point;\n /**\n * The AC vector\n */\n AC: Point;\n /**\n * The angle of A (∠BAC)\n */\n alpha: TRadian;\n /**\n * The bisector of A (∠BAC)\n */\n bisector: Point;\n\n static getOrthogonalRotationFactor(vector1: Point, vector2?: Point) {\n const angle = vector2\n ? calcAngleBetweenVectors(vector1, vector2)\n : calcVectorRotation(vector1);\n return Math.abs(angle) < halfPI ? -1 : 1;\n }\n\n constructor(A: XY, B: XY, C: XY, options: TProjectStrokeOnPointsOptions) {\n super(options);\n this.A = new Point(A);\n this.B = new Point(B);\n this.C = new Point(C);\n this.AB = this.createSideVector(this.A, this.B);\n this.AC = this.createSideVector(this.A, this.C);\n this.alpha = calcAngleBetweenVectors(this.AB, this.AC);\n this.bisector = getUnitVector(\n // if AC is also the zero vector nothing will be projected\n // in that case the next point will handle the projection\n rotateVector(this.AB.eq(zeroVector) ? this.AC : this.AB, this.alpha / 2),\n );\n }\n\n calcOrthogonalProjection(\n from: Point,\n to: Point,\n magnitude: number = this.strokeProjectionMagnitude,\n ) {\n const vector = this.createSideVector(from, to);\n const orthogonalProjection = getOrthonormalVector(vector);\n const correctSide = StrokeLineJoinProjections.getOrthogonalRotationFactor(\n orthogonalProjection,\n this.bisector,\n );\n return this.scaleUnitVector(orthogonalProjection, magnitude * correctSide);\n }\n\n /**\n * BEVEL\n * Calculation: the projection points are formed by the vector orthogonal to the vertex.\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-2-bevel\n */\n projectBevel() {\n const projections: Point[] = [];\n // if `alpha` equals 0 or 2*PI, the projections are the same for `B` and `C`\n (this.alpha % twoMathPi === 0 ? [this.B] : [this.B, this.C]).forEach(\n (to) => {\n projections.push(this.projectOrthogonally(this.A, to));\n projections.push(\n this.projectOrthogonally(this.A, to, -this.strokeProjectionMagnitude),\n );\n },\n );\n return projections;\n }\n\n /**\n * MITER\n * Calculation: the corner is formed by extending the outer edges of the stroke\n * at the tangents of the path segments until they intersect.\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-1-miter\n */\n projectMiter() {\n const projections: Point[] = [],\n alpha = Math.abs(this.alpha),\n hypotUnitScalar = 1 / Math.sin(alpha / 2),\n miterVector = this.scaleUnitVector(\n this.bisector,\n -this.strokeProjectionMagnitude * hypotUnitScalar,\n );\n\n // When two line segments meet at a sharp angle, it is possible for the join to extend,\n // far beyond the thickness of the line stroking the path. The stroke-miterlimit imposes\n // a limit on the extent of the line join.\n // MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit\n // When the stroke is uniform, scaling changes the arrangement of points, this changes the miter-limit\n const strokeMiterLimit = this.options.strokeUniform\n ? magnitude(\n this.scaleUnitVector(this.bisector, this.options.strokeMiterLimit),\n )\n : this.options.strokeMiterLimit;\n\n if (\n magnitude(miterVector) / this.strokeProjectionMagnitude <=\n strokeMiterLimit\n ) {\n projections.push(this.applySkew(this.A.add(miterVector)));\n }\n /* when the miter-limit is reached, the stroke line join becomes of type bevel.\n We always need two orthogonal projections which are basically bevel-type projections,\n so regardless of whether the miter-limit was reached or not, we include these projections.\n */\n projections.push(...this.projectBevel());\n\n return projections;\n }\n\n /**\n * ROUND (without skew)\n * Calculation: the projections are the two vectors parallel to X and Y axes\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-3-1-round-without-skew\n */\n private projectRoundNoSkew(startCircle: Point, endCircle: Point) {\n const projections: Point[] = [],\n // correctSide is used to only consider projecting for the outer side\n correctSide = new Point(\n StrokeLineJoinProjections.getOrthogonalRotationFactor(this.bisector),\n StrokeLineJoinProjections.getOrthogonalRotationFactor(\n new Point(this.bisector.y, this.bisector.x),\n ),\n ),\n radiusOnAxisX = new Point(1, 0)\n .scalarMultiply(this.strokeProjectionMagnitude)\n .multiply(this.strokeUniformScalar)\n .multiply(correctSide),\n radiusOnAxisY = new Point(0, 1)\n .scalarMultiply(this.strokeProjectionMagnitude)\n .multiply(this.strokeUniformScalar)\n .multiply(correctSide);\n\n [radiusOnAxisX, radiusOnAxisY].forEach((vector) => {\n if (isBetweenVectors(vector, startCircle, endCircle)) {\n projections.push(this.A.add(vector));\n }\n });\n return projections;\n }\n\n /**\n * ROUND (with skew)\n * Calculation: the projections are the points furthest from the vertex in\n * the direction of the X and Y axes after distortion.\n *\n * @see https://github.com/fabricjs/fabric.js/pull/8344#2-3-2-round-skew\n */\n private projectRoundWithSkew(startCircle: Point, endCircle: Point) {\n const projections: Point[] = [];\n\n const { skewX, skewY, scaleX, scaleY, strokeUniform } = this.options,\n shearing = new Point(\n Math.tan(degreesToRadians(skewX)),\n Math.tan(degreesToRadians(skewY)),\n );\n // The points furthest from the vertex in the direction of the X and Y axes after distortion\n const circleRadius = this.strokeProjectionMagnitude,\n newY = strokeUniform\n ? circleRadius /\n scaleY /\n Math.sqrt(1 / scaleY ** 2 + (1 / scaleX ** 2) * shearing.y ** 2)\n : circleRadius / Math.sqrt(1 + shearing.y ** 2),\n furthestY = new Point(\n // Safe guard due to floating point precision. In some situations the square root\n // was returning NaN because of a negative number close to zero.\n Math.sqrt(Math.max(circleRadius ** 2 - newY ** 2, 0)),\n newY,\n ),\n newX = strokeUniform\n ? circleRadius /\n Math.sqrt(\n 1 +\n (shearing.x ** 2 * (1 / scaleY) ** 2) /\n (1 / scaleX + (1 / scaleX) * shearing.x * shearing.y) ** 2,\n )\n : circleRadius /\n Math.sqrt(1 + shearing.x ** 2 / (1 + shearing.x * shearing.y) ** 2),\n furthestX = new Point(\n newX,\n Math.sqrt(Math.max(circleRadius ** 2 - newX ** 2, 0)),\n );\n\n [\n furthestX,\n furthestX.scalarMultiply(-1),\n furthestY,\n furthestY.scalarMultiply(-1),\n ]\n // We need to skew the vector here as this information is used to check if\n // it is between the start and end of the circle segment\n .map((vector) =>\n this.applySkew(\n strokeUniform ? vector.multiply(this.strokeUniformScalar) : vector,\n ),\n )\n .forEach((vector) => {\n if (isBetweenVectors(vector, startCircle, endCircle)) {\n projections.push(this.applySkew(this.A).add(vector));\n }\n });\n\n return projections;\n }\n\n projectRound() {\n const projections: Point[] = [];\n /* Include the start and end points of the circle segment, so that only\n the projections contained within it are included */\n // add the orthogonal projections (start and end points of circle segment)\n projections.push(...this.projectBevel());\n // let's determines which one of the orthogonal projection is the beginning and end of the circle segment.\n // when `alpha` equals 0 or 2*PI, we have a straight line, so the way to find the start/end is different.\n const isStraightLine = this.alpha % twoMathPi === 0,\n // change the origin of the projections to point A\n // so that the cross product calculation is correct\n newOrigin = this.applySkew(this.A),\n proj0 = projections[isStraightLine ? 0 : 2].subtract(newOrigin),\n proj1 = projections[isStraightLine ? 1 : 0].subtract(newOrigin),\n // when `isStraightLine` === true, we compare with the vector opposite AB, otherwise we compare with the bisector.\n comparisonVector = isStraightLine\n ? this.applySkew(this.AB.scalarMultiply(-1))\n : this.applySkew(\n this.bisector.multiply(this.strokeUniformScalar).scalarMultiply(-1),\n ),\n // the beginning of the circle segment is always to the right of the comparison vector (cross product > 0)\n isProj0Start = crossProduct(proj0, comparisonVector) > 0,\n startCircle = isProj0Start ? proj0 : proj1,\n endCircle = isProj0Start ? proj1 : proj0;\n if (!this.isSkewed()) {\n projections.push(...this.projectRoundNoSkew(startCircle, endCircle));\n } else {\n projections.push(...this.projectRoundWithSkew(startCircle, endCircle));\n }\n return projections;\n }\n\n /**\n * Project stroke width on points returning projections for each point as follows:\n * - `miter`: 1 point corresponding to the outer boundary. If the miter limit is exceeded, it will be 2 points (becomes bevel)\n * - `bevel`: 2 points corresponding to the bevel possible boundaries, orthogonal to the stroke.\n * - `round`: same as `bevel` when it has no skew, with skew are 4 points.\n */\n protected projectPoints() {\n switch (this.options.strokeLineJoin) {\n case 'miter':\n return this.projectMiter();\n case 'round':\n return this.projectRound();\n default:\n return this.projectBevel();\n }\n }\n\n public project(): TProjection[] {\n return this.projectPoints().map((point) => ({\n originPoint: this.A,\n projectedPoint: point,\n angle: this.alpha,\n bisector: this.bisector,\n }));\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _defineProperty } from "../../../../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import { _defineProperty } from "../../../../_virtual/_@oxc-project_runtime@0.126.0/helpers/defineProperty.mjs";
|
|
2
2
|
import { halfPI, twoMathPi } from "../../../constants.mjs";
|
|
3
3
|
import { Point } from "../../../Point.mjs";
|
|
4
4
|
import { degreesToRadians } from "../radiansDegreesConversion.mjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TBBox, SVGElementName } from '../../typedefs';
|
|
1
|
+
import type { TBBox, SVGElementName, TFiller } from '../../typedefs';
|
|
2
2
|
/**
|
|
3
3
|
* Returns array of attributes for given svg that fabric parses
|
|
4
4
|
* @param {SVGElementName} type Type of svg element (eg. 'circle')
|
|
@@ -35,6 +35,6 @@ export declare const parsePreserveAspectRatioAttribute: (attribute: string) => T
|
|
|
35
35
|
* @param {boolean} inlineStyle The default is inline style, the separator used is ":", The other is "="
|
|
36
36
|
* @returns
|
|
37
37
|
*/
|
|
38
|
-
export declare const colorPropToSVG: (prop: string, value?:
|
|
38
|
+
export declare const colorPropToSVG: (prop: string, value?: string | TFiller | null, inlineStyle?: boolean) => string;
|
|
39
39
|
export declare const createSVGRect: (color: string, { left, top, width, height }: TBBox, precision?: number) => string;
|
|
40
40
|
//# sourceMappingURL=svgParsing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"svgParsing.d.ts","sourceRoot":"","sources":["../../../../src/util/misc/svgParsing.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"svgParsing.d.ts","sourceRoot":"","sources":["../../../../src/util/misc/svgParsing.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,KAAK,EACL,cAAc,EAEd,OAAO,EACR,MAAM,gBAAgB,CAAC;AAKxB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,cAAc,aA2BpD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,EAAE,iBAAgC,WA0BxE,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3C,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC;AAaF;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,GAC5C,WAAW,MAAM,KAChB,iBAWF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,QAAQ,MAAM,GAAG,OAAO,GAAG,IAAI,EAC/B,qBAAkB,WAgCnB,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,OAAO,MAAM,EACb,8BAA8B,KAAK,EACnC,kBAAsC,WAOvC,CAAC"}
|