harfbuzzjs 0.3.5 → 0.4.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.
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "cSpell.words": [
3
- "dfuncs"
3
+ "dfuncs",
4
+ "DONT"
4
5
  ]
5
6
  }
package/build-subset.sh CHANGED
@@ -7,7 +7,6 @@ em++ \
7
7
  -fno-rtti \
8
8
  -fno-threadsafe-statics \
9
9
  -fvisibility-inlines-hidden \
10
- -flto \
11
10
  -Oz \
12
11
  -I. \
13
12
  -DHB_TINY \
package/build.sh CHANGED
@@ -15,7 +15,11 @@ em++ \
15
15
  -DHB_CONFIG_OVERRIDE_H=\"config-override.h\" \
16
16
  -DHB_EXPERIMENTAL_API \
17
17
  --no-entry \
18
- -s EXPORTED_FUNCTIONS=@hbjs.symbols \
18
+ -s MODULARIZE \
19
+ -s EXPORTED_FUNCTIONS=@hb.symbols \
20
+ -s EXPORTED_RUNTIME_METHODS='["addFunction", "wasmMemory", "wasmExports"]' \
19
21
  -s INITIAL_MEMORY=65MB \
20
- -o hb.wasm \
21
- hbjs.cc
22
+ -s ALLOW_TABLE_GROWTH \
23
+ -lexports.js \
24
+ -o hb.js \
25
+ harfbuzz/src/harfbuzz.cc
package/hb-subset.wasm CHANGED
Binary file
package/hb.js ADDED
@@ -0,0 +1,19 @@
1
+
2
+ var Module = (() => {
3
+ var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
4
+ if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename;
5
+ return (
6
+ function(moduleArg = {}) {
7
+ var moduleRtn;
8
+
9
+ var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);var ret=fs.readFileSync(filename);return ret};readAsync=(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return new Promise((resolve,reject)=>{fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)reject(err);else resolve(binary?data.buffer:data)})})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var wasmBinary=Module["wasmBinary"];var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function findWasmBinary(){var f="hb.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{env:wasmImports,wasi_snapshot_preview1:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;Module["wasmExports"]=wasmExports;wasmMemory=wasmExports["memory"];Module["wasmMemory"]=wasmMemory;updateMemoryViews();wasmTable=wasmExports["__indirect_function_table"];addOnInit(wasmExports["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var noExitRuntime=Module["noExitRuntime"]||true;var __abort_js=()=>{abort("")};var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}};var _emscripten_get_now;_emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};var uleb128Encode=(n,target)=>{if(n<128){target.push(n)}else{target.push(n%128|128,n>>7)}};var sigToWasmTypes=sig=>{var typeNames={i:"i32",j:"i64",f:"f32",d:"f64",e:"externref",p:"i32"};var type={parameters:[],results:sig[0]=="v"?[]:[typeNames[sig[0]]]};for(var i=1;i<sig.length;++i){type.parameters.push(typeNames[sig[i]])}return type};var generateFuncType=(sig,target)=>{var sigRet=sig.slice(0,1);var sigParam=sig.slice(1);var typeCodes={i:127,p:127,j:126,f:125,d:124,e:111};target.push(96);uleb128Encode(sigParam.length,target);for(var i=0;i<sigParam.length;++i){target.push(typeCodes[sigParam[i]])}if(sigRet=="v"){target.push(0)}else{target.push(1,typeCodes[sigRet])}};var convertJsFunctionToWasm=(func,sig)=>{if(typeof WebAssembly.Function=="function"){return new WebAssembly.Function(sigToWasmTypes(sig),func)}var typeSectionBody=[1];generateFuncType(sig,typeSectionBody);var bytes=[0,97,115,109,1,0,0,0,1];uleb128Encode(typeSectionBody.length,bytes);bytes.push(...typeSectionBody);bytes.push(2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);var module=new WebAssembly.Module(new Uint8Array(bytes));var instance=new WebAssembly.Instance(module,{e:{f:func}});var wrappedFunc=instance.exports["f"];return wrappedFunc};var wasmTable;var getWasmTableEntry=funcPtr=>wasmTable.get(funcPtr);var updateTableMap=(offset,count)=>{if(functionsInTableMap){for(var i=offset;i<offset+count;i++){var item=getWasmTableEntry(i);if(item){functionsInTableMap.set(item,i)}}}};var functionsInTableMap;var getFunctionAddress=func=>{if(!functionsInTableMap){functionsInTableMap=new WeakMap;updateTableMap(0,wasmTable.length)}return functionsInTableMap.get(func)||0};var freeTableIndexes=[];var getEmptyTableSlot=()=>{if(freeTableIndexes.length){return freeTableIndexes.pop()}try{wasmTable.grow(1)}catch(err){if(!(err instanceof RangeError)){throw err}throw"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH."}return wasmTable.length-1};var setWasmTableEntry=(idx,func)=>wasmTable.set(idx,func);var addFunction=(func,sig)=>{var rtn=getFunctionAddress(func);if(rtn){return rtn}var ret=getEmptyTableSlot();try{setWasmTableEntry(ret,func)}catch(err){if(!(err instanceof TypeError)){throw err}var wrapped=convertJsFunctionToWasm(func,sig);setWasmTableEntry(ret,wrapped)}functionsInTableMap.set(func,ret);return ret};var wasmImports={_abort_js:__abort_js,_emscripten_runtime_keepalive_clear:__emscripten_runtime_keepalive_clear,_setitimer_js:__setitimer_js,emscripten_resize_heap:_emscripten_resize_heap,proc_exit:_proc_exit};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["__wasm_call_ctors"])();var _hb_blob_create=Module["_hb_blob_create"]=(a0,a1,a2,a3,a4)=>(_hb_blob_create=Module["_hb_blob_create"]=wasmExports["hb_blob_create"])(a0,a1,a2,a3,a4);var _hb_blob_destroy=Module["_hb_blob_destroy"]=a0=>(_hb_blob_destroy=Module["_hb_blob_destroy"]=wasmExports["hb_blob_destroy"])(a0);var _free=Module["_free"]=a0=>(_free=Module["_free"]=wasmExports["free"])(a0);var _hb_blob_get_length=Module["_hb_blob_get_length"]=a0=>(_hb_blob_get_length=Module["_hb_blob_get_length"]=wasmExports["hb_blob_get_length"])(a0);var _hb_blob_get_data=Module["_hb_blob_get_data"]=(a0,a1)=>(_hb_blob_get_data=Module["_hb_blob_get_data"]=wasmExports["hb_blob_get_data"])(a0,a1);var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["malloc"])(a0);var _hb_buffer_serialize_glyphs=Module["_hb_buffer_serialize_glyphs"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8)=>(_hb_buffer_serialize_glyphs=Module["_hb_buffer_serialize_glyphs"]=wasmExports["hb_buffer_serialize_glyphs"])(a0,a1,a2,a3,a4,a5,a6,a7,a8);var _hb_buffer_create=Module["_hb_buffer_create"]=()=>(_hb_buffer_create=Module["_hb_buffer_create"]=wasmExports["hb_buffer_create"])();var _hb_buffer_destroy=Module["_hb_buffer_destroy"]=a0=>(_hb_buffer_destroy=Module["_hb_buffer_destroy"]=wasmExports["hb_buffer_destroy"])(a0);var _hb_buffer_get_content_type=Module["_hb_buffer_get_content_type"]=a0=>(_hb_buffer_get_content_type=Module["_hb_buffer_get_content_type"]=wasmExports["hb_buffer_get_content_type"])(a0);var _hb_buffer_set_direction=Module["_hb_buffer_set_direction"]=(a0,a1)=>(_hb_buffer_set_direction=Module["_hb_buffer_set_direction"]=wasmExports["hb_buffer_set_direction"])(a0,a1);var _hb_buffer_set_script=Module["_hb_buffer_set_script"]=(a0,a1)=>(_hb_buffer_set_script=Module["_hb_buffer_set_script"]=wasmExports["hb_buffer_set_script"])(a0,a1);var _hb_buffer_set_language=Module["_hb_buffer_set_language"]=(a0,a1)=>(_hb_buffer_set_language=Module["_hb_buffer_set_language"]=wasmExports["hb_buffer_set_language"])(a0,a1);var _hb_buffer_set_flags=Module["_hb_buffer_set_flags"]=(a0,a1)=>(_hb_buffer_set_flags=Module["_hb_buffer_set_flags"]=wasmExports["hb_buffer_set_flags"])(a0,a1);var _hb_buffer_set_cluster_level=Module["_hb_buffer_set_cluster_level"]=(a0,a1)=>(_hb_buffer_set_cluster_level=Module["_hb_buffer_set_cluster_level"]=wasmExports["hb_buffer_set_cluster_level"])(a0,a1);var _hb_buffer_get_length=Module["_hb_buffer_get_length"]=a0=>(_hb_buffer_get_length=Module["_hb_buffer_get_length"]=wasmExports["hb_buffer_get_length"])(a0);var _hb_buffer_get_glyph_infos=Module["_hb_buffer_get_glyph_infos"]=(a0,a1)=>(_hb_buffer_get_glyph_infos=Module["_hb_buffer_get_glyph_infos"]=wasmExports["hb_buffer_get_glyph_infos"])(a0,a1);var _hb_buffer_get_glyph_positions=Module["_hb_buffer_get_glyph_positions"]=(a0,a1)=>(_hb_buffer_get_glyph_positions=Module["_hb_buffer_get_glyph_positions"]=wasmExports["hb_buffer_get_glyph_positions"])(a0,a1);var _hb_glyph_info_get_glyph_flags=Module["_hb_glyph_info_get_glyph_flags"]=a0=>(_hb_glyph_info_get_glyph_flags=Module["_hb_glyph_info_get_glyph_flags"]=wasmExports["hb_glyph_info_get_glyph_flags"])(a0);var _hb_buffer_guess_segment_properties=Module["_hb_buffer_guess_segment_properties"]=a0=>(_hb_buffer_guess_segment_properties=Module["_hb_buffer_guess_segment_properties"]=wasmExports["hb_buffer_guess_segment_properties"])(a0);var _hb_buffer_add_utf8=Module["_hb_buffer_add_utf8"]=(a0,a1,a2,a3,a4)=>(_hb_buffer_add_utf8=Module["_hb_buffer_add_utf8"]=wasmExports["hb_buffer_add_utf8"])(a0,a1,a2,a3,a4);var _hb_buffer_add_utf16=Module["_hb_buffer_add_utf16"]=(a0,a1,a2,a3,a4)=>(_hb_buffer_add_utf16=Module["_hb_buffer_add_utf16"]=wasmExports["hb_buffer_add_utf16"])(a0,a1,a2,a3,a4);var _hb_buffer_set_message_func=Module["_hb_buffer_set_message_func"]=(a0,a1,a2,a3)=>(_hb_buffer_set_message_func=Module["_hb_buffer_set_message_func"]=wasmExports["hb_buffer_set_message_func"])(a0,a1,a2,a3);var _hb_language_from_string=Module["_hb_language_from_string"]=(a0,a1)=>(_hb_language_from_string=Module["_hb_language_from_string"]=wasmExports["hb_language_from_string"])(a0,a1);var _hb_script_from_string=Module["_hb_script_from_string"]=(a0,a1)=>(_hb_script_from_string=Module["_hb_script_from_string"]=wasmExports["hb_script_from_string"])(a0,a1);var _hb_version=Module["_hb_version"]=(a0,a1,a2)=>(_hb_version=Module["_hb_version"]=wasmExports["hb_version"])(a0,a1,a2);var _hb_version_string=Module["_hb_version_string"]=()=>(_hb_version_string=Module["_hb_version_string"]=wasmExports["hb_version_string"])();var _hb_feature_from_string=Module["_hb_feature_from_string"]=(a0,a1,a2)=>(_hb_feature_from_string=Module["_hb_feature_from_string"]=wasmExports["hb_feature_from_string"])(a0,a1,a2);var _hb_draw_funcs_set_move_to_func=Module["_hb_draw_funcs_set_move_to_func"]=(a0,a1,a2,a3)=>(_hb_draw_funcs_set_move_to_func=Module["_hb_draw_funcs_set_move_to_func"]=wasmExports["hb_draw_funcs_set_move_to_func"])(a0,a1,a2,a3);var _hb_draw_funcs_set_line_to_func=Module["_hb_draw_funcs_set_line_to_func"]=(a0,a1,a2,a3)=>(_hb_draw_funcs_set_line_to_func=Module["_hb_draw_funcs_set_line_to_func"]=wasmExports["hb_draw_funcs_set_line_to_func"])(a0,a1,a2,a3);var _hb_draw_funcs_set_quadratic_to_func=Module["_hb_draw_funcs_set_quadratic_to_func"]=(a0,a1,a2,a3)=>(_hb_draw_funcs_set_quadratic_to_func=Module["_hb_draw_funcs_set_quadratic_to_func"]=wasmExports["hb_draw_funcs_set_quadratic_to_func"])(a0,a1,a2,a3);var _hb_draw_funcs_set_cubic_to_func=Module["_hb_draw_funcs_set_cubic_to_func"]=(a0,a1,a2,a3)=>(_hb_draw_funcs_set_cubic_to_func=Module["_hb_draw_funcs_set_cubic_to_func"]=wasmExports["hb_draw_funcs_set_cubic_to_func"])(a0,a1,a2,a3);var _hb_draw_funcs_set_close_path_func=Module["_hb_draw_funcs_set_close_path_func"]=(a0,a1,a2,a3)=>(_hb_draw_funcs_set_close_path_func=Module["_hb_draw_funcs_set_close_path_func"]=wasmExports["hb_draw_funcs_set_close_path_func"])(a0,a1,a2,a3);var _hb_draw_funcs_create=Module["_hb_draw_funcs_create"]=()=>(_hb_draw_funcs_create=Module["_hb_draw_funcs_create"]=wasmExports["hb_draw_funcs_create"])();var _hb_face_create=Module["_hb_face_create"]=(a0,a1)=>(_hb_face_create=Module["_hb_face_create"]=wasmExports["hb_face_create"])(a0,a1);var _hb_face_destroy=Module["_hb_face_destroy"]=a0=>(_hb_face_destroy=Module["_hb_face_destroy"]=wasmExports["hb_face_destroy"])(a0);var _hb_face_reference_table=Module["_hb_face_reference_table"]=(a0,a1)=>(_hb_face_reference_table=Module["_hb_face_reference_table"]=wasmExports["hb_face_reference_table"])(a0,a1);var _hb_face_get_upem=Module["_hb_face_get_upem"]=a0=>(_hb_face_get_upem=Module["_hb_face_get_upem"]=wasmExports["hb_face_get_upem"])(a0);var _hb_face_collect_unicodes=Module["_hb_face_collect_unicodes"]=(a0,a1)=>(_hb_face_collect_unicodes=Module["_hb_face_collect_unicodes"]=wasmExports["hb_face_collect_unicodes"])(a0,a1);var _hb_font_draw_glyph=Module["_hb_font_draw_glyph"]=(a0,a1,a2,a3)=>(_hb_font_draw_glyph=Module["_hb_font_draw_glyph"]=wasmExports["hb_font_draw_glyph"])(a0,a1,a2,a3);var _hb_font_glyph_to_string=Module["_hb_font_glyph_to_string"]=(a0,a1,a2,a3)=>(_hb_font_glyph_to_string=Module["_hb_font_glyph_to_string"]=wasmExports["hb_font_glyph_to_string"])(a0,a1,a2,a3);var _hb_font_create=Module["_hb_font_create"]=a0=>(_hb_font_create=Module["_hb_font_create"]=wasmExports["hb_font_create"])(a0);var _hb_font_destroy=Module["_hb_font_destroy"]=a0=>(_hb_font_destroy=Module["_hb_font_destroy"]=wasmExports["hb_font_destroy"])(a0);var _hb_font_set_scale=Module["_hb_font_set_scale"]=(a0,a1,a2)=>(_hb_font_set_scale=Module["_hb_font_set_scale"]=wasmExports["hb_font_set_scale"])(a0,a1,a2);var _hb_font_set_variations=Module["_hb_font_set_variations"]=(a0,a1,a2)=>(_hb_font_set_variations=Module["_hb_font_set_variations"]=wasmExports["hb_font_set_variations"])(a0,a1,a2);var _hb_set_create=Module["_hb_set_create"]=()=>(_hb_set_create=Module["_hb_set_create"]=wasmExports["hb_set_create"])();var _hb_set_destroy=Module["_hb_set_destroy"]=a0=>(_hb_set_destroy=Module["_hb_set_destroy"]=wasmExports["hb_set_destroy"])(a0);var _hb_ot_var_get_axis_infos=Module["_hb_ot_var_get_axis_infos"]=(a0,a1,a2,a3)=>(_hb_ot_var_get_axis_infos=Module["_hb_ot_var_get_axis_infos"]=wasmExports["hb_ot_var_get_axis_infos"])(a0,a1,a2,a3);var _hb_set_get_population=Module["_hb_set_get_population"]=a0=>(_hb_set_get_population=Module["_hb_set_get_population"]=wasmExports["hb_set_get_population"])(a0);var _hb_set_next_many=Module["_hb_set_next_many"]=(a0,a1,a2,a3)=>(_hb_set_next_many=Module["_hb_set_next_many"]=wasmExports["hb_set_next_many"])(a0,a1,a2,a3);var _hb_shape=Module["_hb_shape"]=(a0,a1,a2,a3)=>(_hb_shape=Module["_hb_shape"]=wasmExports["hb_shape"])(a0,a1,a2,a3);var __emscripten_timeout=(a0,a1)=>(__emscripten_timeout=wasmExports["_emscripten_timeout"])(a0,a1);Module["wasmMemory"]=wasmMemory;Module["wasmExports"]=wasmExports;Module["addFunction"]=addFunction;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise;
10
+
11
+
12
+ return moduleRtn;
13
+ }
14
+ );
15
+ })();
16
+ if (typeof exports === 'object' && typeof module === 'object')
17
+ module.exports = Module;
18
+ else if (typeof define === 'function' && define['amd'])
19
+ define([], () => Module);
@@ -9,12 +9,15 @@ _hb_buffer_destroy
9
9
  _hb_buffer_get_glyph_infos
10
10
  _hb_buffer_get_glyph_positions
11
11
  _hb_buffer_get_length
12
+ _hb_buffer_get_content_type
12
13
  _hb_buffer_guess_segment_properties
13
14
  _hb_buffer_set_cluster_level
14
15
  _hb_buffer_set_direction
15
16
  _hb_buffer_set_flags
16
17
  _hb_buffer_set_language
17
18
  _hb_buffer_set_script
19
+ _hb_buffer_set_message_func
20
+ _hb_buffer_serialize_glyphs
18
21
  _hb_face_create
19
22
  _hb_face_collect_unicodes
20
23
  _hb_face_destroy
@@ -25,17 +28,24 @@ _hb_font_destroy
25
28
  _hb_font_glyph_to_string
26
29
  _hb_font_set_scale
27
30
  _hb_font_set_variations
31
+ _hb_font_draw_glyph
32
+ _hb_draw_funcs_create
33
+ _hb_draw_funcs_set_move_to_func
34
+ _hb_draw_funcs_set_line_to_func
35
+ _hb_draw_funcs_set_quadratic_to_func
36
+ _hb_draw_funcs_set_cubic_to_func
37
+ _hb_draw_funcs_set_close_path_func
28
38
  _hb_glyph_info_get_glyph_flags
29
39
  _hb_language_from_string
30
40
  _hb_ot_var_get_axis_infos
31
41
  _hb_script_from_string
42
+ _hb_feature_from_string
32
43
  _hb_set_create
33
44
  _hb_set_destroy
34
45
  _hb_set_get_population
35
46
  _hb_set_next_many
36
47
  _hb_shape
37
- _hbjs_glyph_svg
38
- _hbjs_shape_with_trace
48
+ _hb_version
49
+ _hb_version_string
39
50
  _malloc
40
51
  _free
41
- _free_ptr
package/hb.wasm CHANGED
Binary file
package/hbjs.js CHANGED
@@ -1,15 +1,22 @@
1
- function hbjs(instance) {
1
+ function hbjs(Module) {
2
2
  'use strict';
3
3
 
4
- var exports = instance.exports;
5
- var heapu8 = new Uint8Array(exports.memory.buffer);
6
- var heapu32 = new Uint32Array(exports.memory.buffer);
7
- var heapi32 = new Int32Array(exports.memory.buffer);
8
- var heapf32 = new Float32Array(exports.memory.buffer);
4
+ var exports = Module.wasmExports;
5
+ var heapu8 = Module.HEAPU8;
6
+ var heapu32 = Module.HEAPU32;
7
+ var heapi32 = Module.HEAP32;
8
+ var heapf32 = Module.HEAPF32;
9
9
  var utf8Decoder = new TextDecoder("utf8");
10
+ let addFunction = Module.addFunction;
11
+
12
+ var freeFuncPtr = addFunction(function (ptr) { exports.free(ptr); }, 'vi');
10
13
 
11
14
  var HB_MEMORY_MODE_WRITABLE = 2;
12
15
  var HB_SET_VALUE_INVALID = -1;
16
+ var HB_BUFFER_CONTENT_TYPE_GLYPHS = 2;
17
+ var DONT_STOP = 0;
18
+ var GSUB_PHASE = 1;
19
+ var GPOS_PHASE = 2;
13
20
 
14
21
  function hb_tag(s) {
15
22
  return (
@@ -20,6 +27,9 @@ function hbjs(instance) {
20
27
  );
21
28
  }
22
29
 
30
+ var HB_BUFFER_SERIALIZE_FORMAT_JSON = hb_tag('JSON');
31
+ var HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 4;
32
+
23
33
  function _hb_untag(tag) {
24
34
  return [
25
35
  String.fromCharCode((tag >> 24) & 0xFF),
@@ -46,7 +56,7 @@ function hbjs(instance) {
46
56
  function createBlob(blob) {
47
57
  var blobPtr = exports.malloc(blob.byteLength);
48
58
  heapu8.set(new Uint8Array(blob), blobPtr);
49
- var ptr = exports.hb_blob_create(blobPtr, blob.byteLength, HB_MEMORY_MODE_WRITABLE, blobPtr, exports.free_ptr());
59
+ var ptr = exports.hb_blob_create(blobPtr, blob.byteLength, HB_MEMORY_MODE_WRITABLE, blobPtr, freeFuncPtr);
50
60
  return {
51
61
  ptr: ptr,
52
62
  /**
@@ -155,8 +165,7 @@ function hbjs(instance) {
155
165
  };
156
166
  }
157
167
 
158
- var pathBufferSize = 65536; // should be enough for most glyphs
159
- var pathBuffer = exports.malloc(pathBufferSize); // permanently allocated
168
+ var pathBuffer = "";
160
169
 
161
170
  var nameBufferSize = 256; // should be enough for most glyphs
162
171
  var nameBuffer = exports.malloc(nameBufferSize); // permanently allocated
@@ -167,14 +176,46 @@ function hbjs(instance) {
167
176
  **/
168
177
  function createFont(face) {
169
178
  var ptr = exports.hb_font_create(face.ptr);
179
+ var drawFuncsPtr = null;
170
180
 
171
181
  /**
172
182
  * Return a glyph as an SVG path string.
173
183
  * @param {number} glyphId ID of the requested glyph in the font.
174
184
  **/
175
185
  function glyphToPath(glyphId) {
176
- var svgLength = exports.hbjs_glyph_svg(ptr, glyphId, pathBuffer, pathBufferSize);
177
- return svgLength > 0 ? utf8Decoder.decode(heapu8.subarray(pathBuffer, pathBuffer + svgLength)) : "";
186
+ if (!drawFuncsPtr) {
187
+ var moveTo = function (dfuncs, draw_data, draw_state, to_x, to_y, user_data) {
188
+ pathBuffer += `M${to_x},${to_y}`;
189
+ }
190
+ var lineTo = function (dfuncs, draw_data, draw_state, to_x, to_y, user_data) {
191
+ pathBuffer += `L${to_x},${to_y}`;
192
+ }
193
+ var cubicTo = function (dfuncs, draw_data, draw_state, c1_x, c1_y, c2_x, c2_y, to_x, to_y, user_data) {
194
+ pathBuffer += `C${c1_x},${c1_y} ${c2_x},${c2_y} ${to_x},${to_y}`;
195
+ }
196
+ var quadTo = function (dfuncs, draw_data, draw_state, c_x, c_y, to_x, to_y, user_data) {
197
+ pathBuffer += `Q${c_x},${c_y} ${to_x},${to_y}`;
198
+ }
199
+ var closePath = function (dfuncs, draw_data, draw_state, user_data) {
200
+ pathBuffer += 'Z';
201
+ }
202
+
203
+ var moveToPtr = addFunction(moveTo, 'viiiffi');
204
+ var lineToPtr = addFunction(lineTo, 'viiiffi');
205
+ var cubicToPtr = addFunction(cubicTo, 'viiiffffffi');
206
+ var quadToPtr = addFunction(quadTo, 'viiiffffi');
207
+ var closePathPtr = addFunction(closePath, 'viiii');
208
+ drawFuncsPtr = exports.hb_draw_funcs_create();
209
+ exports.hb_draw_funcs_set_move_to_func(drawFuncsPtr, moveToPtr, 0, 0);
210
+ exports.hb_draw_funcs_set_line_to_func(drawFuncsPtr, lineToPtr, 0, 0);
211
+ exports.hb_draw_funcs_set_cubic_to_func(drawFuncsPtr, cubicToPtr, 0, 0);
212
+ exports.hb_draw_funcs_set_quadratic_to_func(drawFuncsPtr, quadToPtr, 0, 0);
213
+ exports.hb_draw_funcs_set_close_path_func(drawFuncsPtr, closePathPtr, 0, 0);
214
+ }
215
+
216
+ pathBuffer = "";
217
+ exports.hb_font_draw_glyph(ptr, glyphId, drawFuncsPtr, 0);
218
+ return pathBuffer;
178
219
  }
179
220
 
180
221
  /**
@@ -259,7 +300,7 @@ function hbjs(instance) {
259
300
 
260
301
  function createJsString(text) {
261
302
  const ptr = exports.malloc(text.length * 2);
262
- const words = new Uint16Array(exports.memory.buffer, ptr, text.length);
303
+ const words = new Uint16Array(Module.wasmMemory.buffer, ptr, text.length);
263
304
  for (let i = 0; i < words.length; ++i) words[i] = text.charCodeAt(i);
264
305
  return {
265
306
  ptr: ptr,
@@ -401,10 +442,25 @@ function hbjs(instance) {
401
442
  * @param {object} font: A font returned from `createFont`
402
443
  * @param {object} buffer: A buffer returned from `createBuffer` and suitably
403
444
  * prepared.
404
- * @param {object} features: (Currently unused).
445
+ * @param {object} features: A string of comma-separated OpenType features to apply.
405
446
  */
406
447
  function shape(font, buffer, features) {
407
- exports.hb_shape(font.ptr, buffer.ptr, 0, 0);
448
+ var featuresPtr = 0;
449
+ var featuresLen = 0;
450
+ if (features) {
451
+ features = features.split(",");
452
+ featuresPtr = exports.malloc(16 * features.length);
453
+ features.forEach(function (feature, i) {
454
+ var str = createAsciiString(feature);
455
+ if (exports.hb_feature_from_string(str.ptr, -1, featuresPtr + featuresLen * 16))
456
+ featuresLen++;
457
+ str.free();
458
+ });
459
+ }
460
+
461
+ exports.hb_shape(font.ptr, buffer.ptr, featuresPtr, featuresLen);
462
+ if (featuresPtr)
463
+ exports.free(featuresPtr);
408
464
  }
409
465
 
410
466
  /**
@@ -418,22 +474,81 @@ function hbjs(instance) {
418
474
  * @param {object} font: A font returned from `createFont`
419
475
  * @param {object} buffer: A buffer returned from `createBuffer` and suitably
420
476
  * prepared.
421
- * @param {object} features: A dictionary of OpenType features to apply.
477
+ * @param {object} features: A string of comma-separated OpenType features to apply.
422
478
  * @param {number} stop_at: A lookup ID at which to terminate shaping.
423
479
  * @param {number} stop_phase: Either 0 (don't terminate shaping), 1 (`stop_at`
424
480
  refers to a lookup ID in the GSUB table), 2 (`stop_at` refers to a lookup
425
481
  ID in the GPOS table).
426
482
  */
427
-
428
483
  function shapeWithTrace(font, buffer, features, stop_at, stop_phase) {
429
- var bufLen = 1024 * 1024;
430
- var traceBuffer = exports.malloc(bufLen);
431
- var featurestr = createAsciiString(features);
432
- var traceLen = exports.hbjs_shape_with_trace(font.ptr, buffer.ptr, featurestr.ptr, stop_at, stop_phase, traceBuffer, bufLen);
433
- featurestr.free();
434
- var trace = utf8Decoder.decode(heapu8.subarray(traceBuffer, traceBuffer + traceLen - 1));
435
- exports.free(traceBuffer);
436
- return JSON.parse(trace);
484
+ var trace = [];
485
+ var currentPhase = DONT_STOP;
486
+ var stopping = false;
487
+ var failure = false;
488
+
489
+ var traceBufLen = 1024 * 1024;
490
+ var traceBufPtr = exports.malloc(traceBufLen);
491
+
492
+ var traceFunc = function (bufferPtr, fontPtr, messagePtr, user_data) {
493
+ var message = utf8Decoder.decode(heapu8.subarray(messagePtr, heapu8.indexOf(0, messagePtr)));
494
+ if (message.startsWith("start table GSUB"))
495
+ currentPhase = GSUB_PHASE;
496
+ else if (message.startsWith("start table GPOS"))
497
+ currentPhase = GPOS_PHASE;
498
+
499
+ if (currentPhase != stop_phase)
500
+ stopping = false;
501
+
502
+ if (failure)
503
+ return 1;
504
+
505
+ if (stop_phase != DONT_STOP && currentPhase == stop_phase && message.startsWith("end lookup " + stop_at))
506
+ stopping = true;
507
+
508
+ if (stopping)
509
+ return 0;
510
+
511
+ exports.hb_buffer_serialize_glyphs(
512
+ bufferPtr,
513
+ 0, exports.hb_buffer_get_length(bufferPtr),
514
+ traceBufPtr, traceBufLen, 0,
515
+ fontPtr,
516
+ HB_BUFFER_SERIALIZE_FORMAT_JSON,
517
+ HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES);
518
+
519
+ trace.push({
520
+ m: message,
521
+ t: JSON.parse(utf8Decoder.decode(heapu8.subarray(traceBufPtr, heapu8.indexOf(0, traceBufPtr)))),
522
+ glyphs: exports.hb_buffer_get_content_type(bufferPtr) == HB_BUFFER_CONTENT_TYPE_GLYPHS,
523
+ });
524
+
525
+ return 1;
526
+ }
527
+
528
+ var traceFuncPtr = addFunction(traceFunc, 'iiiii');
529
+ exports.hb_buffer_set_message_func(buffer.ptr, traceFuncPtr, 0, 0);
530
+ shape(font, buffer, features, 0);
531
+ exports.free(traceBufPtr);
532
+
533
+ return trace;
534
+ }
535
+
536
+ function version() {
537
+ var versionPtr = exports.malloc(12);
538
+ exports.hb_version(versionPtr, versionPtr + 4, versionPtr + 8);
539
+ var version = {
540
+ major: heapu32[versionPtr / 4],
541
+ minor: heapu32[(versionPtr + 4) / 4],
542
+ micro: heapu32[(versionPtr + 8) / 4],
543
+ };
544
+ exports.free(versionPtr);
545
+ return version;
546
+ }
547
+
548
+ function version_string() {
549
+ var versionPtr = exports.hb_version_string();
550
+ var version = utf8Decoder.decode(heapu8.subarray(versionPtr, heapu8.indexOf(0, versionPtr)));
551
+ return version;
437
552
  }
438
553
 
439
554
  return {
@@ -442,9 +557,13 @@ function hbjs(instance) {
442
557
  createFont: createFont,
443
558
  createBuffer: createBuffer,
444
559
  shape: shape,
445
- shapeWithTrace: shapeWithTrace
560
+ shapeWithTrace: shapeWithTrace,
561
+ version: version,
562
+ version_string: version_string,
446
563
  };
447
- };
564
+ }
448
565
 
449
566
  // Should be replaced with something more reliable
450
- try { module.exports = hbjs; } catch(e) {}
567
+ try {
568
+ module.exports = hbjs;
569
+ } catch (e) {}
package/index.js CHANGED
@@ -1,12 +1,8 @@
1
- var fs = require('fs');
2
- var path = require('path');
3
- var hbjs = require('./hbjs.js')
1
+ var hbjs = require('./hbjs.js');
2
+ var hb = require('./hb.js');
4
3
 
5
4
  module.exports = new Promise(function (resolve, reject) {
6
- fs.readFile(path.resolve(__dirname, 'hb.wasm'), function (err, data) {
7
- if (err) { reject(err); return; }
8
- WebAssembly.instantiate(data).then(function (result) {
9
- resolve(hbjs(result.instance));
10
- }, reject);
11
- });
5
+ hb().then((instance) => {
6
+ resolve(hbjs(instance));
7
+ }, reject);
12
8
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harfbuzzjs",
3
- "version": "0.3.5",
3
+ "version": "0.4.0",
4
4
  "description": "Minimal version of HarfBuzz for JavaScript use",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/perf.js ADDED
@@ -0,0 +1,66 @@
1
+ var fs = require('fs');
2
+ var path = require('path');
3
+
4
+ function example(hb, fontBlob, text) {
5
+ var blob = hb.createBlob(fontBlob);
6
+ var face = hb.createFace(blob, 0);
7
+ // console.log(face.getAxisInfos());
8
+ var font = hb.createFont(face);
9
+ // font.setVariations({ wdth: 200, wght: 700 });
10
+ font.setScale(1000, 1000); // Optional, if not given will be in font upem
11
+
12
+ var buffer = hb.createBuffer();
13
+ buffer.addText(text || 'abc');
14
+ buffer.guessSegmentProperties();
15
+ // buffer.setDirection('ltr'); // optional as can be set by guessSegmentProperties also
16
+ hb.shape(font, buffer); // features are not supported yet
17
+ var result = buffer.json(font);
18
+
19
+ // returns glyphs paths, totally optional
20
+ var glyphs = {};
21
+ result.forEach(function (x) {
22
+ if (glyphs[x.g]) return;
23
+ glyphs[x.g] = {
24
+ name: font.glyphName(x.g),
25
+ path: font.glyphToPath(x.g),
26
+ json: font.glyphToJson(x.g)
27
+ };
28
+ });
29
+
30
+ var unicodes = face.collectUnicodes()
31
+
32
+ buffer.destroy();
33
+ font.destroy();
34
+ face.destroy();
35
+ blob.destroy();
36
+ return { shape: result, glyphs: glyphs, unicodes: unicodes };
37
+ }
38
+
39
+ require('./').then(function (hb) {
40
+ var fontBlob = new Uint8Array(fs.readFileSync(path.resolve(__dirname, './test/fonts/noto/NotoSans-Regular.ttf')));
41
+ var blob = hb.createBlob(fontBlob);
42
+ var face = hb.createFace(blob, 0);
43
+ var font = hb.createFont(face);
44
+
45
+ /*
46
+ for (var i = 0; i < 100; i++) {
47
+ for (var g = 0; g < 4688; g++)
48
+ font.glyphToPath(g);
49
+ }
50
+ */
51
+
52
+ for (var i = 0; i < 100; i++) {
53
+ var buffer = hb.createBuffer();
54
+ buffer.addText('abc');
55
+ buffer.guessSegmentProperties();
56
+ var trace;
57
+ if (i < 50)
58
+ trace = hb.shapeWithTrace(font, buffer, "", i, 1);
59
+ else
60
+ trace = hb.shapeWithTrace(font, buffer, "", i - 50, 2);
61
+ //console.log(trace);
62
+ }
63
+
64
+ //example(hb, new Uint8Array(fs.readFileSync(path.resolve(__dirname, './test/fonts/noto/NotoSans-Regular.ttf'))));
65
+ //example(hb, new Uint8Array(fs.readFileSync(path.resolve(__dirname, './test/fonts/noto/NotoSansArabic-Variable.ttf'))), "أبجد");
66
+ });
package/test/index.js CHANGED
@@ -22,6 +22,8 @@ describe('Face', function () {
22
22
  const codepoints = [...this.face.collectUnicodes()];
23
23
  expect(codepoints).to.include('a'.codePointAt(0));
24
24
  expect(codepoints).not.to.include('ا'.codePointAt(0));
25
+ this.face.destroy();
26
+ this.blob.destroy();
25
27
  });
26
28
 
27
29
  it('exposes upem', function () {
@@ -79,6 +81,35 @@ describe('Font', function () {
79
81
  const glyphs = this.buffer.json();
80
82
  expect(glyphs[0].ax).to.equal(526);
81
83
  });
84
+
85
+ it('glyphToPath converts quadratic glyph to path', function () {
86
+ this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
87
+ this.face = hb.createFace(this.blob);
88
+ this.font = hb.createFont(this.face);
89
+ const expected21 = 'M520,0L48,0L48,73L235,262Q289,316 326,358Q363,400 382,440.5Q401,481 401,529Q401,\
90
+ 588 366,618.5Q331,649 275,649Q223,649 183.5,631Q144,613 103,581L56,640Q98,675 152.5,699.5Q207,724 275,\
91
+ 724Q375,724 433,673.5Q491,623 491,534Q491,478 468,429Q445,380 404,332.5Q363,285 308,231L159,84L159,80L520,80L520,0Z';
92
+ expect(this.font.glyphToPath(21)).to.equal(expected21);
93
+ const expected22 = 'M493,547Q493,475 453,432.5Q413,390 345,376L345,372Q431,362 473,318Q515,274 515,203Q515,\
94
+ 141 486,92.5Q457,44 396.5,17Q336,-10 241,-10Q185,-10 137,-1.5Q89,7 45,29L45,111Q90,89 142,76.5Q194,64 242,64Q338,\
95
+ 64 380.5,101.5Q423,139 423,205Q423,272 370.5,301.5Q318,331 223,331L154,331L154,406L224,406Q312,406 357.5,443Q403,\
96
+ 480 403,541Q403,593 368,621.5Q333,650 273,650Q215,650 174,633Q133,616 93,590L49,650Q87,680 143.5,702Q200,724 272,\
97
+ 724Q384,724 438.5,674Q493,624 493,547Z';
98
+ expect(this.font.glyphToPath(22)).to.equal(expected22);
99
+ });
100
+
101
+ it('glyphToPath converts cubic glyph to path', function () {
102
+ this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.otf')));
103
+ this.face = hb.createFace(this.blob);
104
+ this.font = hb.createFont(this.face);
105
+ const expected21 = 'M520,0L520,80L159,80L159,84L308,231C418,338 491,422 491,534C491,652 408,724 275,724C184,724 112,\
106
+ 687 56,640L103,581C158,624 205,649 275,649C350,649 401,607 401,529C401,432 342,370 235,262L48,73L48,0L520,0Z';
107
+ expect(this.font.glyphToPath(21)).to.equal(expected21);
108
+ const expected22 = 'M493,547C493,649 421,724 272,724C176,724 100,690 49,650L93,590C146,625 196,650 273,650C353,\
109
+ 650 403,610 403,541C403,460 341,406 224,406L154,406L154,331L223,331C349,331 423,294 423,205C423,117 370,64 242,64C178,\
110
+ 64 105,81 45,111L45,29C104,0 166,-10 241,-10C430,-10 515,78 515,203C515,297 459,358 345,372L345,376C435,394 493,451 493,547Z';
111
+ expect(this.font.glyphToPath(22)).to.equal(expected22);
112
+ });
82
113
  });
83
114
 
84
115
  describe('Buffer', function () {
@@ -161,7 +192,7 @@ describe('shape', function () {
161
192
  this.buffer = hb.createBuffer();
162
193
  this.buffer.addText('abc');
163
194
  this.buffer.guessSegmentProperties();
164
- const result = hb.shapeWithTrace(this.font, this.buffer, 0, 0)
195
+ const result = hb.shapeWithTrace(this.font, this.buffer, "", 0, 0)
165
196
  expect(result).to.have.lengthOf(42);
166
197
  expect(result[0]).to.deep.equal({
167
198
  "m": "start table GSUB script tag 'latn'",
@@ -182,4 +213,51 @@ describe('shape', function () {
182
213
  ],
183
214
  });
184
215
  });
216
+
217
+ it('shape with tracing and features', function () {
218
+ this.blob = hb.createBlob(fs.readFileSync(path.join(__dirname, 'fonts/noto/NotoSans-Regular.ttf')));
219
+ this.face = hb.createFace(this.blob);
220
+ this.font = hb.createFont(this.face);
221
+ this.buffer = hb.createBuffer();
222
+ this.buffer.addText('fi AV');
223
+ this.buffer.guessSegmentProperties();
224
+ const result = hb.shapeWithTrace(this.font, this.buffer, "-liga,-kern", 0, 0)
225
+ expect(result).to.have.lengthOf(29);
226
+ expect(result[0]).to.deep.equal({
227
+ "m": "start table GSUB script tag 'latn'",
228
+ "glyphs": true,
229
+ "t": [
230
+ {cl: 0, g: 73},
231
+ {cl: 1, g: 76},
232
+ {cl: 2, g: 3},
233
+ {cl: 3, g: 36},
234
+ {cl: 4, g: 57},
235
+ ],
236
+ });
237
+ expect(result[28]).to.deep.equal({
238
+ "m": "end table GPOS script tag 'latn'",
239
+ "glyphs": true,
240
+ "t": [
241
+ {cl: 0, g: 73, ax: 344, ay: 0, dx: 0, dy: 0},
242
+ {cl: 1, g: 76, ax: 258, ay: 0, dx: 0, dy: 0},
243
+ {cl: 2, g: 3, ax: 260, ay: 0, dx: 0, dy: 0},
244
+ {cl: 3, g: 36, ax: 639, ay: 0, dx: 0, dy: 0},
245
+ {cl: 4, g: 57, ax: 600, ay: 0, dx: 0, dy: 0},
246
+ ],
247
+ });
248
+ });
249
+ });
250
+
251
+ describe('misc', function () {
252
+ it('get version', function () {
253
+ const version = hb.version();
254
+ expect(version).to.have.property('major').that.is.a('number');
255
+ expect(version).to.have.property('minor').that.is.a('number');
256
+ expect(version).to.have.property('micro').that.is.a('number');
257
+ expect(version.major).to.be.at.least(10);
258
+ });
259
+ it('get version string', function () {
260
+ const version_string = hb.version_string();
261
+ expect(version_string).to.match(/^\d+\.\d+\.\d+$/);
262
+ });
185
263
  });
package/hbjs.cc DELETED
@@ -1,261 +0,0 @@
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_draw_glyph (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 (strncmp(message, "start table GSUB", 16) == 0) {
157
- user_data->current_phase = HB_SHAPE_GSUB_PHASE;
158
- } else if (strncmp(message, "start table GPOS", 16) == 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
- (strncmp(message + 11, buf, strlen(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
- if (hb_buffer_get_content_type(buffer) == HB_BUFFER_CONTENT_TYPE_GLYPHS) {
194
- _user_data_printf (user_data, ", \"glyphs\": true");
195
- } else {
196
- _user_data_printf (user_data, ", \"glyphs\": false");
197
- }
198
- _user_data_printf (user_data, "},\n");
199
-
200
- return 1;
201
- }
202
-
203
- unsigned
204
- hbjs_shape_with_trace (hb_font_t *font, hb_buffer_t* buf,
205
- char* featurestring,
206
- unsigned int stop_at, unsigned int stop_phase,
207
- char *outbuf, unsigned buf_size) {
208
- user_data_t user_data(outbuf, buf_size, stop_at, stop_phase);
209
-
210
- int num_features = 0;
211
- hb_feature_t* features = nullptr;
212
-
213
- if (*featurestring) {
214
- /* count the features first, so we can allocate memory */
215
- char* p = featurestring;
216
- do {
217
- num_features++;
218
- p = strchr (p, ',');
219
- if (p)
220
- p++;
221
- } while (p);
222
-
223
- features = (hb_feature_t *) calloc (num_features, sizeof (*features));
224
-
225
- /* now do the actual parsing */
226
- p = featurestring;
227
- num_features = 0;
228
- while (p && *p) {
229
- char *end = strchr (p, ',');
230
- if (hb_feature_from_string (p, end ? end - p : -1, &features[num_features]))
231
- num_features++;
232
- p = end ? end + 1 : nullptr;
233
- }
234
- }
235
-
236
- hb_buffer_set_message_func (buf, (hb_buffer_message_func_t)do_trace, &user_data, nullptr);
237
- user_data.str[user_data.consumed++] = '[';
238
- hb_shape(font, buf, features, num_features);
239
-
240
- if (user_data.failure) return -1;
241
-
242
- user_data.str[user_data.consumed-2] = ']';
243
- user_data.str[user_data.consumed-1] = '\0';
244
- return user_data.consumed;
245
- }
246
-
247
- #ifdef MAIN
248
- #include <stdio.h>
249
- int main() {
250
- hb_blob_t *blob = hb_blob_create_from_file ("/home/ebrahim/Desktop/harfbuzzjs/harfbuzz/test/subset/data/fonts/Roboto-Regular.ttf");
251
- hb_face_t *face = hb_face_create (blob, 0);
252
- hb_blob_destroy (blob);
253
- hb_font_t *font = hb_font_create (face);
254
- hb_face_destroy (face);
255
- char buf[1024];
256
- buf[0] = '\0';
257
- printf ("%d %d\n", hb_blob_get_length (blob), hbjs_ot_glyph_svg (font, 0, buf, sizeof (buf)));
258
- puts (buf);
259
- hb_font_destroy (font);
260
- }
261
- #endif