@nasser-sw/fabric 7.0.0-beta1 → 7.0.1-beta10
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/0 +0 -0
- package/debug/{konva → konva-master}/CHANGELOG.md +2 -1
- package/debug/{konva → konva-master}/README.md +7 -3
- package/debug/{konva → konva-master}/package.json +1 -1
- package/debug/{konva → konva-master}/release.sh +1 -4
- package/debug/{konva → konva-master}/src/Canvas.ts +37 -0
- package/debug/{konva → konva-master}/src/shapes/Text.ts +2 -2
- package/dist/index.js +2198 -272
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.min.mjs +1 -1
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +2198 -272
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.cjs +2198 -272
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +2198 -272
- package/dist/index.node.mjs.map +1 -1
- package/dist/package.json.min.mjs +1 -1
- package/dist/package.json.mjs +1 -1
- package/dist/src/shapes/Line.d.ts +33 -86
- package/dist/src/shapes/Line.d.ts.map +1 -1
- package/dist/src/shapes/Line.min.mjs +1 -1
- package/dist/src/shapes/Line.min.mjs.map +1 -1
- package/dist/src/shapes/Line.mjs +405 -159
- package/dist/src/shapes/Line.mjs.map +1 -1
- package/dist/src/shapes/Polyline.d.ts +7 -0
- package/dist/src/shapes/Polyline.d.ts.map +1 -1
- package/dist/src/shapes/Polyline.min.mjs +1 -1
- package/dist/src/shapes/Polyline.min.mjs.map +1 -1
- package/dist/src/shapes/Polyline.mjs +48 -16
- package/dist/src/shapes/Polyline.mjs.map +1 -1
- package/dist/src/shapes/Text/Text.d.ts +19 -0
- package/dist/src/shapes/Text/Text.d.ts.map +1 -1
- package/dist/src/shapes/Text/Text.min.mjs +1 -1
- package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
- package/dist/src/shapes/Text/Text.mjs +302 -16
- package/dist/src/shapes/Text/Text.mjs.map +1 -1
- package/dist/src/shapes/Textbox.d.ts +56 -1
- package/dist/src/shapes/Textbox.d.ts.map +1 -1
- package/dist/src/shapes/Textbox.min.mjs +1 -1
- package/dist/src/shapes/Textbox.min.mjs.map +1 -1
- package/dist/src/shapes/Textbox.mjs +633 -11
- package/dist/src/shapes/Textbox.mjs.map +1 -1
- package/dist/src/shapes/Triangle.d.ts +27 -2
- package/dist/src/shapes/Triangle.d.ts.map +1 -1
- package/dist/src/shapes/Triangle.min.mjs +1 -1
- package/dist/src/shapes/Triangle.min.mjs.map +1 -1
- package/dist/src/shapes/Triangle.mjs +72 -12
- package/dist/src/shapes/Triangle.mjs.map +1 -1
- package/dist/src/text/examples/arabicTextExample.d.ts +60 -0
- package/dist/src/text/examples/arabicTextExample.d.ts.map +1 -0
- package/dist/src/text/measure.d.ts +9 -0
- package/dist/src/text/measure.d.ts.map +1 -1
- package/dist/src/text/measure.min.mjs +1 -1
- package/dist/src/text/measure.min.mjs.map +1 -1
- package/dist/src/text/measure.mjs +175 -4
- package/dist/src/text/measure.mjs.map +1 -1
- package/dist/src/text/overlayEditor.d.ts +8 -0
- package/dist/src/text/overlayEditor.d.ts.map +1 -1
- package/dist/src/text/overlayEditor.min.mjs +1 -1
- package/dist/src/text/overlayEditor.min.mjs.map +1 -1
- package/dist/src/text/overlayEditor.mjs +395 -56
- package/dist/src/text/overlayEditor.mjs.map +1 -1
- package/dist/src/text/scriptUtils.d.ts +142 -0
- package/dist/src/text/scriptUtils.d.ts.map +1 -0
- package/dist/src/text/scriptUtils.min.mjs +2 -0
- package/dist/src/text/scriptUtils.min.mjs.map +1 -0
- package/dist/src/text/scriptUtils.mjs +212 -0
- package/dist/src/text/scriptUtils.mjs.map +1 -0
- package/dist/src/util/misc/cornerRadius.d.ts +70 -0
- package/dist/src/util/misc/cornerRadius.d.ts.map +1 -0
- package/dist/src/util/misc/cornerRadius.min.mjs +2 -0
- package/dist/src/util/misc/cornerRadius.min.mjs.map +1 -0
- package/dist/src/util/misc/cornerRadius.mjs +181 -0
- package/dist/src/util/misc/cornerRadius.mjs.map +1 -0
- package/dist-extensions/src/shapes/CustomLine.d.ts +10 -0
- package/dist-extensions/src/shapes/CustomLine.d.ts.map +1 -0
- package/dist-extensions/src/shapes/Line.d.ts +33 -86
- package/dist-extensions/src/shapes/Line.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Polyline.d.ts +7 -0
- package/dist-extensions/src/shapes/Polyline.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Text/Text.d.ts +19 -0
- package/dist-extensions/src/shapes/Text/Text.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Textbox.d.ts +56 -1
- package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Triangle.d.ts +27 -2
- package/dist-extensions/src/shapes/Triangle.d.ts.map +1 -1
- package/dist-extensions/src/text/measure.d.ts +9 -0
- package/dist-extensions/src/text/measure.d.ts.map +1 -1
- package/dist-extensions/src/text/overlayEditor.d.ts +8 -0
- package/dist-extensions/src/text/overlayEditor.d.ts.map +1 -1
- package/dist-extensions/src/text/scriptUtils.d.ts +142 -0
- package/dist-extensions/src/text/scriptUtils.d.ts.map +1 -0
- package/dist-extensions/src/util/misc/cornerRadius.d.ts +70 -0
- package/dist-extensions/src/util/misc/cornerRadius.d.ts.map +1 -0
- package/fabric-test-editor.html +3552 -0
- package/fabric-test2.html +647 -0
- package/fabric.ts +182 -182
- package/fonts/STV Bold.ttf +0 -0
- package/fonts/STV Light.ttf +0 -0
- package/fonts/STV Regular.ttf +0 -0
- package/package.json +164 -164
- package/src/shapes/Line.ts +484 -157
- package/src/shapes/Polyline.ts +70 -29
- package/src/shapes/Text/Text.ts +317 -19
- package/src/shapes/Textbox.ts +663 -12
- package/src/shapes/Triangle.spec.ts +76 -0
- package/src/shapes/Triangle.ts +85 -15
- package/src/text/measure.ts +200 -50
- package/src/text/overlayEditor.ts +504 -94
- package/src/util/misc/cornerRadius.spec.ts +141 -0
- package/src/util/misc/cornerRadius.ts +269 -0
- /package/debug/{konva → konva-master}/LICENSE +0 -0
- /package/debug/{konva → konva-master}/gulpfile.mjs +0 -0
- /package/debug/{konva → konva-master}/resources/doc-includes/ContainerParams.txt +0 -0
- /package/debug/{konva → konva-master}/resources/doc-includes/NodeParams.txt +0 -0
- /package/debug/{konva → konva-master}/resources/doc-includes/ShapeParams.txt +0 -0
- /package/debug/{konva → konva-master}/resources/jsdoc.conf.json +0 -0
- /package/debug/{konva → konva-master}/rollup.config.mjs +0 -0
- /package/debug/{konva → konva-master}/src/Animation.ts +0 -0
- /package/debug/{konva → konva-master}/src/BezierFunctions.ts +0 -0
- /package/debug/{konva → konva-master}/src/Container.ts +0 -0
- /package/debug/{konva → konva-master}/src/Context.ts +0 -0
- /package/debug/{konva → konva-master}/src/Core.ts +0 -0
- /package/debug/{konva → konva-master}/src/DragAndDrop.ts +0 -0
- /package/debug/{konva → konva-master}/src/Factory.ts +0 -0
- /package/debug/{konva → konva-master}/src/FastLayer.ts +0 -0
- /package/debug/{konva → konva-master}/src/Global.ts +0 -0
- /package/debug/{konva → konva-master}/src/Group.ts +0 -0
- /package/debug/{konva → konva-master}/src/Layer.ts +0 -0
- /package/debug/{konva → konva-master}/src/Node.ts +0 -0
- /package/debug/{konva → konva-master}/src/PointerEvents.ts +0 -0
- /package/debug/{konva → konva-master}/src/Shape.ts +0 -0
- /package/debug/{konva → konva-master}/src/Stage.ts +0 -0
- /package/debug/{konva → konva-master}/src/Tween.ts +0 -0
- /package/debug/{konva → konva-master}/src/Util.ts +0 -0
- /package/debug/{konva → konva-master}/src/Validators.ts +0 -0
- /package/debug/{konva → konva-master}/src/_CoreInternals.ts +0 -0
- /package/debug/{konva → konva-master}/src/_FullInternals.ts +0 -0
- /package/debug/{konva → konva-master}/src/canvas-backend.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Blur.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Brighten.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Brightness.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Contrast.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Emboss.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Enhance.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Grayscale.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/HSL.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/HSV.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Invert.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Kaleidoscope.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Mask.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Noise.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Pixelate.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Posterize.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/RGB.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/RGBA.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Sepia.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Solarize.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Threshold.ts +0 -0
- /package/debug/{konva → konva-master}/src/index.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Arc.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Arrow.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Circle.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Ellipse.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Image.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Label.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Line.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Path.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Rect.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/RegularPolygon.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Ring.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Sprite.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Star.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/TextPath.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Transformer.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Wedge.ts +0 -0
- /package/debug/{konva → konva-master}/src/skia-backend.ts +0 -0
- /package/debug/{konva → konva-master}/src/types.ts +0 -0
- /package/debug/{konva → konva-master}/tsconfig.json +0 -0
- /package/debug/{konva → konva-master}/tsconfig.test.json +0 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Script Detection and Font Metrics Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides script-aware text measurement for improved bounding box calculations
|
|
5
|
+
* across different writing systems like Arabic, Latin, CJK, etc.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Unicode ranges for different scripts
|
|
10
|
+
*/
|
|
11
|
+
const SCRIPT_RANGES = {
|
|
12
|
+
latin: [[0x0000, 0x007F],
|
|
13
|
+
// Basic Latin
|
|
14
|
+
[0x0080, 0x00FF],
|
|
15
|
+
// Latin-1 Supplement
|
|
16
|
+
[0x0100, 0x017F],
|
|
17
|
+
// Latin Extended-A
|
|
18
|
+
[0x0180, 0x024F],
|
|
19
|
+
// Latin Extended-B
|
|
20
|
+
[0x1E00, 0x1EFF] // Latin Extended Additional
|
|
21
|
+
],
|
|
22
|
+
arabic: [[0x0600, 0x06FF],
|
|
23
|
+
// Arabic
|
|
24
|
+
[0x0750, 0x077F],
|
|
25
|
+
// Arabic Supplement
|
|
26
|
+
[0x08A0, 0x08FF],
|
|
27
|
+
// Arabic Extended-A
|
|
28
|
+
[0xFB50, 0xFDFF],
|
|
29
|
+
// Arabic Presentation Forms-A
|
|
30
|
+
[0xFE70, 0xFEFF] // Arabic Presentation Forms-B
|
|
31
|
+
],
|
|
32
|
+
hebrew: [[0x0590, 0x05FF],
|
|
33
|
+
// Hebrew
|
|
34
|
+
[0xFB1D, 0xFB4F] // Hebrew Presentation Forms
|
|
35
|
+
],
|
|
36
|
+
cjk: [[0x2E80, 0x2EFF],
|
|
37
|
+
// CJK Radicals Supplement
|
|
38
|
+
[0x3000, 0x303F],
|
|
39
|
+
// CJK Symbols and Punctuation
|
|
40
|
+
[0x3400, 0x4DBF],
|
|
41
|
+
// CJK Extension A
|
|
42
|
+
[0x4E00, 0x9FFF],
|
|
43
|
+
// CJK Unified Ideographs
|
|
44
|
+
[0xF900, 0xFAFF],
|
|
45
|
+
// CJK Compatibility Ideographs
|
|
46
|
+
[0x20000, 0x2A6DF] // CJK Extension B
|
|
47
|
+
],
|
|
48
|
+
devanagari: [[0x0900, 0x097F],
|
|
49
|
+
// Devanagari
|
|
50
|
+
[0xA8E0, 0xA8FF] // Devanagari Extended
|
|
51
|
+
],
|
|
52
|
+
thai: [[0x0E00, 0x0E7F] // Thai
|
|
53
|
+
]
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Reference characters for font metrics by script
|
|
58
|
+
*/
|
|
59
|
+
const SCRIPT_REFERENCE_CHARS = {
|
|
60
|
+
latin: 'M',
|
|
61
|
+
arabic: 'ا',
|
|
62
|
+
// Arabic Letter Alef
|
|
63
|
+
hebrew: 'ם',
|
|
64
|
+
// Hebrew Letter Final Mem
|
|
65
|
+
cjk: '中',
|
|
66
|
+
// Chinese character for "middle"
|
|
67
|
+
devanagari: 'म',
|
|
68
|
+
// Devanagari Letter Ma
|
|
69
|
+
thai: 'ก',
|
|
70
|
+
// Thai Letter Ko Kai
|
|
71
|
+
mixed: 'M',
|
|
72
|
+
// Fallback to Latin
|
|
73
|
+
unknown: 'M' // Fallback to Latin
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Script-specific fallback proportions for font metrics
|
|
78
|
+
*/
|
|
79
|
+
const SCRIPT_METRICS = {
|
|
80
|
+
latin: {
|
|
81
|
+
ascentRatio: 0.91,
|
|
82
|
+
descentRatio: 0.21,
|
|
83
|
+
actualAscentRatio: 0.716,
|
|
84
|
+
actualDescentRatio: 0.0
|
|
85
|
+
},
|
|
86
|
+
arabic: {
|
|
87
|
+
ascentRatio: 0.85,
|
|
88
|
+
// Arabic fonts typically have lower ascenders
|
|
89
|
+
descentRatio: 0.30,
|
|
90
|
+
// But deeper descenders for diacritics
|
|
91
|
+
actualAscentRatio: 0.65,
|
|
92
|
+
actualDescentRatio: 0.25
|
|
93
|
+
},
|
|
94
|
+
hebrew: {
|
|
95
|
+
ascentRatio: 0.88,
|
|
96
|
+
descentRatio: 0.25,
|
|
97
|
+
actualAscentRatio: 0.70,
|
|
98
|
+
actualDescentRatio: 0.15
|
|
99
|
+
},
|
|
100
|
+
cjk: {
|
|
101
|
+
ascentRatio: 0.88,
|
|
102
|
+
// CJK fonts are more square
|
|
103
|
+
descentRatio: 0.12,
|
|
104
|
+
actualAscentRatio: 0.80,
|
|
105
|
+
actualDescentRatio: 0.10
|
|
106
|
+
},
|
|
107
|
+
devanagari: {
|
|
108
|
+
ascentRatio: 1.0,
|
|
109
|
+
// Devanagari has tall ascenders
|
|
110
|
+
descentRatio: 0.25,
|
|
111
|
+
actualAscentRatio: 0.85,
|
|
112
|
+
actualDescentRatio: 0.15
|
|
113
|
+
},
|
|
114
|
+
thai: {
|
|
115
|
+
ascentRatio: 0.95,
|
|
116
|
+
// Thai has tall ascenders
|
|
117
|
+
descentRatio: 0.30,
|
|
118
|
+
// And some descenders
|
|
119
|
+
actualAscentRatio: 0.75,
|
|
120
|
+
actualDescentRatio: 0.20
|
|
121
|
+
},
|
|
122
|
+
mixed: {
|
|
123
|
+
ascentRatio: 0.91,
|
|
124
|
+
descentRatio: 0.21,
|
|
125
|
+
actualAscentRatio: 0.716,
|
|
126
|
+
actualDescentRatio: 0.0
|
|
127
|
+
},
|
|
128
|
+
unknown: {
|
|
129
|
+
ascentRatio: 0.91,
|
|
130
|
+
descentRatio: 0.21,
|
|
131
|
+
actualAscentRatio: 0.716,
|
|
132
|
+
actualDescentRatio: 0.0
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Detect the primary script of a text string
|
|
138
|
+
*/
|
|
139
|
+
function detectScript(text) {
|
|
140
|
+
if (!text || text.length === 0) return 'unknown';
|
|
141
|
+
const scriptCounts = {
|
|
142
|
+
latin: 0,
|
|
143
|
+
arabic: 0,
|
|
144
|
+
hebrew: 0,
|
|
145
|
+
cjk: 0,
|
|
146
|
+
devanagari: 0,
|
|
147
|
+
thai: 0,
|
|
148
|
+
mixed: 0,
|
|
149
|
+
unknown: 0
|
|
150
|
+
};
|
|
151
|
+
for (const char of text) {
|
|
152
|
+
const codePoint = char.codePointAt(0);
|
|
153
|
+
if (codePoint === undefined) continue;
|
|
154
|
+
let detected = false;
|
|
155
|
+
for (const [script, ranges] of Object.entries(SCRIPT_RANGES)) {
|
|
156
|
+
for (const [start, end] of ranges) {
|
|
157
|
+
if (codePoint >= start && codePoint <= end) {
|
|
158
|
+
scriptCounts[script]++;
|
|
159
|
+
detected = true;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (detected) break;
|
|
164
|
+
}
|
|
165
|
+
if (!detected) {
|
|
166
|
+
scriptCounts.unknown++;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Find the script with the highest count
|
|
171
|
+
const entries = Object.entries(scriptCounts);
|
|
172
|
+
entries.sort((a, b) => b[1] - a[1]);
|
|
173
|
+
const [topScript, topCount] = entries[0];
|
|
174
|
+
const [secondScript, secondCount] = entries[1];
|
|
175
|
+
|
|
176
|
+
// If we have significant counts in multiple scripts, consider it mixed
|
|
177
|
+
if (topCount > 0 && secondCount > topCount * 0.3) {
|
|
178
|
+
return 'mixed';
|
|
179
|
+
}
|
|
180
|
+
return topScript === 'unknown' && topCount === 0 ? 'latin' : topScript;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Get reference character for a given script
|
|
185
|
+
*/
|
|
186
|
+
function getScriptReferenceChar(script) {
|
|
187
|
+
return SCRIPT_REFERENCE_CHARS[script];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Get script-specific metric ratios
|
|
192
|
+
*/
|
|
193
|
+
function getScriptMetrics(script) {
|
|
194
|
+
return SCRIPT_METRICS[script];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Detect script for a single grapheme/character
|
|
199
|
+
*/
|
|
200
|
+
function detectGraphemeScript(grapheme) {
|
|
201
|
+
return detectScript(grapheme);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Check if text contains complex script characteristics
|
|
206
|
+
*/
|
|
207
|
+
function isComplexScript(script) {
|
|
208
|
+
return ['arabic', 'hebrew', 'devanagari', 'thai'].includes(script);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export { SCRIPT_METRICS, SCRIPT_REFERENCE_CHARS, detectGraphemeScript, detectScript, getScriptMetrics, getScriptReferenceChar, isComplexScript };
|
|
212
|
+
//# sourceMappingURL=scriptUtils.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scriptUtils.mjs","sources":["../../../src/text/scriptUtils.ts"],"sourcesContent":["/**\n * Script Detection and Font Metrics Utilities\n * \n * Provides script-aware text measurement for improved bounding box calculations\n * across different writing systems like Arabic, Latin, CJK, etc.\n */\n\nexport type ScriptType = 'latin' | 'arabic' | 'hebrew' | 'cjk' | 'devanagari' | 'thai' | 'mixed' | 'unknown';\n\n/**\n * Unicode ranges for different scripts\n */\nconst SCRIPT_RANGES = {\n latin: [\n [0x0000, 0x007F], // Basic Latin\n [0x0080, 0x00FF], // Latin-1 Supplement\n [0x0100, 0x017F], // Latin Extended-A\n [0x0180, 0x024F], // Latin Extended-B\n [0x1E00, 0x1EFF], // Latin Extended Additional\n ],\n arabic: [\n [0x0600, 0x06FF], // Arabic\n [0x0750, 0x077F], // Arabic Supplement\n [0x08A0, 0x08FF], // Arabic Extended-A\n [0xFB50, 0xFDFF], // Arabic Presentation Forms-A\n [0xFE70, 0xFEFF], // Arabic Presentation Forms-B\n ],\n hebrew: [\n [0x0590, 0x05FF], // Hebrew\n [0xFB1D, 0xFB4F], // Hebrew Presentation Forms\n ],\n cjk: [\n [0x2E80, 0x2EFF], // CJK Radicals Supplement\n [0x3000, 0x303F], // CJK Symbols and Punctuation\n [0x3400, 0x4DBF], // CJK Extension A\n [0x4E00, 0x9FFF], // CJK Unified Ideographs\n [0xF900, 0xFAFF], // CJK Compatibility Ideographs\n [0x20000, 0x2A6DF], // CJK Extension B\n ],\n devanagari: [\n [0x0900, 0x097F], // Devanagari\n [0xA8E0, 0xA8FF], // Devanagari Extended\n ],\n thai: [\n [0x0E00, 0x0E7F], // Thai\n ],\n};\n\n/**\n * Reference characters for font metrics by script\n */\nexport const SCRIPT_REFERENCE_CHARS = {\n latin: 'M',\n arabic: 'ا', // Arabic Letter Alef\n hebrew: 'ם', // Hebrew Letter Final Mem\n cjk: '中', // Chinese character for \"middle\"\n devanagari: 'म', // Devanagari Letter Ma\n thai: 'ก', // Thai Letter Ko Kai\n mixed: 'M', // Fallback to Latin\n unknown: 'M', // Fallback to Latin\n} as const;\n\n/**\n * Script-specific fallback proportions for font metrics\n */\nexport const SCRIPT_METRICS = {\n latin: {\n ascentRatio: 0.91,\n descentRatio: 0.21,\n actualAscentRatio: 0.716,\n actualDescentRatio: 0.0,\n },\n arabic: {\n ascentRatio: 0.85, // Arabic fonts typically have lower ascenders\n descentRatio: 0.30, // But deeper descenders for diacritics\n actualAscentRatio: 0.65,\n actualDescentRatio: 0.25,\n },\n hebrew: {\n ascentRatio: 0.88,\n descentRatio: 0.25,\n actualAscentRatio: 0.70,\n actualDescentRatio: 0.15,\n },\n cjk: {\n ascentRatio: 0.88, // CJK fonts are more square\n descentRatio: 0.12,\n actualAscentRatio: 0.80,\n actualDescentRatio: 0.10,\n },\n devanagari: {\n ascentRatio: 1.0, // Devanagari has tall ascenders\n descentRatio: 0.25,\n actualAscentRatio: 0.85,\n actualDescentRatio: 0.15,\n },\n thai: {\n ascentRatio: 0.95, // Thai has tall ascenders\n descentRatio: 0.30, // And some descenders\n actualAscentRatio: 0.75,\n actualDescentRatio: 0.20,\n },\n mixed: {\n ascentRatio: 0.91,\n descentRatio: 0.21,\n actualAscentRatio: 0.716,\n actualDescentRatio: 0.0,\n },\n unknown: {\n ascentRatio: 0.91,\n descentRatio: 0.21,\n actualAscentRatio: 0.716,\n actualDescentRatio: 0.0,\n },\n} as const;\n\n/**\n * Detect the primary script of a text string\n */\nexport function detectScript(text: string): ScriptType {\n if (!text || text.length === 0) return 'unknown';\n\n const scriptCounts: Record<ScriptType, number> = {\n latin: 0,\n arabic: 0,\n hebrew: 0,\n cjk: 0,\n devanagari: 0,\n thai: 0,\n mixed: 0,\n unknown: 0,\n };\n\n for (const char of text) {\n const codePoint = char.codePointAt(0);\n if (codePoint === undefined) continue;\n\n let detected = false;\n \n for (const [script, ranges] of Object.entries(SCRIPT_RANGES)) {\n for (const [start, end] of ranges) {\n if (codePoint >= start && codePoint <= end) {\n scriptCounts[script as ScriptType]++;\n detected = true;\n break;\n }\n }\n if (detected) break;\n }\n\n if (!detected) {\n scriptCounts.unknown++;\n }\n }\n\n // Find the script with the highest count\n const entries = Object.entries(scriptCounts) as [ScriptType, number][];\n entries.sort((a, b) => b[1] - a[1]);\n\n const [topScript, topCount] = entries[0];\n const [secondScript, secondCount] = entries[1];\n\n // If we have significant counts in multiple scripts, consider it mixed\n if (topCount > 0 && secondCount > topCount * 0.3) {\n return 'mixed';\n }\n\n return topScript === 'unknown' && topCount === 0 ? 'latin' : topScript;\n}\n\n/**\n * Get reference character for a given script\n */\nexport function getScriptReferenceChar(script: ScriptType): string {\n return SCRIPT_REFERENCE_CHARS[script];\n}\n\n/**\n * Get script-specific metric ratios\n */\nexport function getScriptMetrics(script: ScriptType) {\n return SCRIPT_METRICS[script];\n}\n\n/**\n * Detect script for a single grapheme/character\n */\nexport function detectGraphemeScript(grapheme: string): ScriptType {\n return detectScript(grapheme);\n}\n\n/**\n * Check if text contains complex script characteristics\n */\nexport function isComplexScript(script: ScriptType): boolean {\n return ['arabic', 'hebrew', 'devanagari', 'thai'].includes(script);\n}\n\n/**\n * Check if script requires special glyph shaping\n */\nexport function requiresGlyphShaping(script: ScriptType): boolean {\n return ['arabic', 'devanagari', 'thai'].includes(script);\n}\n\n/**\n * Get optimal sample text for measuring font metrics\n */\nexport function getSampleTextForScript(script: ScriptType): string {\n const samples = {\n latin: 'AaBbCcMmWwXxYyZz',\n arabic: 'أابتجحدرسعفقلمنهويء',\n hebrew: 'אבגדהוחטיכלמנעפקרשת',\n cjk: '中文字体测试样本',\n devanagari: 'अआइईउऊएऐओऔकगचजट',\n thai: 'กขคงจชดตนบปพมยรลวสหอฮ',\n mixed: 'AaBbCcMmWwXxYyZz',\n unknown: 'AaBbCcMmWwXxYyZz',\n };\n \n return samples[script];\n}"],"names":["SCRIPT_RANGES","latin","arabic","hebrew","cjk","devanagari","thai","SCRIPT_REFERENCE_CHARS","mixed","unknown","SCRIPT_METRICS","ascentRatio","descentRatio","actualAscentRatio","actualDescentRatio","detectScript","text","length","scriptCounts","char","codePoint","codePointAt","undefined","detected","script","ranges","Object","entries","start","end","sort","a","b","topScript","topCount","secondScript","secondCount","getScriptReferenceChar","getScriptMetrics","detectGraphemeScript","grapheme","isComplexScript","includes"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;AACA,MAAMA,aAAa,GAAG;AACpBC,EAAAA,KAAK,EAAE,CACL,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;AAClB,EAAA,CAAC,MAAM,EAAE,MAAM,CAAC;GACjB;AACDC,EAAAA,MAAM,EAAE,CACN,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;AAClB,EAAA,CAAC,MAAM,EAAE,MAAM,CAAC;GACjB;AACDC,EAAAA,MAAM,EAAE,CACN,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;AAClB,EAAA,CAAC,MAAM,EAAE,MAAM,CAAC;GACjB;AACDC,EAAAA,GAAG,EAAE,CACH,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;EAClB,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;AAClB,EAAA,CAAC,OAAO,EAAE,OAAO,CAAC;GACnB;AACDC,EAAAA,UAAU,EAAE,CACV,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;AAClB,EAAA,CAAC,MAAM,EAAE,MAAM,CAAC;GACjB;AACDC,EAAAA,IAAI,EAAE,CACJ,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE;AAEtB,CAAC;;AAED;AACA;AACA;AACO,MAAMC,sBAAsB,GAAG;AACpCN,EAAAA,KAAK,EAAE,GAAG;AACVC,EAAAA,MAAM,EAAE,GAAG;AAAE;AACbC,EAAAA,MAAM,EAAE,GAAG;AAAE;AACbC,EAAAA,GAAG,EAAE,GAAG;AAAE;AACVC,EAAAA,UAAU,EAAE,GAAG;AAAE;AACjBC,EAAAA,IAAI,EAAE,GAAG;AAAE;AACXE,EAAAA,KAAK,EAAE,GAAG;AAAE;EACZC,OAAO,EAAE,GAAG;AACd;;AAEA;AACA;AACA;AACO,MAAMC,cAAc,GAAG;AAC5BT,EAAAA,KAAK,EAAE;AACLU,IAAAA,WAAW,EAAE,IAAI;AACjBC,IAAAA,YAAY,EAAE,IAAI;AAClBC,IAAAA,iBAAiB,EAAE,KAAK;AACxBC,IAAAA,kBAAkB,EAAE;GACrB;AACDZ,EAAAA,MAAM,EAAE;AACNS,IAAAA,WAAW,EAAE,IAAI;AAAE;AACnBC,IAAAA,YAAY,EAAE,IAAI;AAAE;AACpBC,IAAAA,iBAAiB,EAAE,IAAI;AACvBC,IAAAA,kBAAkB,EAAE;GACrB;AACDX,EAAAA,MAAM,EAAE;AACNQ,IAAAA,WAAW,EAAE,IAAI;AACjBC,IAAAA,YAAY,EAAE,IAAI;AAClBC,IAAAA,iBAAiB,EAAE,IAAI;AACvBC,IAAAA,kBAAkB,EAAE;GACrB;AACDV,EAAAA,GAAG,EAAE;AACHO,IAAAA,WAAW,EAAE,IAAI;AAAE;AACnBC,IAAAA,YAAY,EAAE,IAAI;AAClBC,IAAAA,iBAAiB,EAAE,IAAI;AACvBC,IAAAA,kBAAkB,EAAE;GACrB;AACDT,EAAAA,UAAU,EAAE;AACVM,IAAAA,WAAW,EAAE,GAAG;AAAE;AAClBC,IAAAA,YAAY,EAAE,IAAI;AAClBC,IAAAA,iBAAiB,EAAE,IAAI;AACvBC,IAAAA,kBAAkB,EAAE;GACrB;AACDR,EAAAA,IAAI,EAAE;AACJK,IAAAA,WAAW,EAAE,IAAI;AAAE;AACnBC,IAAAA,YAAY,EAAE,IAAI;AAAE;AACpBC,IAAAA,iBAAiB,EAAE,IAAI;AACvBC,IAAAA,kBAAkB,EAAE;GACrB;AACDN,EAAAA,KAAK,EAAE;AACLG,IAAAA,WAAW,EAAE,IAAI;AACjBC,IAAAA,YAAY,EAAE,IAAI;AAClBC,IAAAA,iBAAiB,EAAE,KAAK;AACxBC,IAAAA,kBAAkB,EAAE;GACrB;AACDL,EAAAA,OAAO,EAAE;AACPE,IAAAA,WAAW,EAAE,IAAI;AACjBC,IAAAA,YAAY,EAAE,IAAI;AAClBC,IAAAA,iBAAiB,EAAE,KAAK;AACxBC,IAAAA,kBAAkB,EAAE;AACtB;AACF;;AAEA;AACA;AACA;AACO,SAASC,YAAYA,CAACC,IAAY,EAAc;EACrD,IAAI,CAACA,IAAI,IAAIA,IAAI,CAACC,MAAM,KAAK,CAAC,EAAE,OAAO,SAAS;AAEhD,EAAA,MAAMC,YAAwC,GAAG;AAC/CjB,IAAAA,KAAK,EAAE,CAAC;AACRC,IAAAA,MAAM,EAAE,CAAC;AACTC,IAAAA,MAAM,EAAE,CAAC;AACTC,IAAAA,GAAG,EAAE,CAAC;AACNC,IAAAA,UAAU,EAAE,CAAC;AACbC,IAAAA,IAAI,EAAE,CAAC;AACPE,IAAAA,KAAK,EAAE,CAAC;AACRC,IAAAA,OAAO,EAAE;GACV;AAED,EAAA,KAAK,MAAMU,IAAI,IAAIH,IAAI,EAAE;AACvB,IAAA,MAAMI,SAAS,GAAGD,IAAI,CAACE,WAAW,CAAC,CAAC,CAAC;IACrC,IAAID,SAAS,KAAKE,SAAS,EAAE;IAE7B,IAAIC,QAAQ,GAAG,KAAK;AAEpB,IAAA,KAAK,MAAM,CAACC,MAAM,EAAEC,MAAM,CAAC,IAAIC,MAAM,CAACC,OAAO,CAAC3B,aAAa,CAAC,EAAE;MAC5D,KAAK,MAAM,CAAC4B,KAAK,EAAEC,GAAG,CAAC,IAAIJ,MAAM,EAAE;AACjC,QAAA,IAAIL,SAAS,IAAIQ,KAAK,IAAIR,SAAS,IAAIS,GAAG,EAAE;UAC1CX,YAAY,CAACM,MAAM,CAAe,EAAE;AACpCD,UAAAA,QAAQ,GAAG,IAAI;AACf,UAAA;AACF,QAAA;AACF,MAAA;AACA,MAAA,IAAIA,QAAQ,EAAE;AAChB,IAAA;IAEA,IAAI,CAACA,QAAQ,EAAE;MACbL,YAAY,CAACT,OAAO,EAAE;AACxB,IAAA;AACF,EAAA;;AAEA;AACA,EAAA,MAAMkB,OAAO,GAAGD,MAAM,CAACC,OAAO,CAACT,YAAY,CAA2B;AACtES,EAAAA,OAAO,CAACG,IAAI,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAKA,CAAC,CAAC,CAAC,CAAC,GAAGD,CAAC,CAAC,CAAC,CAAC,CAAC;EAEnC,MAAM,CAACE,SAAS,EAAEC,QAAQ,CAAC,GAAGP,OAAO,CAAC,CAAC,CAAC;EACxC,MAAM,CAACQ,YAAY,EAAEC,WAAW,CAAC,GAAGT,OAAO,CAAC,CAAC,CAAC;;AAE9C;EACA,IAAIO,QAAQ,GAAG,CAAC,IAAIE,WAAW,GAAGF,QAAQ,GAAG,GAAG,EAAE;AAChD,IAAA,OAAO,OAAO;AAChB,EAAA;EAEA,OAAOD,SAAS,KAAK,SAAS,IAAIC,QAAQ,KAAK,CAAC,GAAG,OAAO,GAAGD,SAAS;AACxE;;AAEA;AACA;AACA;AACO,SAASI,sBAAsBA,CAACb,MAAkB,EAAU;EACjE,OAAOjB,sBAAsB,CAACiB,MAAM,CAAC;AACvC;;AAEA;AACA;AACA;AACO,SAASc,gBAAgBA,CAACd,MAAkB,EAAE;EACnD,OAAOd,cAAc,CAACc,MAAM,CAAC;AAC/B;;AAEA;AACA;AACA;AACO,SAASe,oBAAoBA,CAACC,QAAgB,EAAc;EACjE,OAAOzB,YAAY,CAACyB,QAAQ,CAAC;AAC/B;;AAEA;AACA;AACA;AACO,SAASC,eAAeA,CAACjB,MAAkB,EAAW;AAC3D,EAAA,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,CAACkB,QAAQ,CAAClB,MAAM,CAAC;AACpE;;;;"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { XY } from '../../Point';
|
|
2
|
+
export interface CornerRadiusOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Corner radius value
|
|
5
|
+
*/
|
|
6
|
+
radius: number;
|
|
7
|
+
/**
|
|
8
|
+
* Whether to apply radius as percentage of the smallest dimension
|
|
9
|
+
*/
|
|
10
|
+
radiusAsPercentage?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface RoundedCornerPoint {
|
|
13
|
+
/**
|
|
14
|
+
* Original corner point
|
|
15
|
+
*/
|
|
16
|
+
corner: XY;
|
|
17
|
+
/**
|
|
18
|
+
* Start point of the rounded corner arc
|
|
19
|
+
*/
|
|
20
|
+
start: XY;
|
|
21
|
+
/**
|
|
22
|
+
* End point of the rounded corner arc
|
|
23
|
+
*/
|
|
24
|
+
end: XY;
|
|
25
|
+
/**
|
|
26
|
+
* First control point for bezier curve
|
|
27
|
+
*/
|
|
28
|
+
cp1: XY;
|
|
29
|
+
/**
|
|
30
|
+
* Second control point for bezier curve
|
|
31
|
+
*/
|
|
32
|
+
cp2: XY;
|
|
33
|
+
/**
|
|
34
|
+
* Actual radius used (may be different from requested if constrained)
|
|
35
|
+
*/
|
|
36
|
+
actualRadius: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Calculate the distance between two points
|
|
40
|
+
*/
|
|
41
|
+
export declare function pointDistance(p1: XY, p2: XY): number;
|
|
42
|
+
/**
|
|
43
|
+
* Normalize a vector
|
|
44
|
+
*/
|
|
45
|
+
export declare function normalizeVector(vector: XY): XY;
|
|
46
|
+
/**
|
|
47
|
+
* Calculate the angle between two vectors
|
|
48
|
+
*/
|
|
49
|
+
export declare function angleBetweenVectors(v1: XY, v2: XY): number;
|
|
50
|
+
/**
|
|
51
|
+
* Get the maximum allowed radius for a corner based on adjacent edge lengths
|
|
52
|
+
*/
|
|
53
|
+
export declare function getMaxRadius(prevPoint: XY, currentPoint: XY, nextPoint: XY): number;
|
|
54
|
+
/**
|
|
55
|
+
* Calculate rounded corner data for a single corner
|
|
56
|
+
*/
|
|
57
|
+
export declare function calculateRoundedCorner(prevPoint: XY, currentPoint: XY, nextPoint: XY, radius: number): RoundedCornerPoint;
|
|
58
|
+
/**
|
|
59
|
+
* Apply corner radius to a polygon defined by points
|
|
60
|
+
*/
|
|
61
|
+
export declare function applyCornerRadiusToPolygon(points: XY[], radius: number, radiusAsPercentage?: boolean): RoundedCornerPoint[];
|
|
62
|
+
/**
|
|
63
|
+
* Render a rounded polygon to a canvas context
|
|
64
|
+
*/
|
|
65
|
+
export declare function renderRoundedPolygon(ctx: CanvasRenderingContext2D, roundedCorners: RoundedCornerPoint[], closed?: boolean): void;
|
|
66
|
+
/**
|
|
67
|
+
* Generate SVG path data for a rounded polygon
|
|
68
|
+
*/
|
|
69
|
+
export declare function generateRoundedPolygonPath(roundedCorners: RoundedCornerPoint[], closed?: boolean): string;
|
|
70
|
+
//# sourceMappingURL=cornerRadius.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cornerRadius.d.ts","sourceRoot":"","sources":["../../../../src/util/misc/cornerRadius.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAItC,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,MAAM,EAAE,EAAE,CAAC;IACX;;OAEG;IACH,KAAK,EAAE,EAAE,CAAC;IACV;;OAEG;IACH,GAAG,EAAE,EAAE,CAAC;IACR;;OAEG;IACH,GAAG,EAAE,EAAE,CAAC;IACR;;OAEG;IACH,GAAG,EAAE,EAAE,CAAC;IACR;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,MAAM,CAEpD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAI9C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,MAAM,CAI1D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,EAAE,EACb,YAAY,EAAE,EAAE,EAChB,SAAS,EAAE,EAAE,GACZ,MAAM,CAIR;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,EAAE,EACb,YAAY,EAAE,EAAE,EAChB,SAAS,EAAE,EAAE,EACb,MAAM,EAAE,MAAM,GACb,kBAAkB,CAoDpB;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,EAAE,EAAE,EACZ,MAAM,EAAE,MAAM,EACd,kBAAkB,UAAQ,GACzB,kBAAkB,EAAE,CAuCtB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,wBAAwB,EAC7B,cAAc,EAAE,kBAAkB,EAAE,EACpC,MAAM,UAAO,QAkCd;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,kBAAkB,EAAE,EACpC,MAAM,UAAO,GACZ,MAAM,CA8BR"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{kRect as t}from"../../constants.min.mjs";function n(t,n){return Math.sqrt(Math.pow(n.x-t.x,2)+Math.pow(n.y-t.y,2))}function e(t){const n=Math.sqrt(t.x*t.x+t.y*t.y);return 0===n?{x:0,y:0}:{x:t.x/n,y:t.y/n}}function o(t,e,o){const r=n(t,e),x=n(e,o);return Math.min(r,x)/2}function r(n,r,x,y){const h={x:r.x-n.x,y:r.y-n.y},a={x:x.x-r.x,y:x.y-r.y},s=e(h),c=e(a),l=o(n,r,x),i=Math.min(y,l),p={x:r.x-s.x*i,y:r.y-s.y*i},u={x:r.x+c.x*i,y:r.y+c.y*i},g=i*t;return{corner:r,start:p,end:u,cp1:{x:p.x+s.x*g,y:p.y+s.y*g},cp2:{x:u.x-c.x*g,y:u.y-c.y*g},actualRadius:i}}function x(t,n){let e=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(t.length<3)throw new Error("Polygon must have at least 3 points");let o=n;if(e){const e=Math.min(...t.map(t=>t.x)),r=Math.max(...t.map(t=>t.x)),x=Math.min(...t.map(t=>t.y)),y=r-e,h=Math.max(...t.map(t=>t.y))-x;o=n/100*Math.min(y,h)}const x=[];for(let n=0;n<t.length;n++){const e=(n-1+t.length)%t.length,y=(n+1)%t.length,h=r(t[e],t[n],t[y],o);x.push(h)}return x}function y(t,n){let e=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(0===n.length)return;t.beginPath();const o=n[0];t.moveTo(o.start.x,o.start.y);for(let o=0;o<n.length;o++){const r=n[o],x=n[(o+1)%n.length];t.bezierCurveTo(r.cp1.x,r.cp1.y,r.cp2.x,r.cp2.y,r.end.x,r.end.y),(o<n.length-1||e)&&t.lineTo(x.start.x,x.start.y)}e&&t.closePath()}function h(t){let n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(0===t.length)return"";const e=[],o=t[0];e.push(`M ${o.start.x} ${o.start.y}`);for(let o=0;o<t.length;o++){const r=t[o],x=t[(o+1)%t.length];e.push(`C ${r.cp1.x} ${r.cp1.y} ${r.cp2.x} ${r.cp2.y} ${r.end.x} ${r.end.y}`),(o<t.length-1||n)&&e.push(`L ${x.start.x} ${x.start.y}`)}return n&&e.push("Z"),e.join(" ")}export{x as applyCornerRadiusToPolygon,r as calculateRoundedCorner,h as generateRoundedPolygonPath,o as getMaxRadius,e as normalizeVector,n as pointDistance,y as renderRoundedPolygon};
|
|
2
|
+
//# sourceMappingURL=cornerRadius.min.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cornerRadius.min.mjs","sources":["../../../../src/util/misc/cornerRadius.ts"],"sourcesContent":["import type { XY } from '../../Point';\nimport { Point } from '../../Point';\nimport { kRect } from '../../constants';\n\nexport interface CornerRadiusOptions {\n /**\n * Corner radius value\n */\n radius: number;\n /**\n * Whether to apply radius as percentage of the smallest dimension\n */\n radiusAsPercentage?: boolean;\n}\n\nexport interface RoundedCornerPoint {\n /**\n * Original corner point\n */\n corner: XY;\n /**\n * Start point of the rounded corner arc\n */\n start: XY;\n /**\n * End point of the rounded corner arc\n */\n end: XY;\n /**\n * First control point for bezier curve\n */\n cp1: XY;\n /**\n * Second control point for bezier curve\n */\n cp2: XY;\n /**\n * Actual radius used (may be different from requested if constrained)\n */\n actualRadius: number;\n}\n\n/**\n * Calculate the distance between two points\n */\nexport function pointDistance(p1: XY, p2: XY): number {\n return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));\n}\n\n/**\n * Normalize a vector\n */\nexport function normalizeVector(vector: XY): XY {\n const length = Math.sqrt(vector.x * vector.x + vector.y * vector.y);\n if (length === 0) return { x: 0, y: 0 };\n return { x: vector.x / length, y: vector.y / length };\n}\n\n/**\n * Calculate the angle between two vectors\n */\nexport function angleBetweenVectors(v1: XY, v2: XY): number {\n const dot = v1.x * v2.x + v1.y * v2.y;\n const det = v1.x * v2.y - v1.y * v2.x;\n return Math.atan2(det, dot);\n}\n\n/**\n * Get the maximum allowed radius for a corner based on adjacent edge lengths\n */\nexport function getMaxRadius(\n prevPoint: XY,\n currentPoint: XY,\n nextPoint: XY,\n): number {\n const dist1 = pointDistance(prevPoint, currentPoint);\n const dist2 = pointDistance(currentPoint, nextPoint);\n return Math.min(dist1, dist2) / 2;\n}\n\n/**\n * Calculate rounded corner data for a single corner\n */\nexport function calculateRoundedCorner(\n prevPoint: XY,\n currentPoint: XY,\n nextPoint: XY,\n radius: number,\n): RoundedCornerPoint {\n // Calculate edge vectors\n const edge1 = {\n x: currentPoint.x - prevPoint.x,\n y: currentPoint.y - prevPoint.y,\n };\n const edge2 = {\n x: nextPoint.x - currentPoint.x,\n y: nextPoint.y - currentPoint.y,\n };\n\n // Normalize edge vectors\n const norm1 = normalizeVector(edge1);\n const norm2 = normalizeVector(edge2);\n\n // Calculate the maximum allowed radius\n const maxRadius = getMaxRadius(prevPoint, currentPoint, nextPoint);\n const actualRadius = Math.min(radius, maxRadius);\n\n // Calculate start and end points of the rounded corner\n const startPoint = {\n x: currentPoint.x - norm1.x * actualRadius,\n y: currentPoint.y - norm1.y * actualRadius,\n };\n\n const endPoint = {\n x: currentPoint.x + norm2.x * actualRadius,\n y: currentPoint.y + norm2.y * actualRadius,\n };\n\n // Calculate control points for bezier curve\n // Using the magic number kRect for optimal circular approximation\n const controlOffset = actualRadius * kRect;\n\n const cp1 = {\n x: startPoint.x + norm1.x * controlOffset,\n y: startPoint.y + norm1.y * controlOffset,\n };\n\n const cp2 = {\n x: endPoint.x - norm2.x * controlOffset,\n y: endPoint.y - norm2.y * controlOffset,\n };\n\n return {\n corner: currentPoint,\n start: startPoint,\n end: endPoint,\n cp1,\n cp2,\n actualRadius,\n };\n}\n\n/**\n * Apply corner radius to a polygon defined by points\n */\nexport function applyCornerRadiusToPolygon(\n points: XY[],\n radius: number,\n radiusAsPercentage = false,\n): RoundedCornerPoint[] {\n if (points.length < 3) {\n throw new Error('Polygon must have at least 3 points');\n }\n\n // Calculate bounding box if radius is percentage-based\n let actualRadius = radius;\n if (radiusAsPercentage) {\n const minX = Math.min(...points.map((p) => p.x));\n const maxX = Math.max(...points.map((p) => p.x));\n const minY = Math.min(...points.map((p) => p.y));\n const maxY = Math.max(...points.map((p) => p.y));\n const width = maxX - minX;\n const height = maxY - minY;\n const minDimension = Math.min(width, height);\n actualRadius = (radius / 100) * minDimension;\n }\n\n const roundedCorners: RoundedCornerPoint[] = [];\n\n for (let i = 0; i < points.length; i++) {\n const prevIndex = (i - 1 + points.length) % points.length;\n const nextIndex = (i + 1) % points.length;\n\n const prevPoint = points[prevIndex];\n const currentPoint = points[i];\n const nextPoint = points[nextIndex];\n\n const roundedCorner = calculateRoundedCorner(\n prevPoint,\n currentPoint,\n nextPoint,\n actualRadius,\n );\n\n roundedCorners.push(roundedCorner);\n }\n\n return roundedCorners;\n}\n\n/**\n * Render a rounded polygon to a canvas context\n */\nexport function renderRoundedPolygon(\n ctx: CanvasRenderingContext2D,\n roundedCorners: RoundedCornerPoint[],\n closed = true,\n) {\n if (roundedCorners.length === 0) return;\n\n ctx.beginPath();\n\n // Start at the first corner's start point\n const firstCorner = roundedCorners[0];\n ctx.moveTo(firstCorner.start.x, firstCorner.start.y);\n\n for (let i = 0; i < roundedCorners.length; i++) {\n const corner = roundedCorners[i];\n const nextIndex = (i + 1) % roundedCorners.length;\n const nextCorner = roundedCorners[nextIndex];\n\n // Draw the rounded corner using bezier curve\n ctx.bezierCurveTo(\n corner.cp1.x,\n corner.cp1.y,\n corner.cp2.x,\n corner.cp2.y,\n corner.end.x,\n corner.end.y,\n );\n\n // Draw line to next corner's start point (if not the last segment in open path)\n if (i < roundedCorners.length - 1 || closed) {\n ctx.lineTo(nextCorner.start.x, nextCorner.start.y);\n }\n }\n\n if (closed) {\n ctx.closePath();\n }\n}\n\n/**\n * Generate SVG path data for a rounded polygon\n */\nexport function generateRoundedPolygonPath(\n roundedCorners: RoundedCornerPoint[],\n closed = true,\n): string {\n if (roundedCorners.length === 0) return '';\n\n const pathData: string[] = [];\n const firstCorner = roundedCorners[0];\n\n // Move to first corner's start point\n pathData.push(`M ${firstCorner.start.x} ${firstCorner.start.y}`);\n\n for (let i = 0; i < roundedCorners.length; i++) {\n const corner = roundedCorners[i];\n const nextIndex = (i + 1) % roundedCorners.length;\n const nextCorner = roundedCorners[nextIndex];\n\n // Add bezier curve for the rounded corner\n pathData.push(\n `C ${corner.cp1.x} ${corner.cp1.y} ${corner.cp2.x} ${corner.cp2.y} ${corner.end.x} ${corner.end.y}`,\n );\n\n // Add line to next corner's start point (if not the last segment in open path)\n if (i < roundedCorners.length - 1 || closed) {\n pathData.push(`L ${nextCorner.start.x} ${nextCorner.start.y}`);\n }\n }\n\n if (closed) {\n pathData.push('Z');\n }\n\n return pathData.join(' ');\n}"],"names":["pointDistance","p1","p2","Math","sqrt","pow","x","y","normalizeVector","vector","length","getMaxRadius","prevPoint","currentPoint","nextPoint","dist1","dist2","min","calculateRoundedCorner","radius","edge1","edge2","norm1","norm2","maxRadius","actualRadius","startPoint","endPoint","controlOffset","kRect","corner","start","end","cp1","cp2","applyCornerRadiusToPolygon","points","radiusAsPercentage","arguments","undefined","Error","minX","map","p","maxX","max","minY","width","height","roundedCorners","i","prevIndex","nextIndex","roundedCorner","push","renderRoundedPolygon","ctx","closed","beginPath","firstCorner","moveTo","nextCorner","bezierCurveTo","lineTo","closePath","generateRoundedPolygonPath","pathData","join"],"mappings":"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"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { kRect } from '../../constants.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Calculate the distance between two points
|
|
5
|
+
*/
|
|
6
|
+
function pointDistance(p1, p2) {
|
|
7
|
+
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Normalize a vector
|
|
12
|
+
*/
|
|
13
|
+
function normalizeVector(vector) {
|
|
14
|
+
const length = Math.sqrt(vector.x * vector.x + vector.y * vector.y);
|
|
15
|
+
if (length === 0) return {
|
|
16
|
+
x: 0,
|
|
17
|
+
y: 0
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
x: vector.x / length,
|
|
21
|
+
y: vector.y / length
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the maximum allowed radius for a corner based on adjacent edge lengths
|
|
27
|
+
*/
|
|
28
|
+
function getMaxRadius(prevPoint, currentPoint, nextPoint) {
|
|
29
|
+
const dist1 = pointDistance(prevPoint, currentPoint);
|
|
30
|
+
const dist2 = pointDistance(currentPoint, nextPoint);
|
|
31
|
+
return Math.min(dist1, dist2) / 2;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Calculate rounded corner data for a single corner
|
|
36
|
+
*/
|
|
37
|
+
function calculateRoundedCorner(prevPoint, currentPoint, nextPoint, radius) {
|
|
38
|
+
// Calculate edge vectors
|
|
39
|
+
const edge1 = {
|
|
40
|
+
x: currentPoint.x - prevPoint.x,
|
|
41
|
+
y: currentPoint.y - prevPoint.y
|
|
42
|
+
};
|
|
43
|
+
const edge2 = {
|
|
44
|
+
x: nextPoint.x - currentPoint.x,
|
|
45
|
+
y: nextPoint.y - currentPoint.y
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Normalize edge vectors
|
|
49
|
+
const norm1 = normalizeVector(edge1);
|
|
50
|
+
const norm2 = normalizeVector(edge2);
|
|
51
|
+
|
|
52
|
+
// Calculate the maximum allowed radius
|
|
53
|
+
const maxRadius = getMaxRadius(prevPoint, currentPoint, nextPoint);
|
|
54
|
+
const actualRadius = Math.min(radius, maxRadius);
|
|
55
|
+
|
|
56
|
+
// Calculate start and end points of the rounded corner
|
|
57
|
+
const startPoint = {
|
|
58
|
+
x: currentPoint.x - norm1.x * actualRadius,
|
|
59
|
+
y: currentPoint.y - norm1.y * actualRadius
|
|
60
|
+
};
|
|
61
|
+
const endPoint = {
|
|
62
|
+
x: currentPoint.x + norm2.x * actualRadius,
|
|
63
|
+
y: currentPoint.y + norm2.y * actualRadius
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Calculate control points for bezier curve
|
|
67
|
+
// Using the magic number kRect for optimal circular approximation
|
|
68
|
+
const controlOffset = actualRadius * kRect;
|
|
69
|
+
const cp1 = {
|
|
70
|
+
x: startPoint.x + norm1.x * controlOffset,
|
|
71
|
+
y: startPoint.y + norm1.y * controlOffset
|
|
72
|
+
};
|
|
73
|
+
const cp2 = {
|
|
74
|
+
x: endPoint.x - norm2.x * controlOffset,
|
|
75
|
+
y: endPoint.y - norm2.y * controlOffset
|
|
76
|
+
};
|
|
77
|
+
return {
|
|
78
|
+
corner: currentPoint,
|
|
79
|
+
start: startPoint,
|
|
80
|
+
end: endPoint,
|
|
81
|
+
cp1,
|
|
82
|
+
cp2,
|
|
83
|
+
actualRadius
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Apply corner radius to a polygon defined by points
|
|
89
|
+
*/
|
|
90
|
+
function applyCornerRadiusToPolygon(points, radius) {
|
|
91
|
+
let radiusAsPercentage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
92
|
+
if (points.length < 3) {
|
|
93
|
+
throw new Error('Polygon must have at least 3 points');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Calculate bounding box if radius is percentage-based
|
|
97
|
+
let actualRadius = radius;
|
|
98
|
+
if (radiusAsPercentage) {
|
|
99
|
+
const minX = Math.min(...points.map(p => p.x));
|
|
100
|
+
const maxX = Math.max(...points.map(p => p.x));
|
|
101
|
+
const minY = Math.min(...points.map(p => p.y));
|
|
102
|
+
const maxY = Math.max(...points.map(p => p.y));
|
|
103
|
+
const width = maxX - minX;
|
|
104
|
+
const height = maxY - minY;
|
|
105
|
+
const minDimension = Math.min(width, height);
|
|
106
|
+
actualRadius = radius / 100 * minDimension;
|
|
107
|
+
}
|
|
108
|
+
const roundedCorners = [];
|
|
109
|
+
for (let i = 0; i < points.length; i++) {
|
|
110
|
+
const prevIndex = (i - 1 + points.length) % points.length;
|
|
111
|
+
const nextIndex = (i + 1) % points.length;
|
|
112
|
+
const prevPoint = points[prevIndex];
|
|
113
|
+
const currentPoint = points[i];
|
|
114
|
+
const nextPoint = points[nextIndex];
|
|
115
|
+
const roundedCorner = calculateRoundedCorner(prevPoint, currentPoint, nextPoint, actualRadius);
|
|
116
|
+
roundedCorners.push(roundedCorner);
|
|
117
|
+
}
|
|
118
|
+
return roundedCorners;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Render a rounded polygon to a canvas context
|
|
123
|
+
*/
|
|
124
|
+
function renderRoundedPolygon(ctx, roundedCorners) {
|
|
125
|
+
let closed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
126
|
+
if (roundedCorners.length === 0) return;
|
|
127
|
+
ctx.beginPath();
|
|
128
|
+
|
|
129
|
+
// Start at the first corner's start point
|
|
130
|
+
const firstCorner = roundedCorners[0];
|
|
131
|
+
ctx.moveTo(firstCorner.start.x, firstCorner.start.y);
|
|
132
|
+
for (let i = 0; i < roundedCorners.length; i++) {
|
|
133
|
+
const corner = roundedCorners[i];
|
|
134
|
+
const nextIndex = (i + 1) % roundedCorners.length;
|
|
135
|
+
const nextCorner = roundedCorners[nextIndex];
|
|
136
|
+
|
|
137
|
+
// Draw the rounded corner using bezier curve
|
|
138
|
+
ctx.bezierCurveTo(corner.cp1.x, corner.cp1.y, corner.cp2.x, corner.cp2.y, corner.end.x, corner.end.y);
|
|
139
|
+
|
|
140
|
+
// Draw line to next corner's start point (if not the last segment in open path)
|
|
141
|
+
if (i < roundedCorners.length - 1 || closed) {
|
|
142
|
+
ctx.lineTo(nextCorner.start.x, nextCorner.start.y);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (closed) {
|
|
146
|
+
ctx.closePath();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Generate SVG path data for a rounded polygon
|
|
152
|
+
*/
|
|
153
|
+
function generateRoundedPolygonPath(roundedCorners) {
|
|
154
|
+
let closed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
155
|
+
if (roundedCorners.length === 0) return '';
|
|
156
|
+
const pathData = [];
|
|
157
|
+
const firstCorner = roundedCorners[0];
|
|
158
|
+
|
|
159
|
+
// Move to first corner's start point
|
|
160
|
+
pathData.push(`M ${firstCorner.start.x} ${firstCorner.start.y}`);
|
|
161
|
+
for (let i = 0; i < roundedCorners.length; i++) {
|
|
162
|
+
const corner = roundedCorners[i];
|
|
163
|
+
const nextIndex = (i + 1) % roundedCorners.length;
|
|
164
|
+
const nextCorner = roundedCorners[nextIndex];
|
|
165
|
+
|
|
166
|
+
// Add bezier curve for the rounded corner
|
|
167
|
+
pathData.push(`C ${corner.cp1.x} ${corner.cp1.y} ${corner.cp2.x} ${corner.cp2.y} ${corner.end.x} ${corner.end.y}`);
|
|
168
|
+
|
|
169
|
+
// Add line to next corner's start point (if not the last segment in open path)
|
|
170
|
+
if (i < roundedCorners.length - 1 || closed) {
|
|
171
|
+
pathData.push(`L ${nextCorner.start.x} ${nextCorner.start.y}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (closed) {
|
|
175
|
+
pathData.push('Z');
|
|
176
|
+
}
|
|
177
|
+
return pathData.join(' ');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export { applyCornerRadiusToPolygon, calculateRoundedCorner, generateRoundedPolygonPath, getMaxRadius, normalizeVector, pointDistance, renderRoundedPolygon };
|
|
181
|
+
//# sourceMappingURL=cornerRadius.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cornerRadius.mjs","sources":["../../../../src/util/misc/cornerRadius.ts"],"sourcesContent":["import type { XY } from '../../Point';\nimport { Point } from '../../Point';\nimport { kRect } from '../../constants';\n\nexport interface CornerRadiusOptions {\n /**\n * Corner radius value\n */\n radius: number;\n /**\n * Whether to apply radius as percentage of the smallest dimension\n */\n radiusAsPercentage?: boolean;\n}\n\nexport interface RoundedCornerPoint {\n /**\n * Original corner point\n */\n corner: XY;\n /**\n * Start point of the rounded corner arc\n */\n start: XY;\n /**\n * End point of the rounded corner arc\n */\n end: XY;\n /**\n * First control point for bezier curve\n */\n cp1: XY;\n /**\n * Second control point for bezier curve\n */\n cp2: XY;\n /**\n * Actual radius used (may be different from requested if constrained)\n */\n actualRadius: number;\n}\n\n/**\n * Calculate the distance between two points\n */\nexport function pointDistance(p1: XY, p2: XY): number {\n return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));\n}\n\n/**\n * Normalize a vector\n */\nexport function normalizeVector(vector: XY): XY {\n const length = Math.sqrt(vector.x * vector.x + vector.y * vector.y);\n if (length === 0) return { x: 0, y: 0 };\n return { x: vector.x / length, y: vector.y / length };\n}\n\n/**\n * Calculate the angle between two vectors\n */\nexport function angleBetweenVectors(v1: XY, v2: XY): number {\n const dot = v1.x * v2.x + v1.y * v2.y;\n const det = v1.x * v2.y - v1.y * v2.x;\n return Math.atan2(det, dot);\n}\n\n/**\n * Get the maximum allowed radius for a corner based on adjacent edge lengths\n */\nexport function getMaxRadius(\n prevPoint: XY,\n currentPoint: XY,\n nextPoint: XY,\n): number {\n const dist1 = pointDistance(prevPoint, currentPoint);\n const dist2 = pointDistance(currentPoint, nextPoint);\n return Math.min(dist1, dist2) / 2;\n}\n\n/**\n * Calculate rounded corner data for a single corner\n */\nexport function calculateRoundedCorner(\n prevPoint: XY,\n currentPoint: XY,\n nextPoint: XY,\n radius: number,\n): RoundedCornerPoint {\n // Calculate edge vectors\n const edge1 = {\n x: currentPoint.x - prevPoint.x,\n y: currentPoint.y - prevPoint.y,\n };\n const edge2 = {\n x: nextPoint.x - currentPoint.x,\n y: nextPoint.y - currentPoint.y,\n };\n\n // Normalize edge vectors\n const norm1 = normalizeVector(edge1);\n const norm2 = normalizeVector(edge2);\n\n // Calculate the maximum allowed radius\n const maxRadius = getMaxRadius(prevPoint, currentPoint, nextPoint);\n const actualRadius = Math.min(radius, maxRadius);\n\n // Calculate start and end points of the rounded corner\n const startPoint = {\n x: currentPoint.x - norm1.x * actualRadius,\n y: currentPoint.y - norm1.y * actualRadius,\n };\n\n const endPoint = {\n x: currentPoint.x + norm2.x * actualRadius,\n y: currentPoint.y + norm2.y * actualRadius,\n };\n\n // Calculate control points for bezier curve\n // Using the magic number kRect for optimal circular approximation\n const controlOffset = actualRadius * kRect;\n\n const cp1 = {\n x: startPoint.x + norm1.x * controlOffset,\n y: startPoint.y + norm1.y * controlOffset,\n };\n\n const cp2 = {\n x: endPoint.x - norm2.x * controlOffset,\n y: endPoint.y - norm2.y * controlOffset,\n };\n\n return {\n corner: currentPoint,\n start: startPoint,\n end: endPoint,\n cp1,\n cp2,\n actualRadius,\n };\n}\n\n/**\n * Apply corner radius to a polygon defined by points\n */\nexport function applyCornerRadiusToPolygon(\n points: XY[],\n radius: number,\n radiusAsPercentage = false,\n): RoundedCornerPoint[] {\n if (points.length < 3) {\n throw new Error('Polygon must have at least 3 points');\n }\n\n // Calculate bounding box if radius is percentage-based\n let actualRadius = radius;\n if (radiusAsPercentage) {\n const minX = Math.min(...points.map((p) => p.x));\n const maxX = Math.max(...points.map((p) => p.x));\n const minY = Math.min(...points.map((p) => p.y));\n const maxY = Math.max(...points.map((p) => p.y));\n const width = maxX - minX;\n const height = maxY - minY;\n const minDimension = Math.min(width, height);\n actualRadius = (radius / 100) * minDimension;\n }\n\n const roundedCorners: RoundedCornerPoint[] = [];\n\n for (let i = 0; i < points.length; i++) {\n const prevIndex = (i - 1 + points.length) % points.length;\n const nextIndex = (i + 1) % points.length;\n\n const prevPoint = points[prevIndex];\n const currentPoint = points[i];\n const nextPoint = points[nextIndex];\n\n const roundedCorner = calculateRoundedCorner(\n prevPoint,\n currentPoint,\n nextPoint,\n actualRadius,\n );\n\n roundedCorners.push(roundedCorner);\n }\n\n return roundedCorners;\n}\n\n/**\n * Render a rounded polygon to a canvas context\n */\nexport function renderRoundedPolygon(\n ctx: CanvasRenderingContext2D,\n roundedCorners: RoundedCornerPoint[],\n closed = true,\n) {\n if (roundedCorners.length === 0) return;\n\n ctx.beginPath();\n\n // Start at the first corner's start point\n const firstCorner = roundedCorners[0];\n ctx.moveTo(firstCorner.start.x, firstCorner.start.y);\n\n for (let i = 0; i < roundedCorners.length; i++) {\n const corner = roundedCorners[i];\n const nextIndex = (i + 1) % roundedCorners.length;\n const nextCorner = roundedCorners[nextIndex];\n\n // Draw the rounded corner using bezier curve\n ctx.bezierCurveTo(\n corner.cp1.x,\n corner.cp1.y,\n corner.cp2.x,\n corner.cp2.y,\n corner.end.x,\n corner.end.y,\n );\n\n // Draw line to next corner's start point (if not the last segment in open path)\n if (i < roundedCorners.length - 1 || closed) {\n ctx.lineTo(nextCorner.start.x, nextCorner.start.y);\n }\n }\n\n if (closed) {\n ctx.closePath();\n }\n}\n\n/**\n * Generate SVG path data for a rounded polygon\n */\nexport function generateRoundedPolygonPath(\n roundedCorners: RoundedCornerPoint[],\n closed = true,\n): string {\n if (roundedCorners.length === 0) return '';\n\n const pathData: string[] = [];\n const firstCorner = roundedCorners[0];\n\n // Move to first corner's start point\n pathData.push(`M ${firstCorner.start.x} ${firstCorner.start.y}`);\n\n for (let i = 0; i < roundedCorners.length; i++) {\n const corner = roundedCorners[i];\n const nextIndex = (i + 1) % roundedCorners.length;\n const nextCorner = roundedCorners[nextIndex];\n\n // Add bezier curve for the rounded corner\n pathData.push(\n `C ${corner.cp1.x} ${corner.cp1.y} ${corner.cp2.x} ${corner.cp2.y} ${corner.end.x} ${corner.end.y}`,\n );\n\n // Add line to next corner's start point (if not the last segment in open path)\n if (i < roundedCorners.length - 1 || closed) {\n pathData.push(`L ${nextCorner.start.x} ${nextCorner.start.y}`);\n }\n }\n\n if (closed) {\n pathData.push('Z');\n }\n\n return pathData.join(' ');\n}"],"names":["pointDistance","p1","p2","Math","sqrt","pow","x","y","normalizeVector","vector","length","getMaxRadius","prevPoint","currentPoint","nextPoint","dist1","dist2","min","calculateRoundedCorner","radius","edge1","edge2","norm1","norm2","maxRadius","actualRadius","startPoint","endPoint","controlOffset","kRect","cp1","cp2","corner","start","end","applyCornerRadiusToPolygon","points","radiusAsPercentage","arguments","undefined","Error","minX","map","p","maxX","max","minY","maxY","width","height","minDimension","roundedCorners","i","prevIndex","nextIndex","roundedCorner","push","renderRoundedPolygon","ctx","closed","beginPath","firstCorner","moveTo","nextCorner","bezierCurveTo","lineTo","closePath","generateRoundedPolygonPath","pathData","join"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Polyline, SerializedPolylineProps } from './Polyline';
|
|
2
|
+
import type { FabricObjectProps } from './Object/types';
|
|
3
|
+
import type { TOptions } from '../typedefs';
|
|
4
|
+
import type { ObjectEvents } from '../EventTypeDefs';
|
|
5
|
+
export declare class CustomLine<Props extends TOptions<FabricObjectProps> = Partial<FabricObjectProps>, SProps extends SerializedPolylineProps = SerializedPolylineProps, EventSpec extends ObjectEvents = ObjectEvents> extends Polyline<Props, SProps, EventSpec> {
|
|
6
|
+
static type: string;
|
|
7
|
+
constructor(points?: [number, number, number, number], options?: Props);
|
|
8
|
+
static fromObject<T extends TOptions<SerializedPolylineProps>>(object: T): Promise<CustomLine<Partial<FabricObjectProps>, SerializedPolylineProps, ObjectEvents>>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=CustomLine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CustomLine.d.ts","sourceRoot":"","sources":["../../../src/shapes/CustomLine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,qBAAa,UAAU,CACrB,KAAK,SAAS,QAAQ,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,EACtE,MAAM,SAAS,uBAAuB,GAAG,uBAAuB,EAChE,SAAS,SAAS,YAAY,GAAG,YAAY,CAC7C,SAAQ,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC;IAC1C,MAAM,CAAC,IAAI,SAAgB;gBAGzB,MAAM,GAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAgB,EACvD,OAAO,GAAE,KAAmB;IAU9B,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;CAwBzE"}
|