rapier-math 1.0.1 → 1.0.2
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/README.md +4 -4
- package/index.mjs +164 -95
- package/math-components.json +6 -6
- package/package.json +3 -3
- package/rapier-math-1.0.2.js +2952 -0
- package/src/math/FONT-SOURCE.md +32 -6
- package/src/math/api.js +4 -3
- package/src/math/browser.js +60 -29
- package/src/math/build-font.py +237 -95
- package/src/math/fallbacks.js +5 -5
- package/src/math/font.js +59 -26
- package/src/math/layout.js +36 -32
- package/src/package.json +1 -1
- package/src/shell/math-resources.json +22 -22
- package/src/tools/build-math.mjs +5 -2
- package/rapier-math-1.0.1.js +0 -2883
package/src/math/layout.js
CHANGED
|
@@ -13,9 +13,9 @@ function mathScale(c) {
|
|
|
13
13
|
return c.size * (c.screen ? Math.max(scale, Math.min(1, (c.level === 1 ? 12 : 10) / c.screen.fontSize)) : scale);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
function mathScreenStroke(c) {
|
|
16
|
+
function mathScreenStroke(c, scale) {
|
|
17
17
|
if (!c.screen) return 0;
|
|
18
|
-
const {fontSize, pixelRatio, dark} = c.screen, size = fontSize * mathScale(c);
|
|
18
|
+
const {fontSize, pixelRatio, dark} = c.screen, size = fontSize * (scale ?? mathScale(c));
|
|
19
19
|
if (!(size > 0)) return 0;
|
|
20
20
|
const small = Math.max(0, Math.min(1, (32 - size) / 16));
|
|
21
21
|
const hairline = MATH_FONT.constants.FractionRuleThickness / MATH_FONT.units * size;
|
|
@@ -41,35 +41,37 @@ function mathCompose(items, width, extra = {}) {
|
|
|
41
41
|
return mathBox(width, h, d, svg, {left, right, inkTop:Number.isFinite(inkTop)?inkTop:-h, inkBottom:Number.isFinite(inkBottom)?inkBottom:d,...glyph,...extra});
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
const MATH_STYLED_RANGES = {
|
|
45
|
+
italic: [0x1d434, 0x1d44e, null], bold: [0x1d400, 0x1d41a, 0x1d7ce],
|
|
46
|
+
'bold-italic': [0x1d468, 0x1d482, null], script: [0x1d49c, 0x1d4b6, null],
|
|
47
|
+
'bold-script': [0x1d4d0, 0x1d4ea, null], fraktur: [0x1d504, 0x1d51e, null],
|
|
48
|
+
'bold-fraktur': [0x1d56c, 0x1d586, null], 'double-struck': [0x1d538, 0x1d552, 0x1d7d8],
|
|
49
|
+
'sans-serif': [0x1d5a0, 0x1d5ba, 0x1d7e2], 'sans-serif-bold': [0x1d5d4, 0x1d5ee, 0x1d7ec],
|
|
50
|
+
'sans-serif-italic': [0x1d608, 0x1d622, null], 'sans-serif-bold-italic': [0x1d63c, 0x1d656, null],
|
|
51
|
+
monospace: [0x1d670, 0x1d68a, 0x1d7f6],
|
|
52
|
+
};
|
|
53
|
+
const MATH_STYLED_LEGACY = {
|
|
54
|
+
italic: {104: 0x210e},
|
|
55
|
+
script: {66:0x212c,69:0x2130,70:0x2131,72:0x210b,73:0x2110,76:0x2112,77:0x2133,82:0x211b,101:0x212f,103:0x210a,111:0x2134},
|
|
56
|
+
fraktur: {67:0x212d,72:0x210c,73:0x2111,82:0x211c,90:0x2128},
|
|
57
|
+
'double-struck': {67:0x2102,72:0x210d,78:0x2115,80:0x2119,81:0x211a,82:0x211d,90:0x2124},
|
|
58
|
+
};
|
|
59
|
+
const MATH_STYLED_GREEK = {bold:0x1d6a8, italic:0x1d6e2, 'bold-italic':0x1d71c, 'sans-serif-bold':0x1d756, 'sans-serif-bold-italic':0x1d790};
|
|
60
|
+
const MATH_STYLED_GREEK_SPECIAL = [0x2207,0x2202,0x3f5,0x3d1,0x3f0,0x3d5,0x3f1,0x3d6];
|
|
44
61
|
function mathStyledCodePoint(cp, variant) {
|
|
45
|
-
const ranges = {
|
|
46
|
-
italic: [0x1d434, 0x1d44e, null], bold: [0x1d400, 0x1d41a, 0x1d7ce],
|
|
47
|
-
'bold-italic': [0x1d468, 0x1d482, null], script: [0x1d49c, 0x1d4b6, null],
|
|
48
|
-
'bold-script': [0x1d4d0, 0x1d4ea, null], fraktur: [0x1d504, 0x1d51e, null],
|
|
49
|
-
'bold-fraktur': [0x1d56c, 0x1d586, null], 'double-struck': [0x1d538, 0x1d552, 0x1d7d8],
|
|
50
|
-
'sans-serif': [0x1d5a0, 0x1d5ba, 0x1d7e2], 'sans-serif-bold': [0x1d5d4, 0x1d5ee, 0x1d7ec],
|
|
51
|
-
'sans-serif-italic': [0x1d608, 0x1d622, null], 'sans-serif-bold-italic': [0x1d63c, 0x1d656, null],
|
|
52
|
-
monospace: [0x1d670, 0x1d68a, 0x1d7f6],
|
|
53
|
-
};
|
|
54
|
-
const legacy = {
|
|
55
|
-
italic: {104: 0x210e},
|
|
56
|
-
script: {66:0x212c,69:0x2130,70:0x2131,72:0x210b,73:0x2110,76:0x2112,77:0x2133,82:0x211b,101:0x212f,103:0x210a,111:0x2134},
|
|
57
|
-
fraktur: {67:0x212d,72:0x210c,73:0x2111,82:0x211c,90:0x2128},
|
|
58
|
-
'double-struck': {67:0x2102,72:0x210d,78:0x2115,80:0x2119,81:0x211a,82:0x211d,90:0x2124},
|
|
59
|
-
};
|
|
60
62
|
if (variant === 'normal') variant = 'italic';
|
|
61
|
-
if (
|
|
62
|
-
const r =
|
|
63
|
+
if (MATH_STYLED_LEGACY[variant]?.[cp] !== undefined) return MATH_STYLED_LEGACY[variant][cp];
|
|
64
|
+
const r = MATH_STYLED_RANGES[variant];
|
|
63
65
|
if (r) {
|
|
64
66
|
if (cp >= 65 && cp <= 90) return r[0] + cp - 65;
|
|
65
67
|
if (cp >= 97 && cp <= 122) return r[1] + cp - 97;
|
|
66
68
|
if (r[2] && cp >= 48 && cp <= 57) return r[2] + cp - 48;
|
|
67
69
|
}
|
|
68
|
-
const greek =
|
|
70
|
+
const greek = MATH_STYLED_GREEK[variant];
|
|
69
71
|
if (greek !== undefined) {
|
|
70
72
|
if (cp >= 0x391 && cp <= 0x3a9 && cp !== 0x3a2) return greek + cp - 0x391;
|
|
71
73
|
if (cp >= 0x3b1 && cp <= 0x3c9) return greek + 26 + cp - 0x3b1;
|
|
72
|
-
const special =
|
|
74
|
+
const special = MATH_STYLED_GREEK_SPECIAL.indexOf(cp);
|
|
73
75
|
if (special === 0) return greek + 25;
|
|
74
76
|
if (special > 0) return greek + 50 + special;
|
|
75
77
|
}
|
|
@@ -78,19 +80,19 @@ function mathStyledCodePoint(cp, variant) {
|
|
|
78
80
|
|
|
79
81
|
function mathGlyphIndex(id, c, extra = {}) {
|
|
80
82
|
if(c.dotless)id=MATH_FONT.dotless?.[id] ?? id;
|
|
81
|
-
const alternates=MATH_FONT.scriptAlternates[id];
|
|
82
|
-
const pixels=c.screen?c.screen.fontSize*
|
|
83
|
+
const alternates=MATH_FONT.scriptAlternates[id],scale=mathScale(c);
|
|
84
|
+
const pixels=c.screen?c.screen.fontSize*scale:Infinity,
|
|
83
85
|
optical=Math.max(c.level,pixels<10?2:pixels<15?1:0);
|
|
84
86
|
if(optical && alternates)id=alternates[Math.min(optical,alternates.length)-1];
|
|
85
87
|
if(c.flattenAccent)id=MATH_FONT.flatAccents[id] ?? id;
|
|
86
|
-
const g = MATH_FONT.
|
|
88
|
+
const g = MATH_FONT.glyph(id), s = scale / MATH_FONT.units, stroke = mathScreenStroke(c,scale), radius = stroke / 2;
|
|
87
89
|
if (!g) throw Object.assign(new Error('Unsupported mathematical glyph'), {code:'unsupported-glyph'});
|
|
88
90
|
if(c.budget) {
|
|
89
91
|
c.budget.outlineBytes=(c.budget.outlineBytes || 0)+g[7].length+96;
|
|
90
92
|
if(c.budget.outlineBytes>4*1024*1024)throw Object.assign(new Error('Mathematical outlines exceed the rendering budget'),{code:'resource-limit'});
|
|
91
93
|
}
|
|
92
94
|
const svg = g[7] ? '<path d="' + g[7] + '" transform="scale(' + mathNumber(s) + ' ' + mathNumber(-s) + ')"'+
|
|
93
|
-
(c.screen ? ' data-math-ink="' + mathNumber(
|
|
95
|
+
(c.screen ? ' data-math-ink="' + mathNumber(scale) + '"' : '') +
|
|
94
96
|
(stroke ? ' stroke="currentColor" stroke-width="' + mathNumber(stroke / s) + '" stroke-linejoin="round" paint-order="stroke fill"' : '') + '/>' : '';
|
|
95
97
|
return mathBox(g[0] * s, Math.max(0, g[4] * s + radius), Math.max(0, -g[2] * s + radius), svg,
|
|
96
98
|
{left: Math.min(0,g[1]*s-radius), right: Math.max(g[0]*s,g[3]*s+radius), inkTop:-g[4]*s-radius, inkBottom:-g[2]*s+radius, italic: g[5]*s, stroke,
|
|
@@ -98,8 +100,9 @@ function mathGlyphIndex(id, c, extra = {}) {
|
|
|
98
100
|
}
|
|
99
101
|
|
|
100
102
|
function mathGlyph(value, c, extra = {}) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
const cp = value.codePointAt(0);
|
|
104
|
+
if (value.length !== (cp > 0xffff ? 2 : 1)) return mathText(value, c, extra);
|
|
105
|
+
const mapped = mathStyledCodePoint(cp, extra.variant || c.variant);
|
|
103
106
|
const id = MATH_FONT.chars[mapped] ?? MATH_FONT.chars[cp];
|
|
104
107
|
if (id === undefined) {
|
|
105
108
|
const composed = mathFallbackGlyph(value, c, extra);
|
|
@@ -134,7 +137,7 @@ function mathStretch(value, target, c, horizontal = false) {
|
|
|
134
137
|
const shape = (glyph, advance) => {
|
|
135
138
|
const b = mathGlyphIndex(glyph,c);
|
|
136
139
|
if (!horizontal || b.w !== 0) return b;
|
|
137
|
-
const g = MATH_FONT.
|
|
140
|
+
const g = MATH_FONT.glyph(b.glyph), unit = b.unitScale, x = -g[1] * unit;
|
|
138
141
|
const width = (advance ?? g[3] - g[1]) * unit;
|
|
139
142
|
return mathCompose([[b,x,0]],width,{italic:b.italic,accent:b.accent+x});
|
|
140
143
|
};
|
|
@@ -150,7 +153,7 @@ function mathStretch(value, target, c, horizontal = false) {
|
|
|
150
153
|
// These font glyphs have straight central shafts but no MATH assembly.
|
|
151
154
|
// Preserve both end shapes and widen only a narrow central strip.
|
|
152
155
|
if('=⇌⇋↞↠→↔↦'.includes(value)) {
|
|
153
|
-
const g=MATH_FONT.
|
|
156
|
+
const g=MATH_FONT.glyph(natural.glyph),unit=natural.unitScale,added=target-natural.w,
|
|
154
157
|
split=g[0]*(value==='↞'?0.75:value==='↠'?0.25:0.5),half=g[0]*0.05,
|
|
155
158
|
left=split-half,right=split+half,delta=added/unit;
|
|
156
159
|
// The two-headed arrows have their plain shaft opposite both heads.
|
|
@@ -201,7 +204,7 @@ function mathStretch(value, target, c, horizontal = false) {
|
|
|
201
204
|
length=(full-overlap*connections.length)*unit;
|
|
202
205
|
const items=[]; let pos=0, width=0;
|
|
203
206
|
for (let i=0;i<pieces.length;i++) {
|
|
204
|
-
const p=pieces[i], b=mathGlyphIndex(p[0],c), g=MATH_FONT.
|
|
207
|
+
const p=pieces[i], b=mathGlyphIndex(p[0],c), g=MATH_FONT.glyph(b.glyph);
|
|
205
208
|
if (horizontal) items.push([b,pos,0]);
|
|
206
209
|
else items.push([b,0,-pos+g[2]*unit]);
|
|
207
210
|
width=Math.max(width,b.w);
|
|
@@ -273,8 +276,9 @@ function mathKern(b,corner,height) {
|
|
|
273
276
|
}
|
|
274
277
|
|
|
275
278
|
function mathContourBands(box, dy = 0) {
|
|
276
|
-
|
|
277
|
-
|
|
279
|
+
if (!box.unitScale || box.extended) return null;
|
|
280
|
+
const profile = MATH_FONT.profile(box.glyph);
|
|
281
|
+
if (!profile) return null;
|
|
278
282
|
const bands = [], step = MATH_FONT.edgeStep, unit = box.unitScale;
|
|
279
283
|
const x = box.glyphX || 0, y = (box.glyphY || 0) + dy, radius = (box.stroke || 0) / 2;
|
|
280
284
|
for (let i = profile.length - 1; i > 0; i--) if (profile[i]) {
|
package/src/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
-
"bundle": "rapier-math-1.0.
|
|
3
|
-
"version": "1.0.
|
|
2
|
+
"bundle": "rapier-math-1.0.2.js",
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"license": "MIT AND LicenseRef-GUST-Font-License",
|
|
5
|
-
"bytes":
|
|
6
|
-
"gzipBytes":
|
|
7
|
-
"sha256": "
|
|
8
|
-
"sha384": "
|
|
5
|
+
"bytes": 712164,
|
|
6
|
+
"gzipBytes": 441919,
|
|
7
|
+
"sha256": "55c326429ed51564670c67fb4e35eddbe4115fb077440146e4fbb5f81a247f9a",
|
|
8
|
+
"sha384": "Pg2MvS4Eg4s41yUZiSPn+TCRuA4gM3JHxxbCEkuSFyHgC+t143Iv48n8P4XlkE23",
|
|
9
9
|
"sources": [
|
|
10
10
|
{
|
|
11
11
|
"file": "math/font.js",
|
|
12
|
-
"bytes":
|
|
13
|
-
"sha256": "
|
|
12
|
+
"bytes": 558719,
|
|
13
|
+
"sha256": "1263135501cb049efb087975db43c0fa6d131e5deee4282d982995d4ab0884c4"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"file": "math/symbols.js",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"file": "math/layout.js",
|
|
27
|
-
"bytes":
|
|
28
|
-
"sha256": "
|
|
27
|
+
"bytes": 37583,
|
|
28
|
+
"sha256": "04c6d931b4c81495adb8bfdfa70093625cde4faf5aa16a4cb3baf84e9106c4e8"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"file": "math/fallbacks.js",
|
|
32
|
-
"bytes":
|
|
33
|
-
"sha256": "
|
|
32
|
+
"bytes": 7953,
|
|
33
|
+
"sha256": "400c5771756d5a4d4cf431d471b33c280791ce4aa276a0fd2615d91ee88ae8ce"
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"file": "math/responsive.js",
|
|
@@ -39,25 +39,25 @@
|
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"file": "math/browser.js",
|
|
42
|
-
"bytes":
|
|
43
|
-
"sha256": "
|
|
42
|
+
"bytes": 9598,
|
|
43
|
+
"sha256": "fe55a2ffe969f9f2b30fe20357e85089afbd41ecfa983222131ec06855f1f2e8"
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
"file": "math/api.js",
|
|
47
|
-
"bytes":
|
|
48
|
-
"sha256": "
|
|
47
|
+
"bytes": 5857,
|
|
48
|
+
"sha256": "52b34c348f4cd30bf3a7f2805a37d347ea9aa668a8abb2dc0b799fe749bf8ee1"
|
|
49
49
|
}
|
|
50
50
|
],
|
|
51
51
|
"recipe": [
|
|
52
52
|
{
|
|
53
53
|
"file": "math/build-font.py",
|
|
54
|
-
"bytes":
|
|
55
|
-
"sha256": "
|
|
54
|
+
"bytes": 33369,
|
|
55
|
+
"sha256": "d54dba7b83d945da4bdeeac6a262c45d0b8f531c0801114451ac3f3d8dab9d35"
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"file": "math/FONT-SOURCE.md",
|
|
59
|
-
"bytes":
|
|
60
|
-
"sha256": "
|
|
59
|
+
"bytes": 10357,
|
|
60
|
+
"sha256": "84ab319b1f9342fa08b421231965dd685063d8fd6bb8a071e1f1c186848dcdd9"
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
"file": "math/FONT-LICENSE.txt",
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"file": "tools/build-math.mjs",
|
|
74
|
-
"bytes":
|
|
75
|
-
"sha256": "
|
|
74
|
+
"bytes": 6012,
|
|
75
|
+
"sha256": "5698ec3e5aaa6a3ad833ceb240a851c0447d23ebf80455e95ef7003aa6287342"
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
"file": "math/LICENSE-MIT",
|
package/src/tools/build-math.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import {gzipSync} from 'node:zlib';
|
|
|
9
9
|
import {Script} from 'node:vm';
|
|
10
10
|
|
|
11
11
|
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
12
|
-
export const MATH_VERSION = '1.0.
|
|
12
|
+
export const MATH_VERSION = '1.0.2';
|
|
13
13
|
export const MATH_BUNDLE = 'rapier-math-' + MATH_VERSION + '.js';
|
|
14
14
|
export const MATH_SOURCES = ['font.js', 'symbols.js', 'parser.js', 'layout.js', 'fallbacks.js', 'responsive.js', 'browser.js', 'api.js'].map(name => 'math/' + name);
|
|
15
15
|
export const MATH_RECIPE = ['math/build-font.py', 'math/FONT-SOURCE.md', 'math/FONT-LICENSE.txt', 'math/package-verify.mjs', 'tools/build-math.mjs', 'math/LICENSE-MIT'];
|
|
@@ -82,7 +82,10 @@ export async function buildMath({root = ROOT, updatePins = true} = {}) {
|
|
|
82
82
|
const loader = await readFile(loaderPath, 'utf8');
|
|
83
83
|
const block = /(key: 'math',[\s\S]*?bytes: )\d+(,[\s\S]*?sri: ')[^']+(')/;
|
|
84
84
|
if (!block.test(loader)) throw new Error('The math loader pin could not be located');
|
|
85
|
-
|
|
85
|
+
const version = /var MATH_VERSION = '[^']+';/;
|
|
86
|
+
if (!version.test(loader)) throw new Error('The math loader version could not be located');
|
|
87
|
+
await writeFile(loaderPath, loader.replace(version, "var MATH_VERSION = '" + MATH_VERSION + "';")
|
|
88
|
+
.replace(block, (_, before, middle, after) => before + bytes.length + middle + sha384 + after));
|
|
86
89
|
}
|
|
87
90
|
return {bundle: MATH_BUNDLE, bytes: bytes.length, gzipBytes, sha256, sha384};
|
|
88
91
|
}
|