diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh index 5a43cabcb..d50641ef2 100644 --- a/src/hb-buffer.hh +++ b/src/hb-buffer.hh @@ -493,6 +493,13 @@ struct hb_buffer_t HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size); + HB_NODISCARD bool resize (unsigned length) + { + assert (!have_output); + if (unlikely (!ensure (length))) return false; + len = length; + return true; + } HB_NODISCARD bool ensure (unsigned int size) { return likely (!size || size < allocated) ? true : enlarge (size); } diff --git a/src/hb-wasm-api-buffer.hh b/src/hb-wasm-api-buffer.hh index 07d7ab418..3164b7617 100644 --- a/src/hb-wasm-api-buffer.hh +++ b/src/hb-wasm-api-buffer.hh @@ -32,6 +32,8 @@ namespace hb { namespace wasm { +static_assert (sizeof (glyph_info_t) == sizeof (hb_glyph_info_t), ""); +static_assert (sizeof (glyph_position_t) == sizeof (hb_glyph_position_t), ""); void buffer_contents_free (HB_WASM_EXEC_ENV @@ -59,9 +61,6 @@ buffer_copy_contents (HB_WASM_EXEC_ENV_COMPOUND if (buffer->have_output) buffer->sync (); - static_assert (sizeof (glyph_info_t) == sizeof (hb_glyph_info_t), ""); - static_assert (sizeof (glyph_position_t) == sizeof (hb_glyph_position_t), ""); - unsigned length = buffer->len; ret.length = length; ret.info = wasm_runtime_module_dup_data (module_inst, (const char *) buffer->info, length * sizeof (buffer->info[0])); @@ -69,6 +68,35 @@ buffer_copy_contents (HB_WASM_EXEC_ENV_COMPOUND } +bool_t +buffer_set_contents (HB_WASM_EXEC_ENV + ptr_t(buffer_t) bufferref, + ptr_t(const buffer_contents_t) contentsptr) +{ + HB_REF2OBJ (buffer); + HB_STRUCT_TYPE (buffer_contents_t, contents); + if (unlikely (!contents)) + return false; + + unsigned length = contents->length; + unsigned bytes; + if (unlikely (hb_unsigned_mul_overflows (length, sizeof (buffer->info[0]), &bytes))) + return false; + + if (unlikely (!buffer->resize (length))) + return false; + + glyph_info_t *info = (glyph_info_t *) (validate_app_addr (contents->info, bytes) ? addr_app_to_native (contents->info) : nullptr); + glyph_position_t *pos = (glyph_position_t *) (validate_app_addr (contents->pos, bytes) ? addr_app_to_native (contents->pos) : nullptr); + + buffer->clear_positions (); /* This is wasteful, but we need it to set have_positions=true. */ + memcpy (buffer->info, info, bytes); + memcpy (buffer->pos, pos, bytes); + buffer->len = length; + + return true; +} + }} #endif /* HB_WASM_API_BUFFER_HH */ diff --git a/src/hb-wasm-api-list.hh b/src/hb-wasm-api-list.hh index df39ad17b..dc29b2f8f 100644 --- a/src/hb-wasm-api-list.hh +++ b/src/hb-wasm-api-list.hh @@ -57,15 +57,16 @@ static NativeSymbol _hb_wasm_native_symbols[] = /* buffer */ NATIVE_SYMBOL ("(i)", buffer_contents_free), NATIVE_SYMBOL ("(ii)", buffer_copy_contents), + NATIVE_SYMBOL ("(ii)i", buffer_set_contents), /* face */ NATIVE_SYMBOL ("(iii)", face_reference_table), /* font */ - NATIVE_SYMBOL ("(i)i", font_get_face), + NATIVE_SYMBOL ("(i)i", font_get_face), NATIVE_SYMBOL ("(iii)i", font_get_glyph), - NATIVE_SYMBOL ("(ii)i", font_get_glyph_h_advance), - NATIVE_SYMBOL ("(ii)i", font_get_glyph_v_advance), + NATIVE_SYMBOL ("(ii)i", font_get_glyph_h_advance), + NATIVE_SYMBOL ("(ii)i", font_get_glyph_v_advance), /* debug */ #ifdef HB_DEBUG_WASM diff --git a/src/hb-wasm-api.h b/src/hb-wasm-api.h index 66d5b64c0..e5f6700d1 100644 --- a/src/hb-wasm-api.h +++ b/src/hb-wasm-api.h @@ -123,6 +123,10 @@ typedef struct buffer_t buffer_t; HB_WASM_API_COMPOUND (buffer_contents_t, buffer_copy_contents) (HB_WASM_EXEC_ENV_COMPOUND ptr_t(buffer_t)); +HB_WASM_API (bool_t, buffer_set_contents) (HB_WASM_EXEC_ENV + ptr_t(buffer_t), + ptr_t(const buffer_contents_t)); + /* face */ diff --git a/src/wasm-sample/shape.c b/src/wasm-sample/shape.c index 80486b2b5..c558114c9 100644 --- a/src/wasm-sample/shape.c +++ b/src/wasm-sample/shape.c @@ -23,9 +23,15 @@ shape (font_t *font, buffer_t *buffer) debugprint1 ("buffer length", contents.length); for (unsigned i = 0; i < contents.length; i++) + { debugprint2 ("Codepoint", i, contents.info[i].codepoint); + contents.info[i].codepoint++; + contents.pos[i].x_advance = 256 * 64; + } + + bool_t ret = buffer_set_contents (buffer, &contents); buffer_contents_free (&contents); - return 1; + return ret; }