import { ZigJS } from "zig-js"; const zjs = new ZigJS(); const importObject = { module: {}, env: { memory: new WebAssembly.Memory({ initial: 25, maximum: 65536, shared: true, }), log: (ptr: number, len: number) => { const arr = new Uint8ClampedArray(zjs.memory.buffer, ptr, len); const data = arr.slice(); const str = new TextDecoder("utf-8").decode(data); console.log(str); }, }, ...zjs.importObject(), }; const url = new URL("ghostty-wasm.wasm", import.meta.url); fetch(url.href) .then((response) => response.arrayBuffer()) .then((bytes) => WebAssembly.instantiate(bytes, importObject)) .then((results) => { const memory = importObject.env.memory; const { malloc, free, config_new, config_free, config_load_string, config_finalize, face_new, face_free, face_render_glyph, face_debug_canvas, deferred_face_new, deferred_face_free, deferred_face_load, deferred_face_face, group_new, group_free, group_add_face, group_init_sprite_face, group_index_for_codepoint, group_render_glyph, group_cache_new, group_cache_free, group_cache_index_for_codepoint, group_cache_render_glyph, group_cache_atlas_greyscale, group_cache_atlas_color, atlas_new, atlas_free, atlas_debug_canvas, shaper_new, shaper_free, shaper_test, } = results.instance.exports; // Give us access to the zjs value for debugging. globalThis.zjs = zjs; console.log(zjs); // Initialize our zig-js memory zjs.memory = memory; // Helpers const makeStr = (str) => { const utf8 = new TextEncoder().encode(str); const ptr = malloc(utf8.byteLength); new Uint8Array(memory.buffer, ptr).set(utf8); return { ptr: ptr, len: utf8.byteLength }; }; // Create our config const config = config_new(); const config_str = makeStr("font-family = monospace"); config_load_string(config, config_str.ptr, config_str.len); config_finalize(config); free(config_str.ptr); // Create our atlas // const atlas = atlas_new(512, 0 /* greyscale */); // Create some memory for our string const font_name = makeStr("monospace"); // Initialize our deferred face // const df = deferred_face_new(font_ptr, font.byteLength, 0 /* text */); //deferred_face_load(df, 72 /* size */); //const face = deferred_face_face(df); // Initialize our font face //const face = face_new(font_ptr, font.byteLength, 72 /* size in px */); //free(font_ptr); // Create our group const group = group_new(32 /* size */); group_add_face( group, 0 /* regular */, deferred_face_new(font_name.ptr, font_name.len, 0 /* text */) ); group_add_face( group, 0 /* regular */, deferred_face_new(font_name.ptr, font_name.len, 1 /* emoji */) ); // Initialize our sprite font, without this we just use the browser. group_init_sprite_face(group); // Create our group cache const group_cache = group_cache_new(group); // Render a glyph // for (let i = 33; i <= 126; i++) { // const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); // group_cache_render_glyph(group_cache, font_idx, i, 0); // //face_render_glyph(face, atlas, i); // } // // const emoji = ["🐏","🌞","🌚","🍱","πŸ’Ώ","🐈","πŸ“ƒ","πŸ“€","πŸ•‘","πŸ™ƒ"]; // for (let i = 0; i < emoji.length; i++) { // const cp = emoji[i].codePointAt(0); // const font_idx = group_cache_index_for_codepoint(group_cache, cp, 0, -1 /* best choice */); // group_cache_render_glyph(group_cache, font_idx, cp, 0); // } for (let i = 0x2500; i <= 0x257f; i++) { const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); group_cache_render_glyph(group_cache, font_idx, i, 0); } for (let i = 0x2580; i <= 0x259f; i++) { const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); group_cache_render_glyph(group_cache, font_idx, i, 0); } for (let i = 0x2800; i <= 0x28ff; i++) { const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); group_cache_render_glyph(group_cache, font_idx, i, 0); } for (let i = 0x1fb00; i <= 0x1fb3b; i++) { const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); group_cache_render_glyph(group_cache, font_idx, i, 0); } for (let i = 0x1fb3c; i <= 0x1fb6b; i++) { const font_idx = group_cache_index_for_codepoint(group_cache, i, 0, -1); group_cache_render_glyph(group_cache, font_idx, i, 0); } //face_render_glyph(face, atlas, "ζ©‹".codePointAt(0)); //face_render_glyph(face, atlas, "p".codePointAt(0)); // Debug our canvas //face_debug_canvas(face); // Let's try shaping const shaper = shaper_new(120); //const input = makeStr("hello🐏"); const input = makeStr("helloπŸπŸ‘πŸ½"); shaper_test(shaper, group_cache, input.ptr, input.len); const cp = 1114112; const font_idx = group_cache_index_for_codepoint( group_cache, cp, 0, -1 /* best choice */ ); group_cache_render_glyph(group_cache, font_idx, cp, -1); // Debug our atlas canvas { const atlas = group_cache_atlas_greyscale(group_cache); const id = atlas_debug_canvas(atlas); document.getElementById("atlas-canvas").append(zjs.deleteValue(id)); } { const atlas = group_cache_atlas_color(group_cache); const id = atlas_debug_canvas(atlas); document.getElementById("atlas-color-canvas").append(zjs.deleteValue(id)); } //face_free(face); });