pdf-parser.js 5.2.26 → 5.2.28

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.
Files changed (221) hide show
  1. package/dist/{afm-widths-BYiX2L9D.cjs → afm-widths-BHD2HZIL.cjs} +553 -642
  2. package/dist/{afm-widths-blUDDjlI.js → afm-widths-B_IGbGky.js} +553 -642
  3. package/dist/afm-widths.cjs +1 -1
  4. package/dist/afm-widths.js +1 -1
  5. package/dist/annotations.cjs +5 -3
  6. package/dist/annotations.d.cts +2 -2
  7. package/dist/annotations.d.ts +2 -2
  8. package/dist/annotations.js +5 -3
  9. package/dist/attachments.d.cts +2 -2
  10. package/dist/attachments.d.ts +2 -2
  11. package/dist/builtin-encoding.cjs +17 -6
  12. package/dist/builtin-encoding.js +17 -6
  13. package/dist/bytes/crc32.cjs +5 -3
  14. package/dist/bytes/crc32.js +5 -3
  15. package/dist/bytes/flate.cjs +0 -1
  16. package/dist/bytes/flate.js +0 -1
  17. package/dist/cff-bounds.cjs +73 -45
  18. package/dist/cff-bounds.js +73 -45
  19. package/dist/cff.cjs +13 -6
  20. package/dist/cff.js +13 -6
  21. package/dist/cmap-table.cjs +54 -26
  22. package/dist/cmap-table.js +54 -26
  23. package/dist/cmap.cjs +5 -3
  24. package/dist/cmap.js +5 -3
  25. package/dist/content-read.d.cts +1 -1
  26. package/dist/content-read.d.ts +1 -1
  27. package/dist/content-write.cjs +21 -14
  28. package/dist/content-write.d.cts +2 -2
  29. package/dist/content-write.d.ts +2 -2
  30. package/dist/content-write.js +21 -14
  31. package/dist/crypto/aes.cjs +76 -55
  32. package/dist/crypto/aes.js +76 -55
  33. package/dist/crypto/md5.cjs +345 -149
  34. package/dist/crypto/md5.js +345 -149
  35. package/dist/crypto/rc4.cjs +5 -4
  36. package/dist/crypto/rc4.js +5 -4
  37. package/dist/crypto/sha2.cjs +92 -43
  38. package/dist/crypto/sha2.js +92 -43
  39. package/dist/document.cjs +17 -11
  40. package/dist/document.d.cts +1 -1
  41. package/dist/document.d.ts +1 -1
  42. package/dist/document.js +17 -11
  43. package/dist/{embedded-font-Bnhh4juV.d.ts → embedded-font-ByD7ZiQS.d.ts} +1 -1
  44. package/dist/{embedded-font-CEf-zBCA.d.cts → embedded-font-DgVBedw6.d.cts} +1 -1
  45. package/dist/embedded-font-write.d.cts +2 -2
  46. package/dist/embedded-font-write.d.ts +2 -2
  47. package/dist/embedded-font.cjs +4 -2
  48. package/dist/embedded-font.d.cts +1 -1
  49. package/dist/embedded-font.d.ts +1 -1
  50. package/dist/embedded-font.js +4 -2
  51. package/dist/encoding.cjs +1 -1
  52. package/dist/encoding.js +1 -1
  53. package/dist/encrypt-write.cjs +25 -21
  54. package/dist/encrypt-write.d.cts +1 -1
  55. package/dist/encrypt-write.d.ts +1 -1
  56. package/dist/encrypt-write.js +25 -21
  57. package/dist/encrypt.cjs +43 -64
  58. package/dist/encrypt.d.cts +1 -1
  59. package/dist/encrypt.d.ts +1 -1
  60. package/dist/encrypt.js +43 -64
  61. package/dist/filters.cjs +46 -26
  62. package/dist/filters.d.cts +1 -1
  63. package/dist/filters.d.ts +1 -1
  64. package/dist/filters.js +46 -26
  65. package/dist/font-face.cjs +2 -1
  66. package/dist/font-face.js +2 -1
  67. package/dist/font-read.cjs +12 -6
  68. package/dist/font-read.d.cts +1 -1
  69. package/dist/font-read.d.ts +1 -1
  70. package/dist/font-read.js +12 -6
  71. package/dist/font-registry.d.cts +3 -3
  72. package/dist/font-registry.d.ts +3 -3
  73. package/dist/font-tables.cjs +55 -28
  74. package/dist/font-tables.js +55 -28
  75. package/dist/form.cjs +13 -8
  76. package/dist/form.d.cts +2 -2
  77. package/dist/form.d.ts +2 -2
  78. package/dist/form.js +13 -8
  79. package/dist/gdef-table.cjs +6 -3
  80. package/dist/gdef-table.js +6 -3
  81. package/dist/{glyf-contours-C0epBNqP.d.ts → glyf-contours-B1PsI9oA.d.ts} +1 -1
  82. package/dist/{glyf-contours-BRpvd0rt.d.cts → glyf-contours-NHBpgks-.d.cts} +1 -1
  83. package/dist/glyf-contours.cjs +3 -1
  84. package/dist/glyf-contours.d.cts +1 -1
  85. package/dist/glyf-contours.d.ts +1 -1
  86. package/dist/glyf-contours.js +3 -1
  87. package/dist/glyf.cjs +22 -11
  88. package/dist/glyf.js +22 -11
  89. package/dist/gpos-table.cjs +37 -19
  90. package/dist/gpos-table.js +37 -19
  91. package/dist/gsub-table.cjs +40 -25
  92. package/dist/gsub-table.js +40 -25
  93. package/dist/hmtx-table.cjs +5 -3
  94. package/dist/hmtx-table.js +5 -3
  95. package/dist/image/ccitt-encode.cjs +8 -5
  96. package/dist/image/ccitt-encode.js +8 -5
  97. package/dist/image/ccitt.cjs +801 -209
  98. package/dist/image/ccitt.js +801 -209
  99. package/dist/image/jbig2-arith.cjs +340 -306
  100. package/dist/image/jbig2-arith.js +340 -306
  101. package/dist/image/jbig2-bitmap.cjs +8 -5
  102. package/dist/image/jbig2-bitmap.js +8 -5
  103. package/dist/image/jbig2-generic.cjs +240 -69
  104. package/dist/image/jbig2-generic.js +240 -69
  105. package/dist/image/jbig2-text.cjs +4 -2
  106. package/dist/image/jbig2-text.js +4 -2
  107. package/dist/image/jbig2.cjs +69 -31
  108. package/dist/image/jbig2.js +69 -31
  109. package/dist/image/jp2-boxes.cjs +52 -27
  110. package/dist/image/jp2-boxes.js +52 -27
  111. package/dist/image/jpeg-info.cjs +29 -24
  112. package/dist/image/jpeg-info.js +29 -24
  113. package/dist/image/jpeg2000-codestream.cjs +61 -32
  114. package/dist/image/jpeg2000-codestream.js +61 -32
  115. package/dist/image/jpeg2000-dwt.cjs +2 -1
  116. package/dist/image/jpeg2000-dwt.js +2 -1
  117. package/dist/image/jpeg2000-t1.cjs +21 -11
  118. package/dist/image/jpeg2000-t1.js +21 -11
  119. package/dist/image/jpeg2000-t2.cjs +12 -5
  120. package/dist/image/jpeg2000-t2.js +12 -5
  121. package/dist/image/jpeg2000-tagtree.cjs +8 -4
  122. package/dist/image/jpeg2000-tagtree.js +8 -4
  123. package/dist/image/jpeg2000.cjs +11 -6
  124. package/dist/image/jpeg2000.js +11 -6
  125. package/dist/image/png-decode.cjs +62 -39
  126. package/dist/image/png-decode.d.cts +3 -2
  127. package/dist/image/png-decode.d.ts +3 -2
  128. package/dist/image/png-decode.js +62 -39
  129. package/dist/image/png-filter.cjs +23 -15
  130. package/dist/image/png-filter.js +23 -15
  131. package/dist/images-read.cjs +41 -36
  132. package/dist/images-read.d.cts +2 -2
  133. package/dist/images-read.d.ts +2 -2
  134. package/dist/images-read.js +41 -36
  135. package/dist/index.cjs +1 -1
  136. package/dist/index.d.cts +1 -1
  137. package/dist/index.d.ts +1 -1
  138. package/dist/index.js +1 -1
  139. package/dist/interpret.cjs +68 -40
  140. package/dist/interpret.d.cts +1 -1
  141. package/dist/interpret.d.ts +1 -1
  142. package/dist/interpret.js +68 -40
  143. package/dist/lexer.cjs +86 -51
  144. package/dist/lexer.js +86 -51
  145. package/dist/math-content-write.cjs +9 -5
  146. package/dist/math-content-write.js +9 -5
  147. package/dist/math-font-write.cjs +2 -1
  148. package/dist/math-font-write.d.cts +1 -1
  149. package/dist/math-font-write.d.ts +1 -1
  150. package/dist/math-font-write.js +2 -1
  151. package/dist/math-font.cjs +16 -7
  152. package/dist/math-font.js +16 -7
  153. package/dist/math-table.cjs +25 -13
  154. package/dist/math-table.js +25 -13
  155. package/dist/matrix.cjs +3 -2
  156. package/dist/matrix.js +3 -2
  157. package/dist/measure.cjs +1 -1
  158. package/dist/measure.js +1 -1
  159. package/dist/names.cjs +7 -7
  160. package/dist/names.d.cts +2 -2
  161. package/dist/names.d.ts +2 -2
  162. package/dist/names.js +7 -7
  163. package/dist/navigation.cjs +16 -12
  164. package/dist/navigation.d.cts +4 -4
  165. package/dist/navigation.d.ts +4 -4
  166. package/dist/navigation.js +16 -12
  167. package/dist/{objects-B7HdMeWS.d.cts → objects-e2RS3-yT.d.cts} +3 -3
  168. package/dist/{objects-B7HdMeWS.d.ts → objects-e2RS3-yT.d.ts} +3 -3
  169. package/dist/objects.d.cts +1 -1
  170. package/dist/objects.d.ts +1 -1
  171. package/dist/optional-content.d.cts +2 -2
  172. package/dist/optional-content.d.ts +2 -2
  173. package/dist/ot-layout-common.cjs +22 -15
  174. package/dist/ot-layout-common.js +22 -15
  175. package/dist/parse.cjs +7 -5
  176. package/dist/parse.d.cts +1 -1
  177. package/dist/parse.d.ts +1 -1
  178. package/dist/parse.js +7 -5
  179. package/dist/pdf-text.cjs +5 -2
  180. package/dist/pdf-text.js +5 -2
  181. package/dist/predictors.cjs +14 -9
  182. package/dist/predictors.d.cts +1 -1
  183. package/dist/predictors.d.ts +1 -1
  184. package/dist/predictors.js +14 -9
  185. package/dist/raster.cjs +30 -19
  186. package/dist/raster.d.cts +8 -8
  187. package/dist/raster.d.ts +8 -8
  188. package/dist/raster.js +30 -19
  189. package/dist/read.cjs +29 -16
  190. package/dist/read.js +29 -16
  191. package/dist/serialize.cjs +6 -2
  192. package/dist/serialize.d.cts +1 -1
  193. package/dist/serialize.d.ts +1 -1
  194. package/dist/serialize.js +6 -2
  195. package/dist/sfnt-subset.cjs +25 -13
  196. package/dist/sfnt-subset.d.cts +1 -1
  197. package/dist/sfnt-subset.d.ts +1 -1
  198. package/dist/sfnt-subset.js +25 -13
  199. package/dist/sfnt.cjs +20 -10
  200. package/dist/sfnt.js +20 -10
  201. package/dist/structure.d.cts +2 -2
  202. package/dist/structure.d.ts +2 -2
  203. package/dist/text-group.cjs +0 -1
  204. package/dist/text-group.js +0 -1
  205. package/dist/text-layout.d.cts +1 -1
  206. package/dist/text-layout.d.ts +1 -1
  207. package/dist/tounicode.cjs +4 -2
  208. package/dist/tounicode.d.cts +1 -1
  209. package/dist/tounicode.d.ts +1 -1
  210. package/dist/tounicode.js +4 -2
  211. package/dist/winansi.cjs +1 -1
  212. package/dist/winansi.js +1 -1
  213. package/dist/write.cjs +20 -12
  214. package/dist/write.d.cts +1 -1
  215. package/dist/write.d.ts +1 -1
  216. package/dist/write.js +20 -12
  217. package/dist/xref.cjs +5 -2
  218. package/dist/xref.d.cts +1 -1
  219. package/dist/xref.d.ts +1 -1
  220. package/dist/xref.js +5 -2
  221. package/package.json +1 -1
package/dist/glyf.cjs CHANGED
@@ -16,6 +16,9 @@ function parseLoca(font, options) {
16
16
  return offsets;
17
17
  }
18
18
  const GLYPH_HEADER_SIZE = 10;
19
+ const GLYPH_HEADER_Y_MIN_OFFSET = 4;
20
+ const GLYPH_HEADER_X_MAX_OFFSET = 6;
21
+ const GLYPH_HEADER_Y_MAX_OFFSET = 8;
19
22
  const ARG_1_AND_2_ARE_WORDS = 1;
20
23
  const ARGS_ARE_XY_VALUES = 2;
21
24
  const WE_HAVE_A_SCALE = 8;
@@ -26,8 +29,16 @@ const SCALED_COMPONENT_OFFSET = 2048;
26
29
  const UNSCALED_COMPONENT_OFFSET = 4096;
27
30
  const MAX_COMPOSITE_DEPTH = 5;
28
31
  const COMPONENT_RECORD_HEADER_SIZE = 4;
32
+ const X_AND_Y_SCALE_SIZE = 4;
33
+ const TWO_BY_TWO_SCALE10_OFFSET = 4;
34
+ const TWO_BY_TWO_Y_SCALE_OFFSET = 6;
35
+ const TWO_BY_TWO_SIZE = 8;
36
+ const WORD_ARGS_SIZE = 4;
37
+ const BYTE_ARGS_SIZE = 2;
38
+ const SIGNED_BYTE_SIGN_THRESHOLD = 128;
39
+ const SIGNED_BYTE_MODULUS = 256;
29
40
  function signedByte(value) {
30
- return value >= 128 ? value - 256 : value;
41
+ return value >= SIGNED_BYTE_SIGN_THRESHOLD ? value - SIGNED_BYTE_MODULUS : value;
31
42
  }
32
43
  function readComponents(glyph) {
33
44
  const components = [];
@@ -39,7 +50,7 @@ function readComponents(glyph) {
39
50
  offset += COMPONENT_RECORD_HEADER_SIZE;
40
51
  const argsAreWords = (flags & ARG_1_AND_2_ARE_WORDS) !== 0;
41
52
  const argsAreXyValues = (flags & ARGS_ARE_XY_VALUES) !== 0;
42
- const argsSize = argsAreWords ? 4 : 2;
53
+ const argsSize = argsAreWords ? WORD_ARGS_SIZE : BYTE_ARGS_SIZE;
43
54
  if (!require_sfnt.hasBytes(glyph, offset, argsSize)) return;
44
55
  let argument1;
45
56
  let argument2;
@@ -63,23 +74,23 @@ function readComponents(glyph) {
63
74
  ];
64
75
  offset += 2;
65
76
  } else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) !== 0) {
66
- if (!require_sfnt.hasBytes(glyph, offset, 4)) return;
77
+ if (!require_sfnt.hasBytes(glyph, offset, X_AND_Y_SCALE_SIZE)) return;
67
78
  transform = [
68
79
  require_sfnt.f2dot14(glyph, offset),
69
80
  0,
70
81
  0,
71
82
  require_sfnt.f2dot14(glyph, offset + 2)
72
83
  ];
73
- offset += 4;
84
+ offset += X_AND_Y_SCALE_SIZE;
74
85
  } else if ((flags & WE_HAVE_A_TWO_BY_TWO) !== 0) {
75
- if (!require_sfnt.hasBytes(glyph, offset, 8)) return;
86
+ if (!require_sfnt.hasBytes(glyph, offset, TWO_BY_TWO_SIZE)) return;
76
87
  transform = [
77
88
  require_sfnt.f2dot14(glyph, offset),
78
89
  require_sfnt.f2dot14(glyph, offset + 2),
79
- require_sfnt.f2dot14(glyph, offset + 4),
80
- require_sfnt.f2dot14(glyph, offset + 6)
90
+ require_sfnt.f2dot14(glyph, offset + TWO_BY_TWO_SCALE10_OFFSET),
91
+ require_sfnt.f2dot14(glyph, offset + TWO_BY_TWO_Y_SCALE_OFFSET)
81
92
  ];
82
- offset += 8;
93
+ offset += TWO_BY_TWO_SIZE;
83
94
  }
84
95
  components.push({
85
96
  flags,
@@ -134,9 +145,9 @@ function parseGlyf(font, options) {
134
145
  return {
135
146
  numberOfContours: require_sfnt.i16(glyph, 0),
136
147
  xMin: require_sfnt.i16(glyph, 2),
137
- yMin: require_sfnt.i16(glyph, 4),
138
- xMax: require_sfnt.i16(glyph, 6),
139
- yMax: require_sfnt.i16(glyph, 8)
148
+ yMin: require_sfnt.i16(glyph, GLYPH_HEADER_Y_MIN_OFFSET),
149
+ xMax: require_sfnt.i16(glyph, GLYPH_HEADER_X_MAX_OFFSET),
150
+ yMax: require_sfnt.i16(glyph, GLYPH_HEADER_Y_MAX_OFFSET)
140
151
  };
141
152
  };
142
153
  const compositeComponents = (glyphId) => {
package/dist/glyf.js CHANGED
@@ -15,6 +15,9 @@ function parseLoca(font, options) {
15
15
  return offsets;
16
16
  }
17
17
  const GLYPH_HEADER_SIZE = 10;
18
+ const GLYPH_HEADER_Y_MIN_OFFSET = 4;
19
+ const GLYPH_HEADER_X_MAX_OFFSET = 6;
20
+ const GLYPH_HEADER_Y_MAX_OFFSET = 8;
18
21
  const ARG_1_AND_2_ARE_WORDS = 1;
19
22
  const ARGS_ARE_XY_VALUES = 2;
20
23
  const WE_HAVE_A_SCALE = 8;
@@ -25,8 +28,16 @@ const SCALED_COMPONENT_OFFSET = 2048;
25
28
  const UNSCALED_COMPONENT_OFFSET = 4096;
26
29
  const MAX_COMPOSITE_DEPTH = 5;
27
30
  const COMPONENT_RECORD_HEADER_SIZE = 4;
31
+ const X_AND_Y_SCALE_SIZE = 4;
32
+ const TWO_BY_TWO_SCALE10_OFFSET = 4;
33
+ const TWO_BY_TWO_Y_SCALE_OFFSET = 6;
34
+ const TWO_BY_TWO_SIZE = 8;
35
+ const WORD_ARGS_SIZE = 4;
36
+ const BYTE_ARGS_SIZE = 2;
37
+ const SIGNED_BYTE_SIGN_THRESHOLD = 128;
38
+ const SIGNED_BYTE_MODULUS = 256;
28
39
  function signedByte(value) {
29
- return value >= 128 ? value - 256 : value;
40
+ return value >= SIGNED_BYTE_SIGN_THRESHOLD ? value - SIGNED_BYTE_MODULUS : value;
30
41
  }
31
42
  function readComponents(glyph) {
32
43
  const components = [];
@@ -38,7 +49,7 @@ function readComponents(glyph) {
38
49
  offset += COMPONENT_RECORD_HEADER_SIZE;
39
50
  const argsAreWords = (flags & ARG_1_AND_2_ARE_WORDS) !== 0;
40
51
  const argsAreXyValues = (flags & ARGS_ARE_XY_VALUES) !== 0;
41
- const argsSize = argsAreWords ? 4 : 2;
52
+ const argsSize = argsAreWords ? WORD_ARGS_SIZE : BYTE_ARGS_SIZE;
42
53
  if (!hasBytes(glyph, offset, argsSize)) return;
43
54
  let argument1;
44
55
  let argument2;
@@ -62,23 +73,23 @@ function readComponents(glyph) {
62
73
  ];
63
74
  offset += 2;
64
75
  } else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) !== 0) {
65
- if (!hasBytes(glyph, offset, 4)) return;
76
+ if (!hasBytes(glyph, offset, X_AND_Y_SCALE_SIZE)) return;
66
77
  transform = [
67
78
  f2dot14(glyph, offset),
68
79
  0,
69
80
  0,
70
81
  f2dot14(glyph, offset + 2)
71
82
  ];
72
- offset += 4;
83
+ offset += X_AND_Y_SCALE_SIZE;
73
84
  } else if ((flags & WE_HAVE_A_TWO_BY_TWO) !== 0) {
74
- if (!hasBytes(glyph, offset, 8)) return;
85
+ if (!hasBytes(glyph, offset, TWO_BY_TWO_SIZE)) return;
75
86
  transform = [
76
87
  f2dot14(glyph, offset),
77
88
  f2dot14(glyph, offset + 2),
78
- f2dot14(glyph, offset + 4),
79
- f2dot14(glyph, offset + 6)
89
+ f2dot14(glyph, offset + TWO_BY_TWO_SCALE10_OFFSET),
90
+ f2dot14(glyph, offset + TWO_BY_TWO_Y_SCALE_OFFSET)
80
91
  ];
81
- offset += 8;
92
+ offset += TWO_BY_TWO_SIZE;
82
93
  }
83
94
  components.push({
84
95
  flags,
@@ -133,9 +144,9 @@ function parseGlyf(font, options) {
133
144
  return {
134
145
  numberOfContours: i16(glyph, 0),
135
146
  xMin: i16(glyph, 2),
136
- yMin: i16(glyph, 4),
137
- xMax: i16(glyph, 6),
138
- yMax: i16(glyph, 8)
147
+ yMin: i16(glyph, GLYPH_HEADER_Y_MIN_OFFSET),
148
+ xMax: i16(glyph, GLYPH_HEADER_X_MAX_OFFSET),
149
+ yMax: i16(glyph, GLYPH_HEADER_Y_MAX_OFFSET)
139
150
  };
140
151
  };
141
152
  const compositeComponents = (glyphId) => {
@@ -3,18 +3,27 @@ const require_sfnt = require("./sfnt.cjs");
3
3
  const require_ot_layout_common = require("./ot-layout-common.cjs");
4
4
  //#region src/gpos-table.ts
5
5
  const GPOS_HEADER_SIZE = 10;
6
+ const GPOS_SCRIPT_LIST_OFFSET_FIELD = 4;
7
+ const GPOS_FEATURE_LIST_OFFSET_FIELD = 6;
8
+ const GPOS_LOOKUP_LIST_OFFSET_FIELD = 8;
6
9
  const SCRIPT_RECORD_SIZE = 6;
10
+ const SCRIPT_RECORD_OFFSET_FIELD = 4;
7
11
  const FEATURE_RECORD_SIZE = 6;
12
+ const FEATURE_RECORD_OFFSET_FIELD = 4;
8
13
  const LANG_SYS_HEADER_SIZE = 6;
14
+ const LANG_SYS_FEATURE_INDEX_COUNT_FIELD = 4;
9
15
  const FEATURE_HEADER_SIZE = 4;
10
16
  const LOOKUP_HEADER_SIZE = 6;
17
+ const LOOKUP_SUB_TABLE_COUNT_FIELD = 4;
11
18
  const EXTENSION_POS_HEADER_SIZE = 8;
19
+ const EXTENSION_POS_OFFSET_FIELD = 4;
12
20
  const LOOKUP_TYPE_PAIR_POS = 2;
13
21
  const LOOKUP_TYPE_EXTENSION_POS = 9;
14
22
  const KERN_FEATURE_TAG = "kern";
15
23
  const PREFERRED_SCRIPT_TAGS = ["latn", "DFLT"];
24
+ const TAG_LENGTH_BYTES = 4;
16
25
  function readTag(bytes, offset) {
17
- return String.fromCharCode(require_sfnt.u8(bytes, offset), require_sfnt.u8(bytes, offset + 1), require_sfnt.u8(bytes, offset + 2), require_sfnt.u8(bytes, offset + 3));
26
+ return String.fromCharCode(require_sfnt.u8(bytes, offset), require_sfnt.u8(bytes, offset + 1), require_sfnt.u8(bytes, offset + 2), require_sfnt.u8(bytes, offset + TAG_LENGTH_BYTES - 1));
18
27
  }
19
28
  function valueRecordSize(valueFormat) {
20
29
  let size = 0;
@@ -27,14 +36,17 @@ function xAdvanceOffset(valueFormat) {
27
36
  return valueRecordSize(valueFormat & 3);
28
37
  }
29
38
  const PAIR_POS_FORMAT_1_HEADER_SIZE = 10;
39
+ const PAIR_POS_FORMAT_1_VALUE_FORMAT_1_FIELD = 4;
40
+ const PAIR_POS_FORMAT_1_VALUE_FORMAT_2_FIELD = 6;
41
+ const PAIR_POS_FORMAT_1_PAIR_SET_COUNT_FIELD = 8;
30
42
  const PAIR_VALUE_RECORD_GLYPH_SIZE = 2;
31
43
  function parsePairPosFormat1(bytes, subtableOffset) {
32
44
  if (!require_sfnt.hasBytes(bytes, subtableOffset, PAIR_POS_FORMAT_1_HEADER_SIZE)) return;
33
45
  const coverage = require_ot_layout_common.parseCoverage(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 2));
34
46
  if (coverage === void 0) return;
35
- const valueFormat1 = require_sfnt.u16(bytes, subtableOffset + 4);
36
- const valueFormat2 = require_sfnt.u16(bytes, subtableOffset + 6);
37
- const pairSetCount = require_sfnt.u16(bytes, subtableOffset + 8);
47
+ const valueFormat1 = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_VALUE_FORMAT_1_FIELD);
48
+ const valueFormat2 = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_VALUE_FORMAT_2_FIELD);
49
+ const pairSetCount = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_PAIR_SET_COUNT_FIELD);
38
50
  const pairSetOffsetsOffset = subtableOffset + PAIR_POS_FORMAT_1_HEADER_SIZE;
39
51
  if (!require_sfnt.hasBytes(bytes, pairSetOffsetsOffset, pairSetCount * 2)) return;
40
52
  const recordSize = PAIR_VALUE_RECORD_GLYPH_SIZE + valueRecordSize(valueFormat1) + valueRecordSize(valueFormat2);
@@ -60,16 +72,22 @@ function parsePairPosFormat1(bytes, subtableOffset) {
60
72
  };
61
73
  }
62
74
  const PAIR_POS_FORMAT_2_HEADER_SIZE = 16;
75
+ const PAIR_POS_FORMAT_2_VALUE_FORMAT_1_FIELD = 4;
76
+ const PAIR_POS_FORMAT_2_VALUE_FORMAT_2_FIELD = 6;
77
+ const PAIR_POS_FORMAT_2_CLASS_DEF_1_FIELD = 8;
78
+ const PAIR_POS_FORMAT_2_CLASS_DEF_2_FIELD = 10;
79
+ const PAIR_POS_FORMAT_2_CLASS_1_COUNT_FIELD = 12;
80
+ const PAIR_POS_FORMAT_2_CLASS_2_COUNT_FIELD = 14;
63
81
  function parsePairPosFormat2(bytes, subtableOffset) {
64
82
  if (!require_sfnt.hasBytes(bytes, subtableOffset, PAIR_POS_FORMAT_2_HEADER_SIZE)) return;
65
83
  const coverage = require_ot_layout_common.parseCoverage(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 2));
66
- const classDef1 = require_ot_layout_common.parseClassDef(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 8));
67
- const classDef2 = require_ot_layout_common.parseClassDef(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 10));
84
+ const classDef1 = require_ot_layout_common.parseClassDef(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_DEF_1_FIELD));
85
+ const classDef2 = require_ot_layout_common.parseClassDef(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_DEF_2_FIELD));
68
86
  if (coverage === void 0 || classDef1 === void 0 || classDef2 === void 0) return;
69
- const valueFormat1 = require_sfnt.u16(bytes, subtableOffset + 4);
70
- const valueFormat2 = require_sfnt.u16(bytes, subtableOffset + 6);
71
- const class1Count = require_sfnt.u16(bytes, subtableOffset + 12);
72
- const class2Count = require_sfnt.u16(bytes, subtableOffset + 14);
87
+ const valueFormat1 = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_VALUE_FORMAT_1_FIELD);
88
+ const valueFormat2 = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_VALUE_FORMAT_2_FIELD);
89
+ const class1Count = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_1_COUNT_FIELD);
90
+ const class2Count = require_sfnt.u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_2_COUNT_FIELD);
73
91
  const class2RecordSize = valueRecordSize(valueFormat1) + valueRecordSize(valueFormat2);
74
92
  const class1RecordSize = class2Count * class2RecordSize;
75
93
  const matrixOffset = subtableOffset + PAIR_POS_FORMAT_2_HEADER_SIZE;
@@ -89,7 +107,7 @@ function parseSubtable(bytes, lookupType, subtableOffset) {
89
107
  if (!require_sfnt.hasBytes(bytes, subtableOffset, EXTENSION_POS_HEADER_SIZE) || require_sfnt.u16(bytes, subtableOffset) !== 1) return;
90
108
  const extensionLookupType = require_sfnt.u16(bytes, subtableOffset + 2);
91
109
  if (extensionLookupType === LOOKUP_TYPE_EXTENSION_POS) return;
92
- return parseSubtable(bytes, extensionLookupType, subtableOffset + require_sfnt.u32(bytes, subtableOffset + 4));
110
+ return parseSubtable(bytes, extensionLookupType, subtableOffset + require_sfnt.u32(bytes, subtableOffset + EXTENSION_POS_OFFSET_FIELD));
93
111
  }
94
112
  if (lookupType !== LOOKUP_TYPE_PAIR_POS) return;
95
113
  if (!require_sfnt.hasBytes(bytes, subtableOffset, 2)) return;
@@ -100,7 +118,7 @@ function parseSubtable(bytes, lookupType, subtableOffset) {
100
118
  function parseLookupSubtables(bytes, lookupOffset) {
101
119
  if (!require_sfnt.hasBytes(bytes, lookupOffset, LOOKUP_HEADER_SIZE)) return [];
102
120
  const lookupType = require_sfnt.u16(bytes, lookupOffset);
103
- const subTableCount = require_sfnt.u16(bytes, lookupOffset + 4);
121
+ const subTableCount = require_sfnt.u16(bytes, lookupOffset + LOOKUP_SUB_TABLE_COUNT_FIELD);
104
122
  const offsetsOffset = lookupOffset + LOOKUP_HEADER_SIZE;
105
123
  if (!require_sfnt.hasBytes(bytes, offsetsOffset, subTableCount * 2)) return [];
106
124
  const subtables = [];
@@ -116,7 +134,7 @@ function parseDefaultLangSysFeatureIndices(bytes, scriptOffset) {
116
134
  if (defaultLangSysOffset === 0) return [];
117
135
  const langSysOffset = scriptOffset + defaultLangSysOffset;
118
136
  if (!require_sfnt.hasBytes(bytes, langSysOffset, LANG_SYS_HEADER_SIZE)) return [];
119
- const featureIndexCount = require_sfnt.u16(bytes, langSysOffset + 4);
137
+ const featureIndexCount = require_sfnt.u16(bytes, langSysOffset + LANG_SYS_FEATURE_INDEX_COUNT_FIELD);
120
138
  const indicesOffset = langSysOffset + LANG_SYS_HEADER_SIZE;
121
139
  if (!require_sfnt.hasBytes(bytes, indicesOffset, featureIndexCount * 2)) return [];
122
140
  const indices = [];
@@ -130,9 +148,9 @@ function findScriptOffset(bytes, scriptListOffset) {
130
148
  if (!require_sfnt.hasBytes(bytes, recordsOffset, scriptCount * SCRIPT_RECORD_SIZE) || scriptCount === 0) return;
131
149
  for (const wanted of PREFERRED_SCRIPT_TAGS) for (let i = 0; i < scriptCount; i++) {
132
150
  const recordOffset = recordsOffset + i * SCRIPT_RECORD_SIZE;
133
- if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + require_sfnt.u16(bytes, recordOffset + 4);
151
+ if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + require_sfnt.u16(bytes, recordOffset + SCRIPT_RECORD_OFFSET_FIELD);
134
152
  }
135
- return scriptListOffset + require_sfnt.u16(bytes, recordsOffset + 4);
153
+ return scriptListOffset + require_sfnt.u16(bytes, recordsOffset + SCRIPT_RECORD_OFFSET_FIELD);
136
154
  }
137
155
  function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
138
156
  if (!require_sfnt.hasBytes(bytes, featureListOffset, 2)) return [];
@@ -145,7 +163,7 @@ function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
145
163
  if (featureIndex >= featureCount) continue;
146
164
  const recordOffset = recordsOffset + featureIndex * FEATURE_RECORD_SIZE;
147
165
  if (readTag(bytes, recordOffset) !== KERN_FEATURE_TAG) continue;
148
- const featureOffset = featureListOffset + require_sfnt.u16(bytes, recordOffset + 4);
166
+ const featureOffset = featureListOffset + require_sfnt.u16(bytes, recordOffset + FEATURE_RECORD_OFFSET_FIELD);
149
167
  if (!require_sfnt.hasBytes(bytes, featureOffset, FEATURE_HEADER_SIZE)) continue;
150
168
  const lookupIndexCount = require_sfnt.u16(bytes, featureOffset + 2);
151
169
  const indicesOffset = featureOffset + FEATURE_HEADER_SIZE;
@@ -163,11 +181,11 @@ function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
163
181
  function buildGposKernLookup(font) {
164
182
  const bytes = require_sfnt.sfntTableBytes(font, "GPOS");
165
183
  if (bytes === void 0 || !require_sfnt.hasBytes(bytes, 0, GPOS_HEADER_SIZE) || require_sfnt.u16(bytes, 0) !== 1) return;
166
- const scriptOffset = findScriptOffset(bytes, require_sfnt.u16(bytes, 4));
184
+ const scriptOffset = findScriptOffset(bytes, require_sfnt.u16(bytes, GPOS_SCRIPT_LIST_OFFSET_FIELD));
167
185
  if (scriptOffset === void 0) return;
168
- const lookupIndices = collectKernLookupIndices(bytes, require_sfnt.u16(bytes, 6), parseDefaultLangSysFeatureIndices(bytes, scriptOffset));
186
+ const lookupIndices = collectKernLookupIndices(bytes, require_sfnt.u16(bytes, GPOS_FEATURE_LIST_OFFSET_FIELD), parseDefaultLangSysFeatureIndices(bytes, scriptOffset));
169
187
  if (lookupIndices.length === 0) return;
170
- const lookupListOffset = require_sfnt.u16(bytes, 8);
188
+ const lookupListOffset = require_sfnt.u16(bytes, GPOS_LOOKUP_LIST_OFFSET_FIELD);
171
189
  if (!require_sfnt.hasBytes(bytes, lookupListOffset, 2)) return;
172
190
  const lookupCount = require_sfnt.u16(bytes, lookupListOffset);
173
191
  const lookupOffsetsOffset = lookupListOffset + 2;
@@ -2,18 +2,27 @@ import { hasBytes, i16, sfntTableBytes, u16, u32, u8 } from "./sfnt.js";
2
2
  import { parseClassDef, parseCoverage } from "./ot-layout-common.js";
3
3
  //#region src/gpos-table.ts
4
4
  const GPOS_HEADER_SIZE = 10;
5
+ const GPOS_SCRIPT_LIST_OFFSET_FIELD = 4;
6
+ const GPOS_FEATURE_LIST_OFFSET_FIELD = 6;
7
+ const GPOS_LOOKUP_LIST_OFFSET_FIELD = 8;
5
8
  const SCRIPT_RECORD_SIZE = 6;
9
+ const SCRIPT_RECORD_OFFSET_FIELD = 4;
6
10
  const FEATURE_RECORD_SIZE = 6;
11
+ const FEATURE_RECORD_OFFSET_FIELD = 4;
7
12
  const LANG_SYS_HEADER_SIZE = 6;
13
+ const LANG_SYS_FEATURE_INDEX_COUNT_FIELD = 4;
8
14
  const FEATURE_HEADER_SIZE = 4;
9
15
  const LOOKUP_HEADER_SIZE = 6;
16
+ const LOOKUP_SUB_TABLE_COUNT_FIELD = 4;
10
17
  const EXTENSION_POS_HEADER_SIZE = 8;
18
+ const EXTENSION_POS_OFFSET_FIELD = 4;
11
19
  const LOOKUP_TYPE_PAIR_POS = 2;
12
20
  const LOOKUP_TYPE_EXTENSION_POS = 9;
13
21
  const KERN_FEATURE_TAG = "kern";
14
22
  const PREFERRED_SCRIPT_TAGS = ["latn", "DFLT"];
23
+ const TAG_LENGTH_BYTES = 4;
15
24
  function readTag(bytes, offset) {
16
- return String.fromCharCode(u8(bytes, offset), u8(bytes, offset + 1), u8(bytes, offset + 2), u8(bytes, offset + 3));
25
+ return String.fromCharCode(u8(bytes, offset), u8(bytes, offset + 1), u8(bytes, offset + 2), u8(bytes, offset + TAG_LENGTH_BYTES - 1));
17
26
  }
18
27
  function valueRecordSize(valueFormat) {
19
28
  let size = 0;
@@ -26,14 +35,17 @@ function xAdvanceOffset(valueFormat) {
26
35
  return valueRecordSize(valueFormat & 3);
27
36
  }
28
37
  const PAIR_POS_FORMAT_1_HEADER_SIZE = 10;
38
+ const PAIR_POS_FORMAT_1_VALUE_FORMAT_1_FIELD = 4;
39
+ const PAIR_POS_FORMAT_1_VALUE_FORMAT_2_FIELD = 6;
40
+ const PAIR_POS_FORMAT_1_PAIR_SET_COUNT_FIELD = 8;
29
41
  const PAIR_VALUE_RECORD_GLYPH_SIZE = 2;
30
42
  function parsePairPosFormat1(bytes, subtableOffset) {
31
43
  if (!hasBytes(bytes, subtableOffset, PAIR_POS_FORMAT_1_HEADER_SIZE)) return;
32
44
  const coverage = parseCoverage(bytes, subtableOffset + u16(bytes, subtableOffset + 2));
33
45
  if (coverage === void 0) return;
34
- const valueFormat1 = u16(bytes, subtableOffset + 4);
35
- const valueFormat2 = u16(bytes, subtableOffset + 6);
36
- const pairSetCount = u16(bytes, subtableOffset + 8);
46
+ const valueFormat1 = u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_VALUE_FORMAT_1_FIELD);
47
+ const valueFormat2 = u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_VALUE_FORMAT_2_FIELD);
48
+ const pairSetCount = u16(bytes, subtableOffset + PAIR_POS_FORMAT_1_PAIR_SET_COUNT_FIELD);
37
49
  const pairSetOffsetsOffset = subtableOffset + PAIR_POS_FORMAT_1_HEADER_SIZE;
38
50
  if (!hasBytes(bytes, pairSetOffsetsOffset, pairSetCount * 2)) return;
39
51
  const recordSize = PAIR_VALUE_RECORD_GLYPH_SIZE + valueRecordSize(valueFormat1) + valueRecordSize(valueFormat2);
@@ -59,16 +71,22 @@ function parsePairPosFormat1(bytes, subtableOffset) {
59
71
  };
60
72
  }
61
73
  const PAIR_POS_FORMAT_2_HEADER_SIZE = 16;
74
+ const PAIR_POS_FORMAT_2_VALUE_FORMAT_1_FIELD = 4;
75
+ const PAIR_POS_FORMAT_2_VALUE_FORMAT_2_FIELD = 6;
76
+ const PAIR_POS_FORMAT_2_CLASS_DEF_1_FIELD = 8;
77
+ const PAIR_POS_FORMAT_2_CLASS_DEF_2_FIELD = 10;
78
+ const PAIR_POS_FORMAT_2_CLASS_1_COUNT_FIELD = 12;
79
+ const PAIR_POS_FORMAT_2_CLASS_2_COUNT_FIELD = 14;
62
80
  function parsePairPosFormat2(bytes, subtableOffset) {
63
81
  if (!hasBytes(bytes, subtableOffset, PAIR_POS_FORMAT_2_HEADER_SIZE)) return;
64
82
  const coverage = parseCoverage(bytes, subtableOffset + u16(bytes, subtableOffset + 2));
65
- const classDef1 = parseClassDef(bytes, subtableOffset + u16(bytes, subtableOffset + 8));
66
- const classDef2 = parseClassDef(bytes, subtableOffset + u16(bytes, subtableOffset + 10));
83
+ const classDef1 = parseClassDef(bytes, subtableOffset + u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_DEF_1_FIELD));
84
+ const classDef2 = parseClassDef(bytes, subtableOffset + u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_DEF_2_FIELD));
67
85
  if (coverage === void 0 || classDef1 === void 0 || classDef2 === void 0) return;
68
- const valueFormat1 = u16(bytes, subtableOffset + 4);
69
- const valueFormat2 = u16(bytes, subtableOffset + 6);
70
- const class1Count = u16(bytes, subtableOffset + 12);
71
- const class2Count = u16(bytes, subtableOffset + 14);
86
+ const valueFormat1 = u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_VALUE_FORMAT_1_FIELD);
87
+ const valueFormat2 = u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_VALUE_FORMAT_2_FIELD);
88
+ const class1Count = u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_1_COUNT_FIELD);
89
+ const class2Count = u16(bytes, subtableOffset + PAIR_POS_FORMAT_2_CLASS_2_COUNT_FIELD);
72
90
  const class2RecordSize = valueRecordSize(valueFormat1) + valueRecordSize(valueFormat2);
73
91
  const class1RecordSize = class2Count * class2RecordSize;
74
92
  const matrixOffset = subtableOffset + PAIR_POS_FORMAT_2_HEADER_SIZE;
@@ -88,7 +106,7 @@ function parseSubtable(bytes, lookupType, subtableOffset) {
88
106
  if (!hasBytes(bytes, subtableOffset, EXTENSION_POS_HEADER_SIZE) || u16(bytes, subtableOffset) !== 1) return;
89
107
  const extensionLookupType = u16(bytes, subtableOffset + 2);
90
108
  if (extensionLookupType === LOOKUP_TYPE_EXTENSION_POS) return;
91
- return parseSubtable(bytes, extensionLookupType, subtableOffset + u32(bytes, subtableOffset + 4));
109
+ return parseSubtable(bytes, extensionLookupType, subtableOffset + u32(bytes, subtableOffset + EXTENSION_POS_OFFSET_FIELD));
92
110
  }
93
111
  if (lookupType !== LOOKUP_TYPE_PAIR_POS) return;
94
112
  if (!hasBytes(bytes, subtableOffset, 2)) return;
@@ -99,7 +117,7 @@ function parseSubtable(bytes, lookupType, subtableOffset) {
99
117
  function parseLookupSubtables(bytes, lookupOffset) {
100
118
  if (!hasBytes(bytes, lookupOffset, LOOKUP_HEADER_SIZE)) return [];
101
119
  const lookupType = u16(bytes, lookupOffset);
102
- const subTableCount = u16(bytes, lookupOffset + 4);
120
+ const subTableCount = u16(bytes, lookupOffset + LOOKUP_SUB_TABLE_COUNT_FIELD);
103
121
  const offsetsOffset = lookupOffset + LOOKUP_HEADER_SIZE;
104
122
  if (!hasBytes(bytes, offsetsOffset, subTableCount * 2)) return [];
105
123
  const subtables = [];
@@ -115,7 +133,7 @@ function parseDefaultLangSysFeatureIndices(bytes, scriptOffset) {
115
133
  if (defaultLangSysOffset === 0) return [];
116
134
  const langSysOffset = scriptOffset + defaultLangSysOffset;
117
135
  if (!hasBytes(bytes, langSysOffset, LANG_SYS_HEADER_SIZE)) return [];
118
- const featureIndexCount = u16(bytes, langSysOffset + 4);
136
+ const featureIndexCount = u16(bytes, langSysOffset + LANG_SYS_FEATURE_INDEX_COUNT_FIELD);
119
137
  const indicesOffset = langSysOffset + LANG_SYS_HEADER_SIZE;
120
138
  if (!hasBytes(bytes, indicesOffset, featureIndexCount * 2)) return [];
121
139
  const indices = [];
@@ -129,9 +147,9 @@ function findScriptOffset(bytes, scriptListOffset) {
129
147
  if (!hasBytes(bytes, recordsOffset, scriptCount * SCRIPT_RECORD_SIZE) || scriptCount === 0) return;
130
148
  for (const wanted of PREFERRED_SCRIPT_TAGS) for (let i = 0; i < scriptCount; i++) {
131
149
  const recordOffset = recordsOffset + i * SCRIPT_RECORD_SIZE;
132
- if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + u16(bytes, recordOffset + 4);
150
+ if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + u16(bytes, recordOffset + SCRIPT_RECORD_OFFSET_FIELD);
133
151
  }
134
- return scriptListOffset + u16(bytes, recordsOffset + 4);
152
+ return scriptListOffset + u16(bytes, recordsOffset + SCRIPT_RECORD_OFFSET_FIELD);
135
153
  }
136
154
  function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
137
155
  if (!hasBytes(bytes, featureListOffset, 2)) return [];
@@ -144,7 +162,7 @@ function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
144
162
  if (featureIndex >= featureCount) continue;
145
163
  const recordOffset = recordsOffset + featureIndex * FEATURE_RECORD_SIZE;
146
164
  if (readTag(bytes, recordOffset) !== KERN_FEATURE_TAG) continue;
147
- const featureOffset = featureListOffset + u16(bytes, recordOffset + 4);
165
+ const featureOffset = featureListOffset + u16(bytes, recordOffset + FEATURE_RECORD_OFFSET_FIELD);
148
166
  if (!hasBytes(bytes, featureOffset, FEATURE_HEADER_SIZE)) continue;
149
167
  const lookupIndexCount = u16(bytes, featureOffset + 2);
150
168
  const indicesOffset = featureOffset + FEATURE_HEADER_SIZE;
@@ -162,11 +180,11 @@ function collectKernLookupIndices(bytes, featureListOffset, featureIndices) {
162
180
  function buildGposKernLookup(font) {
163
181
  const bytes = sfntTableBytes(font, "GPOS");
164
182
  if (bytes === void 0 || !hasBytes(bytes, 0, GPOS_HEADER_SIZE) || u16(bytes, 0) !== 1) return;
165
- const scriptOffset = findScriptOffset(bytes, u16(bytes, 4));
183
+ const scriptOffset = findScriptOffset(bytes, u16(bytes, GPOS_SCRIPT_LIST_OFFSET_FIELD));
166
184
  if (scriptOffset === void 0) return;
167
- const lookupIndices = collectKernLookupIndices(bytes, u16(bytes, 6), parseDefaultLangSysFeatureIndices(bytes, scriptOffset));
185
+ const lookupIndices = collectKernLookupIndices(bytes, u16(bytes, GPOS_FEATURE_LIST_OFFSET_FIELD), parseDefaultLangSysFeatureIndices(bytes, scriptOffset));
168
186
  if (lookupIndices.length === 0) return;
169
- const lookupListOffset = u16(bytes, 8);
187
+ const lookupListOffset = u16(bytes, GPOS_LOOKUP_LIST_OFFSET_FIELD);
170
188
  if (!hasBytes(bytes, lookupListOffset, 2)) return;
171
189
  const lookupCount = u16(bytes, lookupListOffset);
172
190
  const lookupOffsetsOffset = lookupListOffset + 2;
@@ -12,17 +12,28 @@ const DEFAULT_GSUB_FEATURE_TAGS = [
12
12
  ];
13
13
  const GSUB_OPT_IN_FEATURE_TAGS = ["smcp", "dlig"];
14
14
  const GSUB_HEADER_SIZE = 10;
15
+ const GSUB_HEADER_SCRIPT_LIST_OFFSET = 4;
16
+ const GSUB_HEADER_FEATURE_LIST_OFFSET = 6;
17
+ const GSUB_HEADER_LOOKUP_LIST_OFFSET = 8;
15
18
  const SCRIPT_RECORD_SIZE = 6;
19
+ const SCRIPT_RECORD_OFFSET_FIELD_OFFSET = 4;
16
20
  const FEATURE_RECORD_SIZE = 6;
21
+ const FEATURE_RECORD_OFFSET_FIELD_OFFSET = 4;
17
22
  const LANG_SYS_HEADER_SIZE = 6;
23
+ const LANG_SYS_FEATURE_INDEX_COUNT_OFFSET = 4;
18
24
  const FEATURE_HEADER_SIZE = 4;
19
25
  const LOOKUP_HEADER_SIZE = 6;
26
+ const LOOKUP_HEADER_SUBTABLE_COUNT_OFFSET = 4;
20
27
  const LOOKUP_TYPE_SINGLE_SUBST = 1;
21
28
  const LOOKUP_TYPE_LIGATURE_SUBST = 4;
22
29
  const LOOKUP_TYPE_CONTEXT_SUBST = 5;
23
30
  const LOOKUP_TYPE_CHAIN_CONTEXT_SUBST = 6;
24
31
  const LOOKUP_TYPE_EXTENSION_SUBST = 7;
25
32
  const EXTENSION_SUBST_HEADER_SIZE = 8;
33
+ const EXTENSION_SUBST_OFFSET_FIELD_OFFSET = 4;
34
+ const BITS_PER_BYTE = 8;
35
+ const BYTE_MASK = 255;
36
+ const SUBST_FORMAT_AND_COVERAGE_SIZE = 4;
26
37
  const LOOKUP_FLAG_IGNORE_BASE_GLYPHS = 2;
27
38
  const LOOKUP_FLAG_IGNORE_LIGATURES = 4;
28
39
  const LOOKUP_FLAG_IGNORE_MARKS = 8;
@@ -31,14 +42,14 @@ const LOOKUP_FLAG_MARK_ATTACHMENT_TYPE = 65280;
31
42
  const MAX_LOOKUP_NESTING_DEPTH = 6;
32
43
  const PREFERRED_SCRIPT_TAGS = ["latn", "DFLT"];
33
44
  function readTag(bytes, offset) {
34
- return String.fromCharCode(require_sfnt.u16(bytes, offset) >> 8, require_sfnt.u16(bytes, offset) & 255, require_sfnt.u16(bytes, offset + 2) >> 8, require_sfnt.u16(bytes, offset + 2) & 255);
45
+ return String.fromCharCode(require_sfnt.u16(bytes, offset) >> BITS_PER_BYTE, require_sfnt.u16(bytes, offset) & BYTE_MASK, require_sfnt.u16(bytes, offset + 2) >> BITS_PER_BYTE, require_sfnt.u16(bytes, offset + 2) & BYTE_MASK);
35
46
  }
36
47
  function glyphSkipper(lookupFlag, markFilteringSet, gdef) {
37
48
  if (gdef === void 0 || lookupFlag === 0) return () => false;
38
49
  const ignoreBase = (lookupFlag & LOOKUP_FLAG_IGNORE_BASE_GLYPHS) !== 0;
39
50
  const ignoreLigatures = (lookupFlag & LOOKUP_FLAG_IGNORE_LIGATURES) !== 0;
40
51
  const ignoreMarks = (lookupFlag & LOOKUP_FLAG_IGNORE_MARKS) !== 0;
41
- const markAttachmentType = (lookupFlag & LOOKUP_FLAG_MARK_ATTACHMENT_TYPE) >> 8;
52
+ const markAttachmentType = (lookupFlag & LOOKUP_FLAG_MARK_ATTACHMENT_TYPE) >> BITS_PER_BYTE;
42
53
  const useMarkFilteringSet = (lookupFlag & LOOKUP_FLAG_USE_MARK_FILTERING_SET) !== 0;
43
54
  return (glyphId) => {
44
55
  const glyphClass = gdef.glyphClass(glyphId);
@@ -61,7 +72,7 @@ function parseSingleSubstFormat1(bytes, subtableOffset, skip) {
61
72
  if (!require_sfnt.hasBytes(bytes, subtableOffset, SINGLE_SUBST_FORMAT_1_SIZE)) return;
62
73
  const coverage = require_ot_layout_common.parseCoverage(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 2));
63
74
  if (coverage === void 0) return;
64
- const delta = require_sfnt.i16(bytes, subtableOffset + 4);
75
+ const delta = require_sfnt.i16(bytes, subtableOffset + SUBST_FORMAT_AND_COVERAGE_SIZE);
65
76
  return (slots, index) => {
66
77
  const slot = slots[index];
67
78
  if (skip(slot.glyphId)) return;
@@ -80,7 +91,7 @@ function parseSingleSubstFormat2(bytes, subtableOffset, skip) {
80
91
  if (!require_sfnt.hasBytes(bytes, subtableOffset, SINGLE_SUBST_FORMAT_2_HEADER_SIZE)) return;
81
92
  const coverage = require_ot_layout_common.parseCoverage(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 2));
82
93
  if (coverage === void 0) return;
83
- const glyphCount = require_sfnt.u16(bytes, subtableOffset + 4);
94
+ const glyphCount = require_sfnt.u16(bytes, subtableOffset + SUBST_FORMAT_AND_COVERAGE_SIZE);
84
95
  const substitutesOffset = subtableOffset + SINGLE_SUBST_FORMAT_2_HEADER_SIZE;
85
96
  if (!require_sfnt.hasBytes(bytes, substitutesOffset, glyphCount * 2)) return;
86
97
  return (slots, index) => {
@@ -104,7 +115,7 @@ function parseLigatureSubstFormat1(bytes, subtableOffset, skip) {
104
115
  if (!require_sfnt.hasBytes(bytes, subtableOffset, LIGATURE_SUBST_FORMAT_1_HEADER_SIZE)) return;
105
116
  const coverage = require_ot_layout_common.parseCoverage(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 2));
106
117
  if (coverage === void 0) return;
107
- const ligSetCount = require_sfnt.u16(bytes, subtableOffset + 4);
118
+ const ligSetCount = require_sfnt.u16(bytes, subtableOffset + SUBST_FORMAT_AND_COVERAGE_SIZE);
108
119
  const ligSetOffsetsOffset = subtableOffset + LIGATURE_SUBST_FORMAT_1_HEADER_SIZE;
109
120
  if (!require_sfnt.hasBytes(bytes, ligSetOffsetsOffset, ligSetCount * 2)) return;
110
121
  return (slots, index) => {
@@ -193,7 +204,10 @@ function applyContextualRule(slots, inputSlots, records, lookupOf, skip, depth)
193
204
  const lookup = lookupOf(record.lookupIndex);
194
205
  if (lookup === void 0 || record.sequenceIndex >= inputSlots.length || depth >= MAX_LOOKUP_NESTING_DEPTH) return;
195
206
  const target = visibleInputSlot(window, record.sequenceIndex, skip);
196
- if (target !== void 0) applyLookupAtSlot(window, target, lookup, depth + 1);
207
+ if (target !== void 0) {
208
+ const application = applyLookupAtSlot(window, target, lookup, depth + 1);
209
+ if (application !== void 0) window.splice(target, application.consumed, ...application.replacement);
210
+ }
197
211
  }
198
212
  return {
199
213
  consumed: last - first + 1,
@@ -211,12 +225,8 @@ function visibleInputSlot(window, position, skip) {
211
225
  function applyLookupAtSlot(slots, index, lookup, depth) {
212
226
  for (const subtable of lookup.subtables) {
213
227
  const application = subtable(slots, index, depth);
214
- if (application !== void 0) {
215
- slots.splice(index, application.consumed, ...application.replacement);
216
- return application.replacement.length;
217
- }
228
+ if (application !== void 0) return application;
218
229
  }
219
- return 0;
220
230
  }
221
231
  const SUBST_LOOKUP_RECORD_SIZE = 4;
222
232
  function readSubstLookupRecords(bytes, offset, count) {
@@ -361,7 +371,7 @@ function parseSubtable(bytes, lookupType, subtableOffset, skip, lookupOf) {
361
371
  if (!require_sfnt.hasBytes(bytes, subtableOffset, EXTENSION_SUBST_HEADER_SIZE) || require_sfnt.u16(bytes, subtableOffset) !== 1) return;
362
372
  const extensionLookupType = require_sfnt.u16(bytes, subtableOffset + 2);
363
373
  if (extensionLookupType === LOOKUP_TYPE_EXTENSION_SUBST) return;
364
- return parseSubtable(bytes, extensionLookupType, subtableOffset + require_sfnt.u32(bytes, subtableOffset + 4), skip, lookupOf);
374
+ return parseSubtable(bytes, extensionLookupType, subtableOffset + require_sfnt.u32(bytes, subtableOffset + EXTENSION_SUBST_OFFSET_FIELD_OFFSET), skip, lookupOf);
365
375
  }
366
376
  if (lookupType === LOOKUP_TYPE_SINGLE_SUBST) {
367
377
  if (!require_sfnt.hasBytes(bytes, subtableOffset, 2)) return;
@@ -389,7 +399,7 @@ function parseContextualSubtable(bytes, chained, subtableOffset, skip, lookupOf)
389
399
  if (!require_sfnt.hasBytes(bytes, subtableOffset, prefixSize)) return;
390
400
  const coverage = require_ot_layout_common.parseCoverage(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 2));
391
401
  if (coverage === void 0) return;
392
- const setCount = require_sfnt.u16(bytes, subtableOffset + 4);
402
+ const setCount = require_sfnt.u16(bytes, subtableOffset + SUBST_FORMAT_AND_COVERAGE_SIZE);
393
403
  const setOffsetsOffset = subtableOffset + prefixSize;
394
404
  if (!require_sfnt.hasBytes(bytes, setOffsetsOffset, setCount * 2)) return;
395
405
  const glyphEquality = (expected) => (glyphId) => glyphId === expected;
@@ -405,10 +415,10 @@ function parseContextualSubtable(bytes, chained, subtableOffset, skip, lookupOf)
405
415
  if (!require_sfnt.hasBytes(bytes, subtableOffset, prefixSize)) return;
406
416
  const coverage = require_ot_layout_common.parseCoverage(bytes, subtableOffset + require_sfnt.u16(bytes, subtableOffset + 2));
407
417
  if (coverage === void 0) return;
408
- const inputClassDefOffset = chained ? require_sfnt.u16(bytes, subtableOffset + 6) : require_sfnt.u16(bytes, subtableOffset + 4);
418
+ const inputClassDefOffset = chained ? require_sfnt.u16(bytes, subtableOffset + 6) : require_sfnt.u16(bytes, subtableOffset + SUBST_FORMAT_AND_COVERAGE_SIZE);
409
419
  const inputClassDef = inputClassDefOffset === 0 ? constantZeroClassDef : require_ot_layout_common.parseClassDef(bytes, subtableOffset + inputClassDefOffset);
410
420
  const readAuxClassDef = (offset) => offset === 0 ? constantZeroClassDef : require_ot_layout_common.parseClassDef(bytes, subtableOffset + offset);
411
- const backtrackClassDef = chained ? readAuxClassDef(require_sfnt.u16(bytes, subtableOffset + 4)) : constantZeroClassDef;
421
+ const backtrackClassDef = chained ? readAuxClassDef(require_sfnt.u16(bytes, subtableOffset + SUBST_FORMAT_AND_COVERAGE_SIZE)) : constantZeroClassDef;
412
422
  const lookaheadClassDef = chained ? readAuxClassDef(require_sfnt.u16(bytes, subtableOffset + 8)) : constantZeroClassDef;
413
423
  if (inputClassDef === void 0 || backtrackClassDef === void 0 || lookaheadClassDef === void 0) return;
414
424
  const setCount = require_sfnt.u16(bytes, subtableOffset + prefixSize - 2);
@@ -430,9 +440,9 @@ function findScriptOffset(bytes, scriptListOffset) {
430
440
  if (!require_sfnt.hasBytes(bytes, recordsOffset, scriptCount * SCRIPT_RECORD_SIZE) || scriptCount === 0) return;
431
441
  for (const wanted of PREFERRED_SCRIPT_TAGS) for (let i = 0; i < scriptCount; i++) {
432
442
  const recordOffset = recordsOffset + i * SCRIPT_RECORD_SIZE;
433
- if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + require_sfnt.u16(bytes, recordOffset + 4);
443
+ if (readTag(bytes, recordOffset) === wanted) return scriptListOffset + require_sfnt.u16(bytes, recordOffset + SCRIPT_RECORD_OFFSET_FIELD_OFFSET);
434
444
  }
435
- return scriptListOffset + require_sfnt.u16(bytes, recordsOffset + 4);
445
+ return scriptListOffset + require_sfnt.u16(bytes, recordsOffset + SCRIPT_RECORD_OFFSET_FIELD_OFFSET);
436
446
  }
437
447
  function parseDefaultLangSysFeatureIndices(bytes, scriptOffset) {
438
448
  if (!require_sfnt.hasBytes(bytes, scriptOffset, 2)) return [];
@@ -440,7 +450,7 @@ function parseDefaultLangSysFeatureIndices(bytes, scriptOffset) {
440
450
  if (defaultLangSysOffset === 0) return [];
441
451
  const langSysOffset = scriptOffset + defaultLangSysOffset;
442
452
  if (!require_sfnt.hasBytes(bytes, langSysOffset, LANG_SYS_HEADER_SIZE)) return [];
443
- const featureIndexCount = require_sfnt.u16(bytes, langSysOffset + 4);
453
+ const featureIndexCount = require_sfnt.u16(bytes, langSysOffset + LANG_SYS_FEATURE_INDEX_COUNT_OFFSET);
444
454
  const indicesOffset = langSysOffset + LANG_SYS_HEADER_SIZE;
445
455
  if (!require_sfnt.hasBytes(bytes, indicesOffset, featureIndexCount * 2)) return [];
446
456
  const indices = [];
@@ -458,7 +468,7 @@ function collectLookupIndices(bytes, featureListOffset, featureIndices, featureT
458
468
  if (featureIndex >= featureCount) continue;
459
469
  const recordOffset = recordsOffset + featureIndex * FEATURE_RECORD_SIZE;
460
470
  if (!featureTags.includes(readTag(bytes, recordOffset))) continue;
461
- const featureOffset = featureListOffset + require_sfnt.u16(bytes, recordOffset + 4);
471
+ const featureOffset = featureListOffset + require_sfnt.u16(bytes, recordOffset + FEATURE_RECORD_OFFSET_FIELD_OFFSET);
462
472
  if (!require_sfnt.hasBytes(bytes, featureOffset, FEATURE_HEADER_SIZE)) continue;
463
473
  const lookupIndexCount = require_sfnt.u16(bytes, featureOffset + 2);
464
474
  const indicesOffset = featureOffset + FEATURE_HEADER_SIZE;
@@ -476,12 +486,12 @@ function collectLookupIndices(bytes, featureListOffset, featureIndices, featureT
476
486
  function buildGsubShaper(font, options = {}) {
477
487
  const bytes = require_sfnt.sfntTableBytes(font, "GSUB");
478
488
  if (bytes === void 0 || !require_sfnt.hasBytes(bytes, 0, GSUB_HEADER_SIZE) || require_sfnt.u16(bytes, 0) !== 1) return;
479
- const scriptOffset = findScriptOffset(bytes, require_sfnt.u16(bytes, 4));
489
+ const scriptOffset = findScriptOffset(bytes, require_sfnt.u16(bytes, GSUB_HEADER_SCRIPT_LIST_OFFSET));
480
490
  if (scriptOffset === void 0) return;
481
491
  const featureTags = [...DEFAULT_GSUB_FEATURE_TAGS, ...options.optInFeatures ?? []];
482
- const lookupIndices = collectLookupIndices(bytes, require_sfnt.u16(bytes, 6), parseDefaultLangSysFeatureIndices(bytes, scriptOffset), featureTags);
492
+ const lookupIndices = collectLookupIndices(bytes, require_sfnt.u16(bytes, GSUB_HEADER_FEATURE_LIST_OFFSET), parseDefaultLangSysFeatureIndices(bytes, scriptOffset), featureTags);
483
493
  if (lookupIndices.length === 0) return;
484
- const lookupListOffset = require_sfnt.u16(bytes, 8);
494
+ const lookupListOffset = require_sfnt.u16(bytes, GSUB_HEADER_LOOKUP_LIST_OFFSET);
485
495
  if (!require_sfnt.hasBytes(bytes, lookupListOffset, 2)) return;
486
496
  const lookupCount = require_sfnt.u16(bytes, lookupListOffset);
487
497
  const lookupOffsetsOffset = lookupListOffset + 2;
@@ -497,7 +507,7 @@ function buildGsubShaper(font, options = {}) {
497
507
  }
498
508
  const lookupFlag = require_sfnt.u16(bytes, lookupOffset + 2);
499
509
  const lookupType = require_sfnt.u16(bytes, lookupOffset);
500
- const subTableCount = require_sfnt.u16(bytes, lookupOffset + 4);
510
+ const subTableCount = require_sfnt.u16(bytes, lookupOffset + LOOKUP_HEADER_SUBTABLE_COUNT_OFFSET);
501
511
  const subtableOffsetsOffset = lookupOffset + LOOKUP_HEADER_SIZE;
502
512
  const markFilteringSetWidth = (lookupFlag & LOOKUP_FLAG_USE_MARK_FILTERING_SET) !== 0 ? 2 : 0;
503
513
  if (!require_sfnt.hasBytes(bytes, subtableOffsetsOffset, subTableCount * 2 + markFilteringSetWidth)) {
@@ -526,8 +536,13 @@ function buildGsubShaper(font, options = {}) {
526
536
  for (const lookup of appliedLookups) {
527
537
  let slotIndex = 0;
528
538
  while (slotIndex < slots.length) {
529
- const advanced = applyLookupAtSlot(slots, slotIndex, lookup, 0);
530
- slotIndex += advanced !== 0 ? advanced : 1;
539
+ const application = applyLookupAtSlot(slots, slotIndex, lookup, 0);
540
+ if (application === void 0) {
541
+ slotIndex += 1;
542
+ continue;
543
+ }
544
+ slots.splice(slotIndex, application.consumed, ...application.replacement);
545
+ slotIndex += application.replacement.length !== 0 ? application.replacement.length : 1;
531
546
  }
532
547
  }
533
548
  return {