fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 32.5 kB
Source Map (JSON)
{"version":3,"file":"ObjectGeometry.mjs","names":[],"sources":["../../../../src/shapes/Object/ObjectGeometry.ts"],"sourcesContent":["import type {\n TBBox,\n TCornerPoint,\n TDegree,\n TMat2D,\n TOriginX,\n TOriginY,\n} from '../../typedefs';\nimport { SCALE_X, SCALE_Y, iMatrix } from '../../constants';\nimport { Intersection } from '../../Intersection';\nimport { Point } from '../../Point';\nimport { makeBoundingBoxFromPoints } from '../../util/misc/boundingBoxFromPoints';\nimport {\n createRotateMatrix,\n createTranslateMatrix,\n composeMatrix,\n invertTransform,\n multiplyTransformMatrices,\n transformPoint,\n calcPlaneRotation,\n} from '../../util/misc/matrix';\nimport { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';\nimport type { Canvas } from '../../canvas/Canvas';\nimport type { StaticCanvas } from '../../canvas/StaticCanvas';\nimport type { ObjectEvents } from '../../EventTypeDefs';\nimport type { ControlProps } from './types/ControlProps';\nimport { resolveOrigin } from '../../util/misc/resolveOrigin';\nimport type { Group } from '../Group';\nimport { calcDimensionsMatrix } from '../../util/misc/matrix';\nimport { sizeAfterTransform } from '../../util/misc/objectTransforms';\nimport { degreesToRadians } from '../../util/misc/radiansDegreesConversion';\nimport { CommonMethods } from '../../CommonMethods';\nimport type { BaseProps } from './types/BaseProps';\nimport type { FillStrokeProps } from './types/FillStrokeProps';\nimport { CENTER, LEFT, TOP } from '../../constants';\n\ntype TMatrixCache = {\n key: number[];\n value: TMat2D;\n};\n\ntype TACoords = TCornerPoint;\n\nexport class ObjectGeometry<EventSpec extends ObjectEvents = ObjectEvents>\n extends CommonMethods<EventSpec>\n implements\n Pick<ControlProps, 'padding'>,\n BaseProps,\n Pick<FillStrokeProps, 'strokeWidth' | 'strokeUniform'>\n{\n // #region Geometry\n\n declare padding: number;\n\n /**\n * Describe object's corner position in scene coordinates.\n * The coordinates are derived from the following:\n * left, top, width, height, scaleX, scaleY, skewX, skewY, angle, strokeWidth.\n * The coordinates do not depend on viewport changes.\n * The coordinates get updated with {@link setCoords}.\n * You can calculate them without updating with {@link calcACoords()}\n */\n declare aCoords: TACoords;\n\n /**\n * storage cache for object transform matrix\n */\n declare ownMatrixCache?: TMatrixCache;\n\n /**\n * storage cache for object full transform matrix\n */\n declare matrixCache?: TMatrixCache;\n\n /**\n * A Reference of the Canvas where the object is actually added\n * @type StaticCanvas | Canvas;\n * @default undefined\n * @private\n */\n declare canvas?: StaticCanvas | Canvas;\n\n /**\n * @returns {number} x position according to object's originX property in canvas coordinate plane\n */\n getX(): number {\n return this.getXY().x;\n }\n\n /**\n * @param {number} value x position according to object's originX property in canvas coordinate plane\n */\n setX(value: number) {\n this.setXY(this.getXY().setX(value));\n }\n\n /**\n * @returns {number} y position according to object's originY property in canvas coordinate plane\n */\n getY(): number {\n return this.getXY().y;\n }\n\n /**\n * @param {number} value y position according to object's originY property in canvas coordinate plane\n */\n setY(value: number) {\n this.setXY(this.getXY().setY(value));\n }\n\n /**\n * @returns {number} x position according to object's originX property in parent's coordinate plane\\\n * if parent is canvas then this property is identical to {@link getX}\n */\n getRelativeX(): number {\n return this.left;\n }\n\n /**\n * @param {number} value x position according to object's originX property in parent's coordinate plane\\\n * if parent is canvas then this method is identical to {@link setX}\n */\n setRelativeX(value: number) {\n this.left = value;\n }\n\n /**\n * @returns {number} y position according to object's originY property in parent's coordinate plane\\\n * if parent is canvas then this property is identical to {@link getY}\n */\n getRelativeY(): number {\n return this.top;\n }\n\n /**\n * @param {number} value y position according to object's originY property in parent's coordinate plane\\\n * if parent is canvas then this property is identical to {@link setY}\n */\n setRelativeY(value: number) {\n this.top = value;\n }\n\n /**\n * @returns {Point} x position according to object's originX originY properties in canvas coordinate plane\n */\n getXY(): Point {\n const relativePosition = this.getRelativeXY();\n return this.group\n ? transformPoint(relativePosition, this.group.calcTransformMatrix())\n : relativePosition;\n }\n\n /**\n * Set an object position to a particular point, the point is intended in absolute ( canvas ) coordinate.\n * You can specify originX and originY values,\n * that otherwise are the object's current values.\n * @example <caption>Set object's bottom left corner to point (5,5) on canvas</caption>\n * object.setXY(new Point(5, 5), 'left', 'bottom').\n * @param {Point} point position in scene coordinate plane\n * @param {TOriginX} [originX] Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} [originY] Vertical origin: 'top', 'center' or 'bottom'\n */\n setXY(point: Point, originX?: TOriginX, originY?: TOriginY) {\n if (this.group) {\n point = transformPoint(\n point,\n invertTransform(this.group.calcTransformMatrix()),\n );\n }\n this.setRelativeXY(point, originX, originY);\n }\n\n /**\n * @returns {Point} x,y position according to object's originX originY properties in parent's coordinate plane\n */\n getRelativeXY(): Point {\n return new Point(this.left, this.top);\n }\n\n /**\n * As {@link setXY}, but in current parent's coordinate plane (the current group if any or the canvas)\n * @param {Point} point position according to object's originX originY properties in parent's coordinate plane\n * @param {TOriginX} [originX] Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} [originY] Vertical origin: 'top', 'center' or 'bottom'\n */\n setRelativeXY(\n point: Point,\n originX: TOriginX = this.originX,\n originY: TOriginY = this.originY,\n ) {\n this.setPositionByOrigin(point, originX, originY);\n }\n\n /**\n * @deprecated intermidiate method to be removed, do not use\n */\n protected isStrokeAccountedForInDimensions() {\n return false;\n }\n\n /**\n * @return {Point[]} [tl, tr, br, bl] in the scene plane\n */\n getCoords(): Point[] {\n const { tl, tr, br, bl } =\n this.aCoords || (this.aCoords = this.calcACoords());\n const coords = [tl, tr, br, bl];\n if (this.group) {\n const t = this.group.calcTransformMatrix();\n return coords.map((p) => transformPoint(p, t));\n }\n return coords;\n }\n\n /**\n * Checks if object intersects with the scene rect formed by tl and br\n */\n intersectsWithRect(tl: Point, br: Point): boolean {\n const intersection = Intersection.intersectPolygonRectangle(\n this.getCoords(),\n tl,\n br,\n );\n return intersection.status === 'Intersection';\n }\n\n /**\n * Checks if object intersects with another object\n * @param {Object} other Object to test\n * @return {Boolean} true if object intersects with another object\n */\n intersectsWithObject(other: ObjectGeometry): boolean {\n const intersection = Intersection.intersectPolygonPolygon(\n this.getCoords(),\n other.getCoords(),\n );\n\n return (\n intersection.status === 'Intersection' ||\n intersection.status === 'Coincident' ||\n other.isContainedWithinObject(this) ||\n this.isContainedWithinObject(other)\n );\n }\n\n /**\n * Checks if object is fully contained within area of another object\n * @param {Object} other Object to test\n * @return {Boolean} true if object is fully contained within area of another object\n */\n isContainedWithinObject(other: ObjectGeometry): boolean {\n const points = this.getCoords();\n return points.every((point) => other.containsPoint(point));\n }\n\n /**\n * Checks if object is fully contained within the scene rect formed by tl and br\n */\n isContainedWithinRect(tl: Point, br: Point): boolean {\n const { left, top, width, height } = this.getBoundingRect();\n return (\n left >= tl.x &&\n left + width <= br.x &&\n top >= tl.y &&\n top + height <= br.y\n );\n }\n\n isOverlapping<T extends ObjectGeometry>(other: T): boolean {\n return (\n this.intersectsWithObject(other) ||\n this.isContainedWithinObject(other) ||\n other.isContainedWithinObject(this)\n );\n }\n\n /**\n * Checks if point is inside the object\n * @param {Point} point Point to check against\n * @return {Boolean} true if point is inside the object\n */\n containsPoint(point: Point): boolean {\n return Intersection.isPointInPolygon(point, this.getCoords());\n }\n\n /**\n * Checks if object is contained within the canvas with current viewportTransform\n * the check is done stopping at first point that appears on screen\n * @return {Boolean} true if object is fully or partially contained within canvas\n */\n isOnScreen(): boolean {\n if (!this.canvas) {\n return false;\n }\n const { tl, br } = this.canvas.vptCoords;\n const points = this.getCoords();\n // if some point is on screen, the object is on screen.\n if (\n points.some(\n (point) =>\n point.x <= br.x &&\n point.x >= tl.x &&\n point.y <= br.y &&\n point.y >= tl.y,\n )\n ) {\n return true;\n }\n // no points on screen, check intersection with absolute coordinates\n if (this.intersectsWithRect(tl, br)) {\n return true;\n }\n // check if the object is so big that it contains the entire viewport\n return this.containsPoint(tl.midPointFrom(br));\n }\n\n /**\n * Checks if object is partially contained within the canvas with current viewportTransform\n * @return {Boolean} true if object is partially contained within canvas\n */\n isPartiallyOnScreen(): boolean {\n if (!this.canvas) {\n return false;\n }\n const { tl, br } = this.canvas.vptCoords;\n if (this.intersectsWithRect(tl, br)) {\n return true;\n }\n const allPointsAreOutside = this.getCoords().every(\n (point) =>\n (point.x >= br.x || point.x <= tl.x) &&\n (point.y >= br.y || point.y <= tl.y),\n );\n // check if the object is so big that it contains the entire viewport\n return allPointsAreOutside && this.containsPoint(tl.midPointFrom(br));\n }\n\n /**\n * Returns coordinates of object's bounding rectangle (left, top, width, height)\n * the box is intended as aligned to axis of canvas.\n * @return {Object} Object with left, top, width, height properties\n */\n getBoundingRect(): TBBox {\n return makeBoundingBoxFromPoints(this.getCoords());\n }\n\n /**\n * Returns width of an object's bounding box counting transformations\n * @todo shouldn't this account for group transform and return the actual size in canvas coordinate plane?\n * @return {Number} width value\n */\n getScaledWidth(): number {\n return this._getTransformedDimensions().x;\n }\n\n /**\n * Returns height of an object bounding box counting transformations\n * @todo shouldn't this account for group transform and return the actual size in canvas coordinate plane?\n * @return {Number} height value\n */\n getScaledHeight(): number {\n return this._getTransformedDimensions().y;\n }\n\n /**\n * Scales an object (equally by x and y)\n * @param {Number} value Scale factor\n * @return {void}\n */\n scale(value: number): void {\n this._set(SCALE_X, value);\n this._set(SCALE_Y, value);\n this.setCoords();\n }\n\n /**\n * Scales an object to a given width, with respect to bounding box (scaling by x/y equally)\n * @param {Number} value New width value\n * @return {void}\n */\n scaleToWidth(value: number) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n const boundingRectFactor =\n this.getBoundingRect().width / this.getScaledWidth();\n return this.scale(value / this.width / boundingRectFactor);\n }\n\n /**\n * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)\n * @param {Number} value New height value\n * @return {void}\n */\n scaleToHeight(value: number) {\n // adjust to bounding rect factor so that rotated shapes would fit as well\n const boundingRectFactor =\n this.getBoundingRect().height / this.getScaledHeight();\n return this.scale(value / this.height / boundingRectFactor);\n }\n\n getCanvasRetinaScaling() {\n return this.canvas?.getRetinaScaling() || 1;\n }\n\n /**\n * Returns the object angle relative to canvas counting also the group property\n * @returns {TDegree}\n */\n getTotalAngle(): TDegree {\n return this.group\n ? radiansToDegrees(calcPlaneRotation(this.calcTransformMatrix()))\n : this.angle;\n }\n\n /**\n * Retrieves viewportTransform from Object's canvas if available\n * @return {TMat2D}\n */\n getViewportTransform(): TMat2D {\n return this.canvas?.viewportTransform || (iMatrix.concat() as TMat2D);\n }\n\n /**\n * Calculates the coordinates of the 4 corner of the bbox, in absolute coordinates.\n * those never change with zoom or viewport changes.\n * @return {TCornerPoint}\n */\n calcACoords(): TCornerPoint {\n const rotateMatrix = createRotateMatrix({ angle: this.angle }),\n { x, y } = this.getRelativeCenterPoint(),\n tMatrix = createTranslateMatrix(x, y),\n finalMatrix = multiplyTransformMatrices(tMatrix, rotateMatrix),\n dim = this._getTransformedDimensions(),\n w = dim.x / 2,\n h = dim.y / 2;\n return {\n // corners\n tl: transformPoint({ x: -w, y: -h }, finalMatrix),\n tr: transformPoint({ x: w, y: -h }, finalMatrix),\n bl: transformPoint({ x: -w, y: h }, finalMatrix),\n br: transformPoint({ x: w, y: h }, finalMatrix),\n };\n }\n\n /**\n * Sets corner and controls position coordinates based on current angle, width and height, left and top.\n * aCoords are used to quickly find an object on the canvas.\n * See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabric5.fabricjs.com/fabric-gotchas}\n */\n setCoords(): void {\n this.aCoords = this.calcACoords();\n }\n\n transformMatrixKey(skipGroup = false): number[] {\n let prefix: number[] = [];\n if (!skipGroup && this.group) {\n prefix = this.group.transformMatrixKey(skipGroup);\n }\n prefix.push(\n this.top,\n this.left,\n this.width,\n this.height,\n this.scaleX,\n this.scaleY,\n this.angle,\n this.strokeWidth,\n this.skewX,\n this.skewY,\n +this.flipX,\n +this.flipY,\n resolveOrigin(this.originX),\n resolveOrigin(this.originY),\n );\n\n return prefix;\n }\n\n /**\n * calculate transform matrix that represents the current transformations from the\n * object's properties.\n * @param {Boolean} [skipGroup] return transform matrix for object not counting parent transformations\n * There are some situation in which this is useful to avoid the fake rotation.\n * @return {TMat2D} transform matrix for the object\n */\n calcTransformMatrix(skipGroup = false): TMat2D {\n let matrix = this.calcOwnMatrix();\n if (skipGroup || !this.group) {\n return matrix;\n }\n const key = this.transformMatrixKey(skipGroup),\n cache = this.matrixCache;\n if (cache && cache.key.every((x, i) => x === key[i])) {\n return cache.value;\n }\n if (this.group) {\n matrix = multiplyTransformMatrices(\n this.group.calcTransformMatrix(false),\n matrix,\n );\n }\n this.matrixCache = {\n key,\n value: matrix,\n };\n return matrix;\n }\n\n /**\n * calculate transform matrix that represents the current transformations from the\n * object's properties, this matrix does not include the group transformation\n * @return {TMat2D} transform matrix for the object\n */\n calcOwnMatrix(): TMat2D {\n const key = this.transformMatrixKey(true),\n cache = this.ownMatrixCache;\n if (cache && cache.key.every((x, i) => x === key[i])) {\n return cache.value;\n }\n const center = this.getRelativeCenterPoint(),\n options = {\n angle: this.angle,\n translateX: center.x,\n translateY: center.y,\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n skewX: this.skewX,\n skewY: this.skewY,\n flipX: this.flipX,\n flipY: this.flipY,\n },\n value = composeMatrix(options);\n this.ownMatrixCache = {\n key,\n value,\n };\n return value;\n }\n\n /**\n * Calculate object dimensions from its properties\n * @private\n * @returns {Point} dimensions\n */\n _getNonTransformedDimensions(): Point {\n return new Point(this.width, this.height).scalarAdd(this.strokeWidth);\n }\n\n /**\n * Calculate object dimensions for controls box, including padding and canvas zoom.\n * and active selection\n * @private\n * @param {object} [options] transform options\n * @returns {Point} dimensions\n */\n _calculateCurrentDimensions(options?: any): Point {\n return this._getTransformedDimensions(options)\n .transform(this.getViewportTransform(), true)\n .scalarAdd(2 * this.padding);\n }\n\n // #region Origin\n\n declare top: number;\n declare left: number;\n declare width: number;\n declare height: number;\n declare flipX: boolean;\n declare flipY: boolean;\n declare scaleX: number;\n declare scaleY: number;\n declare skewX: number;\n declare skewY: number;\n /**\n * @deprecated please use 'center' as value in new projects\n * */\n declare originX: TOriginX;\n /**\n * @deprecated please use 'center' as value in new projects\n * */\n declare originY: TOriginY;\n declare angle: TDegree;\n declare strokeWidth: number;\n declare strokeUniform: boolean;\n\n /**\n * Object containing this object.\n * can influence its size and position\n */\n declare group?: Group;\n\n /**\n * Calculate object bounding box dimensions from its properties scale, skew.\n * This bounding box is aligned with object angle and not with canvas axis or screen.\n * @param {Object} [options]\n * @param {Number} [options.scaleX]\n * @param {Number} [options.scaleY]\n * @param {Number} [options.skewX]\n * @param {Number} [options.skewY]\n * @private\n * @returns {Point} dimensions\n */\n _getTransformedDimensions(options: any = {}): Point {\n const dimOptions = {\n // if scaleX or scaleY are negative numbers,\n // this will return dimensions that are negative.\n // and this will break assumptions around the codebase\n scaleX: this.scaleX,\n scaleY: this.scaleY,\n skewX: this.skewX,\n skewY: this.skewY,\n width: this.width,\n height: this.height,\n strokeWidth: this.strokeWidth,\n // TODO remove this spread. is visible in the performance inspection\n ...options,\n };\n // stroke is applied before/after transformations are applied according to `strokeUniform`\n const strokeWidth = dimOptions.strokeWidth;\n let preScalingStrokeValue = strokeWidth,\n postScalingStrokeValue = 0;\n\n if (this.strokeUniform) {\n preScalingStrokeValue = 0;\n postScalingStrokeValue = strokeWidth;\n }\n const dimX = dimOptions.width + preScalingStrokeValue,\n dimY = dimOptions.height + preScalingStrokeValue,\n noSkew = dimOptions.skewX === 0 && dimOptions.skewY === 0;\n let finalDimensions;\n if (noSkew) {\n finalDimensions = new Point(\n dimX * dimOptions.scaleX,\n dimY * dimOptions.scaleY,\n );\n } else {\n finalDimensions = sizeAfterTransform(\n dimX,\n dimY,\n calcDimensionsMatrix(dimOptions),\n );\n }\n\n return finalDimensions.scalarAdd(postScalingStrokeValue);\n }\n\n /**\n * Translates the coordinates from a set of origin to another (based on the object's dimensions)\n * @param {Point} point The point which corresponds to the originX and originY params\n * @param {TOriginX} fromOriginX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} fromOriginY Vertical origin: 'top', 'center' or 'bottom'\n * @param {TOriginX} toOriginX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} toOriginY Vertical origin: 'top', 'center' or 'bottom'\n * @return {Point}\n */\n translateToGivenOrigin(\n point: Point,\n fromOriginX: TOriginX,\n fromOriginY: TOriginY,\n toOriginX: TOriginX,\n toOriginY: TOriginY,\n ): Point {\n let x = point.x,\n y = point.y;\n const offsetX = resolveOrigin(toOriginX) - resolveOrigin(fromOriginX),\n offsetY = resolveOrigin(toOriginY) - resolveOrigin(fromOriginY);\n\n if (offsetX || offsetY) {\n const dim = this._getTransformedDimensions();\n x += offsetX * dim.x;\n y += offsetY * dim.y;\n }\n\n return new Point(x, y);\n }\n\n /**\n * Translates the coordinates from origin to center coordinates (based on the object's dimensions)\n * @param {Point} point The point which corresponds to the originX and originY params\n * @param {TOriginX} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {Point}\n */\n translateToCenterPoint(\n point: Point,\n originX: TOriginX,\n originY: TOriginY,\n ): Point {\n if (originX === CENTER && originY === CENTER) {\n return point;\n }\n const p = this.translateToGivenOrigin(\n point,\n originX,\n originY,\n CENTER,\n CENTER,\n );\n if (this.angle) {\n return p.rotate(degreesToRadians(this.angle), point);\n }\n return p;\n }\n\n /**\n * Translates the coordinates from center to origin coordinates (based on the object's dimensions)\n * @param {Point} center The point which corresponds to center of the object\n * @param {OriginX} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {OriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {Point}\n */\n translateToOriginPoint(\n center: Point,\n originX: TOriginX,\n originY: TOriginY,\n ): Point {\n const p = this.translateToGivenOrigin(\n center,\n CENTER,\n CENTER,\n originX,\n originY,\n );\n if (this.angle) {\n return p.rotate(degreesToRadians(this.angle), center);\n }\n return p;\n }\n\n /**\n * Returns the center coordinates of the object relative to canvas\n * @return {Point}\n */\n getCenterPoint(): Point {\n const relCenter = this.getRelativeCenterPoint();\n return this.group\n ? transformPoint(relCenter, this.group.calcTransformMatrix())\n : relCenter;\n }\n\n /**\n * Returns the center coordinates of the object relative to it's parent\n * @return {Point}\n */\n getRelativeCenterPoint(): Point {\n return this.translateToCenterPoint(\n new Point(this.left, this.top),\n this.originX,\n this.originY,\n );\n }\n\n /**\n * Alias of {@link getPositionByOrigin}\n * @deprecated use {@link getPositionByOrigin} instead\n */\n getPointByOrigin(originX: TOriginX, originY: TOriginY): Point {\n return this.getPositionByOrigin(originX, originY);\n }\n\n /**\n * This function is the mirror of {@link setPositionByOrigin}\n * Returns the position of the object based on specified origin.\n * Take an object that has left, top set to 100, 100 with origin 'left', 'top'.\n * Return the values of left top ( wrapped in a point ) that you would need to keep\n * the same position if origin where different ( ex: center, bottom )\n * Alternatively you can use this to also find which point in the parent plane is a specific origin\n * ( where is the bottom right corner of my object? )\n * @param {TOriginX} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {Point}\n */\n getPositionByOrigin(originX: TOriginX, originY: TOriginY) {\n return this.translateToOriginPoint(\n this.getRelativeCenterPoint(),\n originX,\n originY,\n );\n }\n\n /**\n * Sets the position of the object taking into consideration the object's origin\n * @param {Point} pos The new position of the object\n * @param {TOriginX} originX Horizontal origin: 'left', 'center' or 'right'\n * @param {TOriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n * @return {void}\n */\n setPositionByOrigin(pos: Point, originX: TOriginX, originY: TOriginY) {\n const center = this.translateToCenterPoint(pos, originX, originY),\n position = this.translateToOriginPoint(\n center,\n this.originX,\n this.originY,\n );\n this.set({ left: position.x, top: position.y });\n }\n\n /**\n * @private\n */\n _getLeftTopCoords() {\n return this.getPositionByOrigin(LEFT, TOP);\n }\n\n /**\n * An utility method to position the object by its left top corner.\n * Useful to reposition objects since now the default origin is center/center\n * Places the left/top corner of the object bounding box in p.\n */\n positionByLeftTop(p: Point) {\n return this.setPositionByOrigin(p, LEFT, TOP);\n }\n}\n"],"mappings":"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"}