1 /*
2 * Copyright © 2023 Behdad Esfahbod
3 *
4 * This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 */
24
25 #ifndef HB_WASM_API_BUFFER_HH
26 #define HB_WASM_API_BUFFER_HH
27
28 #include "hb-wasm-api.hh"
29
30 #include "hb-buffer.hh"
31
32 namespace hb {
33 namespace wasm {
34
35 static_assert (sizeof (glyph_info_t) == sizeof (hb_glyph_info_t), "");
36 static_assert (sizeof (glyph_position_t) == sizeof (hb_glyph_position_t), "");
37
HB_WASM_API(bool_t,buffer_contents_realloc)38 HB_WASM_API (bool_t, buffer_contents_realloc) (HB_WASM_EXEC_ENV
39 ptr_d(buffer_contents_t, contents),
40 uint32_t size)
41 {
42 HB_PTR_PARAM (buffer_contents_t, contents);
43 if (unlikely (!contents))
44 return false;
45
46 if (size <= contents->length)
47 return true;
48
49 unsigned bytes;
50 if (hb_unsigned_mul_overflows (size, sizeof (glyph_info_t), &bytes))
51 return false;
52
53 glyph_info_t *info = HB_ARRAY_APP2NATIVE (glyph_info_t, contents->info, contents->length);
54 glyph_position_t *pos = HB_ARRAY_APP2NATIVE (glyph_position_t, contents->pos, contents->length);
55
56 if (unlikely (!info || !pos))
57 return false;
58
59 glyph_info_t *new_info = nullptr;
60 uint32_t new_inforef = module_malloc (bytes, (void **) &new_info);
61 glyph_position_t *new_pos = nullptr;
62 uint32_t new_posref = module_malloc (bytes, (void **) &new_pos);
63
64 unsigned old_bytes = contents->length * sizeof (glyph_info_t);
65 if (likely (new_inforef))
66 {
67 hb_memcpy (new_info, info, old_bytes);
68 module_free (contents->info);
69 contents->info = new_inforef;
70 }
71 if (likely (new_posref))
72 {
73 hb_memcpy (new_pos, pos, old_bytes);
74 module_free (contents->pos);
75 contents->pos = new_posref;
76 }
77
78 if (likely (new_info && new_pos))
79 {
80 contents->length = size;
81 return true;
82 }
83
84 return false;
85 }
86
HB_WASM_API(void,buffer_contents_free)87 HB_WASM_API (void, buffer_contents_free) (HB_WASM_EXEC_ENV
88 ptr_d(buffer_contents_t, contents))
89 {
90 HB_PTR_PARAM (buffer_contents_t, contents);
91 if (unlikely (!contents))
92 return;
93
94 module_free (contents->info);
95 module_free (contents->pos);
96
97 contents->info = nullref;
98 contents->pos = nullref;
99 contents->length = 0;
100 }
101
HB_WASM_API(bool_t,buffer_copy_contents)102 HB_WASM_API (bool_t, buffer_copy_contents) (HB_WASM_EXEC_ENV
103 ptr_d(buffer_t, buffer),
104 ptr_d(buffer_contents_t, contents))
105 {
106 HB_REF2OBJ (buffer);
107 HB_PTR_PARAM (buffer_contents_t, contents);
108 if (unlikely (!contents))
109 return false;
110
111 if (buffer->have_output)
112 buffer->sync ();
113 if (!buffer->have_positions)
114 buffer->clear_positions ();
115
116 unsigned length = buffer->len;
117
118 if (length <= contents->length)
119 {
120 glyph_info_t *info = HB_ARRAY_APP2NATIVE (glyph_info_t, contents->info, length);
121 glyph_position_t *pos = HB_ARRAY_APP2NATIVE (glyph_position_t, contents->pos, length);
122
123 if (unlikely (!info || !pos))
124 {
125 contents->length = 0;
126 return false;
127 }
128
129 unsigned bytes = length * sizeof (hb_glyph_info_t);
130 hb_memcpy (info, buffer->info, bytes);
131 hb_memcpy (pos, buffer->pos, bytes);
132
133 return true;
134 }
135
136 module_free (contents->info);
137 module_free (contents->pos);
138
139 contents->length = length;
140 unsigned bytes = length * sizeof (hb_glyph_info_t);
141 contents->info = wasm_runtime_module_dup_data (module_inst, (const char *) buffer->info, bytes);
142 contents->pos = wasm_runtime_module_dup_data (module_inst, (const char *) buffer->pos, bytes);
143
144 if (length && (!contents->info || !contents->pos))
145 {
146 contents->length = 0;
147 return false;
148 }
149
150 return true;
151 }
152
HB_WASM_API(bool_t,buffer_set_contents)153 HB_WASM_API (bool_t, buffer_set_contents) (HB_WASM_EXEC_ENV
154 ptr_d(buffer_t, buffer),
155 ptr_d(const buffer_contents_t, contents))
156 {
157 HB_REF2OBJ (buffer);
158 HB_PTR_PARAM (buffer_contents_t, contents);
159 if (unlikely (!contents))
160 return false;
161
162 unsigned length = contents->length;
163 unsigned bytes;
164 if (unlikely (hb_unsigned_mul_overflows (length, sizeof (buffer->info[0]), &bytes)))
165 return false;
166
167 if (unlikely (!buffer->resize (length)))
168 return false;
169
170 glyph_info_t *info = (glyph_info_t *) (validate_app_addr (contents->info, bytes) ? addr_app_to_native (contents->info) : nullptr);
171 glyph_position_t *pos = (glyph_position_t *) (validate_app_addr (contents->pos, bytes) ? addr_app_to_native (contents->pos) : nullptr);
172
173 if (!buffer->have_positions)
174 buffer->clear_positions (); /* This is wasteful. */
175
176 hb_memcpy (buffer->info, info, bytes);
177 hb_memcpy (buffer->pos, pos, bytes);
178 buffer->len = length;
179
180 return true;
181 }
182
HB_WASM_API(direction_t,buffer_get_direction)183 HB_WASM_API (direction_t, buffer_get_direction) (HB_WASM_EXEC_ENV
184 ptr_d(buffer_t, buffer))
185 {
186 HB_REF2OBJ (buffer);
187
188 return (direction_t) hb_buffer_get_direction (buffer);
189 }
190
HB_WASM_API(script_t,buffer_get_script)191 HB_WASM_API (script_t, buffer_get_script) (HB_WASM_EXEC_ENV
192 ptr_d(buffer_t, buffer))
193 {
194 HB_REF2OBJ (buffer);
195
196 return hb_script_to_iso15924_tag (hb_buffer_get_script (buffer));
197 }
198
HB_WASM_API(void,buffer_reverse)199 HB_WASM_API (void, buffer_reverse) (HB_WASM_EXEC_ENV
200 ptr_d(buffer_t, buffer))
201 {
202 HB_REF2OBJ (buffer);
203
204 hb_buffer_reverse (buffer);
205 }
206
HB_WASM_API(void,buffer_reverse_clusters)207 HB_WASM_API (void, buffer_reverse_clusters) (HB_WASM_EXEC_ENV
208 ptr_d(buffer_t, buffer))
209 {
210 HB_REF2OBJ (buffer);
211
212 hb_buffer_reverse_clusters (buffer);
213 }
214
215 }}
216
217 #endif /* HB_WASM_API_BUFFER_HH */
218