@canvas-commons/2d 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/editor/index.css +40 -0
- package/editor/index.js +525 -0
- package/editor/index.js.map +1 -0
- package/lib/index-OvpZ-GsA.d.ts +5673 -0
- package/lib/index-OvpZ-GsA.d.ts.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +10326 -0
- package/lib/index.js.map +1 -0
- package/lib/jsx-dev-runtime.d.ts +2 -0
- package/lib/jsx-dev-runtime.js +2 -0
- package/lib/jsx-runtime.d.ts +2 -0
- package/lib/jsx-runtime.js +28 -0
- package/lib/jsx-runtime.js.map +1 -0
- package/package.json +79 -0
- package/src/editor/NodeInspectorConfig.tsx +76 -0
- package/src/editor/PreviewOverlayConfig.tsx +65 -0
- package/src/editor/Provider.tsx +109 -0
- package/src/editor/SceneGraphTabConfig.tsx +87 -0
- package/src/editor/icons/CircleIcon.tsx +7 -0
- package/src/editor/icons/CodeIcon.tsx +8 -0
- package/src/editor/icons/CurveIcon.tsx +7 -0
- package/src/editor/icons/GridIcon.tsx +7 -0
- package/src/editor/icons/IconMap.ts +35 -0
- package/src/editor/icons/ImgIcon.tsx +8 -0
- package/src/editor/icons/LayoutIcon.tsx +9 -0
- package/src/editor/icons/LineIcon.tsx +7 -0
- package/src/editor/icons/NodeIcon.tsx +7 -0
- package/src/editor/icons/RayIcon.tsx +7 -0
- package/src/editor/icons/RectIcon.tsx +7 -0
- package/src/editor/icons/ShapeIcon.tsx +7 -0
- package/src/editor/icons/TxtIcon.tsx +8 -0
- package/src/editor/icons/VideoIcon.tsx +7 -0
- package/src/editor/icons/View2DIcon.tsx +10 -0
- package/src/editor/index.css +0 -0
- package/src/editor/index.ts +19 -0
- package/src/editor/shortcuts.ts +27 -0
- package/src/editor/tree/DetachedRoot.tsx +27 -0
- package/src/editor/tree/NodeElement.tsx +72 -0
- package/src/editor/tree/TreeElement.tsx +70 -0
- package/src/editor/tree/TreeRoot.tsx +10 -0
- package/src/editor/tree/ViewRoot.tsx +20 -0
- package/src/editor/tree/index.module.scss +45 -0
- package/src/editor/tree/index.ts +4 -0
- package/src/editor/tree/navigation.ts +145 -0
- package/src/editor/tsconfig.build.json +5 -0
- package/src/editor/tsconfig.json +12 -0
- package/src/editor/tsdoc.json +4 -0
- package/src/editor/utils/SignalSet.ts +37 -0
- package/src/editor/utils/index.ts +1 -0
- package/src/editor/vite-env.d.ts +1 -0
- package/src/lib/code/CodeCursor.ts +468 -0
- package/src/lib/code/CodeDiffer.ts +77 -0
- package/src/lib/code/CodeFragment.ts +96 -0
- package/src/lib/code/CodeHighlighter.ts +73 -0
- package/src/lib/code/CodeMetrics.ts +47 -0
- package/src/lib/code/CodeRange.test.ts +113 -0
- package/src/lib/code/CodeRange.ts +222 -0
- package/src/lib/code/CodeScope.ts +100 -0
- package/src/lib/code/CodeSelection.ts +28 -0
- package/src/lib/code/CodeSignal.ts +348 -0
- package/src/lib/code/CodeTokenizer.ts +54 -0
- package/src/lib/code/DefaultHighlightStyle.ts +98 -0
- package/src/lib/code/LezerHighlighter.ts +113 -0
- package/src/lib/code/diff.test.ts +311 -0
- package/src/lib/code/diff.ts +319 -0
- package/src/lib/code/extractRange.ts +125 -0
- package/src/lib/code/index.ts +13 -0
- package/src/lib/components/Bezier.ts +103 -0
- package/src/lib/components/Camera.ts +401 -0
- package/src/lib/components/Circle.ts +310 -0
- package/src/lib/components/Code.ts +532 -0
- package/src/lib/components/CubicBezier.ts +115 -0
- package/src/lib/components/Curve.ts +460 -0
- package/src/lib/components/Grid.ts +134 -0
- package/src/lib/components/Icon.ts +153 -0
- package/src/lib/components/Img.ts +328 -0
- package/src/lib/components/Knot.ts +156 -0
- package/src/lib/components/Latex.ts +537 -0
- package/src/lib/components/Layout.ts +1101 -0
- package/src/lib/components/Line.ts +394 -0
- package/src/lib/components/Node.ts +1941 -0
- package/src/lib/components/Path.ts +132 -0
- package/src/lib/components/Polygon.ts +266 -0
- package/src/lib/components/QuadBezier.ts +103 -0
- package/src/lib/components/Ray.ts +126 -0
- package/src/lib/components/Rect.ts +219 -0
- package/src/lib/components/SVG.ts +853 -0
- package/src/lib/components/Shape.ts +322 -0
- package/src/lib/components/Spline.ts +318 -0
- package/src/lib/components/Txt.test.tsx +81 -0
- package/src/lib/components/Txt.ts +204 -0
- package/src/lib/components/TxtLeaf.ts +210 -0
- package/src/lib/components/Video.ts +368 -0
- package/src/lib/components/View2D.ts +85 -0
- package/src/lib/components/__logs__/image-without-source.ts +18 -0
- package/src/lib/components/__logs__/line-without-points.ts +31 -0
- package/src/lib/components/__logs__/reactive-playback-rate.ts +22 -0
- package/src/lib/components/__logs__/spline-with-insufficient-knots.ts +25 -0
- package/src/lib/components/__tests__/Camera.test.tsx +73 -0
- package/src/lib/components/__tests__/children.test.tsx +142 -0
- package/src/lib/components/__tests__/clone.test.tsx +126 -0
- package/src/lib/components/__tests__/fontInheritance.test.tsx +102 -0
- package/src/lib/components/__tests__/generatorTest.ts +27 -0
- package/src/lib/components/__tests__/mockScene2D.ts +50 -0
- package/src/lib/components/__tests__/query.test.tsx +122 -0
- package/src/lib/components/__tests__/state.test.tsx +60 -0
- package/src/lib/components/index.ts +26 -0
- package/src/lib/components/types.ts +35 -0
- package/src/lib/curves/ArcSegment.ts +169 -0
- package/src/lib/curves/CircleSegment.ts +99 -0
- package/src/lib/curves/CubicBezierSegment.ts +80 -0
- package/src/lib/curves/CurveDrawingInfo.ts +11 -0
- package/src/lib/curves/CurvePoint.ts +15 -0
- package/src/lib/curves/CurveProfile.ts +28 -0
- package/src/lib/curves/KnotInfo.ts +10 -0
- package/src/lib/curves/LineSegment.ts +75 -0
- package/src/lib/curves/Polynomial.ts +355 -0
- package/src/lib/curves/Polynomial2D.ts +62 -0
- package/src/lib/curves/PolynomialSegment.ts +151 -0
- package/src/lib/curves/QuadBezierSegment.ts +66 -0
- package/src/lib/curves/Segment.ts +31 -0
- package/src/lib/curves/UniformPolynomialCurveSampler.ts +93 -0
- package/src/lib/curves/createCurveProfileLerp.ts +471 -0
- package/src/lib/curves/getBezierSplineProfile.ts +227 -0
- package/src/lib/curves/getCircleProfile.ts +86 -0
- package/src/lib/curves/getPathProfile.ts +177 -0
- package/src/lib/curves/getPointAtDistance.ts +21 -0
- package/src/lib/curves/getPolylineProfile.test.ts +21 -0
- package/src/lib/curves/getPolylineProfile.ts +88 -0
- package/src/lib/curves/getRectProfile.ts +138 -0
- package/src/lib/curves/index.ts +16 -0
- package/src/lib/decorators/canvasStyleSignal.ts +15 -0
- package/src/lib/decorators/colorSignal.ts +9 -0
- package/src/lib/decorators/compound.ts +85 -0
- package/src/lib/decorators/computed.ts +18 -0
- package/src/lib/decorators/defaultStyle.ts +15 -0
- package/src/lib/decorators/filtersSignal.ts +133 -0
- package/src/lib/decorators/index.ts +10 -0
- package/src/lib/decorators/initializers.ts +32 -0
- package/src/lib/decorators/nodeName.ts +13 -0
- package/src/lib/decorators/signal.test.ts +89 -0
- package/src/lib/decorators/signal.ts +348 -0
- package/src/lib/decorators/spacingSignal.ts +15 -0
- package/src/lib/decorators/transformSignals.test.ts +858 -0
- package/src/lib/decorators/transformSignals.ts +1633 -0
- package/src/lib/decorators/vector2Signal.ts +35 -0
- package/src/lib/globals.d.ts +2 -0
- package/src/lib/index.ts +9 -0
- package/src/lib/jsx-dev-runtime.ts +2 -0
- package/src/lib/jsx-runtime.ts +45 -0
- package/src/lib/morphers/PathMorpher.ts +8 -0
- package/src/lib/morphers/defaultMorpher.ts +43 -0
- package/src/lib/morphers/index.ts +4 -0
- package/src/lib/morphers/manimMorpher.ts +658 -0
- package/src/lib/parse-svg-path.d.ts +14 -0
- package/src/lib/partials/Filter.ts +185 -0
- package/src/lib/partials/Gradient.ts +103 -0
- package/src/lib/partials/Pattern.ts +35 -0
- package/src/lib/partials/RoughConfig.ts +180 -0
- package/src/lib/partials/ShaderConfig.ts +122 -0
- package/src/lib/partials/index.ts +5 -0
- package/src/lib/partials/types.ts +58 -0
- package/src/lib/scenes/Scene2D.ts +167 -0
- package/src/lib/scenes/index.ts +3 -0
- package/src/lib/scenes/makeScene2D.ts +19 -0
- package/src/lib/scenes/useScene2D.ts +6 -0
- package/src/lib/tsconfig.build.json +5 -0
- package/src/lib/tsconfig.json +11 -0
- package/src/lib/tsdoc.json +4 -0
- package/src/lib/utils/CanvasUtils.ts +304 -0
- package/src/lib/utils/PathDataBuilder.ts +320 -0
- package/src/lib/utils/diff.test.ts +453 -0
- package/src/lib/utils/diff.ts +148 -0
- package/src/lib/utils/index.ts +5 -0
- package/src/lib/utils/is.ts +11 -0
- package/src/lib/utils/makeSignalExtensions.ts +29 -0
- package/src/lib/utils/rough.ts +513 -0
- package/src/lib/utils/withDefaults.tsx +26 -0
- package/src/tsconfig.base.json +18 -0
- package/src/tsconfig.build.json +8 -0
- package/src/tsconfig.json +5 -0
- package/tsconfig.project.json +7 -0
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
import {BBox, Spacing, Vector2} from '@canvas-commons/core';
|
|
2
|
+
import rough from 'roughjs';
|
|
3
|
+
import type {RoughCanvas} from 'roughjs/bin/canvas';
|
|
4
|
+
import type {Drawable, Options} from 'roughjs/bin/core';
|
|
5
|
+
import {RoughConfig, RoughFillStyle} from '../partials';
|
|
6
|
+
import {PossibleCanvasStyle} from '../partials/types';
|
|
7
|
+
import {
|
|
8
|
+
adjustRectRadius,
|
|
9
|
+
canvasStyleParser,
|
|
10
|
+
resolveCanvasStyle,
|
|
11
|
+
} from './CanvasUtils';
|
|
12
|
+
|
|
13
|
+
// Export Drawable type for use in other modules
|
|
14
|
+
export type {Drawable};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Cache for RoughCanvas instances per canvas element.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* We cache RoughCanvas instances to avoid recreating them for each draw call.
|
|
21
|
+
*/
|
|
22
|
+
const RoughCanvasCache = new WeakMap<HTMLCanvasElement, RoughCanvas>();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get or create a RoughCanvas instance for the given canvas context.
|
|
26
|
+
*
|
|
27
|
+
* @param context - The 2D rendering context
|
|
28
|
+
* @returns A RoughCanvas instance for drawing rough shapes
|
|
29
|
+
*/
|
|
30
|
+
function getRoughCanvas(context: CanvasRenderingContext2D): RoughCanvas {
|
|
31
|
+
const canvas = context.canvas;
|
|
32
|
+
let rc = RoughCanvasCache.get(canvas);
|
|
33
|
+
|
|
34
|
+
if (!rc) {
|
|
35
|
+
rc = rough.canvas(canvas);
|
|
36
|
+
RoughCanvasCache.set(canvas, rc);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return rc;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Convert Canvas Commons fill style to a color string for Rough.js.
|
|
44
|
+
*
|
|
45
|
+
* @param style - The fill style (color, gradient, or pattern)
|
|
46
|
+
* @param context - The rendering context
|
|
47
|
+
* @returns A color string or undefined
|
|
48
|
+
*/
|
|
49
|
+
function styleToColor(
|
|
50
|
+
style: PossibleCanvasStyle | null,
|
|
51
|
+
context: CanvasRenderingContext2D,
|
|
52
|
+
): string | undefined {
|
|
53
|
+
if (style === null) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Parse the style to CanvasStyle
|
|
58
|
+
const parsedStyle = canvasStyleParser(style);
|
|
59
|
+
|
|
60
|
+
if (parsedStyle === null) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Resolve to canvas-compatible format
|
|
65
|
+
const resolvedStyle = resolveCanvasStyle(parsedStyle, context);
|
|
66
|
+
|
|
67
|
+
// Rough.js only accepts string colors, not gradients or patterns
|
|
68
|
+
// For gradients and patterns, return undefined (rough.js will use default)
|
|
69
|
+
if (typeof resolvedStyle === 'string') {
|
|
70
|
+
return resolvedStyle;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Convert Canvas Commons rough config to Rough.js options.
|
|
78
|
+
*
|
|
79
|
+
* @param config - Canvas Commons rough configuration
|
|
80
|
+
* @param fill - Fill style from shape
|
|
81
|
+
* @param stroke - Stroke style from shape
|
|
82
|
+
* @param strokeWidth - Line width from shape
|
|
83
|
+
* @param context - The rendering context
|
|
84
|
+
* @returns Rough.js options object
|
|
85
|
+
*/
|
|
86
|
+
function configToRoughOptions(
|
|
87
|
+
config: Partial<RoughConfig>,
|
|
88
|
+
fill: PossibleCanvasStyle | null,
|
|
89
|
+
stroke: PossibleCanvasStyle | null,
|
|
90
|
+
strokeWidth: number,
|
|
91
|
+
context: CanvasRenderingContext2D,
|
|
92
|
+
): Options {
|
|
93
|
+
const options: Options = {
|
|
94
|
+
roughness: config.roughness ?? 1,
|
|
95
|
+
bowing: config.bowing ?? 1,
|
|
96
|
+
seed: config.seed,
|
|
97
|
+
stroke: styleToColor(stroke, context),
|
|
98
|
+
strokeWidth: strokeWidth,
|
|
99
|
+
fill: styleToColor(fill, context),
|
|
100
|
+
fillStyle: config.fillStyle ?? 'hachure',
|
|
101
|
+
fillWeight: config.fillWeight,
|
|
102
|
+
hachureAngle: config.hachureAngle ?? -41,
|
|
103
|
+
hachureGap: config.hachureGap ?? strokeWidth * 4,
|
|
104
|
+
curveStepCount: config.curveStepCount,
|
|
105
|
+
simplification: config.simplification,
|
|
106
|
+
disableMultiStroke: config.disableMultiStroke,
|
|
107
|
+
disableMultiStrokeFill: config.disableMultiStrokeFill,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
return options;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Convert a rounded rectangle to SVG path data.
|
|
115
|
+
*
|
|
116
|
+
* @param box - The bounding box of the rectangle
|
|
117
|
+
* @param radius - Corner radius values
|
|
118
|
+
* @param smoothCorners - Whether to use smooth corners (bezier curves)
|
|
119
|
+
* @param cornerSharpness - Sharpness of smooth corners
|
|
120
|
+
* @returns SVG path data string
|
|
121
|
+
*/
|
|
122
|
+
export function roundedRectToSVGPath(
|
|
123
|
+
box: BBox,
|
|
124
|
+
radius: Spacing,
|
|
125
|
+
smoothCorners: boolean,
|
|
126
|
+
cornerSharpness: number,
|
|
127
|
+
): string {
|
|
128
|
+
const topLeft = adjustRectRadius(radius.top, radius.right, radius.left, box);
|
|
129
|
+
const topRight = adjustRectRadius(
|
|
130
|
+
radius.right,
|
|
131
|
+
radius.top,
|
|
132
|
+
radius.bottom,
|
|
133
|
+
box,
|
|
134
|
+
);
|
|
135
|
+
const bottomRight = adjustRectRadius(
|
|
136
|
+
radius.bottom,
|
|
137
|
+
radius.left,
|
|
138
|
+
radius.right,
|
|
139
|
+
box,
|
|
140
|
+
);
|
|
141
|
+
const bottomLeft = adjustRectRadius(
|
|
142
|
+
radius.left,
|
|
143
|
+
radius.bottom,
|
|
144
|
+
radius.top,
|
|
145
|
+
box,
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
if (smoothCorners) {
|
|
149
|
+
const sharpness = (r: number): number => {
|
|
150
|
+
const val = r * cornerSharpness;
|
|
151
|
+
return r - val;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// Build SVG path with bezier curves for smooth corners
|
|
155
|
+
return [
|
|
156
|
+
`M ${box.left + topLeft} ${box.top}`,
|
|
157
|
+
`L ${box.right - topRight} ${box.top}`,
|
|
158
|
+
`C ${box.right - sharpness(topRight)} ${box.top} ${box.right} ${box.top + sharpness(topRight)} ${box.right} ${box.top + topRight}`,
|
|
159
|
+
`L ${box.right} ${box.bottom - bottomRight}`,
|
|
160
|
+
`C ${box.right} ${box.bottom - sharpness(bottomRight)} ${box.right - sharpness(bottomRight)} ${box.bottom} ${box.right - bottomRight} ${box.bottom}`,
|
|
161
|
+
`L ${box.left + bottomLeft} ${box.bottom}`,
|
|
162
|
+
`C ${box.left + sharpness(bottomLeft)} ${box.bottom} ${box.left} ${box.bottom - sharpness(bottomLeft)} ${box.left} ${box.bottom - bottomLeft}`,
|
|
163
|
+
`L ${box.left} ${box.top + topLeft}`,
|
|
164
|
+
`C ${box.left} ${box.top + sharpness(topLeft)} ${box.left + sharpness(topLeft)} ${box.top} ${box.left + topLeft} ${box.top}`,
|
|
165
|
+
'Z',
|
|
166
|
+
].join(' ');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// For regular rounded corners, we need to use arcs
|
|
170
|
+
// SVG arc command: A rx ry x-axis-rotation large-arc-flag sweep-flag x y
|
|
171
|
+
// Canvas arcTo draws a 90-degree arc, so we use: A r r 0 0 1 x y
|
|
172
|
+
const pathParts: string[] = [];
|
|
173
|
+
|
|
174
|
+
// Start at top-left corner (after the radius)
|
|
175
|
+
pathParts.push(`M ${box.left + topLeft} ${box.top}`);
|
|
176
|
+
|
|
177
|
+
// Top edge to top-right corner
|
|
178
|
+
pathParts.push(`L ${box.right - topRight} ${box.top}`);
|
|
179
|
+
if (topRight > 0) {
|
|
180
|
+
pathParts.push(
|
|
181
|
+
`A ${topRight} ${topRight} 0 0 1 ${box.right} ${box.top + topRight}`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Right edge to bottom-right corner
|
|
186
|
+
pathParts.push(`L ${box.right} ${box.bottom - bottomRight}`);
|
|
187
|
+
if (bottomRight > 0) {
|
|
188
|
+
pathParts.push(
|
|
189
|
+
`A ${bottomRight} ${bottomRight} 0 0 1 ${box.right - bottomRight} ${box.bottom}`,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Bottom edge to bottom-left corner
|
|
194
|
+
pathParts.push(`L ${box.left + bottomLeft} ${box.bottom}`);
|
|
195
|
+
if (bottomLeft > 0) {
|
|
196
|
+
pathParts.push(
|
|
197
|
+
`A ${bottomLeft} ${bottomLeft} 0 0 1 ${box.left} ${box.bottom - bottomLeft}`,
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Left edge to top-left corner
|
|
202
|
+
pathParts.push(`L ${box.left} ${box.top + topLeft}`);
|
|
203
|
+
if (topLeft > 0) {
|
|
204
|
+
pathParts.push(
|
|
205
|
+
`A ${topLeft} ${topLeft} 0 0 1 ${box.left + topLeft} ${box.top}`,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Close the path
|
|
210
|
+
pathParts.push('Z');
|
|
211
|
+
|
|
212
|
+
return pathParts.join(' ');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Generate a rough rectangle drawable.
|
|
217
|
+
*
|
|
218
|
+
* @param context - The 2D rendering context
|
|
219
|
+
* @param box - The bounding box of the rectangle
|
|
220
|
+
* @param config - Rough configuration
|
|
221
|
+
* @param fill - Fill style
|
|
222
|
+
* @param stroke - Stroke style
|
|
223
|
+
* @param strokeWidth - Line width
|
|
224
|
+
* @returns A Drawable object that can be cached and drawn
|
|
225
|
+
*/
|
|
226
|
+
export function generateRoughRect(
|
|
227
|
+
context: CanvasRenderingContext2D,
|
|
228
|
+
box: BBox,
|
|
229
|
+
config: Partial<RoughConfig>,
|
|
230
|
+
fill: PossibleCanvasStyle | null,
|
|
231
|
+
stroke: PossibleCanvasStyle | null,
|
|
232
|
+
strokeWidth: number,
|
|
233
|
+
): Drawable {
|
|
234
|
+
const rc = getRoughCanvas(context);
|
|
235
|
+
const options = configToRoughOptions(
|
|
236
|
+
config,
|
|
237
|
+
fill,
|
|
238
|
+
stroke,
|
|
239
|
+
strokeWidth,
|
|
240
|
+
context,
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
// Rough.js draws from top-left, canvas-commons uses center origin
|
|
244
|
+
const x = box.x;
|
|
245
|
+
const y = box.y;
|
|
246
|
+
const width = box.width;
|
|
247
|
+
const height = box.height;
|
|
248
|
+
|
|
249
|
+
return rc.generator.rectangle(x, y, width, height, options);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Draw a rough rectangle.
|
|
254
|
+
*
|
|
255
|
+
* @param context - The 2D rendering context
|
|
256
|
+
* @param box - The bounding box of the rectangle
|
|
257
|
+
* @param config - Rough configuration
|
|
258
|
+
* @param fill - Fill style
|
|
259
|
+
* @param stroke - Stroke style
|
|
260
|
+
* @param strokeWidth - Line width
|
|
261
|
+
*/
|
|
262
|
+
export function drawRoughRect(
|
|
263
|
+
context: CanvasRenderingContext2D,
|
|
264
|
+
box: BBox,
|
|
265
|
+
config: Partial<RoughConfig>,
|
|
266
|
+
fill: PossibleCanvasStyle | null,
|
|
267
|
+
stroke: PossibleCanvasStyle | null,
|
|
268
|
+
strokeWidth: number,
|
|
269
|
+
): void {
|
|
270
|
+
const drawable = generateRoughRect(
|
|
271
|
+
context,
|
|
272
|
+
box,
|
|
273
|
+
config,
|
|
274
|
+
fill,
|
|
275
|
+
stroke,
|
|
276
|
+
strokeWidth,
|
|
277
|
+
);
|
|
278
|
+
const rc = getRoughCanvas(context);
|
|
279
|
+
rc.draw(drawable);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Draw a cached rough drawable.
|
|
284
|
+
*
|
|
285
|
+
* @param context - The 2D rendering context
|
|
286
|
+
* @param drawable - The cached drawable to render
|
|
287
|
+
*/
|
|
288
|
+
export function drawRoughDrawable(
|
|
289
|
+
context: CanvasRenderingContext2D,
|
|
290
|
+
drawable: Drawable,
|
|
291
|
+
): void {
|
|
292
|
+
const rc = getRoughCanvas(context);
|
|
293
|
+
rc.draw(drawable);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Generate a rough rounded rectangle drawable.
|
|
298
|
+
*
|
|
299
|
+
* @param context - The 2D rendering context
|
|
300
|
+
* @param box - The bounding box of the rectangle
|
|
301
|
+
* @param radius - Corner radius values
|
|
302
|
+
* @param smoothCorners - Whether to use smooth corners
|
|
303
|
+
* @param cornerSharpness - Sharpness of smooth corners
|
|
304
|
+
* @param config - Rough configuration
|
|
305
|
+
* @param fill - Fill style
|
|
306
|
+
* @param stroke - Stroke style
|
|
307
|
+
* @param strokeWidth - Line width
|
|
308
|
+
* @returns A Drawable object that can be cached and drawn
|
|
309
|
+
*/
|
|
310
|
+
export function generateRoughRoundedRect(
|
|
311
|
+
context: CanvasRenderingContext2D,
|
|
312
|
+
box: BBox,
|
|
313
|
+
radius: Spacing,
|
|
314
|
+
smoothCorners: boolean,
|
|
315
|
+
cornerSharpness: number,
|
|
316
|
+
config: Partial<RoughConfig>,
|
|
317
|
+
fill: PossibleCanvasStyle | null,
|
|
318
|
+
stroke: PossibleCanvasStyle | null,
|
|
319
|
+
strokeWidth: number,
|
|
320
|
+
): Drawable {
|
|
321
|
+
// Convert the rounded rectangle to SVG path data
|
|
322
|
+
const pathData = roundedRectToSVGPath(
|
|
323
|
+
box,
|
|
324
|
+
radius,
|
|
325
|
+
smoothCorners,
|
|
326
|
+
cornerSharpness,
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
// Generate using rough path
|
|
330
|
+
return generateRoughPath(
|
|
331
|
+
context,
|
|
332
|
+
pathData,
|
|
333
|
+
config,
|
|
334
|
+
fill,
|
|
335
|
+
stroke,
|
|
336
|
+
strokeWidth,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Draw a rough rounded rectangle.
|
|
342
|
+
*
|
|
343
|
+
* @param context - The 2D rendering context
|
|
344
|
+
* @param box - The bounding box of the rectangle
|
|
345
|
+
* @param radius - Corner radius values
|
|
346
|
+
* @param smoothCorners - Whether to use smooth corners
|
|
347
|
+
* @param cornerSharpness - Sharpness of smooth corners
|
|
348
|
+
* @param config - Rough configuration
|
|
349
|
+
* @param fill - Fill style
|
|
350
|
+
* @param stroke - Stroke style
|
|
351
|
+
* @param strokeWidth - Line width
|
|
352
|
+
*/
|
|
353
|
+
export function drawRoughRoundedRect(
|
|
354
|
+
context: CanvasRenderingContext2D,
|
|
355
|
+
box: BBox,
|
|
356
|
+
radius: Spacing,
|
|
357
|
+
smoothCorners: boolean,
|
|
358
|
+
cornerSharpness: number,
|
|
359
|
+
config: Partial<RoughConfig>,
|
|
360
|
+
fill: PossibleCanvasStyle | null,
|
|
361
|
+
stroke: PossibleCanvasStyle | null,
|
|
362
|
+
strokeWidth: number,
|
|
363
|
+
): void {
|
|
364
|
+
const drawable = generateRoughRoundedRect(
|
|
365
|
+
context,
|
|
366
|
+
box,
|
|
367
|
+
radius,
|
|
368
|
+
smoothCorners,
|
|
369
|
+
cornerSharpness,
|
|
370
|
+
config,
|
|
371
|
+
fill,
|
|
372
|
+
stroke,
|
|
373
|
+
strokeWidth,
|
|
374
|
+
);
|
|
375
|
+
drawRoughDrawable(context, drawable);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Draw a rough circle/ellipse.
|
|
380
|
+
*
|
|
381
|
+
* @param context - The 2D rendering context
|
|
382
|
+
* @param center - Center point of the circle
|
|
383
|
+
* @param size - Size (width and height) of the ellipse
|
|
384
|
+
* @param config - Rough configuration
|
|
385
|
+
* @param fill - Fill style
|
|
386
|
+
* @param stroke - Stroke style
|
|
387
|
+
* @param strokeWidth - Line width
|
|
388
|
+
*/
|
|
389
|
+
export function drawRoughCircle(
|
|
390
|
+
context: CanvasRenderingContext2D,
|
|
391
|
+
center: Vector2,
|
|
392
|
+
size: Vector2,
|
|
393
|
+
config: Partial<RoughConfig>,
|
|
394
|
+
fill: PossibleCanvasStyle | null,
|
|
395
|
+
stroke: PossibleCanvasStyle | null,
|
|
396
|
+
strokeWidth: number,
|
|
397
|
+
): void {
|
|
398
|
+
const rc = getRoughCanvas(context);
|
|
399
|
+
const options = configToRoughOptions(
|
|
400
|
+
config,
|
|
401
|
+
fill,
|
|
402
|
+
stroke,
|
|
403
|
+
strokeWidth,
|
|
404
|
+
context,
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
const drawable = rc.generator.ellipse(
|
|
408
|
+
center.x,
|
|
409
|
+
center.y,
|
|
410
|
+
size.x * 2,
|
|
411
|
+
size.y * 2,
|
|
412
|
+
options,
|
|
413
|
+
);
|
|
414
|
+
rc.draw(drawable);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Generate a rough path drawable from SVG path data.
|
|
419
|
+
*
|
|
420
|
+
* @param context - The 2D rendering context
|
|
421
|
+
* @param pathData - SVG path string
|
|
422
|
+
* @param config - Rough configuration
|
|
423
|
+
* @param fill - Fill style
|
|
424
|
+
* @param stroke - Stroke style
|
|
425
|
+
* @param strokeWidth - Line width
|
|
426
|
+
* @returns A Drawable object that can be cached and drawn
|
|
427
|
+
*/
|
|
428
|
+
export function generateRoughPath(
|
|
429
|
+
context: CanvasRenderingContext2D,
|
|
430
|
+
pathData: string,
|
|
431
|
+
config: Partial<RoughConfig>,
|
|
432
|
+
fill: PossibleCanvasStyle | null,
|
|
433
|
+
stroke: PossibleCanvasStyle | null,
|
|
434
|
+
strokeWidth: number,
|
|
435
|
+
): Drawable {
|
|
436
|
+
const rc = getRoughCanvas(context);
|
|
437
|
+
const options = configToRoughOptions(
|
|
438
|
+
config,
|
|
439
|
+
fill,
|
|
440
|
+
stroke,
|
|
441
|
+
strokeWidth,
|
|
442
|
+
context,
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
return rc.generator.path(pathData, options);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Draw a rough path from SVG path data.
|
|
450
|
+
*
|
|
451
|
+
* @param context - The 2D rendering context
|
|
452
|
+
* @param pathData - SVG path string
|
|
453
|
+
* @param config - Rough configuration
|
|
454
|
+
* @param fill - Fill style
|
|
455
|
+
* @param stroke - Stroke style
|
|
456
|
+
* @param strokeWidth - Line width
|
|
457
|
+
*/
|
|
458
|
+
export function drawRoughPath(
|
|
459
|
+
context: CanvasRenderingContext2D,
|
|
460
|
+
pathData: string,
|
|
461
|
+
config: Partial<RoughConfig>,
|
|
462
|
+
fill: PossibleCanvasStyle | null,
|
|
463
|
+
stroke: PossibleCanvasStyle | null,
|
|
464
|
+
strokeWidth: number,
|
|
465
|
+
): void {
|
|
466
|
+
const drawable = generateRoughPath(
|
|
467
|
+
context,
|
|
468
|
+
pathData,
|
|
469
|
+
config,
|
|
470
|
+
fill,
|
|
471
|
+
stroke,
|
|
472
|
+
strokeWidth,
|
|
473
|
+
);
|
|
474
|
+
drawRoughDrawable(context, drawable);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Helper to create rough config from individual signals.
|
|
479
|
+
*
|
|
480
|
+
* @param roughness - Roughness value
|
|
481
|
+
* @param bowing - Bowing value
|
|
482
|
+
* @param fillStyle - Fill style
|
|
483
|
+
* @param fillWeight - Fill weight
|
|
484
|
+
* @param hachureAngle - Hachure angle
|
|
485
|
+
* @param hachureGap - Hachure gap
|
|
486
|
+
* @param seed - Random seed (always defined, generated from useRandom if not specified)
|
|
487
|
+
* @param disableMultiStroke - Disable multiple strokes for stroke
|
|
488
|
+
* @param disableMultiStrokeFill - Disable multiple strokes for fill
|
|
489
|
+
* @returns Partial rough configuration
|
|
490
|
+
*/
|
|
491
|
+
export function createRoughConfig(
|
|
492
|
+
roughness: number,
|
|
493
|
+
bowing: number,
|
|
494
|
+
fillStyle: RoughFillStyle,
|
|
495
|
+
fillWeight: number | undefined,
|
|
496
|
+
hachureAngle: number,
|
|
497
|
+
hachureGap: number,
|
|
498
|
+
seed: number,
|
|
499
|
+
disableMultiStroke: boolean,
|
|
500
|
+
disableMultiStrokeFill: boolean,
|
|
501
|
+
): Partial<RoughConfig> {
|
|
502
|
+
return {
|
|
503
|
+
roughness,
|
|
504
|
+
bowing,
|
|
505
|
+
fillStyle,
|
|
506
|
+
fillWeight,
|
|
507
|
+
hachureAngle,
|
|
508
|
+
hachureGap,
|
|
509
|
+
seed,
|
|
510
|
+
disableMultiStroke,
|
|
511
|
+
disableMultiStrokeFill,
|
|
512
|
+
};
|
|
513
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {FunctionComponent, NodeConstructor, PropsOf} from '../components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create a higher order component with default props.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* const MyTxt = withDefaults(Txt, {
|
|
9
|
+
* fill: '#f3303f',
|
|
10
|
+
* });
|
|
11
|
+
*
|
|
12
|
+
* // ...
|
|
13
|
+
*
|
|
14
|
+
* view.add(<MyTxt>Hello, World!</MyTxt>);
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @param component - The base class or function component to wrap.
|
|
18
|
+
* @param defaults - The default props to apply.
|
|
19
|
+
*/
|
|
20
|
+
export function withDefaults<T extends FunctionComponent | NodeConstructor>(
|
|
21
|
+
component: T,
|
|
22
|
+
defaults: PropsOf<T>,
|
|
23
|
+
) {
|
|
24
|
+
const Node = component;
|
|
25
|
+
return (props: PropsOf<T>) => <Node {...defaults} {...props} />;
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"rootDir": ".",
|
|
4
|
+
"outDir": "..",
|
|
5
|
+
"strict": true,
|
|
6
|
+
"noImplicitOverride": true,
|
|
7
|
+
"module": "esnext",
|
|
8
|
+
"target": "es2022",
|
|
9
|
+
"moduleResolution": "bundler",
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"declarationMap": true,
|
|
13
|
+
"inlineSourceMap": true,
|
|
14
|
+
"experimentalDecorators": true,
|
|
15
|
+
"skipLibCheck": true,
|
|
16
|
+
"composite": true
|
|
17
|
+
}
|
|
18
|
+
}
|