harfbuzzjs 1.0.0-beta.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -37,7 +37,7 @@ function hb_untag(tag) {
37
37
  }
38
38
  function utf8_ptr_to_string(ptr, length) {
39
39
  let end;
40
- if (length === void 0) end = Module.HEAPU8.indexOf(0, ptr);
40
+ if (length == void 0) end = Module.HEAPU8.indexOf(0, ptr);
41
41
  else end = ptr + length;
42
42
  return utf8Decoder.decode(Module.HEAPU8.subarray(ptr, end));
43
43
  }
@@ -355,7 +355,7 @@ var Face = class {
355
355
  * Get the name IDs of the specified feature.
356
356
  * @param table The table to query, either "GSUB" or "GPOS".
357
357
  * @param featureIndex The index of the feature to query.
358
- * @returns An object with name IDs, or null if not found.
358
+ * @returns An object with name IDs, or undefined if not found.
359
359
  */
360
360
  getFeatureNameIds(table, featureIndex) {
361
361
  const sp = Module.stackSave();
@@ -366,20 +366,17 @@ var Face = class {
366
366
  const numNamedParametersPtr = Module.stackAlloc(4);
367
367
  const firstParameterIdPtr = Module.stackAlloc(4);
368
368
  const found = exports.hb_ot_layout_feature_get_name_ids(this.ptr, tableTag, featureIndex, labelIdPtr, tooltipIdPtr, sampleIdPtr, numNamedParametersPtr, firstParameterIdPtr);
369
- let names = null;
369
+ let names;
370
370
  if (found) {
371
371
  const uiLabelNameId = Module.HEAPU32[labelIdPtr / 4];
372
372
  const uiTooltipTextNameId = Module.HEAPU32[tooltipIdPtr / 4];
373
373
  const sampleTextNameId = Module.HEAPU32[sampleIdPtr / 4];
374
374
  const numNamedParameters = Module.HEAPU32[numNamedParametersPtr / 4];
375
375
  const firstParameterId = Module.HEAPU32[firstParameterIdPtr / 4];
376
- const paramUiLabelNameIds = Array.from({ length: numNamedParameters }, (_, i) => firstParameterId + i);
377
- names = {
378
- uiLabelNameId: uiLabelNameId == HB_OT_NAME_ID_INVALID ? null : uiLabelNameId,
379
- uiTooltipTextNameId: uiTooltipTextNameId == HB_OT_NAME_ID_INVALID ? null : uiTooltipTextNameId,
380
- sampleTextNameId: sampleTextNameId == HB_OT_NAME_ID_INVALID ? null : sampleTextNameId,
381
- paramUiLabelNameIds
382
- };
376
+ names = { paramUiLabelNameIds: Array.from({ length: numNamedParameters }, (_, i) => firstParameterId + i) };
377
+ if (uiLabelNameId != HB_OT_NAME_ID_INVALID) names.uiLabelNameId = uiLabelNameId;
378
+ if (uiTooltipTextNameId != HB_OT_NAME_ID_INVALID) names.uiTooltipTextNameId = uiTooltipTextNameId;
379
+ if (sampleTextNameId != HB_OT_NAME_ID_INVALID) names.sampleTextNameId = sampleTextNameId;
383
380
  }
384
381
  Module.stackRestore(sp);
385
382
  return names;
@@ -395,15 +392,7 @@ var Face = class {
395
392
  */
396
393
  var Font = class Font {
397
394
  constructor(arg) {
398
- this.drawPtrs = {
399
- drawFuncsPtr: null,
400
- moveToPtr: null,
401
- lineToPtr: null,
402
- cubicToPtr: null,
403
- quadToPtr: null,
404
- closePathPtr: null,
405
- pathBuffer: ""
406
- };
395
+ this.drawPtrs = { pathBuffer: "" };
407
396
  if (typeof arg === "number") this.ptr = exports.hb_font_reference(arg);
408
397
  else this.ptr = exports.hb_font_create(arg.ptr);
409
398
  const ptr = this.ptr;
@@ -531,13 +520,13 @@ var Font = class Font {
531
520
  /**
532
521
  * Return glyph horizontal origin.
533
522
  * @param glyphId ID of the requested glyph in the font.
534
- * @returns [x, y] origin coordinates, or null if not available.
523
+ * @returns [x, y] origin coordinates, or undefined if not available.
535
524
  */
536
525
  glyphHOrigin(glyphId) {
537
526
  const sp = Module.stackSave();
538
527
  const xPtr = Module.stackAlloc(4);
539
528
  const yPtr = Module.stackAlloc(4);
540
- let origin = null;
529
+ let origin;
541
530
  if (exports.hb_font_get_glyph_h_origin(this.ptr, glyphId, xPtr, yPtr)) origin = [Module.HEAP32[xPtr / 4], Module.HEAP32[yPtr / 4]];
542
531
  Module.stackRestore(sp);
543
532
  return origin;
@@ -545,13 +534,13 @@ var Font = class Font {
545
534
  /**
546
535
  * Return glyph vertical origin.
547
536
  * @param glyphId ID of the requested glyph in the font.
548
- * @returns [x, y] origin coordinates, or null if not available.
537
+ * @returns [x, y] origin coordinates, or undefined if not available.
549
538
  */
550
539
  glyphVOrigin(glyphId) {
551
540
  const sp = Module.stackSave();
552
541
  const xPtr = Module.stackAlloc(4);
553
542
  const yPtr = Module.stackAlloc(4);
554
- let origin = null;
543
+ let origin;
555
544
  if (exports.hb_font_get_glyph_v_origin(this.ptr, glyphId, xPtr, yPtr)) origin = [Module.HEAP32[xPtr / 4], Module.HEAP32[yPtr / 4]];
556
545
  Module.stackRestore(sp);
557
546
  return origin;
@@ -559,12 +548,12 @@ var Font = class Font {
559
548
  /**
560
549
  * Return glyph extents.
561
550
  * @param glyphId ID of the requested glyph in the font.
562
- * @returns An object with xBearing, yBearing, width, and height, or null.
551
+ * @returns An object with xBearing, yBearing, width, and height, or undefined.
563
552
  */
564
553
  glyphExtents(glyphId) {
565
554
  const sp = Module.stackSave();
566
555
  const extentsPtr = Module.stackAlloc(16);
567
- let extents = null;
556
+ let extents;
568
557
  if (exports.hb_font_get_glyph_extents(this.ptr, glyphId, extentsPtr)) extents = {
569
558
  xBearing: Module.HEAP32[extentsPtr / 4],
570
559
  yBearing: Module.HEAP32[extentsPtr / 4 + 1],
@@ -575,15 +564,71 @@ var Font = class Font {
575
564
  return extents;
576
565
  }
577
566
  /**
567
+ * Fetches the glyph ID for a Unicode code point in the specified
568
+ * font, with an optional variation selector.
569
+ *
570
+ * If `variationSelector` is 0, it is equivalent to
571
+ * {@link Font.nominalGlyph}; otherwise it is equivalent to
572
+ * {@link Font.variationGlyph}.
573
+ *
574
+ * @param unicode The Unicode code point to query.
575
+ * @param variationSelector A variation-selector code point.
576
+ * @returns The glyph ID, or undefined if not found.
577
+ */
578
+ glyph(unicode, variationSelector = 0) {
579
+ const sp = Module.stackSave();
580
+ const glyphIdPtr = Module.stackAlloc(4);
581
+ let glyphId;
582
+ if (exports.hb_font_get_glyph(this.ptr, unicode, variationSelector, glyphIdPtr)) glyphId = Module.HEAPU32[glyphIdPtr / 4];
583
+ Module.stackRestore(sp);
584
+ return glyphId;
585
+ }
586
+ /**
587
+ * Fetches the nominal glyph ID for a Unicode code point in the
588
+ * specified font.
589
+ *
590
+ * This version of the function should not be used to fetch glyph IDs
591
+ * for code points modified by variation selectors. For variation-selector
592
+ * support, use {@link Font.variationGlyph} or {@link Font.glyph}.
593
+ *
594
+ * @param unicode The Unicode code point to query.
595
+ * @returns The glyph ID, or undefined if not found.
596
+ */
597
+ nominalGlyph(unicode) {
598
+ const sp = Module.stackSave();
599
+ const glyphIdPtr = Module.stackAlloc(4);
600
+ let glyphId;
601
+ if (exports.hb_font_get_nominal_glyph(this.ptr, unicode, glyphIdPtr)) glyphId = Module.HEAPU32[glyphIdPtr / 4];
602
+ Module.stackRestore(sp);
603
+ return glyphId;
604
+ }
605
+ /**
606
+ * Fetches the glyph ID for a Unicode code point when followed by
607
+ * by the specified variation-selector code point, in the specified
608
+ * font.
609
+ *
610
+ * @param unicode The Unicode code point to query.
611
+ * @param variationSelector The variation-selector code point to query.
612
+ * @returns The glyph ID, or undefined if not found.
613
+ */
614
+ variationGlyph(unicode, variationSelector) {
615
+ const sp = Module.stackSave();
616
+ const glyphIdPtr = Module.stackAlloc(4);
617
+ let glyphId;
618
+ if (exports.hb_font_get_variation_glyph(this.ptr, unicode, variationSelector, glyphIdPtr)) glyphId = Module.HEAPU32[glyphIdPtr / 4];
619
+ Module.stackRestore(sp);
620
+ return glyphId;
621
+ }
622
+ /**
578
623
  * Return glyph ID from name.
579
624
  * @param name Name of the requested glyph in the font.
580
- * @returns The glyph ID, or null if not found.
625
+ * @returns The glyph ID, or undefined if not found.
581
626
  */
582
627
  glyphFromName(name) {
583
628
  const sp = Module.stackSave();
584
629
  const glyphIdPtr = Module.stackAlloc(4);
585
630
  const namePtr = string_to_utf8_ptr(name);
586
- let glyphId = null;
631
+ let glyphId;
587
632
  if (exports.hb_font_get_glyph_from_name(this.ptr, namePtr.ptr, namePtr.length, glyphIdPtr)) glyphId = Module.HEAPU32[glyphIdPtr / 4];
588
633
  namePtr.free();
589
634
  Module.stackRestore(sp);
@@ -614,18 +659,22 @@ var Font = class Font {
614
659
  exports.hb_font_set_scale(this.ptr, xScale, yScale);
615
660
  }
616
661
  /**
617
- * Set the font's variations.
618
- * @param variations Dictionary of variations to set.
662
+ * Applies a list of font-variation settings to a font.
663
+ *
664
+ * Note that this overrides all existing variations set on the font.
665
+ * Axes not included in `variations` will be effectively set to their
666
+ * default values.
667
+ *
668
+ * @param variations Array of variation settings to apply.
619
669
  */
620
670
  setVariations(variations) {
621
- const entries = Object.entries(variations);
622
- const vars = exports.malloc(8 * entries.length);
623
- entries.forEach(([tag, value], i) => {
624
- Module.HEAPU32[vars / 4 + i * 2 + 0] = hb_tag(tag);
625
- Module.HEAPF32[vars / 4 + i * 2 + 1] = value;
671
+ const sp = Module.stackSave();
672
+ const vars = Module.stackAlloc(8 * variations.length);
673
+ variations.forEach((variation, i) => {
674
+ variation.writeTo(vars + i * 8);
626
675
  });
627
- exports.hb_font_set_variations(this.ptr, vars, entries.length);
628
- exports.free(vars);
676
+ exports.hb_font_set_variations(this.ptr, vars, variations.length);
677
+ Module.stackRestore(sp);
629
678
  }
630
679
  /** Set the font's font functions. */
631
680
  setFuncs(fontFuncs) {
@@ -648,7 +697,7 @@ var FontFuncs = class {
648
697
  /**
649
698
  * Set the font's glyph extents function.
650
699
  * @param func The callback receives a Font and glyph ID. It should return
651
- * an object with xBearing, yBearing, width, and height, or null on failure.
700
+ * an object with xBearing, yBearing, width, and height, or undefined on failure.
652
701
  */
653
702
  setGlyphExtentsFunc(func) {
654
703
  const funcPtr = Module.addFunction((fontPtr, font_data, glyph, extentsPtr, user_data) => {
@@ -667,7 +716,7 @@ var FontFuncs = class {
667
716
  /**
668
717
  * Set the font's glyph from name function.
669
718
  * @param func The callback receives a Font and glyph name. It should return
670
- * the glyph ID, or null on failure.
719
+ * the glyph ID, or undefined on failure.
671
720
  */
672
721
  setGlyphFromNameFunc(func) {
673
722
  const funcPtr = Module.addFunction((fontPtr, font_data, namePtr, len, glyphPtr, user_data) => {
@@ -705,7 +754,7 @@ var FontFuncs = class {
705
754
  /**
706
755
  * Set the font's glyph horizontal origin function.
707
756
  * @param func The callback receives a Font and glyph ID. It should return
708
- * the [x, y] horizontal origin of the glyph, or null on failure.
757
+ * the [x, y] horizontal origin of the glyph, or undefined on failure.
709
758
  */
710
759
  setGlyphHOriginFunc(func) {
711
760
  const funcPtr = Module.addFunction((fontPtr, font_data, glyph, xPtr, yPtr, user_data) => {
@@ -722,7 +771,7 @@ var FontFuncs = class {
722
771
  /**
723
772
  * Set the font's glyph vertical origin function.
724
773
  * @param func The callback receives a Font and glyph ID. It should return
725
- * the [x, y] vertical origin of the glyph, or null on failure.
774
+ * the [x, y] vertical origin of the glyph, or undefined on failure.
726
775
  */
727
776
  setGlyphVOriginFunc(func) {
728
777
  const funcPtr = Module.addFunction((fontPtr, font_data, glyph, xPtr, yPtr, user_data) => {
@@ -750,7 +799,7 @@ var FontFuncs = class {
750
799
  /**
751
800
  * Set the font's glyph name function.
752
801
  * @param func The callback receives a Font and glyph ID. It should return
753
- * the name of the glyph, or null on failure.
802
+ * the name of the glyph, or undefined on failure.
754
803
  */
755
804
  setGlyphNameFunc(func) {
756
805
  const utf8Encoder = new TextEncoder();
@@ -767,7 +816,7 @@ var FontFuncs = class {
767
816
  /**
768
817
  * Set the font's nominal glyph function.
769
818
  * @param func The callback receives a Font and unicode code point. It should
770
- * return the nominal glyph of the unicode, or null on failure.
819
+ * return the nominal glyph of the unicode, or undefined on failure.
771
820
  */
772
821
  setNominalGlyphFunc(func) {
773
822
  const funcPtr = Module.addFunction((fontPtr, font_data, unicode, glyphPtr, user_data) => {
@@ -783,7 +832,7 @@ var FontFuncs = class {
783
832
  /**
784
833
  * Set the font's variation glyph function.
785
834
  * @param func The callback receives a Font, unicode code point, and variation
786
- * selector. It should return the variation glyph, or null on failure.
835
+ * selector. It should return the variation glyph, or undefined on failure.
787
836
  */
788
837
  setVariationGlyphFunc(func) {
789
838
  const funcPtr = Module.addFunction((fontPtr, font_data, unicode, variationSelector, glyphPtr, user_data) => {
@@ -799,7 +848,7 @@ var FontFuncs = class {
799
848
  /**
800
849
  * Set the font's horizontal extents function.
801
850
  * @param func The callback receives a Font. It should return an object with
802
- * ascender, descender, and lineGap, or null on failure.
851
+ * ascender, descender, and lineGap, or undefined on failure.
803
852
  */
804
853
  setFontHExtentsFunc(func) {
805
854
  const funcPtr = Module.addFunction((fontPtr, font_data, extentsPtr, user_data) => {
@@ -817,7 +866,7 @@ var FontFuncs = class {
817
866
  /**
818
867
  * Set the font's vertical extents function.
819
868
  * @param func The callback receives a Font. It should return an object with
820
- * ascender, descender, and lineGap, or null on failure.
869
+ * ascender, descender, and lineGap, or undefined on failure.
821
870
  */
822
871
  setFontVExtentsFunc(func) {
823
872
  const funcPtr = Module.addFunction((fontPtr, font_data, extentsPtr, user_data) => {
@@ -869,6 +918,13 @@ const Direction = {
869
918
  TTB: 6,
870
919
  BTT: 7
871
920
  };
921
+ const ClusterLevel = {
922
+ MONOTONE_GRAPHEMES: 0,
923
+ MONOTONE_CHARACTERS: 1,
924
+ CHARACTERS: 2,
925
+ GRAPHEMES: 3,
926
+ DEFAULT: 0
927
+ };
872
928
  const BufferSerializeFormat = {
873
929
  INVALID: 0,
874
930
  TEXT: hb_tag("TEXT"),
@@ -880,34 +936,50 @@ const BufferSerializeFormat = {
880
936
  * output glyphs and their information after shaping.
881
937
  */
882
938
  var Buffer = class Buffer {
939
+ /**
940
+ * @param existingPtr @internal Wrap an existing buffer pointer.
941
+ */
883
942
  constructor(existingPtr) {
884
- if (existingPtr !== void 0) this.ptr = exports.hb_buffer_reference(existingPtr);
943
+ if (existingPtr != void 0) this.ptr = exports.hb_buffer_reference(existingPtr);
885
944
  else this.ptr = exports.hb_buffer_create();
886
945
  track(this, exports.hb_buffer_destroy);
887
946
  }
888
947
  /**
948
+ * Appends a character with the Unicode value of `codePoint` to the buffer,
949
+ * and gives it the initial cluster value of `cluster`. Clusters can be any
950
+ * thing the client wants, they are usually used to refer to the index of the
951
+ * character in the input text stream and are output in the `cluster` field
952
+ * of {@link GlyphInfo}.
953
+ *
954
+ * This function does not check the validity of `codePoint`, it is up to the
955
+ * caller to ensure it is a valid Unicode code point.
956
+ * @param codePoint A Unicode code point.
957
+ * @param cluster The cluster value of `codePoint`.
958
+ */
959
+ add(codePoint, cluster) {
960
+ exports.hb_buffer_add(this.ptr, codePoint, cluster);
961
+ }
962
+ /**
889
963
  * Add text to the buffer.
890
964
  * @param text Text to be added to the buffer.
891
965
  * @param itemOffset The offset of the first character to add to the buffer.
892
- * @param itemLength The number of characters to add to the buffer, or null for the end of text.
966
+ * @param itemLength The number of characters to add to the buffer, or omit for the end of text.
893
967
  */
894
- addText(text, itemOffset = 0, itemLength = null) {
968
+ addText(text, itemOffset = 0, itemLength) {
895
969
  const str = string_to_utf16_ptr(text);
896
- if (itemLength == null) itemLength = str.length;
897
- exports.hb_buffer_add_utf16(this.ptr, str.ptr, str.length, itemOffset, itemLength);
970
+ exports.hb_buffer_add_utf16(this.ptr, str.ptr, str.length, itemOffset, itemLength ?? str.length);
898
971
  str.free();
899
972
  }
900
973
  /**
901
974
  * Add code points to the buffer.
902
975
  * @param codePoints Array of code points to be added to the buffer.
903
976
  * @param itemOffset The offset of the first code point to add to the buffer.
904
- * @param itemLength The number of code points to add to the buffer, or null for the end of the array.
977
+ * @param itemLength The number of code points to add to the buffer, or omit for the end of the array.
905
978
  */
906
- addCodePoints(codePoints, itemOffset = 0, itemLength = null) {
979
+ addCodePoints(codePoints, itemOffset = 0, itemLength) {
907
980
  const codePointsPtr = exports.malloc(codePoints.length * 4);
908
981
  Module.HEAPU32.subarray(codePointsPtr / 4, codePointsPtr / 4 + codePoints.length).set(codePoints);
909
- if (itemLength == null) itemLength = codePoints.length;
910
- exports.hb_buffer_add_codepoints(this.ptr, codePointsPtr, codePoints.length, itemOffset, itemLength);
982
+ exports.hb_buffer_add_codepoints(this.ptr, codePointsPtr, codePoints.length, itemOffset, itemLength ?? codePoints.length);
911
983
  exports.free(codePointsPtr);
912
984
  }
913
985
  /**
@@ -954,7 +1026,7 @@ var Buffer = class Buffer {
954
1026
  * Set the HarfBuzz clustering level.
955
1027
  *
956
1028
  * Affects the cluster values returned from shaping.
957
- * @param level Clustering level. See the HarfBuzz manual chapter on Clusters.
1029
+ * @param level A {@link ClusterLevel} value. See the HarfBuzz manual chapter on Clusters.
958
1030
  */
959
1031
  setClusterLevel(level) {
960
1032
  exports.hb_buffer_set_cluster_level(this.ptr, level);
@@ -996,12 +1068,13 @@ var Buffer = class Buffer {
996
1068
  * @returns An array of {@link GlyphInfo} objects.
997
1069
  */
998
1070
  getGlyphInfos() {
999
- const infosPtr32 = exports.hb_buffer_get_glyph_infos(this.ptr, 0) / 4;
1000
- const infosArray = Module.HEAPU32.subarray(infosPtr32, infosPtr32 + this.getLength() * 5);
1071
+ const infosPtr = exports.hb_buffer_get_glyph_infos(this.ptr, 0);
1072
+ const infosArray = Module.HEAPU32.subarray(infosPtr / 4, infosPtr / 4 + this.getLength() * 5);
1001
1073
  const infos = [];
1002
1074
  for (let i = 0; i < infosArray.length; i += 5) infos.push({
1003
1075
  codepoint: infosArray[i],
1004
- cluster: infosArray[i + 2]
1076
+ cluster: infosArray[i + 2],
1077
+ flags: exports.hb_glyph_info_get_glyph_flags(infosPtr + i * 4)
1005
1078
  });
1006
1079
  return infos;
1007
1080
  }
@@ -1030,15 +1103,16 @@ var Buffer = class Buffer {
1030
1103
  * properties from getGlyphInfos and getGlyphPositions combined.
1031
1104
  */
1032
1105
  getGlyphInfosAndPositions() {
1033
- const infosPtr32 = exports.hb_buffer_get_glyph_infos(this.ptr, 0) / 4;
1034
- const infosArray = Module.HEAPU32.subarray(infosPtr32, infosPtr32 + this.getLength() * 5);
1106
+ const infosPtr = exports.hb_buffer_get_glyph_infos(this.ptr, 0);
1107
+ const infosArray = Module.HEAPU32.subarray(infosPtr / 4, infosPtr / 4 + this.getLength() * 5);
1035
1108
  const positionsPtr32 = exports.hb_buffer_get_glyph_positions(this.ptr, 0) / 4;
1036
- const positionsArray = positionsPtr32 ? Module.HEAP32.subarray(positionsPtr32, positionsPtr32 + this.getLength() * 5) : null;
1109
+ const positionsArray = positionsPtr32 ? Module.HEAP32.subarray(positionsPtr32, positionsPtr32 + this.getLength() * 5) : void 0;
1037
1110
  const out = [];
1038
1111
  for (let i = 0; i < infosArray.length; i += 5) {
1039
1112
  const info = {
1040
1113
  codepoint: infosArray[i],
1041
- cluster: infosArray[i + 2]
1114
+ cluster: infosArray[i + 2],
1115
+ flags: exports.hb_glyph_info_get_glyph_flags(infosPtr + i * 4)
1042
1116
  };
1043
1117
  for (const [name, idx] of [
1044
1118
  ["mask", 1],
@@ -1080,15 +1154,16 @@ var Buffer = class Buffer {
1080
1154
  }
1081
1155
  /**
1082
1156
  * Serialize the buffer contents to a string.
1083
- * @param font The font to use for serialization.
1084
- * @param start The starting index of the glyphs to serialize.
1085
- * @param end The ending index of the glyphs to serialize.
1086
- * @param format The {@link BufferSerializeFormat} to serialize the buffer contents to.
1087
- * @param flags A combination of {@link BufferSerializeFlag} values (OR them together).
1088
- *
1157
+ * @param options Serialization options:
1158
+ * - `font`: the font to use for serialization;
1159
+ * - `start`: the starting index of the glyphs (default `0`);
1160
+ * - `end`: the ending index of the glyphs (default end of buffer);
1161
+ * - `format`: a {@link BufferSerializeFormat} value (default `TEXT`);
1162
+ * - `flags`: a combination of {@link BufferSerializeFlag} values (default `0`).
1089
1163
  * @returns The serialized buffer contents.
1090
1164
  */
1091
- serialize(font, start = 0, end, format = BufferSerializeFormat.TEXT, flags = 0) {
1165
+ serialize(options = {}) {
1166
+ let { font, start = 0, end, format = BufferSerializeFormat.TEXT, flags = 0 } = options;
1092
1167
  const sp = Module.stackSave();
1093
1168
  const endPos = end ?? this.getLength();
1094
1169
  const bufLen = 32 * 1024;
@@ -1113,13 +1188,161 @@ var Buffer = class Buffer {
1113
1188
  getContentType() {
1114
1189
  return exports.hb_buffer_get_content_type(this.ptr);
1115
1190
  }
1191
+ };
1192
+ //#endregion
1193
+ //#region src/feature.ts
1194
+ /**
1195
+ * A {@link https://harfbuzz.github.io/harfbuzz-hb-common.html#hb-feature-t | HarfBuzz feature}.
1196
+ *
1197
+ * The structure that holds information about requested feature application.
1198
+ * The feature will be applied with the given value to all glyphs which are in
1199
+ * clusters between {@link Feature.start} (inclusive) and {@link Feature.end}
1200
+ * (exclusive). Setting `start` to `0` and `end` to `0xffffffff` specifies that
1201
+ * the feature always applies to the entire buffer.
1202
+ */
1203
+ var Feature = class Feature {
1204
+ static {
1205
+ this.GLOBAL_START = 0;
1206
+ }
1207
+ static {
1208
+ this.GLOBAL_END = 4294967295;
1209
+ }
1210
+ constructor(tag, value = 1, start = Feature.GLOBAL_START, end = Feature.GLOBAL_END) {
1211
+ this.tag = tag;
1212
+ this.value = value;
1213
+ this.start = start;
1214
+ this.end = end;
1215
+ }
1116
1216
  /**
1117
- * Return the buffer contents as a JSON object.
1118
- * @returns An array of {@link JsonGlyph} objects.
1217
+ * Parses a string into a Feature.
1218
+ *
1219
+ * The format for specifying feature strings follows. All valid CSS
1220
+ * font-feature-settings values other than `normal` and the global values are
1221
+ * also accepted, though not documented below. CSS string escapes are not
1222
+ * supported.
1223
+ *
1224
+ * The range indices refer to the positions between Unicode characters. The
1225
+ * position before the first character is always 0.
1226
+ *
1227
+ * The format is Python-esque. Here is how it all works:
1228
+ *
1229
+ * | Syntax | Value | Start | End | Meaning |
1230
+ * | ------------- | ----- | ----- | --- | -------------------------------- |
1231
+ * | `kern` | 1 | 0 | ∞ | Turn feature on |
1232
+ * | `+kern` | 1 | 0 | ∞ | Turn feature on |
1233
+ * | `-kern` | 0 | 0 | ∞ | Turn feature off |
1234
+ * | `kern=0` | 0 | 0 | ∞ | Turn feature off |
1235
+ * | `kern=1` | 1 | 0 | ∞ | Turn feature on |
1236
+ * | `aalt=2` | 2 | 0 | ∞ | Choose 2nd alternate |
1237
+ * | `kern[]` | 1 | 0 | ∞ | Turn feature on |
1238
+ * | `kern[:]` | 1 | 0 | ∞ | Turn feature on |
1239
+ * | `kern[5:]` | 1 | 5 | ∞ | Turn feature on, partial |
1240
+ * | `kern[:5]` | 1 | 0 | 5 | Turn feature on, partial |
1241
+ * | `kern[3:5]` | 1 | 3 | 5 | Turn feature on, range |
1242
+ * | `kern[3]` | 1 | 3 | 3+1 | Turn feature on, single char |
1243
+ * | `aalt[3:5]=2` | 2 | 3 | 5 | Turn 2nd alternate on for range |
1244
+ *
1245
+ * @param str The string to parse.
1246
+ * @returns A Feature, or undefined if the string is not a valid feature.
1119
1247
  */
1120
- json() {
1121
- const buf = this.serialize(null, 0, null, BufferSerializeFormat.JSON, BufferSerializeFlag.NO_GLYPH_NAMES | BufferSerializeFlag.GLYPH_FLAGS);
1122
- return JSON.parse(buf);
1248
+ static fromString(str) {
1249
+ const sp = Module.stackSave();
1250
+ const featurePtr = Module.stackAlloc(16);
1251
+ const strPtr = string_to_ascii_ptr(str);
1252
+ let feature;
1253
+ if (exports.hb_feature_from_string(strPtr.ptr, -1, featurePtr)) feature = new Feature(hb_untag(Module.HEAPU32[featurePtr / 4]), Module.HEAPU32[featurePtr / 4 + 1], Module.HEAPU32[featurePtr / 4 + 2], Module.HEAPU32[featurePtr / 4 + 3]);
1254
+ strPtr.free();
1255
+ Module.stackRestore(sp);
1256
+ return feature;
1257
+ }
1258
+ /**
1259
+ * Converts the feature to a string in the format understood by
1260
+ * {@link Feature.fromString}.
1261
+ *
1262
+ * Note that the feature value will be omitted if it is `1`, but the string
1263
+ * won't include any whitespace.
1264
+ *
1265
+ * @returns The feature string.
1266
+ */
1267
+ toString() {
1268
+ const sp = Module.stackSave();
1269
+ const featurePtr = Module.stackAlloc(16);
1270
+ this.writeTo(featurePtr);
1271
+ const bufLen = 128;
1272
+ const bufPtr = Module.stackAlloc(bufLen);
1273
+ exports.hb_feature_to_string(featurePtr, bufPtr, bufLen);
1274
+ const result = utf8_ptr_to_string(bufPtr);
1275
+ Module.stackRestore(sp);
1276
+ return result;
1277
+ }
1278
+ /** @internal Write this feature into the given hb_feature_t pointer. */
1279
+ writeTo(ptr) {
1280
+ Module.HEAPU32[ptr / 4] = hb_tag(this.tag);
1281
+ Module.HEAPU32[ptr / 4 + 1] = this.value;
1282
+ Module.HEAPU32[ptr / 4 + 2] = this.start;
1283
+ Module.HEAPU32[ptr / 4 + 3] = this.end;
1284
+ }
1285
+ };
1286
+ //#endregion
1287
+ //#region src/variation.ts
1288
+ /**
1289
+ * A {@link https://harfbuzz.github.io/harfbuzz-hb-common.html#hb-variation-t | HarfBuzz variation}.
1290
+ *
1291
+ * Data type for holding variation data. Registered OpenType variation-axis
1292
+ * tags are listed in
1293
+ * {@link https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg | OpenType Axis Tag Registry}.
1294
+ */
1295
+ var Variation = class Variation {
1296
+ constructor(tag, value = 0) {
1297
+ this.tag = tag;
1298
+ this.value = value;
1299
+ }
1300
+ /**
1301
+ * Parses a string into a Variation.
1302
+ *
1303
+ * The format for specifying variation settings follows. All valid CSS
1304
+ * font-variation-settings values other than `normal` and `inherited` are
1305
+ * also accepted, though, not documented below.
1306
+ *
1307
+ * The format is a tag, optionally followed by an equals sign, followed by a
1308
+ * number. For example `wght=500`, or `slnt=-7.5`.
1309
+ *
1310
+ * @param str The string to parse.
1311
+ * @returns A Variation, or undefined if the string is not a valid variation.
1312
+ */
1313
+ static fromString(str) {
1314
+ const sp = Module.stackSave();
1315
+ const variationPtr = Module.stackAlloc(8);
1316
+ const strPtr = string_to_ascii_ptr(str);
1317
+ let variation;
1318
+ if (exports.hb_variation_from_string(strPtr.ptr, -1, variationPtr)) variation = new Variation(hb_untag(Module.HEAPU32[variationPtr / 4]), Module.HEAPF32[variationPtr / 4 + 1]);
1319
+ strPtr.free();
1320
+ Module.stackRestore(sp);
1321
+ return variation;
1322
+ }
1323
+ /**
1324
+ * Converts the variation to a string in the format understood by
1325
+ * {@link Variation.fromString}.
1326
+ *
1327
+ * Note that the string won't include any whitespace.
1328
+ *
1329
+ * @returns The variation string.
1330
+ */
1331
+ toString() {
1332
+ const sp = Module.stackSave();
1333
+ const variationPtr = Module.stackAlloc(8);
1334
+ this.writeTo(variationPtr);
1335
+ const bufLen = 128;
1336
+ const bufPtr = Module.stackAlloc(bufLen);
1337
+ exports.hb_variation_to_string(variationPtr, bufPtr, bufLen);
1338
+ const result = utf8_ptr_to_string(bufPtr);
1339
+ Module.stackRestore(sp);
1340
+ return result;
1341
+ }
1342
+ /** @internal Write this variation into the given hb_variation_t pointer. */
1343
+ writeTo(ptr) {
1344
+ Module.HEAPU32[ptr / 4] = hb_tag(this.tag);
1345
+ Module.HEAPF32[ptr / 4 + 1] = this.value;
1123
1346
  }
1124
1347
  };
1125
1348
  //#endregion
@@ -1138,22 +1361,20 @@ const TracePhase = {
1138
1361
  * @param font The Font to shape with.
1139
1362
  * @param buffer The Buffer containing text to shape, suitably prepared
1140
1363
  * (text added, segment properties set).
1141
- * @param features A string of comma-separated OpenType features to apply.
1364
+ * @param features An array of {@link Feature} values to apply.
1142
1365
  */
1143
1366
  function shape(font, buffer, features) {
1367
+ const featuresLen = features?.length ?? 0;
1368
+ const sp = Module.stackSave();
1144
1369
  let featuresPtr = 0;
1145
- let featuresLen = 0;
1146
- if (features) {
1147
- const featureList = features.split(",");
1148
- featuresPtr = exports.malloc(16 * featureList.length);
1149
- featureList.forEach((feature) => {
1150
- const str = string_to_ascii_ptr(feature);
1151
- if (exports.hb_feature_from_string(str.ptr, -1, featuresPtr + featuresLen * 16)) featuresLen++;
1152
- str.free();
1370
+ if (featuresLen) {
1371
+ featuresPtr = Module.stackAlloc(16 * featuresLen);
1372
+ features.forEach((feature, i) => {
1373
+ feature.writeTo(featuresPtr + i * 16);
1153
1374
  });
1154
1375
  }
1155
1376
  exports.hb_shape(font.ptr, buffer.ptr, featuresPtr, featuresLen);
1156
- if (featuresPtr) exports.free(featuresPtr);
1377
+ Module.stackRestore(sp);
1157
1378
  }
1158
1379
  /**
1159
1380
  * Shape a buffer with a given font, returning a JSON trace of the shaping process.
@@ -1163,7 +1384,7 @@ function shape(font, buffer, features) {
1163
1384
  *
1164
1385
  * @param font The Font to shape with.
1165
1386
  * @param buffer The Buffer containing text to shape, suitably prepared.
1166
- * @param features A string of comma-separated OpenType features to apply.
1387
+ * @param features An array of {@link Feature} values to apply.
1167
1388
  * @param stop_at A lookup ID at which to terminate shaping.
1168
1389
  * @param stop_phase The {@link TracePhase} at which to stop shaping.
1169
1390
  * @returns An array of trace entries, each with a message, serialized glyphs, and phase info.
@@ -1178,7 +1399,11 @@ function shapeWithTrace(font, buffer, features, stop_at, stop_phase) {
1178
1399
  if (currentPhase != stop_phase) stopping = false;
1179
1400
  if (stop_phase != TracePhase.DONT_STOP && currentPhase == stop_phase && message.startsWith("end lookup " + stop_at)) stopping = true;
1180
1401
  if (stopping) return false;
1181
- const traceBuf = buffer.serialize(font, 0, null, BufferSerializeFormat.JSON, BufferSerializeFlag.NO_GLYPH_NAMES);
1402
+ const traceBuf = buffer.serialize({
1403
+ font,
1404
+ format: BufferSerializeFormat.JSON,
1405
+ flags: BufferSerializeFlag.NO_GLYPH_NAMES
1406
+ });
1182
1407
  trace.push({
1183
1408
  m: message,
1184
1409
  t: JSON.parse(traceBuf),
@@ -1234,4 +1459,4 @@ function otTagToLanguage(tag) {
1234
1459
  //#region src/index.ts
1235
1460
  init(await createHarfBuzz());
1236
1461
  //#endregion
1237
- export { Blob, Buffer, BufferContentType, BufferFlag, BufferSerializeFlag, BufferSerializeFormat, Direction, Face, Font, FontFuncs, GlyphClass, GlyphFlag, TracePhase, otTagToLanguage, otTagToScript, shape, shapeWithTrace, version, versionString };
1462
+ export { Blob, Buffer, BufferContentType, BufferFlag, BufferSerializeFlag, BufferSerializeFormat, ClusterLevel, Direction, Face, Feature, Font, FontFuncs, GlyphClass, GlyphFlag, TracePhase, Variation, otTagToLanguage, otTagToScript, shape, shapeWithTrace, version, versionString };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harfbuzzjs",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0",
4
4
  "description": "Minimal version of HarfBuzz for JavaScript use",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",