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.
- package/.vscode/settings.json +2 -1
- package/build-subset.sh +0 -1
- package/build.sh +7 -3
- package/hb-subset.wasm +0 -0
- package/hb.js +19 -0
- package/{hbjs.symbols → hb.symbols} +13 -3
- package/hb.wasm +0 -0
- package/hbjs.js +146 -27
- package/index.js +5 -9
- package/package.json +1 -1
- package/perf.js +66 -0
- package/test/fonts/noto/NotoSans-Regular.otf +0 -0
- package/test/index.js +79 -1
- package/hbjs.cc +0 -261
package/.vscode/settings.json
CHANGED
package/build-subset.sh
CHANGED
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
|
|
18
|
+
-s MODULARIZE \
|
|
19
|
+
-s EXPORTED_FUNCTIONS=@hb.symbols \
|
|
20
|
+
-s EXPORTED_RUNTIME_METHODS='["addFunction", "wasmMemory", "wasmExports"]' \
|
|
19
21
|
-s INITIAL_MEMORY=65MB \
|
|
20
|
-
-
|
|
21
|
-
|
|
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
|
-
|
|
38
|
-
|
|
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(
|
|
1
|
+
function hbjs(Module) {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var exports =
|
|
5
|
-
var heapu8 =
|
|
6
|
-
var heapu32 =
|
|
7
|
-
var heapi32 =
|
|
8
|
-
var heapf32 =
|
|
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,
|
|
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
|
|
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
|
-
|
|
177
|
-
|
|
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(
|
|
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:
|
|
445
|
+
* @param {object} features: A string of comma-separated OpenType features to apply.
|
|
405
446
|
*/
|
|
406
447
|
function shape(font, buffer, features) {
|
|
407
|
-
|
|
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
|
|
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
|
|
430
|
-
var
|
|
431
|
-
var
|
|
432
|
-
var
|
|
433
|
-
|
|
434
|
-
var
|
|
435
|
-
exports.
|
|
436
|
-
|
|
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 {
|
|
567
|
+
try {
|
|
568
|
+
module.exports = hbjs;
|
|
569
|
+
} catch (e) {}
|
package/index.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
resolve(hbjs(result.instance));
|
|
10
|
-
}, reject);
|
|
11
|
-
});
|
|
5
|
+
hb().then((instance) => {
|
|
6
|
+
resolve(hbjs(instance));
|
|
7
|
+
}, reject);
|
|
12
8
|
});
|
package/package.json
CHANGED
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
|
+
});
|
|
Binary file
|
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
|