harfbuzzjs 0.2.1 → 0.3.1

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 (63) hide show
  1. package/.github/workflows/build.yml +45 -0
  2. package/.gitmodules +3 -0
  3. package/LICENSE +0 -1
  4. package/README.md +2 -8
  5. package/build-subset.sh +21 -0
  6. package/build.sh +17 -57
  7. package/{subset/config-override.h → config-override-subset.h} +0 -0
  8. package/config-override.h +4 -3
  9. package/examples/Mada.abjad.otf +0 -0
  10. package/{subset/roboto-black.ttf → examples/Roboto-Black.ttf} +0 -0
  11. package/{subset/test.js → examples/hb-subset.example.node.js} +5 -5
  12. package/examples/hbjs.example.html +0 -1
  13. package/examples/hbjs.example.js +6 -3
  14. package/examples/hbjs.example.node.js +2 -0
  15. package/examples/nohbjs.html +0 -1
  16. package/harfbuzz.ts +46 -1
  17. package/hb-subset.symbols +28 -0
  18. package/hb-subset.wasm +0 -0
  19. package/hb.wasm +0 -0
  20. package/hbjs.cc +256 -0
  21. package/hbjs.js +73 -4
  22. package/hbjs.symbols +41 -0
  23. package/index.js +0 -1
  24. package/package.json +1 -1
  25. package/hbjs.c +0 -284
  26. package/libc/ctype.h +0 -73
  27. package/libc/emmalloc.cpp +0 -1202
  28. package/libc/fprintf.c +0 -65
  29. package/libc/include/assert.h +0 -14
  30. package/libc/include/cassert +0 -1
  31. package/libc/include/cfloat +0 -1
  32. package/libc/include/climits +0 -1
  33. package/libc/include/cmath +0 -1
  34. package/libc/include/cstdarg +0 -1
  35. package/libc/include/cstddef +0 -1
  36. package/libc/include/cstdio +0 -1
  37. package/libc/include/cstdlib +0 -1
  38. package/libc/include/cstring +0 -1
  39. package/libc/include/emscripten.h +0 -0
  40. package/libc/include/float.h +0 -6
  41. package/libc/include/limits.h +0 -2
  42. package/libc/include/locale.h +0 -0
  43. package/libc/include/malloc.h +0 -13
  44. package/libc/include/math.h +0 -0
  45. package/libc/include/raqm-version.h +0 -5
  46. package/libc/include/stdarg.h +0 -0
  47. package/libc/include/stdbool.h +0 -12
  48. package/libc/include/stddef.h +0 -0
  49. package/libc/include/stdint.h +0 -1
  50. package/libc/include/stdio.h +0 -0
  51. package/libc/include/stdlib.h +0 -110
  52. package/libc/include/string.h +0 -26
  53. package/libc/include/sys/types.h +0 -1
  54. package/libc/include/unistd.h +0 -14
  55. package/libc/main.c +0 -7
  56. package/libc/malloc.cc +0 -29
  57. package/libc/prf.c +0 -667
  58. package/libc/sprintf.c +0 -112
  59. package/libc/strtol.c +0 -79
  60. package/libc/zephyr-string.c +0 -381
  61. package/subset/build.sh +0 -48
  62. package/subset/hb-subset.wasm +0 -0
  63. package/subset/test.cc +0 -50
@@ -0,0 +1,45 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches: [ "main" ]
6
+ pull_request:
7
+ branches: [ "main" ]
8
+
9
+ env:
10
+ EM_VERSION: 3.1.16
11
+ EM_CACHE_FOLDER: 'emsdk-cache'
12
+
13
+ jobs:
14
+ build:
15
+
16
+ runs-on: ubuntu-latest
17
+
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v3
21
+ with:
22
+ submodules: true
23
+
24
+ - name: Setup cache
25
+ id: cache-system-libraries
26
+ uses: actions/cache@v3
27
+ with:
28
+ path: ${{env.EM_CACHE_FOLDER}}
29
+ key: ${{env.EM_VERSION}}-${{runner.os}}
30
+ - name: Setup Emscripten
31
+ uses: mymindstorm/setup-emsdk@v11
32
+ with:
33
+ version: ${{env.EM_VERSION}}
34
+ actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
35
+ - name: Build hb.wasm
36
+ run: ./build.sh
37
+ - name: Build hb-subset.wasm
38
+ run: ./build-subset.sh
39
+
40
+ - name: Setup Node.js
41
+ uses: actions/setup-node@v3
42
+ - name: Test hb.wasm
43
+ run: node examples/hbjs.example.node.js
44
+ - name: Test hb-subset.wasm
45
+ run: node examples/hb-subset.example.node.js
package/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "harfbuzz"]
2
+ path = harfbuzz
3
+ url = https://github.com/harfbuzz/harfbuzz.git
package/LICENSE CHANGED
@@ -1,6 +1,5 @@
1
1
  Apache license for Zephyr libc implementations (zephyr-string.c),
2
2
  emmalloc.cpp (from emscripten project) and MIT for rest of the project
3
- raqm.js uses fribidi (GPLv3) and libraqm (MIT)
4
3
 
5
4
  Copyright (c) 2019 Ebrahim Byagowi
6
5
 
package/README.md CHANGED
@@ -5,13 +5,9 @@ library for client/server side JavaScript projects.
5
5
  See the demo [here](https://harfbuzz.github.io/harfbuzzjs/).
6
6
 
7
7
  ## Building
8
- 1. Install clang, lld and git
8
+ 1. Install emscripten
9
9
  2. `./build.sh`
10
10
 
11
- Note that if building on Mac OS X, clang 11.0 needs to be installed from Homebrew (`brew install clang`). Also note that Homebrew clang is not in
12
- the path by default, so you need to add `/usr/local/opt/llvm/bin` to your
13
- path or you will get weird compiled errors.
14
-
15
11
  ## Download
16
12
  Download the pack from [releases tab](https://github.com/harfbuzz/harfbuzzjs/releases)
17
13
  of the project, or just download the [demo page](https://harfbuzz.github.io/harfbuzzjs/) (the
@@ -24,8 +20,6 @@ demo source is in [gh-pages](https://github.com/harfbuzz/harfbuzzjs/tree/gh-page
24
20
  ```javascript
25
21
  hb = require("hbjs.js")
26
22
  WebAssembly.instantiateStreaming(fetch("hb.wasm")).then(function (result) {
27
- // WebAssembly needs its own heap - allocate 400 16k pages to do our work in.
28
- result.instance.exports.memory.grow(400);
29
23
  fetch('myfont.ttf').then(function (data) {
30
24
  return data.arrayBuffer();
31
25
  }).then(function (fontdata) {
@@ -84,7 +78,7 @@ how to use it.
84
78
  harfbuzzjs uses a stripped-down version of Harfbuzz generated by compiling Harfbuzz with `-DHB_TINY`. This may mean that some functions you need are not available. Look at `src/hb-config.hh` in the Harfbuzz source directory to see what has been removed. For example, `HB_TINY` defines `HB_LEAN` which (amongst other things) defines `HB_NO_OT_GLYPH_NAMES`. If, for example, you really need to get at the glyph names:
85
79
 
86
80
  1. First, undefine the macro in question, by adding e.g. `#undef HB_NO_OT_GLYPH_NAMES` to `config-override.h`.
87
- 2. Next, export any function that you need by adding a line to `build.sh`; in this case `-Wl,--export=hb_ot_get_glyph_name`.
81
+ 2. Next, export any function that you need by adding a line to `hbjs.symbols`; in this case `_hb_ot_get_glyph_name`.
88
82
  3. Now the function will be exported through the WASM object, but you need to add Javascript to bridge to it - in this case, handling the memory allocation of the `char *` parameter `name` and marshalling it to a JavaScript string with `heapu8.subarray`. The best way to do this is to look at `hbjs.js` for functions which use similar signatures.
89
83
 
90
84
  If you have extended harfbuzzjs in ways that you think others will also benefit from, please raise a pull request. If there are parts of Harfbuzz that you need but the instructions above don't work, describe what you are trying to do in an issue.
@@ -0,0 +1,21 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ em++ \
5
+ -std=c++11 \
6
+ -fno-exceptions \
7
+ -fno-rtti \
8
+ -fno-threadsafe-statics \
9
+ -fvisibility-inlines-hidden \
10
+ -flto \
11
+ -Oz \
12
+ -I. \
13
+ -DHB_TINY \
14
+ -DHB_USE_INTERNAL_QSORT \
15
+ -DHB_CONFIG_OVERRIDE_H=\"config-override-subset.h\" \
16
+ -DHB_EXPERIMENTAL_API \
17
+ --no-entry \
18
+ -s EXPORTED_FUNCTIONS=@hb-subset.symbols \
19
+ -s INITIAL_MEMORY=65MB \
20
+ -o hb-subset.wasm \
21
+ harfbuzz/src/harfbuzz-subset.cc
package/build.sh CHANGED
@@ -1,61 +1,21 @@
1
1
  #!/bin/bash
2
2
  set -e
3
3
 
4
- [ -x "$(command -v git)" ] || (echo "Please install git from your package manager" && exit 1)
5
- [ -x "$(command -v clang)" ] || (echo "Please install clang from your package manager" && exit 1)
6
-
7
- [ -d harfbuzz/src ] || git clone https://github.com/harfbuzz/harfbuzz
8
- (cd harfbuzz; git checkout 3.0.0)
9
-
10
- clang \
11
- -I./libc/include -Oz \
12
- -fno-exceptions -fno-rtti -fno-threadsafe-statics -fvisibility-inlines-hidden \
13
- --target=wasm32 \
14
- -nostdlib -nostdinc \
15
- -Wno-builtin-requires-header \
4
+ em++ \
5
+ -std=c++11 \
6
+ -fno-exceptions \
7
+ -fno-rtti \
8
+ -fno-threadsafe-statics \
9
+ -fvisibility-inlines-hidden \
16
10
  -flto \
17
- -DHB_TINY -DHB_USE_INTERNAL_QSORT \
18
- -Wl,--no-entry \
19
- -Wl,--strip-all \
20
- -Wl,--lto-O3 \
21
- -Wl,--gc-sections \
22
- -Wl,--export=malloc \
23
- -Wl,--export=hb_blob_create \
24
- -Wl,--export=hb_blob_get_data \
25
- -Wl,--export=hb_blob_get_length \
26
- -Wl,--export=hb_face_create \
27
- -Wl,--export=hb_face_reference_table \
28
- -Wl,--export=hb_font_create \
29
- -Wl,--export=hb_buffer_create \
30
- -Wl,--export=hb_buffer_add_utf8 \
31
- -Wl,--export=hb_buffer_add_utf16 \
32
- -Wl,--export=hb_buffer_guess_segment_properties \
33
- -Wl,--export=hb_buffer_set_direction \
34
- -Wl,--export=hb_buffer_set_cluster_level \
35
- -Wl,--export=hb_buffer_set_flags \
36
- -Wl,--export=hb_buffer_set_script \
37
- -Wl,--export=hb_script_from_string \
38
- -Wl,--export=hb_buffer_set_language \
39
- -Wl,--export=hb_language_from_string \
40
- -Wl,--export=hb_shape \
41
- -Wl,--export=hb_buffer_get_glyph_infos \
42
- -Wl,--export=hb_buffer_get_glyph_positions \
43
- -Wl,--export=hb_buffer_get_length \
44
- -Wl,--export=hb_buffer_destroy \
45
- -Wl,--export=hb_font_destroy \
46
- -Wl,--export=hb_face_destroy \
47
- -Wl,--export=hb_face_get_upem \
48
- -Wl,--export=hb_blob_destroy \
49
- -Wl,--export=hb_blob_get_length \
50
- -Wl,--export=hb_font_set_scale \
51
- -Wl,--export=hb_face_get_upem \
52
- -Wl,--export=hbjs_glyph_svg \
53
- -Wl,--export=hbjs_shape_with_trace \
54
- -Wl,--export=hb_ot_var_get_axis_infos \
55
- -Wl,--export=hb_font_set_variations \
56
- -Wl,--export=free \
57
- -Wl,--export=free_ptr \
58
- -Wl,--export=__heap_base \
59
- hbjs.c -DHAVE_CONFIG_OVERRIDE_H -I. -DHB_EXPERIMENTAL_API \
60
- libc/malloc.cc libc/zephyr-string.c libc/prf.c libc/strtol.c libc/sprintf.c libc/main.c harfbuzz/src/harfbuzz.cc \
61
- -o hb.wasm $@
11
+ -Oz \
12
+ -I. \
13
+ -DHB_TINY \
14
+ -DHB_USE_INTERNAL_QSORT \
15
+ -DHB_CONFIG_OVERRIDE_H=\"config-override.h\" \
16
+ -DHB_EXPERIMENTAL_API \
17
+ --no-entry \
18
+ -s EXPORTED_FUNCTIONS=@hbjs.symbols \
19
+ -s INITIAL_MEMORY=65MB \
20
+ -o hb.wasm \
21
+ hbjs.cc
package/config-override.h CHANGED
@@ -1,7 +1,8 @@
1
- // Maybe enable these two also
2
- // #undef HB_NO_CFF
3
- // #undef HB_NO_OT_FONT_CFF
1
+ #undef HB_NO_CFF
2
+ #undef HB_NO_OT_FONT_CFF
4
3
  #undef HB_NO_DRAW
5
4
  #undef HB_NO_BUFFER_MESSAGE
6
5
  #undef HB_NO_BUFFER_SERIALIZE
7
6
  #undef HB_NO_VAR
7
+ #undef HB_NO_OT_FONT_GLYPH_NAMES
8
+ #undef HB_NO_FACE_COLLECT_UNICODES
Binary file
@@ -5,9 +5,8 @@ const readFileAsync = require('util').promisify(fs.readFile);
5
5
  const writeFileAsync = require('util').promisify(fs.writeFile);
6
6
 
7
7
  (async () => {
8
- const { instance: { exports } } = await WebAssembly.instantiate(await readFileAsync(__dirname + '/hb-subset.wasm'));
9
- exports.memory.grow(400); // each page is 64kb in size
10
- const fontBlob = await readFileAsync(__dirname + '/roboto-black.ttf');
8
+ const { instance: { exports } } = await WebAssembly.instantiate(await readFileAsync(__dirname + '/../hb-subset.wasm'));
9
+ const fontBlob = await readFileAsync(__dirname + '/Roboto-Black.ttf');
11
10
 
12
11
  const heapu8 = new Uint8Array(exports.memory.buffer);
13
12
  const fontBuffer = exports.malloc(fontBlob.byteLength);
@@ -26,7 +25,7 @@ const writeFileAsync = require('util').promisify(fs.writeFile);
26
25
  exports.hb_set_add(unicode_set, 'c'.charCodeAt(0));
27
26
 
28
27
  // exports.hb_subset_input_set_drop_hints(input, true);
29
- const subset = exports.hb_subset(face, input);
28
+ const subset = exports.hb_subset_or_fail(face, input);
30
29
 
31
30
  /* Clean up */
32
31
  exports.hb_subset_input_destroy(input);
@@ -37,7 +36,8 @@ const writeFileAsync = require('util').promisify(fs.writeFile);
37
36
  const data = exports.hb_blob_get_data(result, 0);
38
37
  const subsetFontBlob = heapu8.subarray(data, data + exports.hb_blob_get_length(result));
39
38
 
40
- await writeFileAsync(__dirname + '/roboto-black-subset-js.ttf', subsetFontBlob);
39
+ await writeFileAsync(__dirname + '/Roboto-Black.subset.ttf', subsetFontBlob);
40
+ console.log(`Wrote subset to: ${__dirname}/Roboto-Black.subset.ttf`);
41
41
 
42
42
  /* Clean up */
43
43
  exports.hb_blob_destroy(result);
@@ -3,7 +3,6 @@
3
3
  <script>
4
4
  // instantiateStreaming isn't supported in Safari yet, see nohbjs.html
5
5
  WebAssembly.instantiateStreaming(fetch("../hb.wasm")).then(function (result) {
6
- result.instance.exports.memory.grow(400); // each page is 64kb in size
7
6
  fetch('Roboto.abc.ttf').then(function (x) {
8
7
  return x.arrayBuffer();
9
8
  }).then(function (blob) {
@@ -1,4 +1,4 @@
1
- function example(hb, fontBlob) {
1
+ function example(hb, fontBlob, text) {
2
2
  var blob = hb.createBlob(fontBlob);
3
3
  var face = hb.createFace(blob, 0);
4
4
  // console.log(face.getAxisInfos());
@@ -7,7 +7,7 @@ function example(hb, fontBlob) {
7
7
  font.setScale(1000, 1000); // Optional, if not given will be in font upem
8
8
 
9
9
  var buffer = hb.createBuffer();
10
- buffer.addText('abc');
10
+ buffer.addText(text || 'abc');
11
11
  buffer.guessSegmentProperties();
12
12
  // buffer.setDirection('ltr'); // optional as can be set by guessSegmentProperties also
13
13
  hb.shape(font, buffer); // features are not supported yet
@@ -18,16 +18,19 @@ function example(hb, fontBlob) {
18
18
  result.forEach(function (x) {
19
19
  if (glyphs[x.g]) return;
20
20
  glyphs[x.g] = {
21
+ name: font.glyphName(x.g),
21
22
  path: font.glyphToPath(x.g),
22
23
  json: font.glyphToJson(x.g)
23
24
  };
24
25
  });
25
26
 
27
+ var unicodes = face.collectUnicodes()
28
+
26
29
  buffer.destroy();
27
30
  font.destroy();
28
31
  face.destroy();
29
32
  blob.destroy();
30
- return { shape: result, glyphs: glyphs };
33
+ return { shape: result, glyphs: glyphs, unicodes: unicodes };
31
34
  }
32
35
 
33
36
  // Should be replaced with something more reliable
@@ -4,4 +4,6 @@ var example = require('./hbjs.example.js');
4
4
 
5
5
  require('../').then(function (hbjs) {
6
6
  console.log(example(hbjs, new Uint8Array(fs.readFileSync(path.resolve(__dirname, 'Roboto.abc.ttf')))));
7
+ console.log(example(hbjs, new Uint8Array(fs.readFileSync(path.resolve(__dirname, 'Roboto-Black.ttf')))));
8
+ console.log(example(hbjs, new Uint8Array(fs.readFileSync(path.resolve(__dirname, 'Mada.abjad.otf'))), "أبجد"));
7
9
  }, console.log);
@@ -9,7 +9,6 @@ fetch("../hb.wasm").then(function (x) {
9
9
  return WebAssembly.instantiate(wasm);
10
10
  }).then(function (result) {
11
11
  var exports = result.instance.exports;
12
- exports.memory.grow(400); // each page is 64kb in size
13
12
 
14
13
  fetch('Roboto.abc.ttf').then(function (x) {
15
14
  return x.arrayBuffer();
package/harfbuzz.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  type Pointer = number;
2
2
 
3
3
  const HB_MEMORY_MODE_WRITABLE: number = 2;
4
+ const HB_SET_VALUE_INVALID: Pointer = -1;
4
5
 
5
6
  class HarfBuzzExports {
6
7
  readonly heapu8: Uint8Array;
@@ -20,6 +21,16 @@ class HarfBuzzExports {
20
21
  readonly hb_font_create: (facePtr: Pointer) => Pointer
21
22
  readonly hb_font_set_scale: (fontPtr: Pointer, xScale: number, yScale: number) => void
22
23
  readonly hb_font_destroy: (ptr: Pointer) => void
24
+ readonly hb_face_collect_unicodes: (facePtr: Pointer, setPtr: Pointer) => void
25
+ readonly hb_set_create: () => Pointer
26
+ readonly hb_set_destroy: (setPtr: Pointer) => void
27
+ readonly hb_set_get_population: (setPtr: Pointer) => number
28
+ readonly hb_set_next_many: (
29
+ setPtr: Pointer,
30
+ greaterThanUnicodePtr: Pointer,
31
+ outputU32ArrayPtr: Pointer,
32
+ size: number,
33
+ ) => number
23
34
  readonly hb_buffer_create: () => Pointer
24
35
  readonly hb_buffer_add_utf8: (bufferPtr: Pointer, stringPtr: Pointer, stringLength: number, itemOffset: number, itemLength: number) => void
25
36
  readonly hb_buffer_guess_segment_properties: (bufferPtr: Pointer) => void
@@ -44,6 +55,11 @@ class HarfBuzzExports {
44
55
  this.hb_face_create = exports.hb_face_create;
45
56
  this.hb_face_get_upem = exports.hb_face_get_upem;
46
57
  this.hb_face_destroy = exports.hb_face_destroy;
58
+ this.hb_face_collect_unicodes = exports.hb_face_collect_unicodes;
59
+ this.hb_set_create = exports.hb_set_create;
60
+ this.hb_set_destroy = exports.hb_set_destroy;
61
+ this.hb_set_get_population = exports.hb_set_get_population;
62
+ this.hb_set_next_many = exports.hb_set_next_many;
47
63
  this.hb_font_create = exports.hb_font_create;
48
64
  this.hb_font_set_scale = exports.hb_font_set_scale;
49
65
  this.hb_font_destroy = exports.hb_font_destroy;
@@ -92,6 +108,28 @@ export class HarfBuzzBlob {
92
108
  }
93
109
  }
94
110
 
111
+ function typedArrayFromSet<T extends 'u8' | 'u32' | 'i32'>(setPtr: Pointer, arrayType: T) {
112
+ const heap = hb[`heap${arrayType}`];
113
+ const bytesPerElment = heap.BYTES_PER_ELEMENT;
114
+ const setCount = hb.hb_set_get_population(setPtr);
115
+ const arrayPtr = hb.malloc(
116
+ setCount * bytesPerElment,
117
+ );
118
+ const arrayOffset = arrayPtr / bytesPerElment;
119
+ const array = heap.subarray(
120
+ arrayOffset,
121
+ arrayOffset + setCount,
122
+ ) as typeof hb[`heap${T}`];
123
+ heap.set(array, arrayOffset);
124
+ hb.hb_set_next_many(
125
+ setPtr,
126
+ HB_SET_VALUE_INVALID,
127
+ arrayPtr,
128
+ setCount,
129
+ );
130
+ return array;
131
+ }
132
+
95
133
  export class HarfBuzzFace {
96
134
  readonly ptr: Pointer;
97
135
 
@@ -103,6 +141,14 @@ export class HarfBuzzFace {
103
141
  return hb.hb_face_get_upem(this.ptr);
104
142
  }
105
143
 
144
+ collectUnicodes() {
145
+ const unicodeSetPtr = hb.hb_set_create();
146
+ hb.hb_face_collect_unicodes(this.ptr, unicodeSetPtr);
147
+ const result = typedArrayFromSet(unicodeSetPtr, 'u32');
148
+ hb.hb_set_destroy(unicodeSetPtr);
149
+ return result;
150
+ }
151
+
106
152
  destroy() {
107
153
  hb.hb_face_destroy(this.ptr);
108
154
  }
@@ -223,7 +269,6 @@ export function loadHarfbuzz(webAssemblyUrl: string): Promise<void> {
223
269
  return WebAssembly.instantiate(wasm);
224
270
  }).then(result => {
225
271
  //@ts-ignore
226
- result.instance.exports.memory.grow(1000); // each page is 64kb in size => 64mb allowed for webassembly, maybe we need more...
227
272
  hb = new HarfBuzzExports(result.instance.exports);
228
273
  });
229
274
  }
@@ -0,0 +1,28 @@
1
+ _hb_blob_create
2
+ _hb_blob_destroy
3
+ _hb_blob_get_data
4
+ _hb_blob_get_length
5
+ _hb_face_create
6
+ _hb_face_destroy
7
+ _hb_face_get_empty
8
+ _hb_face_reference_blob
9
+ _hb_set_add
10
+ _hb_set_clear
11
+ _hb_set_create
12
+ _hb_set_del
13
+ _hb_set_destroy
14
+ _hb_set_invert
15
+ _hb_set_union
16
+ _hb_subset_input_create_or_fail
17
+ _hb_subset_input_destroy
18
+ _hb_subset_input_get_flags
19
+ _hb_subset_input_get_user_data
20
+ _hb_subset_input_glyph_set
21
+ _hb_subset_input_reference
22
+ _hb_subset_input_set
23
+ _hb_subset_input_set_flags
24
+ _hb_subset_input_set_user_data
25
+ _hb_subset_input_unicode_set
26
+ _hb_subset_or_fail
27
+ _malloc
28
+ _free
package/hb-subset.wasm ADDED
Binary file
package/hb.wasm CHANGED
Binary file
package/hbjs.cc ADDED
@@ -0,0 +1,256 @@
1
+ #include "harfbuzz/src/harfbuzz.cc"
2
+
3
+ HB_BEGIN_DECLS
4
+
5
+ int
6
+ hbjs_glyph_svg (hb_font_t *font, hb_codepoint_t glyph, char *buf, unsigned buf_size);
7
+
8
+ unsigned
9
+ hbjs_shape_with_trace (hb_font_t *font, hb_buffer_t* buf,
10
+ char* featurestring,
11
+ unsigned int stop_at, unsigned int stop_phase,
12
+ char *outbuf, unsigned buf_size);
13
+
14
+ void *free_ptr(void);
15
+
16
+ HB_END_DECLS
17
+
18
+
19
+ void *free_ptr(void) { return (void *) free; }
20
+
21
+ enum {
22
+ HB_SHAPE_DONT_STOP,
23
+ HB_SHAPE_GSUB_PHASE,
24
+ HB_SHAPE_GPOS_PHASE
25
+ };
26
+
27
+ struct user_data_t {
28
+ user_data_t(char *str_,
29
+ unsigned size_,
30
+ unsigned stop_at_ = 0,
31
+ unsigned stop_phase_ = 0)
32
+ : str(str_)
33
+ , size(size_)
34
+ , stop_at(stop_at_)
35
+ , stop_phase(stop_phase_)
36
+ {}
37
+ char *str = nullptr;
38
+ unsigned size = 0;
39
+ unsigned consumed = 0;
40
+ hb_bool_t failure = false;
41
+ unsigned stop_at = 0;
42
+ unsigned stop_phase = 0;
43
+ hb_bool_t stopping = false;
44
+ unsigned current_phase = 0;
45
+ };
46
+
47
+
48
+ static void
49
+ _user_data_printf (user_data_t *data, const char *format, ...)
50
+ {
51
+ #define BUFSIZE 1000
52
+ char buf[BUFSIZE];
53
+ int len;
54
+ va_list va;
55
+
56
+ if (!data || data->failure)
57
+ return;
58
+
59
+ va_start(va, format);
60
+ len = vsnprintf(buf, BUFSIZE, format, va);
61
+ va_end(va);
62
+
63
+ if (data->consumed + len >= data->size || len < 0 || len > BUFSIZE)
64
+ {
65
+ data->failure = true;
66
+ return;
67
+ }
68
+
69
+ memcpy (data->str + data->consumed, buf, len);
70
+ data->consumed += len;
71
+ #undef BUFSIZE
72
+ }
73
+
74
+ static void
75
+ move_to (hb_draw_funcs_t *dfuncs, user_data_t *draw_data, hb_draw_state_t *,
76
+ float to_x, float to_y,
77
+ void *)
78
+ {
79
+ _user_data_printf (draw_data, "M%g,%g", (double)to_x, (double)to_y);
80
+ }
81
+
82
+ static void
83
+ line_to (hb_draw_funcs_t *dfuncs, user_data_t *draw_data, hb_draw_state_t *,
84
+ float to_x, float to_y,
85
+ void *)
86
+ {
87
+ _user_data_printf (draw_data, "L%g,%g", (double)to_x, (double)to_y);
88
+ }
89
+
90
+ static void
91
+ quadratic_to (hb_draw_funcs_t *dfuncs, user_data_t *draw_data, hb_draw_state_t *,
92
+ float control_x, float control_y,
93
+ float to_x, float to_y,
94
+ void *)
95
+ {
96
+ _user_data_printf (draw_data, "Q%g,%g %g,%g",
97
+ (double)control_x,
98
+ (double)control_y,
99
+ (double)to_x,
100
+ (double)to_y);
101
+ }
102
+
103
+ static void
104
+ cubic_to (hb_draw_funcs_t *dfuncs, user_data_t *draw_data, hb_draw_state_t *,
105
+ float control1_x, float control1_y,
106
+ float control2_x, float control2_y,
107
+ float to_x, float to_y,
108
+ void *)
109
+ {
110
+ _user_data_printf (draw_data, "C%g,%g %g,%g %g,%g",
111
+ (double)control1_x,
112
+ (double)control1_y,
113
+ (double)control2_x,
114
+ (double)control2_y,
115
+ (double)to_x,
116
+ (double)to_y);
117
+ }
118
+
119
+ static void
120
+ close_path (hb_draw_funcs_t *dfuncs, user_data_t *draw_data, hb_draw_state_t *, void *)
121
+ {
122
+ _user_data_printf (draw_data, "Z");
123
+ }
124
+
125
+ static hb_draw_funcs_t *funcs = 0;
126
+
127
+ int
128
+ hbjs_glyph_svg (hb_font_t *font, hb_codepoint_t glyph, char *buf, unsigned buf_size)
129
+ {
130
+ if (funcs == 0) /* not the best pattern for multi-threaded apps which is not a concern here */
131
+ {
132
+ funcs = hb_draw_funcs_create (); /* will be leaked */
133
+ hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) move_to, nullptr, nullptr);
134
+ hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) line_to, nullptr, nullptr);
135
+ hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) quadratic_to, nullptr, nullptr);
136
+ hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, nullptr, nullptr);
137
+ hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, nullptr, nullptr);
138
+ }
139
+
140
+ user_data_t draw_data(buf, buf_size);
141
+ hb_font_get_glyph_shape (font, glyph, funcs, &draw_data);
142
+ if (draw_data.failure)
143
+ return -1;
144
+
145
+ buf[draw_data.consumed] = '\0';
146
+ return draw_data.consumed;
147
+ }
148
+
149
+ static hb_bool_t do_trace (hb_buffer_t *buffer,
150
+ hb_font_t *font,
151
+ const char *message,
152
+ user_data_t *user_data) {
153
+ unsigned int consumed;
154
+ unsigned int num_glyphs = hb_buffer_get_length (buffer);
155
+
156
+ if (strcmp(message, "start table GSUB") == 0) {
157
+ user_data->current_phase = HB_SHAPE_GSUB_PHASE;
158
+ } else if (strcmp(message, "start table GPOS") == 0) {
159
+ user_data->current_phase = HB_SHAPE_GPOS_PHASE;
160
+ }
161
+
162
+
163
+ if (user_data->current_phase != user_data->stop_phase) {
164
+ user_data->stopping = false;
165
+ }
166
+
167
+ // If we overflowed, keep going anyway.
168
+ if (user_data->failure) return 1;
169
+
170
+ if (user_data->stop_phase != HB_SHAPE_DONT_STOP) {
171
+ // Do we need to start stopping?
172
+ char buf[12];
173
+ snprintf (buf, 12, "%d", user_data->stop_at);
174
+ if ((user_data->current_phase == user_data->stop_phase) &&
175
+ (strncmp(message, "end lookup ", 11) == 0) &&
176
+ (strcmp(message + 11, buf) == 0)) {
177
+ user_data->stopping = true;
178
+ }
179
+ }
180
+
181
+ // If we need to stop, stop.
182
+ if (user_data->stopping) return 0;
183
+
184
+ _user_data_printf (user_data, "{\"m\":\"%s\",\"t\":", message);
185
+ hb_buffer_serialize_glyphs(buffer, 0, num_glyphs,
186
+ user_data->str + user_data->consumed,
187
+ user_data->size - user_data->consumed,
188
+ &consumed,
189
+ font,
190
+ HB_BUFFER_SERIALIZE_FORMAT_JSON,
191
+ HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES);
192
+ user_data->consumed += consumed;
193
+ _user_data_printf (user_data, "},\n");
194
+
195
+ return 1;
196
+ }
197
+
198
+ unsigned
199
+ hbjs_shape_with_trace (hb_font_t *font, hb_buffer_t* buf,
200
+ char* featurestring,
201
+ unsigned int stop_at, unsigned int stop_phase,
202
+ char *outbuf, unsigned buf_size) {
203
+ user_data_t user_data(outbuf, buf_size, stop_at, stop_phase);
204
+
205
+ int num_features = 0;
206
+ hb_feature_t* features = nullptr;
207
+
208
+ if (*featurestring) {
209
+ /* count the features first, so we can allocate memory */
210
+ char* p = featurestring;
211
+ do {
212
+ num_features++;
213
+ p = strchr (p, ',');
214
+ if (p)
215
+ p++;
216
+ } while (p);
217
+
218
+ features = (hb_feature_t *) calloc (num_features, sizeof (*features));
219
+
220
+ /* now do the actual parsing */
221
+ p = featurestring;
222
+ num_features = 0;
223
+ while (p && *p) {
224
+ char *end = strchr (p, ',');
225
+ if (hb_feature_from_string (p, end ? end - p : -1, &features[num_features]))
226
+ num_features++;
227
+ p = end ? end + 1 : nullptr;
228
+ }
229
+ }
230
+
231
+ hb_buffer_set_message_func (buf, (hb_buffer_message_func_t)do_trace, &user_data, nullptr);
232
+ user_data.str[user_data.consumed++] = '[';
233
+ hb_shape(font, buf, features, num_features);
234
+
235
+ if (user_data.failure) return -1;
236
+
237
+ user_data.str[user_data.consumed-2] = ']';
238
+ user_data.str[user_data.consumed-1] = '\0';
239
+ return user_data.consumed;
240
+ }
241
+
242
+ #ifdef MAIN
243
+ #include <stdio.h>
244
+ int main() {
245
+ hb_blob_t *blob = hb_blob_create_from_file ("/home/ebrahim/Desktop/harfbuzzjs/harfbuzz/test/subset/data/fonts/Roboto-Regular.ttf");
246
+ hb_face_t *face = hb_face_create (blob, 0);
247
+ hb_blob_destroy (blob);
248
+ hb_font_t *font = hb_font_create (face);
249
+ hb_face_destroy (face);
250
+ char buf[1024];
251
+ buf[0] = '\0';
252
+ printf ("%d %d\n", hb_blob_get_length (blob), hbjs_ot_glyph_svg (font, 0, buf, sizeof (buf)));
253
+ puts (buf);
254
+ hb_font_destroy (font);
255
+ }
256
+ #endif