xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-wasm-api-buffer.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
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