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.
@@ -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 (legacy[variant]?.[cp] !== undefined) return legacy[variant][cp];
62
- const r = ranges[variant];
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 = {bold:0x1d6a8, italic:0x1d6e2, 'bold-italic':0x1d71c, 'sans-serif-bold':0x1d756, 'sans-serif-bold-italic':0x1d790}[variant];
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 = [0x2207,0x2202,0x3f5,0x3d1,0x3f0,0x3d5,0x3f1,0x3d6].indexOf(cp);
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*mathScale(c):Infinity,
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.glyphs[id], s = mathScale(c) / MATH_FONT.units, stroke = mathScreenStroke(c), radius = stroke / 2;
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(mathScale(c)) + '"' : '') +
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
- if ([...value].length !== 1) return mathText(value, c, extra);
102
- const cp = value.codePointAt(0), mapped = mathStyledCodePoint(cp, extra.variant || c.variant);
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.glyphs[b.glyph], unit = b.unitScale, x = -g[1] * unit;
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.glyphs[natural.glyph],unit=natural.unitScale,added=target-natural.w,
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.glyphs[b.glyph];
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
- const profile = MATH_FONT.edgeProfiles[box.glyph];
277
- if (!profile || !box.unitScale || box.extended) return null;
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,7 +1,7 @@
1
1
  {
2
2
  "name": "rapier-math-source",
3
3
  "private": true,
4
- "version": "1.0.1",
4
+ "version": "1.0.2",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "build": "node tools/build-math.mjs"
@@ -1,16 +1,16 @@
1
1
  {
2
- "bundle": "rapier-math-1.0.1.js",
3
- "version": "1.0.1",
2
+ "bundle": "rapier-math-1.0.2.js",
3
+ "version": "1.0.2",
4
4
  "license": "MIT AND LicenseRef-GUST-Font-License",
5
- "bytes": 803451,
6
- "gzipBytes": 496298,
7
- "sha256": "77640802b52935b60a66e2fd04c19d4702cee4b1a8b64aece5ca332236c09283",
8
- "sha384": "1kdn6mohx3a5MAiwqRWY+6oviUHUheHfY1VMsxjDsUrn7woTaa7FSKo4juYtuNaF",
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": 651457,
13
- "sha256": "b697b5ba770e35904fe56a0aa6c2f748253b3d3c5b9ab39c68f4a25afae02a0d"
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": 37394,
28
- "sha256": "37cd00667aa1c7ef8b375c5e62171b1a7ceef53490cd13c8a77201e7ea6b13e8"
27
+ "bytes": 37583,
28
+ "sha256": "04c6d931b4c81495adb8bfdfa70093625cde4faf5aa16a4cb3baf84e9106c4e8"
29
29
  },
30
30
  {
31
31
  "file": "math/fallbacks.js",
32
- "bytes": 7958,
33
- "sha256": "a59c9a32f4a1ea49ad7454ea48aa25489e8e786459055d91fef045b8cc2b5f4b"
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": 8363,
43
- "sha256": "0bf9fc6c5f02c2b0c5012118b80a8fad337fe25c3a4557e2747d4d4caa5c2e1b"
42
+ "bytes": 9598,
43
+ "sha256": "fe55a2ffe969f9f2b30fe20357e85089afbd41ecfa983222131ec06855f1f2e8"
44
44
  },
45
45
  {
46
46
  "file": "math/api.js",
47
- "bytes": 5825,
48
- "sha256": "f05bc69c0e13230079526a98072a2ae8ffd58bfb2df2aecb0e2f26fdb43dbeb6"
47
+ "bytes": 5857,
48
+ "sha256": "52b34c348f4cd30bf3a7f2805a37d347ea9aa668a8abb2dc0b799fe749bf8ee1"
49
49
  }
50
50
  ],
51
51
  "recipe": [
52
52
  {
53
53
  "file": "math/build-font.py",
54
- "bytes": 24804,
55
- "sha256": "83f27e773d451a7275f6b7d521a257f79c27b3c61452a869703fe44c4ca8b878"
54
+ "bytes": 33369,
55
+ "sha256": "d54dba7b83d945da4bdeeac6a262c45d0b8f531c0801114451ac3f3d8dab9d35"
56
56
  },
57
57
  {
58
58
  "file": "math/FONT-SOURCE.md",
59
- "bytes": 8095,
60
- "sha256": "05e0bba9e9bf340029c8bcc97492c17958949533717a62644505846905e65499"
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": 5795,
75
- "sha256": "7f8582f07832c2c2a50b0b6b552df3819e8e246f8aa7857e409d443b79d463f4"
74
+ "bytes": 6012,
75
+ "sha256": "5698ec3e5aaa6a3ad833ceb240a851c0447d23ebf80455e95ef7003aa6287342"
76
76
  },
77
77
  {
78
78
  "file": "math/LICENSE-MIT",
@@ -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.1';
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
- await writeFile(loaderPath, loader.replace(block, (_, before, middle, after) => before + bytes.length + middle + sha384 + after));
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
  }