Comparing version 6.0.0-beta3 to 6.0.0-beta4
@@ -14,3 +14,3 @@ /** | ||
export declare const getDocument: () => Document; | ||
export declare const getWindow: () => Window | DOMWindow; | ||
export declare const getWindow: () => (Window & typeof globalThis) | DOMWindow; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -9,3 +9,3 @@ import { GLProbe } from '../filters/GLProbes/GLProbe'; | ||
document: Document; | ||
window: Window | DOMWindow; | ||
window: (Window & typeof globalThis) | DOMWindow; | ||
isTouchSupported: boolean; | ||
@@ -12,0 +12,0 @@ WebGLProbe: GLProbe; |
@@ -9,3 +9,3 @@ export declare const cssRules: {}; | ||
}; | ||
export declare const reNum = "(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:[eE][-+]?\\d+)?)"; | ||
export declare const reNum: string; | ||
export declare const svgNS = "http://www.w3.org/2000/svg"; | ||
@@ -12,0 +12,0 @@ export declare const commaWsp: string; |
@@ -0,12 +1,18 @@ | ||
import { LoadImageOptions } from '../util/misc/objectEnlive'; | ||
import type { TSvgParsedCallback, TSvgReviverCallback } from './typedefs'; | ||
/** | ||
* Takes string corresponding to an SVG document, and parses it into a set of fabric objects | ||
* @memberOf fabric | ||
* @param {String} string | ||
* @param {Function} callback | ||
* @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. | ||
* @param {String} string representing the svg | ||
* @param {TSvgParsedCallback} callback Invoked when the parsing is done, with null if parsing wasn't possible with the list of svg nodes. | ||
* {@link TSvgParsedCallback} also receives `allElements` array as the last argument. This is the full list of svg nodes available in the document. | ||
* You may want to use it if you are trying to regroup the objects as they were originally grouped in the SVG. ( This was the reason why it was added ) | ||
* @param {TSvgReviverCallback} [reviver] Extra callback for further parsing of SVG elements, called after each fabric object has been created. | ||
* Takes as input the original svg element and the generated `FabricObject` as arguments. Used to inspect extra properties not parsed by fabric, | ||
* or extra custom manipulation | ||
* @param {Object} [options] Object containing options for parsing | ||
* @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources | ||
* @param {String} [options.crossOrigin] crossOrigin setting to use for external resources | ||
* @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal | ||
*/ | ||
export declare function loadSVGFromString(string: any, callback: any, reviver: any, options: any): void; | ||
export declare function loadSVGFromString(string: string, callback: TSvgParsedCallback, reviver?: TSvgReviverCallback, options?: LoadImageOptions): void; | ||
//# sourceMappingURL=loadSVGFromString.d.ts.map |
@@ -0,1 +1,3 @@ | ||
import type { TSvgParsedCallback, TSvgReviverCallback } from './typedefs'; | ||
import type { LoadImageOptions } from '../util/misc/objectEnlive'; | ||
/** | ||
@@ -5,10 +7,14 @@ * Takes url corresponding to an SVG document, and parses it into a set of fabric objects. | ||
* @memberOf fabric | ||
* @param {String} url | ||
* @param {Function} callback | ||
* @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. | ||
* @param {string} url where the SVG is | ||
* @param {TSvgParsedCallback} callback Invoked when the parsing is done, with null if parsing wasn't possible with the list of svg nodes. | ||
* {@link TSvgParsedCallback} also receives `allElements` array as the last argument. This is the full list of svg nodes available in the document. | ||
* You may want to use it if you are trying to regroup the objects as they were originally grouped in the SVG. ( This was the reason why it was added ) | ||
* @param {TSvgReviverCallback} [reviver] Extra callback for further parsing of SVG elements, called after each fabric object has been created. | ||
* Takes as input the original svg element and the generated `FabricObject` as arguments. Used to inspect extra properties not parsed by fabric, | ||
* or extra custom manipulation | ||
* @param {Object} [options] Object containing options for parsing | ||
* @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources | ||
* @param {String} [options.crossOrigin] crossOrigin setting to use for external resources | ||
* @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal | ||
*/ | ||
export declare function loadSVGFromURL(url: any, callback: any, reviver: any, options: any): void; | ||
export declare function loadSVGFromURL(url: string, callback: TSvgParsedCallback, reviver?: TSvgReviverCallback, options?: LoadImageOptions): void; | ||
//# sourceMappingURL=loadSVGFromURL.d.ts.map |
@@ -0,1 +1,3 @@ | ||
import type { TSvgParsedCallback, TSvgReviverCallback } from './typedefs'; | ||
import type { LoadImageOptions } from '../util/misc/objectEnlive'; | ||
/** | ||
@@ -6,11 +8,14 @@ * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback | ||
* @memberOf fabric | ||
* @param {SVGDocument} doc SVG document to parse | ||
* @param {Function} callback Callback to call when parsing is finished; | ||
* It's being passed an array of elements (parsed from a document). | ||
* @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. | ||
* @param {Object} [parsingOptions] options for parsing document | ||
* @param {String} [parsingOptions.crossOrigin] crossOrigin settings | ||
* @param {AbortSignal} [parsingOptions.signal] see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal | ||
* @param {HTMLElement} doc SVG document to parse | ||
* @param {TSvgParsedCallback} callback Invoked when the parsing is done, with null if parsing wasn't possible with the list of svg nodes. | ||
* {@link TSvgParsedCallback} also receives `allElements` array as the last argument. This is the full list of svg nodes available in the document. | ||
* You may want to use it if you are trying to regroup the objects as they were originally grouped in the SVG. ( This was the reason why it was added ) | ||
* @param {TSvgReviverCallback} [reviver] Extra callback for further parsing of SVG elements, called after each fabric object has been created. | ||
* Takes as input the original svg element and the generated `FabricObject` as arguments. Used to inspect extra properties not parsed by fabric, | ||
* or extra custom manipulation | ||
* @param {Object} [options] Object containing options for parsing | ||
* @param {String} [options.crossOrigin] crossOrigin setting to use for external resources | ||
* @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal | ||
*/ | ||
export declare function parseSVGDocument(doc: any, callback: any, reviver: any, parsingOptions: any): void; | ||
export declare function parseSVGDocument(doc: HTMLElement, callback: TSvgParsedCallback, reviver?: TSvgReviverCallback, { crossOrigin, signal }?: LoadImageOptions): void; | ||
//# sourceMappingURL=parseSVGDocument.d.ts.map |
@@ -0,1 +1,2 @@ | ||
import { TMat2D } from '../typedefs'; | ||
/** | ||
@@ -7,5 +8,5 @@ * Parses "transform" attribute, returning an array of values | ||
* @param {String} attributeValue String containing attribute value | ||
* @return {Array} Array of 6 elements representing transformation matrix | ||
* @return {TTransformMatrix} Array of 6 elements representing transformation matrix | ||
*/ | ||
export declare function parseTransformAttribute(attributeValue: any): any; | ||
export declare function parseTransformAttribute(attributeValue: string): TMat2D; | ||
//# sourceMappingURL=parseTransformAttribute.d.ts.map |
@@ -1,2 +0,17 @@ | ||
export declare function rotateMatrix(matrix: any, args: any): void; | ||
import { TDegree, TMat2D } from '../typedefs'; | ||
/** | ||
* A rotation matrix | ||
* In the form of | ||
* [cos(a) -sin(a) -xcos(a)+ysin(a)+x] | ||
* [sin(a) cos(a) -xsin(a)-ycos(a)+y] | ||
* [0 0 1 ] | ||
*/ | ||
/** | ||
* Generate a rotation matrix around the center or around a point x,y | ||
* @param {TDegree} angle rotation in degrees | ||
* @param {number} [x] translation on X axis for the pivot point | ||
* @param {number} [y] translation on Y axis for the pivot point | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export declare function rotateMatrix(angle: TDegree, x?: number, y?: number): TMat2D; | ||
//# sourceMappingURL=rotateMatrix.d.ts.map |
@@ -1,2 +0,18 @@ | ||
export declare function scaleMatrix(matrix: any, args: any): void; | ||
import { TMat2D } from '../typedefs'; | ||
/** | ||
* A scale matrix | ||
* Takes form | ||
* [x 0 0] | ||
* [0 y 0] | ||
* [0 0 1] | ||
* For more info, see | ||
* @link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#scale | ||
*/ | ||
/** | ||
* Generate a scale matrix around the point 0,0 | ||
* @param {number} x scale on X axis | ||
* @param {number} [y] scale on Y axis | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export declare const scaleMatrix: (x: number, y?: number) => TMat2D; | ||
//# sourceMappingURL=scaleMatrix.d.ts.map |
@@ -1,2 +0,14 @@ | ||
export declare function skewMatrix(matrix: any, args: any, pos: any): void; | ||
import { TDegree, TMat2D } from '../typedefs'; | ||
/** | ||
* Generate a skew matrix for the X axis | ||
* @param {TDegree} skewValue translation on X axis | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export declare const skewXMatrix: (skewValue: TDegree) => TMat2D; | ||
/** | ||
* Generate a skew matrix for the Y axis | ||
* @param {TDegree} skewValue translation on Y axis | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export declare const skewYMatrix: (skewValue: TDegree) => TMat2D; | ||
//# sourceMappingURL=skewMatrix.d.ts.map |
@@ -1,2 +0,16 @@ | ||
export declare function translateMatrix(matrix: any, args: any): void; | ||
import { TMat2D } from '../typedefs'; | ||
/** | ||
* A translation matrix in the form of | ||
* [ 1 0 x ] | ||
* [ 0 1 y ] | ||
* [ 0 0 1 ] | ||
* See @link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#translate for more details | ||
*/ | ||
/** | ||
* Generate a translation matrix | ||
* @param {number} x translation on X axis | ||
* @param {number} [y] translation on Y axis | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export declare const translateMatrix: (x: number, y?: number) => TMat2D; | ||
//# sourceMappingURL=translateMatrix.d.ts.map |
import { Point } from '../Point'; | ||
import { FabricObject } from './Object/FabricObject'; | ||
import { TPathSegmentInfo, TSimplePathData } from '../util/path/typedefs'; | ||
import { TComplexPathData, TPathSegmentInfo, TSimplePathData } from '../util/path/typedefs'; | ||
import type { FabricObjectProps, SerializedObjectProps, TProps } from './Object/types'; | ||
import type { ObjectEvents } from '../EventTypeDefs'; | ||
import { TClassProperties, TSVGReviver } from '../typedefs'; | ||
import { TBBox, TClassProperties, TSVGReviver } from '../typedefs'; | ||
interface UniquePathProps { | ||
@@ -15,2 +15,7 @@ sourcePath?: string; | ||
} | ||
export interface IPathBBox extends TBBox { | ||
left: number; | ||
top: number; | ||
pathOffset: Point; | ||
} | ||
export declare class Path<Props extends TProps<PathProps> = Partial<PathProps>, SProps extends SerializedPathProps = SerializedPathProps, EventSpec extends ObjectEvents = ObjectEvents> extends FabricObject<Props, SProps, EventSpec> { | ||
@@ -30,16 +35,23 @@ /** | ||
* Constructor | ||
* @param {TSimplePathData} path Path data (sequence of coordinates and corresponding "command" tokens) | ||
* @param {Object} [options] Options object | ||
* @param {TComplexPathData} path Path data (sequence of coordinates and corresponding "command" tokens) | ||
* @param {Partial<PathProps>} [options] Options object | ||
* @return {Path} thisArg | ||
*/ | ||
constructor(path: TSimplePathData | string, { path, left, top, ...options }?: Props); | ||
constructor(path: TComplexPathData | string, { path, left, top, ...options }?: Partial<Props>); | ||
/** | ||
* @private | ||
* @param {TSimplePathData | string} path Path data (sequence of coordinates and corresponding "command" tokens) | ||
* @param {TComplexPathData | string} path Path data (sequence of coordinates and corresponding "command" tokens) | ||
* @param {boolean} [adjustPosition] pass true to reposition the object according to the bounding box | ||
* @returns {Point} top left position of the bounding box, useful for complementary positioning | ||
*/ | ||
_setPath(path: TSimplePathData | string, adjustPosition?: boolean): Point; | ||
_setPath(path: TComplexPathData | string, adjustPosition?: boolean): void; | ||
/** | ||
* This function is an helper for svg import. it returns the center of the object in the svg | ||
* untransformed coordinates, by look at the polyline/polygon points. | ||
* @private | ||
* @return {Point} center point from element coordinates | ||
*/ | ||
_findCenterFromElement(): Point; | ||
/** | ||
* @private | ||
* @param {CanvasRenderingContext2D} ctx context to render path on | ||
@@ -76,2 +88,6 @@ */ | ||
_toSVG(): string[]; | ||
/** | ||
* @private | ||
* @return the path command's translate transform attribute | ||
*/ | ||
_getOffsetTransform(): string; | ||
@@ -95,13 +111,9 @@ /** | ||
complexity(): number; | ||
setDimensions(): Point; | ||
setDimensions(): void; | ||
setBoundingBox(adjustPosition?: boolean): void; | ||
_calcBoundsFromPath(): TBBox; | ||
/** | ||
* @private | ||
*/ | ||
_calcDimensions(): { | ||
left: number; | ||
top: number; | ||
pathOffset: Point; | ||
width: number; | ||
height: number; | ||
}; | ||
_calcDimensions(): IPathBBox; | ||
/** | ||
@@ -127,9 +139,8 @@ * List of attribute names to account for when parsing SVG element (used by `Path.fromElement`) | ||
* @param {SVGElement} element to parse | ||
* @param {Function} callback Callback to invoke when an Path instance is created | ||
* @param {Object} [options] Options object | ||
* @param {Function} [callback] Options callback invoked after parsing is finished | ||
* @param {(path: Path) => void} callback Callback to invoke after the element has been parsed | ||
* @param {Partial<PathProps>} [options] Options object | ||
*/ | ||
static fromElement(element: SVGElement, callback: (path: Path) => void, options: any): void; | ||
static fromElement(element: SVGElement, callback: (path: Path) => void, options: Partial<PathProps>): void; | ||
} | ||
export {}; | ||
//# sourceMappingURL=Path.d.ts.map |
@@ -75,2 +75,9 @@ import { XY, Point } from '../Point'; | ||
}; | ||
/** | ||
* This function is an helper for svg import. it returns the center of the object in the svg | ||
* untransformed coordinates, by look at the polyline/polygon points. | ||
* @private | ||
* @return {Point} center point from element coordinates | ||
*/ | ||
_findCenterFromElement(): Point; | ||
setDimensions(): void; | ||
@@ -77,0 +84,0 @@ setBoundingBox(adjustPosition?: boolean): void; |
@@ -50,4 +50,19 @@ import { BaseFabricObject } from './EventTypeDefs'; | ||
} | ||
export type TMat2D = [number, number, number, number, number, number]; | ||
/** | ||
* A transform matrix. | ||
* Basically a matrix in the form | ||
* [ a c e ] | ||
* [ b d f ] | ||
* [ 0 0 1 ] | ||
* For more details, see @link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#matrix | ||
*/ | ||
export type TMat2D = [ | ||
a: number, | ||
b: number, | ||
c: number, | ||
d: number, | ||
e: number, | ||
f: number | ||
]; | ||
/** | ||
* An invalid keyword and an empty string will be handled as the `anonymous` keyword. | ||
@@ -54,0 +69,0 @@ * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes |
@@ -13,3 +13,3 @@ /** | ||
*/ | ||
export declare function request(url: any, options?: {}): any; | ||
export declare function request(url: any, options?: {}): XMLHttpRequest; | ||
//# sourceMappingURL=dom_request.d.ts.map |
@@ -1,3 +0,2 @@ | ||
export declare const numberRegExStr: string; | ||
export declare const rePathCommand: string; | ||
//# sourceMappingURL=regex.d.ts.map |
@@ -5,3 +5,3 @@ { | ||
"homepage": "http://fabricjs.com/", | ||
"version": "6.0.0-beta3", | ||
"version": "6.0.0-beta4", | ||
"author": "Juriy Zaytsev <kangax@gmail.com>", | ||
@@ -8,0 +8,0 @@ "contributors": [ |
@@ -24,2 +24,3 @@ /** | ||
export const getWindow = (): Window | DOMWindow => getEnv().window; | ||
export const getWindow = (): (Window & typeof globalThis) | DOMWindow => | ||
getEnv().window; |
@@ -10,3 +10,3 @@ import { GLProbe } from '../filters/GLProbes/GLProbe'; | ||
document: Document; | ||
window: Window | DOMWindow; | ||
window: (Window & typeof globalThis) | DOMWindow; | ||
isTouchSupported: boolean; | ||
@@ -13,0 +13,0 @@ WebGLProbe: GLProbe; |
@@ -380,2 +380,3 @@ //@ts-nocheck | ||
const gradientUnits = parseGradientUnits(el); | ||
const center = instance._findCenterFromElement(); | ||
return new this({ | ||
@@ -395,4 +396,4 @@ id: el.getAttribute('id') || undefined, | ||
? { | ||
offsetX: -instance.left, | ||
offsetY: -instance.top, | ||
offsetX: instance.width / 2 - center.x, | ||
offsetY: instance.height / 2 - center.y, | ||
} | ||
@@ -399,0 +400,0 @@ : { |
@@ -14,3 +14,3 @@ //@ts-nocheck | ||
export const reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:[eE][-+]?\\d+)?)'; | ||
export const reNum = String.raw`(?:[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?)`; | ||
@@ -17,0 +17,0 @@ export const svgNS = 'http://www.w3.org/2000/svg'; |
@@ -1,4 +0,5 @@ | ||
//@ts-nocheck | ||
import { getWindow } from '../env'; | ||
import { LoadImageOptions } from '../util/misc/objectEnlive'; | ||
import { parseSVGDocument } from './parseSVGDocument'; | ||
import type { TSvgParsedCallback, TSvgReviverCallback } from './typedefs'; | ||
@@ -8,20 +9,23 @@ /** | ||
* @memberOf fabric | ||
* @param {String} string | ||
* @param {Function} callback | ||
* @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. | ||
* @param {String} string representing the svg | ||
* @param {TSvgParsedCallback} callback Invoked when the parsing is done, with null if parsing wasn't possible with the list of svg nodes. | ||
* {@link TSvgParsedCallback} also receives `allElements` array as the last argument. This is the full list of svg nodes available in the document. | ||
* You may want to use it if you are trying to regroup the objects as they were originally grouped in the SVG. ( This was the reason why it was added ) | ||
* @param {TSvgReviverCallback} [reviver] Extra callback for further parsing of SVG elements, called after each fabric object has been created. | ||
* Takes as input the original svg element and the generated `FabricObject` as arguments. Used to inspect extra properties not parsed by fabric, | ||
* or extra custom manipulation | ||
* @param {Object} [options] Object containing options for parsing | ||
* @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources | ||
* @param {String} [options.crossOrigin] crossOrigin setting to use for external resources | ||
* @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal | ||
*/ | ||
export function loadSVGFromString(string, callback, reviver, options) { | ||
export function loadSVGFromString( | ||
string: string, | ||
callback: TSvgParsedCallback, | ||
reviver?: TSvgReviverCallback, | ||
options?: LoadImageOptions | ||
) { | ||
const parser = new (getWindow().DOMParser)(), | ||
// should we use `image/svg+xml` here? | ||
doc = parser.parseFromString(string.trim(), 'text/xml'); | ||
parseSVGDocument( | ||
doc.documentElement, | ||
function (results, _options, elements, allElements) { | ||
callback(results, _options, elements, allElements); | ||
}, | ||
reviver, | ||
options | ||
); | ||
parseSVGDocument(doc.documentElement, callback, reviver, options); | ||
} |
@@ -1,5 +0,5 @@ | ||
//@ts-nocheck | ||
import { request } from '../util/dom_request'; | ||
import { parseSVGDocument } from './parseSVGDocument'; | ||
import type { TSvgParsedCallback, TSvgReviverCallback } from './typedefs'; | ||
import type { LoadImageOptions } from '../util/misc/objectEnlive'; | ||
@@ -10,32 +10,34 @@ /** | ||
* @memberOf fabric | ||
* @param {String} url | ||
* @param {Function} callback | ||
* @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. | ||
* @param {string} url where the SVG is | ||
* @param {TSvgParsedCallback} callback Invoked when the parsing is done, with null if parsing wasn't possible with the list of svg nodes. | ||
* {@link TSvgParsedCallback} also receives `allElements` array as the last argument. This is the full list of svg nodes available in the document. | ||
* You may want to use it if you are trying to regroup the objects as they were originally grouped in the SVG. ( This was the reason why it was added ) | ||
* @param {TSvgReviverCallback} [reviver] Extra callback for further parsing of SVG elements, called after each fabric object has been created. | ||
* Takes as input the original svg element and the generated `FabricObject` as arguments. Used to inspect extra properties not parsed by fabric, | ||
* or extra custom manipulation | ||
* @param {Object} [options] Object containing options for parsing | ||
* @param {String} [options.crossOrigin] crossOrigin crossOrigin setting to use for external resources | ||
* @param {String} [options.crossOrigin] crossOrigin setting to use for external resources | ||
* @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal | ||
*/ | ||
export function loadSVGFromURL(url, callback, reviver, options) { | ||
new request(url.replace(/^\n\s*/, '').trim(), { | ||
method: 'get', | ||
onComplete: onComplete, | ||
signal: options && options.signal, | ||
}); | ||
function onComplete(r) { | ||
export function loadSVGFromURL( | ||
url: string, | ||
callback: TSvgParsedCallback, | ||
reviver?: TSvgReviverCallback, | ||
options: LoadImageOptions = {} | ||
) { | ||
const onComplete = (r: XMLHttpRequest) => { | ||
const xml = r.responseXML; | ||
if (!xml || !xml.documentElement) { | ||
callback && callback(null); | ||
callback(null, {}, [], []); | ||
return false; | ||
} | ||
parseSVGDocument( | ||
xml.documentElement, | ||
function (results, _options, elements, allElements) { | ||
callback && callback(results, _options, elements, allElements); | ||
}, | ||
reviver, | ||
options | ||
); | ||
} | ||
parseSVGDocument(xml.documentElement, callback, reviver, options); | ||
}; | ||
request(url.replace(/^\n\s*/, '').trim(), { | ||
method: 'get', | ||
onComplete, | ||
signal: options.signal, | ||
}); | ||
} |
//@ts-nocheck | ||
import { uid } from '../util/internals/uid'; | ||
@@ -17,3 +16,4 @@ import { applyViewboxTransform } from './applyViewboxTransform'; | ||
import { parseUseDirectives } from './parseUseDirectives'; | ||
import type { TSvgParsedCallback, TSvgReviverCallback } from './typedefs'; | ||
import type { LoadImageOptions } from '../util/misc/objectEnlive'; | ||
/** | ||
@@ -24,19 +24,23 @@ * Parses an SVG document, converts it to an array of corresponding fabric.* instances and passes them to a callback | ||
* @memberOf fabric | ||
* @param {SVGDocument} doc SVG document to parse | ||
* @param {Function} callback Callback to call when parsing is finished; | ||
* It's being passed an array of elements (parsed from a document). | ||
* @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created. | ||
* @param {Object} [parsingOptions] options for parsing document | ||
* @param {String} [parsingOptions.crossOrigin] crossOrigin settings | ||
* @param {AbortSignal} [parsingOptions.signal] see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal | ||
* @param {HTMLElement} doc SVG document to parse | ||
* @param {TSvgParsedCallback} callback Invoked when the parsing is done, with null if parsing wasn't possible with the list of svg nodes. | ||
* {@link TSvgParsedCallback} also receives `allElements` array as the last argument. This is the full list of svg nodes available in the document. | ||
* You may want to use it if you are trying to regroup the objects as they were originally grouped in the SVG. ( This was the reason why it was added ) | ||
* @param {TSvgReviverCallback} [reviver] Extra callback for further parsing of SVG elements, called after each fabric object has been created. | ||
* Takes as input the original svg element and the generated `FabricObject` as arguments. Used to inspect extra properties not parsed by fabric, | ||
* or extra custom manipulation | ||
* @param {Object} [options] Object containing options for parsing | ||
* @param {String} [options.crossOrigin] crossOrigin setting to use for external resources | ||
* @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal | ||
*/ | ||
export function parseSVGDocument(doc, callback, reviver, parsingOptions) { | ||
export function parseSVGDocument( | ||
doc: HTMLElement, | ||
callback: TSvgParsedCallback, | ||
reviver?: TSvgReviverCallback, | ||
{ crossOrigin, signal }: LoadImageOptions = {} | ||
) { | ||
if (!doc) { | ||
return; | ||
} | ||
if ( | ||
parsingOptions && | ||
parsingOptions.signal && | ||
parsingOptions.signal.aborted | ||
) { | ||
if (signal && signal.aborted) { | ||
throw new Error('`options.signal` is in `aborted` state'); | ||
@@ -47,7 +51,9 @@ } | ||
const svgUid = uid(), | ||
options = applyViewboxTransform(doc), | ||
descendants = Array.from(doc.getElementsByTagName('*')); | ||
options.crossOrigin = parsingOptions && parsingOptions.crossOrigin; | ||
options.svgUid = svgUid; | ||
options.signal = parsingOptions && parsingOptions.signal; | ||
descendants = Array.from(doc.getElementsByTagName('*')), | ||
options = { | ||
...applyViewboxTransform(doc), | ||
crossOrigin, | ||
svgUid, | ||
signal, | ||
}; | ||
@@ -62,3 +68,3 @@ const elements = descendants.filter(function (el) { | ||
if (!elements || (elements && !elements.length)) { | ||
callback && callback([], {}); | ||
callback([], {}, [], descendants); | ||
return; | ||
@@ -68,11 +74,7 @@ } | ||
descendants | ||
.filter(function (el) { | ||
return el.nodeName.replace('svg:', '') === 'clipPath'; | ||
}) | ||
.forEach(function (el) { | ||
.filter((el) => el.nodeName.replace('svg:', '') === 'clipPath') | ||
.forEach((el) => { | ||
const id = el.getAttribute('id'); | ||
localClipPaths[id] = Array.from(el.getElementsByTagName('*')).filter( | ||
function (el) { | ||
return svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', '')); | ||
} | ||
(el) => svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', '')) | ||
); | ||
@@ -86,3 +88,3 @@ }); | ||
elements, | ||
function (instances, elements) { | ||
(instances, elements) => { | ||
if (callback) { | ||
@@ -95,6 +97,6 @@ callback(instances, options, elements, descendants); | ||
}, | ||
Object.assign({}, options), | ||
{ ...options }, | ||
reviver, | ||
parsingOptions | ||
{ crossOrigin, signal } | ||
); | ||
} |
@@ -1,90 +0,26 @@ | ||
//@ts-nocheck | ||
import { iMatrix } from '../constants'; | ||
import { commaWsp, reNum } from './constants'; | ||
import { reNum } from './constants'; | ||
import { multiplyTransformMatrices } from '../util/misc/matrix'; | ||
import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; | ||
import { rotateMatrix } from './rotateMatrix'; | ||
import { scaleMatrix } from './scaleMatrix'; | ||
import { skewMatrix } from './skewMatrix'; | ||
import { translateMatrix } from './translateMatrix'; | ||
import { TMat2D } from '../typedefs'; | ||
import { cleanupSvgAttribute } from '../util/internals/cleanupSvAttribute'; | ||
import { skewXMatrix, skewYMatrix } from './skewMatrix'; | ||
// == begin transform regexp | ||
const number = reNum, | ||
skewX = '(?:(skewX)\\s*\\(\\s*(' + number + ')\\s*\\))', | ||
skewY = '(?:(skewY)\\s*\\(\\s*(' + number + ')\\s*\\))', | ||
rotate = | ||
'(?:(rotate)\\s*\\(\\s*(' + | ||
number + | ||
')(?:' + | ||
commaWsp + | ||
'(' + | ||
number + | ||
')' + | ||
commaWsp + | ||
'(' + | ||
number + | ||
'))?\\s*\\))', | ||
scale = | ||
'(?:(scale)\\s*\\(\\s*(' + | ||
number + | ||
')(?:' + | ||
commaWsp + | ||
'(' + | ||
number + | ||
'))?\\s*\\))', | ||
translate = | ||
'(?:(translate)\\s*\\(\\s*(' + | ||
number + | ||
')(?:' + | ||
commaWsp + | ||
'(' + | ||
number + | ||
'))?\\s*\\))', | ||
matrix = | ||
'(?:(matrix)\\s*\\(\\s*' + | ||
'(' + | ||
number + | ||
')' + | ||
commaWsp + | ||
'(' + | ||
number + | ||
')' + | ||
commaWsp + | ||
'(' + | ||
number + | ||
')' + | ||
commaWsp + | ||
'(' + | ||
number + | ||
')' + | ||
commaWsp + | ||
'(' + | ||
number + | ||
')' + | ||
commaWsp + | ||
'(' + | ||
number + | ||
')' + | ||
'\\s*\\))', | ||
transform = | ||
'(?:' + | ||
matrix + | ||
'|' + | ||
translate + | ||
'|' + | ||
scale + | ||
'|' + | ||
rotate + | ||
'|' + | ||
skewX + | ||
'|' + | ||
skewY + | ||
')', | ||
transforms = | ||
'(?:' + transform + '(?:' + commaWsp + '*' + transform + ')*' + ')', | ||
transformList = '^\\s*(?:' + transforms + '?)\\s*$', | ||
// http://www.w3.org/TR/SVG/coords.html#TransformAttribute | ||
reTransformList = new RegExp(transformList), | ||
// == end transform regexp | ||
reTransform = new RegExp(transform, 'g'); | ||
const p = `(${reNum})`; | ||
const skewX = String.raw`(skewX)\(${p}\)`; | ||
const skewY = String.raw`(skewY)\(${p}\)`; | ||
const rotate = String.raw`(rotate)\(${p}(?: ${p} ${p})?\)`; | ||
const scale = String.raw`(scale)\(${p}(?: ${p})?\)`; | ||
const translate = String.raw`(translate)\(${p}(?: ${p})?\)`; | ||
const matrix = String.raw`(matrix)\(${p} ${p} ${p} ${p} ${p} ${p}\)`; | ||
const transform = `(?:${matrix}|${translate}|${rotate}|${scale}|${skewX}|${skewY})`; | ||
const transforms = `(?:${transform}*)`; | ||
const transformList = String.raw`^\s*(?:${transforms}?)\s*$`; | ||
// http://www.w3.org/TR/SVG/coords.html#TransformAttribute | ||
const reTransformList = new RegExp(transformList); | ||
// == end transform regexp | ||
const reTransform = new RegExp(transform, 'g'); | ||
@@ -97,8 +33,12 @@ /** | ||
* @param {String} attributeValue String containing attribute value | ||
* @return {Array} Array of 6 elements representing transformation matrix | ||
* @return {TTransformMatrix} Array of 6 elements representing transformation matrix | ||
*/ | ||
export function parseTransformAttribute(attributeValue) { | ||
export function parseTransformAttribute(attributeValue: string): TMat2D { | ||
// first we clean the string | ||
attributeValue = cleanupSvgAttribute(attributeValue) | ||
// remove spaces around front parentheses | ||
.replace(/\s*([()])\s*/gi, '$1'); | ||
// start with identity matrix | ||
let matrix = iMatrix.concat(); | ||
const matrices = []; | ||
const matrices: TMat2D[] = []; | ||
@@ -111,32 +51,35 @@ // return if no argument was given or | ||
) { | ||
return matrix; | ||
return [...iMatrix]; | ||
} | ||
attributeValue.replace(reTransform, function (match) { | ||
const m = new RegExp(transform).exec(match).filter(function (match) { | ||
// match !== '' && match != null | ||
return !!match; | ||
}), | ||
operation = m[1], | ||
args = m.slice(2).map(parseFloat); | ||
for (const match of attributeValue.matchAll(reTransform)) { | ||
const transformMatch = new RegExp(transform).exec(match[0]); | ||
if (!transformMatch) { | ||
continue; | ||
} | ||
let matrix: TMat2D = iMatrix; | ||
const matchedParams = transformMatch.filter((m) => !!m); | ||
const [, operation, ...rawArgs] = matchedParams; | ||
const [arg0, arg1, arg2, arg3, arg4, arg5] = rawArgs.map((arg) => | ||
parseFloat(arg) | ||
); | ||
switch (operation) { | ||
case 'translate': | ||
translateMatrix(matrix, args); | ||
matrix = translateMatrix(arg0, arg1); | ||
break; | ||
case 'rotate': | ||
args[0] = degreesToRadians(args[0]); | ||
rotateMatrix(matrix, args); | ||
matrix = rotateMatrix(arg0, arg1, arg2); | ||
break; | ||
case 'scale': | ||
scaleMatrix(matrix, args); | ||
matrix = scaleMatrix(arg0, arg1); | ||
break; | ||
case 'skewX': | ||
skewMatrix(matrix, args, 2); | ||
matrix = skewXMatrix(arg0); | ||
break; | ||
case 'skewY': | ||
skewMatrix(matrix, args, 1); | ||
matrix = skewYMatrix(arg0); | ||
break; | ||
case 'matrix': | ||
matrix = args; | ||
matrix = [arg0, arg1, arg2, arg3, arg4, arg5]; | ||
break; | ||
@@ -146,13 +89,9 @@ } | ||
// snapshot current matrix into matrices array | ||
matrices.push(matrix.concat()); | ||
// reset | ||
matrix = iMatrix.concat(); | ||
}); | ||
matrices.push(matrix); | ||
} | ||
let combinedMatrix = matrices[0]; | ||
while (matrices.length > 1) { | ||
matrices.shift(); | ||
combinedMatrix = multiplyTransformMatrices(combinedMatrix, matrices[0]); | ||
} | ||
return combinedMatrix; | ||
return matrices.reduce( | ||
(acc, matrix) => multiplyTransformMatrices(acc, matrix), | ||
iMatrix | ||
); | ||
} |
@@ -1,21 +0,33 @@ | ||
//@ts-nocheck | ||
import { cos } from '../util/misc/cos'; | ||
import { sin } from '../util/misc/sin'; | ||
import { TDegree, TMat2D } from '../typedefs'; | ||
import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; | ||
export function rotateMatrix(matrix, args) { | ||
const cosValue = cos(args[0]), | ||
sinValue = sin(args[0]); | ||
let x = 0, | ||
y = 0; | ||
if (args.length === 3) { | ||
x = args[1]; | ||
y = args[2]; | ||
} | ||
/** | ||
* A rotation matrix | ||
* In the form of | ||
* [cos(a) -sin(a) -xcos(a)+ysin(a)+x] | ||
* [sin(a) cos(a) -xsin(a)-ycos(a)+y] | ||
* [0 0 1 ] | ||
*/ | ||
matrix[0] = cosValue; | ||
matrix[1] = sinValue; | ||
matrix[2] = -sinValue; | ||
matrix[3] = cosValue; | ||
matrix[4] = x - (cosValue * x - sinValue * y); | ||
matrix[5] = y - (sinValue * x + cosValue * y); | ||
/** | ||
* Generate a rotation matrix around the center or around a point x,y | ||
* @param {TDegree} angle rotation in degrees | ||
* @param {number} [x] translation on X axis for the pivot point | ||
* @param {number} [y] translation on Y axis for the pivot point | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export function rotateMatrix(angle: TDegree, x = 0, y = 0): TMat2D { | ||
const angleRadiant = degreesToRadians(angle), | ||
cosValue = cos(angleRadiant), | ||
sinValue = sin(angleRadiant); | ||
return [ | ||
cosValue, | ||
sinValue, | ||
-sinValue, | ||
cosValue, | ||
x - (cosValue * x - sinValue * y), | ||
y - (sinValue * x + cosValue * y), | ||
]; | ||
} |
@@ -1,9 +0,26 @@ | ||
//@ts-nocheck | ||
import { TMat2D } from '../typedefs'; | ||
export function scaleMatrix(matrix, args) { | ||
const multiplierX = args[0], | ||
multiplierY = args.length === 2 ? args[1] : args[0]; | ||
/** | ||
* A scale matrix | ||
* Takes form | ||
* [x 0 0] | ||
* [0 y 0] | ||
* [0 0 1] | ||
* For more info, see | ||
* @link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#scale | ||
*/ | ||
matrix[0] = multiplierX; | ||
matrix[3] = multiplierY; | ||
} | ||
/** | ||
* Generate a scale matrix around the point 0,0 | ||
* @param {number} x scale on X axis | ||
* @param {number} [y] scale on Y axis | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export const scaleMatrix = (x: number, y: number = x): TMat2D => [ | ||
x, | ||
0, | ||
0, | ||
y, | ||
0, | ||
0, | ||
]; |
@@ -1,6 +0,47 @@ | ||
//@ts-nocheck | ||
import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; | ||
import { TDegree, TMat2D } from '../typedefs'; | ||
export function skewMatrix(matrix, args, pos) { | ||
matrix[pos] = Math.tan(degreesToRadians(args[0])); | ||
} | ||
/** | ||
* A matrix in the form | ||
* [1 x 0] | ||
* [0 1 0] | ||
* [0 0 1] | ||
* | ||
* or | ||
* | ||
* [1 0 0] | ||
* [y 1 0] | ||
* [0 0 1] | ||
* | ||
* For more info, see | ||
* @link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#skewx | ||
*/ | ||
const fromAngleToSkew = (angle: TDegree) => Math.tan(degreesToRadians(angle)); | ||
/** | ||
* Generate a skew matrix for the X axis | ||
* @param {TDegree} skewValue translation on X axis | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export const skewXMatrix = (skewValue: TDegree): TMat2D => [ | ||
1, | ||
0, | ||
fromAngleToSkew(skewValue), | ||
1, | ||
0, | ||
0, | ||
]; | ||
/** | ||
* Generate a skew matrix for the Y axis | ||
* @param {TDegree} skewValue translation on Y axis | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export const skewYMatrix = (skewValue: TDegree): TMat2D => [ | ||
1, | ||
fromAngleToSkew(skewValue), | ||
0, | ||
1, | ||
0, | ||
0, | ||
]; |
@@ -1,8 +0,17 @@ | ||
//@ts-nocheck | ||
import { TMat2D } from '../typedefs'; | ||
export function translateMatrix(matrix, args) { | ||
matrix[4] = args[0]; | ||
if (args.length === 2) { | ||
matrix[5] = args[1]; | ||
} | ||
} | ||
/** | ||
* A translation matrix in the form of | ||
* [ 1 0 x ] | ||
* [ 0 1 y ] | ||
* [ 0 0 1 ] | ||
* See @link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#translate for more details | ||
*/ | ||
/** | ||
* Generate a translation matrix | ||
* @param {number} x translation on X axis | ||
* @param {number} [y] translation on Y axis | ||
* @returns {TMat2D} matrix | ||
*/ | ||
export const translateMatrix = (x: number, y = 0): TMat2D => [1, 0, 0, 1, x, y]; |
@@ -1241,4 +1241,6 @@ import { cache } from '../../cache'; | ||
height = dims.y / this.scaleY / retinaScaling; | ||
pCanvas.width = width; | ||
pCanvas.height = height; | ||
// in case width and height are less than 1px, we have to round up. | ||
// since the pattern is no-repeat, this is fine | ||
pCanvas.width = Math.ceil(width); | ||
pCanvas.height = Math.ceil(height); | ||
const pCtx = pCanvas.getContext('2d'); | ||
@@ -1245,0 +1247,0 @@ if (!pCtx) { |
@@ -29,2 +29,3 @@ import type { | ||
import { ControlProps } from './types/ControlProps'; | ||
import { translateMatrix } from '../../parser/translateMatrix'; | ||
@@ -666,5 +667,5 @@ type TLineDescriptor = { | ||
const rotateMatrix = calcRotateMatrix({ angle: this.angle }), | ||
center = this.getRelativeCenterPoint(), | ||
translateMatrix = [1, 0, 0, 1, center.x, center.y] as TMat2D, | ||
finalMatrix = multiplyTransformMatrices(translateMatrix, rotateMatrix), | ||
{ x, y } = this.getRelativeCenterPoint(), | ||
tMatrix = translateMatrix(x, y), | ||
finalMatrix = multiplyTransformMatrices(tMatrix, rotateMatrix), | ||
dim = this._getTransformedDimensions(), | ||
@@ -671,0 +672,0 @@ w = dim.x / 2, |
@@ -15,3 +15,7 @@ import { config } from '../config'; | ||
import { FabricObject, cacheProperties } from './Object/FabricObject'; | ||
import { TPathSegmentInfo, TSimplePathData } from '../util/path/typedefs'; | ||
import { | ||
TComplexPathData, | ||
TPathSegmentInfo, | ||
TSimplePathData, | ||
} from '../util/path/typedefs'; | ||
import type { | ||
@@ -23,3 +27,3 @@ FabricObjectProps, | ||
import type { ObjectEvents } from '../EventTypeDefs'; | ||
import { TClassProperties, TSVGReviver } from '../typedefs'; | ||
import { TBBox, TClassProperties, TSVGReviver } from '../typedefs'; | ||
import { cloneDeep } from '../util/internals/cloneDeep'; | ||
@@ -38,2 +42,8 @@ | ||
export interface IPathBBox extends TBBox { | ||
left: number; | ||
top: number; | ||
pathOffset: Point; | ||
} | ||
export class Path< | ||
@@ -63,20 +73,14 @@ Props extends TProps<PathProps> = Partial<PathProps>, | ||
* Constructor | ||
* @param {TSimplePathData} path Path data (sequence of coordinates and corresponding "command" tokens) | ||
* @param {Object} [options] Options object | ||
* @param {TComplexPathData} path Path data (sequence of coordinates and corresponding "command" tokens) | ||
* @param {Partial<PathProps>} [options] Options object | ||
* @return {Path} thisArg | ||
*/ | ||
constructor( | ||
path: TSimplePathData | string, | ||
{ path: _, left, top, ...options }: Props = {} as Props | ||
path: TComplexPathData | string, | ||
{ path: _, left, top, ...options }: Partial<Props> = {} | ||
) { | ||
super(options as Props); | ||
const pathTL = this._setPath(path || []); | ||
const origin = this.translateToGivenOrigin( | ||
new Point(left ?? pathTL.x, top ?? pathTL.y), | ||
typeof left === 'number' ? this.originX : 'left', | ||
typeof top === 'number' ? this.originY : 'top', | ||
this.originX, | ||
this.originY | ||
); | ||
this.setPositionByOrigin(origin, this.originX, this.originY); | ||
this._setPath(path || [], true); | ||
typeof left === 'number' && this.set('left', left); | ||
typeof top === 'number' && this.set('top', top); | ||
} | ||
@@ -86,18 +90,28 @@ | ||
* @private | ||
* @param {TSimplePathData | string} path Path data (sequence of coordinates and corresponding "command" tokens) | ||
* @param {TComplexPathData | string} path Path data (sequence of coordinates and corresponding "command" tokens) | ||
* @param {boolean} [adjustPosition] pass true to reposition the object according to the bounding box | ||
* @returns {Point} top left position of the bounding box, useful for complementary positioning | ||
*/ | ||
_setPath(path: TSimplePathData | string, adjustPosition?: boolean) { | ||
_setPath(path: TComplexPathData | string, adjustPosition?: boolean) { | ||
this.path = makePathSimpler(Array.isArray(path) ? path : parsePath(path)); | ||
return this.setDimensions(); | ||
this.setBoundingBox(adjustPosition); | ||
} | ||
/** | ||
* This function is an helper for svg import. it returns the center of the object in the svg | ||
* untransformed coordinates, by look at the polyline/polygon points. | ||
* @private | ||
* @return {Point} center point from element coordinates | ||
*/ | ||
_findCenterFromElement(): Point { | ||
const bbox = this._calcBoundsFromPath(); | ||
return new Point(bbox.left + bbox.width / 2, bbox.top + bbox.height / 2); | ||
} | ||
/** | ||
* @private | ||
* @param {CanvasRenderingContext2D} ctx context to render path on | ||
*/ | ||
_renderPathCommands(ctx: CanvasRenderingContext2D) { | ||
let current, // current instruction | ||
subpathStartX = 0, | ||
let subpathStartX = 0, | ||
subpathStartY = 0, | ||
@@ -113,11 +127,9 @@ x = 0, // current x | ||
for (let i = 0, len = this.path.length; i < len; ++i) { | ||
current = this.path[i]; | ||
for (const command of this.path) { | ||
switch ( | ||
current[0] // first letter | ||
command[0] // first letter | ||
) { | ||
case 'L': // lineto, absolute | ||
x = current[1]; | ||
y = current[2]; | ||
x = command[1]; | ||
y = command[2]; | ||
ctx.lineTo(x + l, y + t); | ||
@@ -127,4 +139,4 @@ break; | ||
case 'M': // moveTo, absolute | ||
x = current[1]; | ||
y = current[2]; | ||
x = command[1]; | ||
y = command[2]; | ||
subpathStartX = x; | ||
@@ -136,9 +148,9 @@ subpathStartY = y; | ||
case 'C': // bezierCurveTo, absolute | ||
x = current[5]; | ||
y = current[6]; | ||
controlX = current[3]; | ||
controlY = current[4]; | ||
x = command[5]; | ||
y = command[6]; | ||
controlX = command[3]; | ||
controlY = command[4]; | ||
ctx.bezierCurveTo( | ||
current[1] + l, | ||
current[2] + t, | ||
command[1] + l, | ||
command[2] + t, | ||
controlX + l, | ||
@@ -153,11 +165,11 @@ controlY + t, | ||
ctx.quadraticCurveTo( | ||
current[1] + l, | ||
current[2] + t, | ||
current[3] + l, | ||
current[4] + t | ||
command[1] + l, | ||
command[2] + t, | ||
command[3] + l, | ||
command[4] + t | ||
); | ||
x = current[3]; | ||
y = current[4]; | ||
controlX = current[1]; | ||
controlY = current[2]; | ||
x = command[3]; | ||
y = command[4]; | ||
controlX = command[1]; | ||
controlY = command[2]; | ||
break; | ||
@@ -239,2 +251,6 @@ | ||
/** | ||
* @private | ||
* @return the path command's translate transform attribute | ||
*/ | ||
_getOffsetTransform() { | ||
@@ -286,11 +302,13 @@ const digits = config.NUM_FRACTION_DIGITS; | ||
setDimensions() { | ||
this.setBoundingBox(); | ||
} | ||
setBoundingBox(adjustPosition?: boolean) { | ||
const { left, top, width, height, pathOffset } = this._calcDimensions(); | ||
this.set({ width, height, pathOffset }); | ||
return new Point(left, top); | ||
adjustPosition && | ||
this.setPositionByOrigin(new Point(left, top), 'left', 'top'); | ||
} | ||
/** | ||
* @private | ||
*/ | ||
_calcDimensions() { | ||
_calcBoundsFromPath(): TBBox { | ||
const bounds: XY[] = []; | ||
@@ -302,10 +320,10 @@ let subpathStartX = 0, | ||
for (let i = 0; i < this.path.length; ++i) { | ||
const current = this.path[i]; // current instruction | ||
for (const command of this.path) { | ||
// current instruction | ||
switch ( | ||
current[0] // first letter | ||
command[0] // first letter | ||
) { | ||
case 'L': // lineto, absolute | ||
x = current[1]; | ||
y = current[2]; | ||
x = command[1]; | ||
y = command[2]; | ||
bounds.push(new Point(subpathStartX, subpathStartY), new Point(x, y)); | ||
@@ -315,4 +333,4 @@ break; | ||
case 'M': // moveTo, absolute | ||
x = current[1]; | ||
y = current[2]; | ||
x = command[1]; | ||
y = command[2]; | ||
subpathStartX = x; | ||
@@ -327,12 +345,12 @@ subpathStartY = y; | ||
y, | ||
current[1], | ||
current[2], | ||
current[3], | ||
current[4], | ||
current[5], | ||
current[6] | ||
command[1], | ||
command[2], | ||
command[3], | ||
command[4], | ||
command[5], | ||
command[6] | ||
) | ||
); | ||
x = current[5]; | ||
y = current[6]; | ||
x = command[5]; | ||
y = command[6]; | ||
break; | ||
@@ -345,12 +363,12 @@ | ||
y, | ||
current[1], | ||
current[2], | ||
current[1], | ||
current[2], | ||
current[3], | ||
current[4] | ||
command[1], | ||
command[2], | ||
command[1], | ||
command[2], | ||
command[3], | ||
command[4] | ||
) | ||
); | ||
x = current[3]; | ||
y = current[4]; | ||
x = command[3]; | ||
y = command[4]; | ||
break; | ||
@@ -364,4 +382,10 @@ | ||
} | ||
return makeBoundingBoxFromPoints(bounds); | ||
} | ||
const bbox = makeBoundingBoxFromPoints(bounds); | ||
/** | ||
* @private | ||
*/ | ||
_calcDimensions(): IPathBBox { | ||
const bbox = this._calcBoundsFromPath(); | ||
const strokeCorrection = this.fromSVG ? 0 : this.strokeWidth / 2; | ||
@@ -406,5 +430,4 @@ | ||
* @param {SVGElement} element to parse | ||
* @param {Function} callback Callback to invoke when an Path instance is created | ||
* @param {Object} [options] Options object | ||
* @param {Function} [callback] Options callback invoked after parsing is finished | ||
* @param {(path: Path) => void} callback Callback to invoke after the element has been parsed | ||
* @param {Partial<PathProps>} [options] Options object | ||
*/ | ||
@@ -414,3 +437,3 @@ static fromElement( | ||
callback: (path: Path) => void, | ||
options: any | ||
options: Partial<PathProps> | ||
) { | ||
@@ -417,0 +440,0 @@ const parsedAttributes = parseAttributes(element, this.ATTRIBUTE_NAMES); |
@@ -163,2 +163,13 @@ import { config } from '../config'; | ||
/** | ||
* This function is an helper for svg import. it returns the center of the object in the svg | ||
* untransformed coordinates, by look at the polyline/polygon points. | ||
* @private | ||
* @return {Point} center point from element coordinates | ||
*/ | ||
_findCenterFromElement(): Point { | ||
const bbox = makeBoundingBoxFromPoints(this.points); | ||
return new Point(bbox.left + bbox.width / 2, bbox.top + bbox.height / 2); | ||
} | ||
setDimensions() { | ||
@@ -165,0 +176,0 @@ this.setBoundingBox(); |
@@ -67,3 +67,18 @@ // https://www.typescriptlang.org/docs/handbook/utility-types.html | ||
export type TMat2D = [number, number, number, number, number, number]; | ||
/** | ||
* A transform matrix. | ||
* Basically a matrix in the form | ||
* [ a c e ] | ||
* [ b d f ] | ||
* [ 0 0 1 ] | ||
* For more details, see @link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#matrix | ||
*/ | ||
export type TMat2D = [ | ||
a: number, | ||
b: number, | ||
c: number, | ||
d: number, | ||
e: number, | ||
f: number | ||
]; | ||
@@ -70,0 +85,0 @@ /** |
import { iMatrix } from '../../constants'; | ||
import { scaleMatrix } from '../../parser/scaleMatrix'; | ||
import { skewXMatrix, skewYMatrix } from '../../parser/skewMatrix'; | ||
import { XY, Point } from '../../Point'; | ||
@@ -148,28 +150,13 @@ import { TDegree, TMat2D } from '../../typedefs'; | ||
}: TScaleMatrixArgs) => { | ||
let scaleMatrix = iMatrix; | ||
if (scaleX !== 1 || scaleY !== 1 || flipX || flipY) { | ||
scaleMatrix = [ | ||
flipX ? -scaleX : scaleX, | ||
0, | ||
0, | ||
flipY ? -scaleY : scaleY, | ||
0, | ||
0, | ||
] as TMat2D; | ||
} | ||
let scaleMat = scaleMatrix( | ||
flipX ? -scaleX : scaleX, | ||
flipY ? -scaleY : scaleY | ||
); | ||
if (skewX) { | ||
scaleMatrix = multiplyTransformMatrices( | ||
scaleMatrix, | ||
[1, 0, Math.tan(degreesToRadians(skewX)), 1] as unknown as TMat2D, | ||
true | ||
); | ||
scaleMat = multiplyTransformMatrices(scaleMat, skewXMatrix(skewX), true); | ||
} | ||
if (skewY) { | ||
scaleMatrix = multiplyTransformMatrices( | ||
scaleMatrix, | ||
[1, Math.tan(degreesToRadians(skewY)), 0, 1] as unknown as TMat2D, | ||
true | ||
); | ||
scaleMat = multiplyTransformMatrices(scaleMat, skewYMatrix(skewY), true); | ||
} | ||
return scaleMatrix; | ||
return scaleMat; | ||
}; | ||
@@ -176,0 +163,0 @@ |
@@ -25,3 +25,4 @@ import { cache } from '../../cache'; | ||
import { XY, Point } from '../../Point'; | ||
import { numberRegExStr, rePathCommand } from './regex'; | ||
import { rePathCommand } from './regex'; | ||
import { cleanupSvgAttribute } from '../internals/cleanupSvAttribute'; | ||
@@ -98,2 +99,5 @@ /** | ||
): TParsedAbsoluteCubicCurveCommand[] => { | ||
if (rx === 0 || ry === 0) { | ||
return []; | ||
} | ||
let fromX = 0, | ||
@@ -844,7 +848,3 @@ fromY = 0, | ||
// add spaces around the numbers | ||
pathString = pathString | ||
.replace(new RegExp(`(${numberRegExStr})`, 'gi'), ' $1 ') | ||
// replace annoying commas and arbitrary whitespace with single spaces | ||
.replace(/,/gi, ' ') | ||
.replace(/\s+/gi, ' '); | ||
pathString = cleanupSvgAttribute(pathString); | ||
@@ -851,0 +851,0 @@ const res: TComplexPathData = []; |
@@ -1,4 +0,2 @@ | ||
// absolute value number | ||
const absNumberRegExStr = String.raw`(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?`; | ||
export const numberRegExStr = `[-+]?${absNumberRegExStr}`; | ||
import { reNum } from '../../parser/constants'; | ||
@@ -9,3 +7,3 @@ /** | ||
*/ | ||
const p = `(${numberRegExStr})`; | ||
const p = `(${reNum})`; | ||
@@ -12,0 +10,0 @@ const reMoveToCommand = `(M) (?:${p} ${p} ?)+`; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
14069815
520
159851