[fix] indicator shapes (#121)
* Fix indicator shape for draw shape, rectangle shape * Fixes perfect-freehand bug * Tweaks streamline
This commit is contained in:
parent
5d3af9cec0
commit
31638c7c90
12 changed files with 198 additions and 78 deletions
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2021 Chris Hager
|
Copyright (c) 2021 Stephen Ruiz Ltd
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
21
packages/core/LICENSE
Normal file
21
packages/core/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Stephen Ruiz Ltd
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -1656,7 +1656,7 @@ left past the initial left edge) then swap points on that axis.
|
||||||
* Turn an array of points into a path of quadradic curves.
|
* Turn an array of points into a path of quadradic curves.
|
||||||
* @param stroke ;
|
* @param stroke ;
|
||||||
*/
|
*/
|
||||||
static getSvgPathFromStroke(points: number[][]): string {
|
static getSvgPathFromStroke(points: number[][], closed = true): string {
|
||||||
if (!points.length) {
|
if (!points.length) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
@ -1667,7 +1667,9 @@ left past the initial left edge) then swap points on that axis.
|
||||||
.reduce(
|
.reduce(
|
||||||
(acc, point, i, arr) => {
|
(acc, point, i, arr) => {
|
||||||
if (i === max) {
|
if (i === max) {
|
||||||
|
if (closed) {
|
||||||
acc.push('Z')
|
acc.push('Z')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
acc.push(point, Vec.med(point, arr[i + 1]))
|
acc.push(point, Vec.med(point, arr[i + 1]))
|
||||||
}
|
}
|
||||||
|
|
21
packages/dev/LICENSE
Normal file
21
packages/dev/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Stephen Ruiz Ltd
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
21
packages/intersect/LICENSE
Normal file
21
packages/intersect/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Stephen Ruiz Ltd
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
21
packages/tldraw/LICENSE
Normal file
21
packages/tldraw/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Stephen Ruiz Ltd
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -67,7 +67,7 @@
|
||||||
"@tldraw/core": "^0.0.102",
|
"@tldraw/core": "^0.0.102",
|
||||||
"@tldraw/intersect": "^0.0.102",
|
"@tldraw/intersect": "^0.0.102",
|
||||||
"@tldraw/vec": "^0.0.102",
|
"@tldraw/vec": "^0.0.102",
|
||||||
"perfect-freehand": "^1.0.9",
|
"perfect-freehand": "^1.0.12",
|
||||||
"react-hotkeys-hook": "^3.4.0",
|
"react-hotkeys-hook": "^3.4.0",
|
||||||
"rko": "^0.5.25"
|
"rko": "^0.5.25"
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,7 @@ import * as React from 'react'
|
||||||
import { SVGContainer, TLBounds, Utils, TLTransformInfo, ShapeUtil } from '@tldraw/core'
|
import { SVGContainer, TLBounds, Utils, TLTransformInfo, ShapeUtil } from '@tldraw/core'
|
||||||
import { Vec } from '@tldraw/vec'
|
import { Vec } from '@tldraw/vec'
|
||||||
import { intersectBoundsBounds, intersectBoundsPolyline } from '@tldraw/intersect'
|
import { intersectBoundsBounds, intersectBoundsPolyline } from '@tldraw/intersect'
|
||||||
import getStroke, { getStrokePoints } from 'perfect-freehand'
|
import getStroke, { getStrokeOutlinePoints, getStrokePoints } from 'perfect-freehand'
|
||||||
import { defaultStyle, getShapeStyle } from '~shape/shape-styles'
|
import { defaultStyle, getShapeStyle } from '~shape/shape-styles'
|
||||||
import { DrawShape, DashStyle, TLDrawShapeType, TLDrawToolType, TLDrawMeta } from '~types'
|
import { DrawShape, DashStyle, TLDrawShapeType, TLDrawToolType, TLDrawMeta } from '~types'
|
||||||
import { EASINGS } from '~state/utils'
|
import { EASINGS } from '~state/utils'
|
||||||
|
@ -38,8 +38,8 @@ export const Draw = new ShapeUtil<DrawShape, SVGSVGElement, TLDrawMeta>(() => ({
|
||||||
|
|
||||||
const pathData = React.useMemo(() => {
|
const pathData = React.useMemo(() => {
|
||||||
return style.dash === DashStyle.Draw
|
return style.dash === DashStyle.Draw
|
||||||
? getDrawStrokePath(shape, isEditing)
|
? getDrawStrokePathData(shape, isEditing)
|
||||||
: getSolidStrokePath(shape)
|
: getSolidStrokePathData(shape, isEditing)
|
||||||
}, [points, style.size, style.dash, isEditing])
|
}, [points, style.size, style.dash, isEditing])
|
||||||
|
|
||||||
const styles = getShapeStyle(style, meta.isDarkMode)
|
const styles = getShapeStyle(style, meta.isDarkMode)
|
||||||
|
@ -89,7 +89,7 @@ export const Draw = new ShapeUtil<DrawShape, SVGSVGElement, TLDrawMeta>(() => ({
|
||||||
d={pathData}
|
d={pathData}
|
||||||
fill={styles.stroke}
|
fill={styles.stroke}
|
||||||
stroke={styles.stroke}
|
stroke={styles.stroke}
|
||||||
strokeWidth={strokeWidth}
|
strokeWidth={styles.strokeWidth}
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
pointerEvents="all"
|
pointerEvents="all"
|
||||||
|
@ -146,7 +146,7 @@ export const Draw = new ShapeUtil<DrawShape, SVGSVGElement, TLDrawMeta>(() => ({
|
||||||
const { points } = shape
|
const { points } = shape
|
||||||
|
|
||||||
const pathData = React.useMemo(() => {
|
const pathData = React.useMemo(() => {
|
||||||
return getSolidStrokePath(shape)
|
return getSolidStrokePathData(shape, false)
|
||||||
}, [points])
|
}, [points])
|
||||||
|
|
||||||
const bounds = this.getBounds(shape)
|
const bounds = this.getBounds(shape)
|
||||||
|
@ -264,6 +264,8 @@ export const Draw = new ShapeUtil<DrawShape, SVGSVGElement, TLDrawMeta>(() => ({
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
/* -------------------------------------------------- */
|
/* -------------------------------------------------- */
|
||||||
|
|
||||||
|
const STREAMLINE = 0.65
|
||||||
|
|
||||||
const simulatePressureSettings = {
|
const simulatePressureSettings = {
|
||||||
simulatePressure: true,
|
simulatePressure: true,
|
||||||
}
|
}
|
||||||
|
@ -288,21 +290,34 @@ function getFillPath(shape: DrawShape) {
|
||||||
thinning: 0.85,
|
thinning: 0.85,
|
||||||
end: { taper: +styles.strokeWidth * 10 },
|
end: { taper: +styles.strokeWidth * 10 },
|
||||||
start: { taper: +styles.strokeWidth * 10 },
|
start: { taper: +styles.strokeWidth * 10 },
|
||||||
|
last: true,
|
||||||
}).map((pt) => pt.point)
|
}).map((pt) => pt.point)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDrawStrokePath(shape: DrawShape, isEditing: boolean) {
|
function getDrawStrokePoints(shape: DrawShape, isEditing: boolean) {
|
||||||
|
return getStrokePoints(shape.points, {
|
||||||
|
streamline: STREAMLINE,
|
||||||
|
last: !isEditing,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get path data for a stroke with the DashStyle.Draw dash style.
|
||||||
|
*/
|
||||||
|
function getDrawStrokePathData(shape: DrawShape, isEditing: boolean) {
|
||||||
const styles = getShapeStyle(shape.style)
|
const styles = getShapeStyle(shape.style)
|
||||||
|
|
||||||
if (shape.points.length < 2) return ''
|
if (shape.points.length < 2) return ''
|
||||||
|
|
||||||
const options = shape.points[1][2] === 0.5 ? simulatePressureSettings : realPressureSettings
|
const options = shape.points[1][2] === 0.5 ? simulatePressureSettings : realPressureSettings
|
||||||
|
|
||||||
const stroke = getStroke(shape.points.slice(2), {
|
const strokePoints = getDrawStrokePoints(shape, isEditing)
|
||||||
|
|
||||||
|
const stroke = getStrokeOutlinePoints(strokePoints, {
|
||||||
size: 1 + styles.strokeWidth * 1.618,
|
size: 1 + styles.strokeWidth * 1.618,
|
||||||
thinning: 0.6,
|
thinning: 0.6,
|
||||||
streamline: 0.7,
|
streamline: STREAMLINE,
|
||||||
smoothing: 0.5,
|
smoothing: 0.5,
|
||||||
end: { taper: styles.strokeWidth * 10, easing: EASINGS.easeOutQuad },
|
end: { taper: styles.strokeWidth * 10, easing: EASINGS.easeOutQuad },
|
||||||
easing: (t) => Math.sin((t * Math.PI) / 2),
|
easing: (t) => Math.sin((t * Math.PI) / 2),
|
||||||
|
@ -315,33 +330,17 @@ function getDrawStrokePath(shape: DrawShape, isEditing: boolean) {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSolidStrokePath(shape: DrawShape) {
|
/**
|
||||||
let { points } = shape
|
* Get SVG path data for a shape that has a DashStyle other than DashStyles.Draw.
|
||||||
|
*/
|
||||||
|
function getSolidStrokePathData(shape: DrawShape, isEditing: boolean) {
|
||||||
|
const { points } = shape
|
||||||
|
|
||||||
let len = points.length
|
if (points.length === 0) return 'M 0 0 L 0 0'
|
||||||
|
|
||||||
if (len === 0) return 'M 0 0 L 0 0'
|
const strokePoints = getDrawStrokePoints(shape, isEditing).map((pt) => pt.point.slice(0, 2))
|
||||||
if (len < 3) return `M ${points[0][0]} ${points[0][1]}`
|
|
||||||
|
|
||||||
points = getStrokePoints(points).map((pt) => pt.point)
|
const path = Utils.getSvgPathFromStroke(strokePoints, false)
|
||||||
|
|
||||||
len = points.length
|
|
||||||
|
|
||||||
const d = points.reduce(
|
|
||||||
(acc, [x0, y0], i, arr) => {
|
|
||||||
if (i === len - 1) {
|
|
||||||
acc.push('L', x0, y0)
|
|
||||||
return acc
|
|
||||||
}
|
|
||||||
|
|
||||||
const [x1, y1] = arr[i + 1]
|
|
||||||
acc.push(x0.toFixed(2), y0.toFixed(2), ((x0 + x1) / 2).toFixed(2), ((y0 + y1) / 2).toFixed(2))
|
|
||||||
return acc
|
|
||||||
},
|
|
||||||
['M', points[0][0], points[0][1], 'Q']
|
|
||||||
)
|
|
||||||
|
|
||||||
const path = d.join(' ').replaceAll(/(\s[0-9]*\.[0-9]{2})([0-9]*)\b/g, '$1')
|
|
||||||
|
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { Utils, SVGContainer, ShapeUtil } from '@tldraw/core'
|
import { Utils, SVGContainer, ShapeUtil } from '@tldraw/core'
|
||||||
import { Vec } from '@tldraw/vec'
|
import { Vec } from '@tldraw/vec'
|
||||||
import getStroke from 'perfect-freehand'
|
import getStroke, { getStrokePoints } from 'perfect-freehand'
|
||||||
import { getPerfectDashProps, defaultStyle, getShapeStyle } from '~shape/shape-styles'
|
import { getPerfectDashProps, defaultStyle, getShapeStyle } from '~shape/shape-styles'
|
||||||
import { RectangleShape, DashStyle, TLDrawShapeType, TLDrawToolType, TLDrawMeta } from '~types'
|
import { RectangleShape, DashStyle, TLDrawShapeType, TLDrawToolType, TLDrawMeta } from '~types'
|
||||||
import { getBoundsRectangle, transformRectangle, transformSingleRectangle } from '../shared'
|
import { getBoundsRectangle, transformRectangle, transformSingleRectangle } from '../shared'
|
||||||
|
@ -37,8 +37,6 @@ export const Rectangle = new ShapeUtil<RectangleShape, SVGSVGElement, TLDrawMeta
|
||||||
const styles = getShapeStyle(style, meta.isDarkMode)
|
const styles = getShapeStyle(style, meta.isDarkMode)
|
||||||
const strokeWidth = +styles.strokeWidth
|
const strokeWidth = +styles.strokeWidth
|
||||||
|
|
||||||
this
|
|
||||||
|
|
||||||
if (style.dash === DashStyle.Draw) {
|
if (style.dash === DashStyle.Draw) {
|
||||||
const pathData = Utils.getFromCache(pathCache, shape.size, () => getRectanglePath(shape))
|
const pathData = Utils.getFromCache(pathCache, shape.size, () => getRectanglePath(shape))
|
||||||
|
|
||||||
|
@ -136,26 +134,7 @@ export const Rectangle = new ShapeUtil<RectangleShape, SVGSVGElement, TLDrawMeta
|
||||||
},
|
},
|
||||||
|
|
||||||
Indicator({ shape }) {
|
Indicator({ shape }) {
|
||||||
const {
|
return <path d={getRectangleIndicatorPathData(shape)} />
|
||||||
style,
|
|
||||||
size: [width, height],
|
|
||||||
} = shape
|
|
||||||
|
|
||||||
const styles = getShapeStyle(style, false)
|
|
||||||
const strokeWidth = +styles.strokeWidth
|
|
||||||
|
|
||||||
const sw = strokeWidth
|
|
||||||
|
|
||||||
return (
|
|
||||||
<rect
|
|
||||||
x={sw / 2}
|
|
||||||
y={sw / 2}
|
|
||||||
rx={1}
|
|
||||||
ry={1}
|
|
||||||
width={Math.max(1, width - sw)}
|
|
||||||
height={Math.max(1, height - sw)}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getBounds(shape) {
|
getBounds(shape) {
|
||||||
|
@ -171,7 +150,7 @@ export const Rectangle = new ShapeUtil<RectangleShape, SVGSVGElement, TLDrawMeta
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
/* -------------------------------------------------- */
|
/* -------------------------------------------------- */
|
||||||
|
|
||||||
function getRectanglePath(shape: RectangleShape) {
|
function getRectangleDrawPoints(shape: RectangleShape) {
|
||||||
const styles = getShapeStyle(shape.style)
|
const styles = getShapeStyle(shape.style)
|
||||||
|
|
||||||
const getRandom = Utils.rng(shape.id)
|
const getRandom = Utils.rng(shape.id)
|
||||||
|
@ -209,22 +188,36 @@ function getRectanglePath(shape: RectangleShape) {
|
||||||
rm
|
rm
|
||||||
)
|
)
|
||||||
|
|
||||||
const edgeDist = rm % 2 === 0 ? px : py
|
return {
|
||||||
|
points: [...lines.flat(), ...lines[0], ...lines[1]].slice(
|
||||||
const stroke = getStroke(
|
|
||||||
[...lines.flat(), ...lines[0], ...lines[1]].slice(
|
|
||||||
4,
|
4,
|
||||||
Math.floor((rm % 2 === 0 ? px : py) / -2) + 2
|
Math.floor((rm % 2 === 0 ? px : py) / -2) + 2
|
||||||
),
|
),
|
||||||
{
|
edgeDistance: rm % 2 === 0 ? px : py,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRectanglePath(shape: RectangleShape) {
|
||||||
|
const { points, edgeDistance } = getRectangleDrawPoints(shape)
|
||||||
|
const styles = getShapeStyle(shape.style)
|
||||||
|
|
||||||
|
const stroke = getStroke(points, {
|
||||||
size: 1 + styles.strokeWidth * 2,
|
size: 1 + styles.strokeWidth * 2,
|
||||||
thinning: 0.5,
|
thinning: 0.5,
|
||||||
end: { taper: edgeDist },
|
end: { taper: edgeDistance },
|
||||||
start: { taper: edgeDist },
|
start: { taper: edgeDistance },
|
||||||
simulatePressure: false,
|
simulatePressure: false,
|
||||||
last: true,
|
last: true,
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
return Utils.getSvgPathFromStroke(stroke)
|
return Utils.getSvgPathFromStroke(stroke)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRectangleIndicatorPathData(shape: RectangleShape) {
|
||||||
|
const { points } = getRectangleDrawPoints(shape)
|
||||||
|
|
||||||
|
return Utils.getSvgPathFromStroke(
|
||||||
|
getStrokePoints(points).map((pt) => pt.point.slice(0, 2)),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
21
packages/vec/LICENSE
Normal file
21
packages/vec/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Stephen Ruiz Ltd
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
21
packages/www/LICENSE
Normal file
21
packages/www/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Stephen Ruiz Ltd
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -10906,10 +10906,10 @@ pbkdf2@^3.0.3:
|
||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
sha.js "^2.4.8"
|
sha.js "^2.4.8"
|
||||||
|
|
||||||
perfect-freehand@^1.0.9:
|
perfect-freehand@^1.0.12:
|
||||||
version "1.0.9"
|
version "1.0.12"
|
||||||
resolved "https://registry.yarnpkg.com/perfect-freehand/-/perfect-freehand-1.0.9.tgz#9b5fb96181004bcec62f3721d25cebea2ec34a3f"
|
resolved "https://registry.yarnpkg.com/perfect-freehand/-/perfect-freehand-1.0.12.tgz#5f3614e099ad459ced4f50da9ce109fdf5b62b90"
|
||||||
integrity sha512-YCbnozlv+Wqmxexi/3YDftCXNjqs6bpTZ01tN+pBJbiA3b8DTvgZGPgd8mxxaXkAQzEsgD0bkS1h9vy3EWnm2w==
|
integrity sha512-tY6ZVUbF672WJdHQMSz+YT45WgkeoLtbD5oe0TQNAZWCd4xD8B0Pcv+3URMEqhErR4JenRgSlV4kT7zHsbvzVg==
|
||||||
|
|
||||||
performance-now@^2.1.0:
|
performance-now@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
|
|
Loading…
Reference in a new issue