blob: 6539b89640a142016904681849214480b950e97b [file] [log] [blame]
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -05001/*
2 * Copyright © 2012,2013 Google, Inc.
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 * Google Author(s): Behdad Esfahbod
25 */
26
Behdad Esfahbodbe1c0ab2019-06-18 13:26:03 -070027#include "hb.hh"
28
29#ifndef HB_NO_BUFFER_SERIALIZE
30
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070031#include "hb-buffer.hh"
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050032
33
34static const char *serialize_formats[] = {
35 "text",
36 "json",
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +020037 nullptr
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050038};
39
Behdad Esfahbod288f2892013-09-06 15:40:22 -040040/**
41 * hb_buffer_serialize_list_formats:
42 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +040043 * Returns a list of supported buffer serialization formats.
Behdad Esfahbod288f2892013-09-06 15:40:22 -040044 *
45 * Return value: (transfer none):
Khaled Hosny9ab9f972016-01-01 20:38:21 +040046 * A string array of buffer serialization formats. Should not be freed.
Behdad Esfahbod288f2892013-09-06 15:40:22 -040047 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +040048 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -040049 **/
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050050const char **
Ebrahim Byagowie4120082018-12-17 21:31:01 +033051hb_buffer_serialize_list_formats ()
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050052{
53 return serialize_formats;
54}
55
Behdad Esfahbod288f2892013-09-06 15:40:22 -040056/**
57 * hb_buffer_serialize_format_from_string:
Khaled Hosny9ab9f972016-01-01 20:38:21 +040058 * @str: (array length=len) (element-type uint8_t): a string to parse
59 * @len: length of @str, or -1 if string is %NULL terminated
Behdad Esfahbod288f2892013-09-06 15:40:22 -040060 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +040061 * Parses a string into an #hb_buffer_serialize_format_t. Does not check if
62 * @str is a valid buffer serialization format, use
63 * hb_buffer_serialize_list_formats() to get the list of supported formats.
Behdad Esfahbod288f2892013-09-06 15:40:22 -040064 *
Ebrahim Byagowi687f6792018-10-20 17:50:39 +033065 * Return value:
Khaled Hosny9ab9f972016-01-01 20:38:21 +040066 * The parsed #hb_buffer_serialize_format_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -040067 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +040068 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -040069 **/
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050070hb_buffer_serialize_format_t
71hb_buffer_serialize_format_from_string (const char *str, int len)
72{
73 /* Upper-case it. */
Behdad Esfahbod76271002014-07-11 14:54:42 -040074 return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u);
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050075}
76
Behdad Esfahbod288f2892013-09-06 15:40:22 -040077/**
78 * hb_buffer_serialize_format_to_string:
Khaled Hosny9ab9f972016-01-01 20:38:21 +040079 * @format: an #hb_buffer_serialize_format_t to convert.
Behdad Esfahbod288f2892013-09-06 15:40:22 -040080 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +040081 * Converts @format to the string corresponding it, or %NULL if it is not a valid
82 * #hb_buffer_serialize_format_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -040083 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +040084 * Return value: (transfer none):
85 * A %NULL terminated string corresponding to @format. Should not be freed.
Behdad Esfahbod288f2892013-09-06 15:40:22 -040086 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +040087 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -040088 **/
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050089const char *
90hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
91{
Behdad Esfahboddba1ac12019-05-12 15:33:31 -070092 switch ((unsigned) format)
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050093 {
Simon Cozens57a528a2020-09-18 09:35:05 +010094 case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0];
95 case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1];
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050096 default:
Simon Cozens57a528a2020-09-18 09:35:05 +010097 case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr;
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -050098 }
99}
100
101static unsigned int
102_hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
Simon Cozens57a528a2020-09-18 09:35:05 +0100103 unsigned int start,
104 unsigned int end,
105 char *buf,
106 unsigned int buf_size,
107 unsigned int *buf_consumed,
108 hb_font_t *font,
109 hb_buffer_serialize_flags_t flags)
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500110{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200111 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
Behdad Esfahbod75504a52015-08-18 18:47:02 +0100112 hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
Simon Cozens57a528a2020-09-18 09:35:05 +0100113 nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500114
115 *buf_consumed = 0;
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100116 hb_position_t x = 0, y = 0;
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500117 for (unsigned int i = start; i < end; i++)
118 {
119 char b[1024];
120 char *p = b;
121
122 /* In the following code, we know b is large enough that no overflow can happen. */
123
124#define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END
125
126 if (i)
127 *p++ = ',';
Simon Cozensc0716bb2020-09-18 10:31:28 +0100128 else
129 *p++ = '[';
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500130
131 *p++ = '{';
132
133 APPEND ("\"g\":");
134 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES))
135 {
136 char g[128];
137 hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g));
138 *p++ = '"';
Behdad Esfahbodc396e162020-10-09 21:13:10 -0600139 for (char *q = g; *q; q++)
140 {
141 if (unlikely (*q == '"' || *q == '\\'))
142 *p++ = '\\';
143 *p++ = *q;
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500144 }
145 *p++ = '"';
146 }
147 else
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700148 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500149
150 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700151 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500152 }
153
154 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
155 {
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700156 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
Behdad Esfahbodc396e162020-10-09 21:13:10 -0600157 x+pos[i].x_offset, y+pos[i].y_offset));
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100158 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
Simon Cozens57a528a2020-09-18 09:35:05 +0100159 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
Behdad Esfahbodc396e162020-10-09 21:13:10 -0600160 pos[i].x_advance, pos[i].y_advance));
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +0200161 }
162
163 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
164 {
Jonathan Kew331d66c2014-07-19 23:09:09 +0100165 if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
Simon Cozens57a528a2020-09-18 09:35:05 +0100166 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED));
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500167 }
168
Behdad Esfahbodfdd17702015-08-24 13:49:55 +0100169 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
170 {
171 hb_glyph_extents_t extents;
172 hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700173 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
Simon Cozens57a528a2020-09-18 09:35:05 +0100174 extents.x_bearing, extents.y_bearing));
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700175 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
Simon Cozens57a528a2020-09-18 09:35:05 +0100176 extents.width, extents.height));
Behdad Esfahbodfdd17702015-08-24 13:49:55 +0100177 }
178
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500179 *p++ = '}';
Simon Cozensc0716bb2020-09-18 10:31:28 +0100180 if (i == end-1)
181 *p++ = ']';
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500182
Behdad Esfahbod176fd172013-10-30 17:27:24 +0000183 unsigned int l = p - b;
184 if (buf_size > l)
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500185 {
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500186 memcpy (buf, b, l);
187 buf += l;
188 buf_size -= l;
189 *buf_consumed += l;
190 *buf = '\0';
191 } else
192 return i - start;
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100193
Behdad Esfahbod994eb772018-01-11 11:37:12 +0100194 if (pos && (flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100195 {
196 x += pos[i].x_advance;
197 y += pos[i].y_advance;
198 }
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500199 }
200
201 return end - start;
202}
203
204static unsigned int
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100205_hb_buffer_serialize_unicode_json (hb_buffer_t *buffer,
Simon Cozens57a528a2020-09-18 09:35:05 +0100206 unsigned int start,
207 unsigned int end,
208 char *buf,
209 unsigned int buf_size,
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100210 unsigned int *buf_consumed,
211 hb_buffer_serialize_flags_t flags)
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100212{
Simon Cozens57a528a2020-09-18 09:35:05 +0100213 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100214
Simon Cozens57a528a2020-09-18 09:35:05 +0100215 *buf_consumed = 0;
216 for (unsigned int i = start; i < end; i++)
217 {
218 char b[1024];
219 char *p = b;
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100220
Simon Cozens57a528a2020-09-18 09:35:05 +0100221 if (i)
222 *p++ = ',';
Simon Cozensc0716bb2020-09-18 10:31:28 +0100223 else
224 *p++ = '[';
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100225
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100226 *p++ = '{';
227
228 APPEND ("\"u\":");
229
Simon Cozens57a528a2020-09-18 09:35:05 +0100230 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100231
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100232 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
233 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
234 }
235
236 *p++ = '}';
237
Simon Cozensc0716bb2020-09-18 10:31:28 +0100238 if (i == end-1)
239 *p++ = ']';
240
Simon Cozens57a528a2020-09-18 09:35:05 +0100241 unsigned int l = p - b;
242 if (buf_size > l)
243 {
244 memcpy (buf, b, l);
245 buf += l;
246 buf_size -= l;
247 *buf_consumed += l;
248 *buf = '\0';
249 } else
250 return i - start;
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100251
Simon Cozens57a528a2020-09-18 09:35:05 +0100252 }
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100253
Simon Cozens57a528a2020-09-18 09:35:05 +0100254 return end - start;
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100255}
256
257static unsigned int
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500258_hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
Simon Cozens57a528a2020-09-18 09:35:05 +0100259 unsigned int start,
260 unsigned int end,
261 char *buf,
262 unsigned int buf_size,
263 unsigned int *buf_consumed,
264 hb_font_t *font,
265 hb_buffer_serialize_flags_t flags)
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500266{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200267 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
Behdad Esfahbod75504a52015-08-18 18:47:02 +0100268 hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ?
Simon Cozens57a528a2020-09-18 09:35:05 +0100269 nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500270
271 *buf_consumed = 0;
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100272 hb_position_t x = 0, y = 0;
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500273 for (unsigned int i = start; i < end; i++)
274 {
275 char b[1024];
276 char *p = b;
277
278 /* In the following code, we know b is large enough that no overflow can happen. */
279
280 if (i)
281 *p++ = '|';
Simon Cozensc0716bb2020-09-18 10:31:28 +0100282 else
283 *p++ = '[';
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500284
285 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES))
286 {
Behdad Esfahbodc396e162020-10-09 21:13:10 -0600287 /* TODO Escape delimiters we use. */
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500288 hb_font_glyph_to_string (font, info[i].codepoint, p, 128);
289 p += strlen (p);
290 }
291 else
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700292 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500293
294 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700295 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500296 }
297
298 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
299 {
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100300 if (x+pos[i].x_offset || y+pos[i].y_offset)
Simon Cozens57a528a2020-09-18 09:35:05 +0100301 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset));
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500302
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100303 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
304 {
Simon Cozens57a528a2020-09-18 09:35:05 +0100305 *p++ = '+';
306 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
307 if (pos[i].y_advance)
308 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100309 }
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500310 }
311
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +0200312 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
313 {
Behdad Esfahbod7251c772018-12-15 21:00:55 -0500314 if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
Simon Cozens57a528a2020-09-18 09:35:05 +0100315 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +0200316 }
317
Behdad Esfahbodfdd17702015-08-24 13:49:55 +0100318 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
319 {
320 hb_glyph_extents_t extents;
321 hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700322 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
Behdad Esfahbodfdd17702015-08-24 13:49:55 +0100323 }
324
Simon Cozensc0716bb2020-09-18 10:31:28 +0100325 if (i == end-1) {
326 *p++ = ']';
327 }
328
Behdad Esfahbod176fd172013-10-30 17:27:24 +0000329 unsigned int l = p - b;
330 if (buf_size > l)
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500331 {
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500332 memcpy (buf, b, l);
333 buf += l;
334 buf_size -= l;
335 *buf_consumed += l;
336 *buf = '\0';
337 } else
338 return i - start;
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100339
Behdad Esfahbod994eb772018-01-11 11:37:12 +0100340 if (pos && (flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
Behdad Esfahbod71fd6322018-01-10 02:20:14 +0100341 {
342 x += pos[i].x_advance;
343 y += pos[i].y_advance;
344 }
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500345 }
346
347 return end - start;
348}
349
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100350
351static unsigned int
352_hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
Simon Cozens57a528a2020-09-18 09:35:05 +0100353 unsigned int start,
354 unsigned int end,
355 char *buf,
356 unsigned int buf_size,
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100357 unsigned int *buf_consumed,
358 hb_buffer_serialize_flags_t flags)
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100359{
Simon Cozensaff6a362020-09-18 09:27:27 +0100360 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
361 *buf_consumed = 0;
362 for (unsigned int i = start; i < end; i++)
363 {
364 char b[1024];
365 char *p = b;
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100366
Simon Cozensaff6a362020-09-18 09:27:27 +0100367 if (i)
368 *p++ = '|';
Simon Cozensc0716bb2020-09-18 10:31:28 +0100369 else
370 *p++ = '<';
Simon Cozensaff6a362020-09-18 09:27:27 +0100371
372 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "U+%04X", info[i].codepoint));
Simon Cozensc0716bb2020-09-18 10:31:28 +0100373
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100374 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
375 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
376 }
377
Simon Cozensc0716bb2020-09-18 10:31:28 +0100378 if (i == end-1)
379 *p++ = '>';
380
Simon Cozensaff6a362020-09-18 09:27:27 +0100381 unsigned int l = p - b;
382 if (buf_size > l)
383 {
384 memcpy (buf, b, l);
385 buf += l;
386 buf_size -= l;
387 *buf_consumed += l;
388 *buf = '\0';
389 } else
390 return i - start;
391 }
392 return end - start;
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100393}
394
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400395/**
396 * hb_buffer_serialize_glyphs:
Khaled Hosny9ab9f972016-01-01 20:38:21 +0400397 * @buffer: an #hb_buffer_t buffer.
398 * @start: the first item in @buffer to serialize.
399 * @end: the last item in @buffer to serialize.
400 * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
401 * write serialized buffer into.
402 * @buf_size: the size of @buf.
Khaled Hosny5151c2b2020-12-31 00:28:27 +0200403 * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
404 * @font: (nullable): the #hb_font_t used to shape this buffer, needed to
Khaled Hosny9ab9f972016-01-01 20:38:21 +0400405 * read glyph names and extents. If %NULL, and empty font will be used.
406 * @format: the #hb_buffer_serialize_format_t to use for formatting the output.
407 * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
408 * to serialize.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400409 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +0400410 * Serializes @buffer into a textual representation of its glyph content,
411 * useful for showing the contents of the buffer, for example during debugging.
412 * There are currently two supported serialization formats:
413 *
414 * ## text
415 * A human-readable, plain text format.
416 * The serialized glyphs will look something like:
417 *
418 * ```
419 * [uni0651=0@518,0+0|uni0628=0+1897]
420 * ```
Khaled Hosny8c3a5302020-12-22 23:52:46 +0200421 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +0400422 * - The serialized glyphs are delimited with `[` and `]`.
423 * - Glyphs are separated with `|`
424 * - Each glyph starts with glyph name, or glyph index if
425 * #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then,
426 * - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster.
427 * - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format:
428 * - If both #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not 0, `@x_offset,y_offset`. Then,
429 * - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then,
Khaled Hosny8c3a5302020-12-22 23:52:46 +0200430 * - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the #hb_glyph_extents_t in the format `<x_bearing,y_bearing,width,height>`
Khaled Hosny9ab9f972016-01-01 20:38:21 +0400431 *
432 * ## json
Simon Cozens36ede562020-09-18 10:24:29 +0100433 * A machine-readable, structured format.
434 * The serialized glyphs will look something like:
435 *
436 * ```
437 * [{"g":"uni0651","cl":0,"dx":518,"dy":0,"ax":0,"ay":0},
438 * {"g":"uni0628","cl":0,"dx":0,"dy":0,"ax":1897,"ay":0}]
439 * ```
Khaled Hosny8c3a5302020-12-22 23:52:46 +0200440 *
Simon Cozens36ede562020-09-18 10:24:29 +0100441 * Each glyph is a JSON object, with the following properties:
442 * - `g`: the glyph name or glyph index if
443 * #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set.
444 * - `cl`: #hb_glyph_info_t.cluster if
445 * #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set.
446 * - `dx`,`dy`,`ax`,`ay`: #hb_glyph_position_t.x_offset, #hb_glyph_position_t.y_offset,
447 * #hb_glyph_position_t.x_advance and #hb_glyph_position_t.y_advance
448 * respectively, if #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set.
449 * - `xb`,`yb`,`w`,`h`: #hb_glyph_extents_t.x_bearing, #hb_glyph_extents_t.y_bearing,
450 * #hb_glyph_extents_t.width and #hb_glyph_extents_t.height respectively if
451 * #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400452 *
Ebrahim Byagowi687f6792018-10-20 17:50:39 +0330453 * Return value:
Khaled Hosny9ab9f972016-01-01 20:38:21 +0400454 * The number of serialized items.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400455 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +0400456 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400457 **/
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500458unsigned int
459hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
Simon Cozens57a528a2020-09-18 09:35:05 +0100460 unsigned int start,
461 unsigned int end,
462 char *buf,
463 unsigned int buf_size,
464 unsigned int *buf_consumed,
465 hb_font_t *font,
466 hb_buffer_serialize_format_t format,
467 hb_buffer_serialize_flags_t flags)
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500468{
Behdad Esfahbod8f5d8b12020-10-09 17:58:57 -0600469 end = hb_clamp (end, start, buffer->len);
470 start = hb_min (start, end);
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500471
Behdad Esfahbodbcc8f322013-02-27 12:02:42 -0500472 unsigned int sconsumed;
473 if (!buf_consumed)
474 buf_consumed = &sconsumed;
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500475 *buf_consumed = 0;
Behdad Esfahbod3c080a72017-03-07 18:13:28 -0800476 if (buf_size)
477 *buf = '\0';
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500478
Behdad Esfahbod77e704d2020-10-15 02:02:04 -0600479 buffer->assert_glyphs ();
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500480
Behdad Esfahbod9ea0aa42015-12-18 17:30:18 +0000481 if (!buffer->have_positions)
482 flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
483
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500484 if (unlikely (start == end))
485 return 0;
486
487 if (!font)
488 font = hb_font_get_empty ();
489
490 switch (format)
491 {
492 case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
493 return _hb_buffer_serialize_glyphs_text (buffer, start, end,
Simon Cozens57a528a2020-09-18 09:35:05 +0100494 buf, buf_size, buf_consumed,
495 font, flags);
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500496
497 case HB_BUFFER_SERIALIZE_FORMAT_JSON:
498 return _hb_buffer_serialize_glyphs_json (buffer, start, end,
Simon Cozens57a528a2020-09-18 09:35:05 +0100499 buf, buf_size, buf_consumed,
500 font, flags);
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500501
502 default:
503 case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
504 return 0;
505
506 }
507}
508
Simon Cozens36ede562020-09-18 10:24:29 +0100509/**
510 * hb_buffer_serialize_unicode:
511 * @buffer: an #hb_buffer_t buffer.
512 * @start: the first item in @buffer to serialize.
513 * @end: the last item in @buffer to serialize.
514 * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
515 * write serialized buffer into.
516 * @buf_size: the size of @buf.
Khaled Hosny5151c2b2020-12-31 00:28:27 +0200517 * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
Simon Cozens36ede562020-09-18 10:24:29 +0100518 * @format: the #hb_buffer_serialize_format_t to use for formatting the output.
Khaled Hosny2fdab782020-12-30 23:44:30 +0200519 * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
520 * to serialize.
Simon Cozens36ede562020-09-18 10:24:29 +0100521 *
522 * Serializes @buffer into a textual representation of its content,
523 * when the buffer contains Unicode codepoints (i.e., before shaping). This is
524 * useful for showing the contents of the buffer, for example during debugging.
525 * There are currently two supported serialization formats:
526 *
527 * ## text
528 * A human-readable, plain text format.
529 * The serialized codepoints will look something like:
530 *
531 * ```
Khaled Hosny8c3a5302020-12-22 23:52:46 +0200532 *  <U+0651=0|U+0628=1>
Simon Cozens36ede562020-09-18 10:24:29 +0100533 * ```
Khaled Hosny8c3a5302020-12-22 23:52:46 +0200534 *
Simon Cozens36ede562020-09-18 10:24:29 +0100535 * - Glyphs are separated with `|`
536 * - Unicode codepoints are expressed as zero-padded four (or more)
537 * digit hexadecimal numbers preceded by `U+`
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100538 * - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, the cluster
539 * will be indicated with a `=` then #hb_glyph_info_t.cluster.
Simon Cozens36ede562020-09-18 10:24:29 +0100540 *
541 * ## json
542 * A machine-readable, structured format.
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100543 * The serialized codepoints will be a list of objects with the following
544 * properties:
Simon Cozens6b1726b2020-09-21 16:35:40 +0100545 * - `u`: the Unicode codepoint as a decimal integer
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100546 * - `cl`: #hb_glyph_info_t.cluster if
547 * #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set.
548 *
549 * For example:
Khaled Hosny8c3a5302020-12-22 23:52:46 +0200550 *
Simon Cozens36ede562020-09-18 10:24:29 +0100551 * ```
Simon Cozens6b1726b2020-09-21 16:35:40 +0100552 * [{u:1617,cl:0},{u:1576,cl:1}]
Simon Cozens36ede562020-09-18 10:24:29 +0100553 * ```
554 *
555 * Return value:
556 * The number of serialized items.
557 *
558 * Since: 2.7.3
559 **/
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100560unsigned int
561hb_buffer_serialize_unicode (hb_buffer_t *buffer,
Simon Cozens57a528a2020-09-18 09:35:05 +0100562 unsigned int start,
563 unsigned int end,
564 char *buf,
565 unsigned int buf_size,
566 unsigned int *buf_consumed,
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100567 hb_buffer_serialize_format_t format,
568 hb_buffer_serialize_flags_t flags)
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100569{
Behdad Esfahbod8f5d8b12020-10-09 17:58:57 -0600570 end = hb_clamp (end, start, buffer->len);
571 start = hb_min (start, end);
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100572
Simon Cozens57a528a2020-09-18 09:35:05 +0100573 unsigned int sconsumed;
574 if (!buf_consumed)
575 buf_consumed = &sconsumed;
576 *buf_consumed = 0;
577 if (buf_size)
578 *buf = '\0';
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100579
Behdad Esfahbod77e704d2020-10-15 02:02:04 -0600580 buffer->assert_unicode ();
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100581
Simon Cozens57a528a2020-09-18 09:35:05 +0100582 if (unlikely (start == end))
583 return 0;
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100584
Simon Cozens57a528a2020-09-18 09:35:05 +0100585 switch (format)
586 {
587 case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
588 return _hb_buffer_serialize_unicode_text (buffer, start, end,
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100589 buf, buf_size, buf_consumed, flags);
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100590
Simon Cozens57a528a2020-09-18 09:35:05 +0100591 case HB_BUFFER_SERIALIZE_FORMAT_JSON:
592 return _hb_buffer_serialize_unicode_json (buffer, start, end,
Simon Cozens3d3c87e2020-09-21 14:35:05 +0100593 buf, buf_size, buf_consumed, flags);
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100594
Simon Cozens57a528a2020-09-18 09:35:05 +0100595 default:
596 case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
597 return 0;
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100598
Simon Cozens57a528a2020-09-18 09:35:05 +0100599 }
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100600}
Simon Cozens7c0bc0b2020-09-25 21:24:41 +0100601
602static unsigned int
603_hb_buffer_serialize_invalid (hb_buffer_t *buffer,
604 unsigned int start,
605 unsigned int end,
606 char *buf,
607 unsigned int buf_size,
608 unsigned int *buf_consumed,
609 hb_buffer_serialize_format_t format,
610 hb_buffer_serialize_flags_t flags)
611{
Behdad Esfahbod140552c2020-10-09 18:01:32 -0600612 assert (!buffer->len);
613
Simon Cozens7c0bc0b2020-09-25 21:24:41 +0100614 unsigned int sconsumed;
615 if (!buf_consumed)
616 buf_consumed = &sconsumed;
617 if (buf_size < 3)
618 return 0;
619 if (format == HB_BUFFER_SERIALIZE_FORMAT_JSON) {
620 *buf++ = '[';
621 *buf++ = ']';
622 *buf = '\0';
623 } else if (format == HB_BUFFER_SERIALIZE_FORMAT_TEXT) {
624 *buf++ = '!';
625 *buf++ = '!';
626 *buf = '\0';
627 }
628 *buf_consumed = 2;
629 return 0;
630}
631
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100632/**
633 * hb_buffer_serialize:
634 * @buffer: an #hb_buffer_t buffer.
635 * @start: the first item in @buffer to serialize.
636 * @end: the last item in @buffer to serialize.
637 * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
638 * write serialized buffer into.
639 * @buf_size: the size of @buf.
Khaled Hosny5151c2b2020-12-31 00:28:27 +0200640 * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
641 * @font: (nullable): the #hb_font_t used to shape this buffer, needed to
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100642 * read glyph names and extents. If %NULL, and empty font will be used.
643 * @format: the #hb_buffer_serialize_format_t to use for formatting the output.
644 * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
645 * to serialize.
646 *
647 * Serializes @buffer into a textual representation of its content, whether
648 * Unicode codepoints or glyph identifiers and positioning information. This is
649 * useful for showing the contents of the buffer, for example during debugging.
Simon Cozens57a528a2020-09-18 09:35:05 +0100650 * See the documentation of hb_buffer_serialize_unicode() and
651 * hb_buffer_serialize_glyphs() for a description of the output format.
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100652 *
653 * Return value:
654 * The number of serialized items.
655 *
656 * Since: 2.7.3
657 **/
658unsigned int
659hb_buffer_serialize (hb_buffer_t *buffer,
Simon Cozens57a528a2020-09-18 09:35:05 +0100660 unsigned int start,
661 unsigned int end,
662 char *buf,
663 unsigned int buf_size,
664 unsigned int *buf_consumed,
665 hb_font_t *font,
666 hb_buffer_serialize_format_t format,
667 hb_buffer_serialize_flags_t flags)
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100668{
Simon Cozens7c0bc0b2020-09-25 21:24:41 +0100669 switch (buffer->content_type)
670 {
671
672 case HB_BUFFER_CONTENT_TYPE_GLYPHS:
Behdad Esfahbod78fb6a12020-10-09 18:02:16 -0600673 return hb_buffer_serialize_glyphs (buffer, start, end, buf, buf_size,
674 buf_consumed, font, format, flags);
Simon Cozens7c0bc0b2020-09-25 21:24:41 +0100675
676 case HB_BUFFER_CONTENT_TYPE_UNICODE:
Behdad Esfahbod78fb6a12020-10-09 18:02:16 -0600677 return hb_buffer_serialize_unicode (buffer, start, end, buf, buf_size,
678 buf_consumed, format, flags);
Simon Cozens7c0bc0b2020-09-25 21:24:41 +0100679
680 case HB_BUFFER_CONTENT_TYPE_INVALID:
681 default:
Behdad Esfahbod78fb6a12020-10-09 18:02:16 -0600682 return _hb_buffer_serialize_invalid (buffer, start, end, buf, buf_size,
683 buf_consumed, format, flags);
Simon Cozens7c0bc0b2020-09-25 21:24:41 +0100684 }
Simon Cozens58bcc1c2020-09-17 16:29:40 +0100685}
686
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +0430687static bool
688parse_int (const char *pp, const char *end, int32_t *pv)
Behdad Esfahbode54dd262013-02-27 13:01:02 -0500689{
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +0430690 int v;
691 const char *p = pp;
Ebrahim Byagowi65690b52019-09-03 23:09:47 +0430692 if (unlikely (!hb_parse_int (&p, end, &v, true/* whole buffer */)))
693 return false;
Behdad Esfahbod20b817a2013-02-27 18:39:37 -0500694
695 *pv = v;
696 return true;
Behdad Esfahbode54dd262013-02-27 13:01:02 -0500697}
698
Ebrahim Byagowi43372fb2019-09-03 01:02:40 +0430699static bool
700parse_uint (const char *pp, const char *end, uint32_t *pv)
Behdad Esfahbod20b817a2013-02-27 18:39:37 -0500701{
Ebrahim Byagowi005389b2019-09-03 17:00:46 +0430702 unsigned int v;
703 const char *p = pp;
Ebrahim Byagowi65690b52019-09-03 23:09:47 +0430704 if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */)))
705 return false;
Behdad Esfahbod20b817a2013-02-27 18:39:37 -0500706
707 *pv = v;
708 return true;
709}
710
Simon Cozensc03a2002020-09-18 14:19:17 +0100711static bool
712parse_hex (const char *pp, const char *end, uint32_t *pv)
713{
714 unsigned int v;
715 const char *p = pp;
716 if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */, 16)))
717 return false;
718
719 *pv = v;
720 return true;
721}
722
Behdad Esfahbod20b817a2013-02-27 18:39:37 -0500723#include "hb-buffer-deserialize-json.hh"
Behdad Esfahbod847794e2013-02-27 17:59:28 -0500724#include "hb-buffer-deserialize-text.hh"
Behdad Esfahbode54dd262013-02-27 13:01:02 -0500725
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400726/**
727 * hb_buffer_deserialize_glyphs:
Khaled Hosny9ab9f972016-01-01 20:38:21 +0400728 * @buffer: an #hb_buffer_t buffer.
Khaled Hosny2fdab782020-12-30 23:44:30 +0200729 * @buf: (array length=buf_len): string to deserialize
730 * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
Khaled Hosny5151c2b2020-12-31 00:28:27 +0200731 * @end_ptr: (out) (optional): output pointer to the character after last
Khaled Hosny2fdab782020-12-30 23:44:30 +0200732 * consumed one.
Khaled Hosny5151c2b2020-12-31 00:28:27 +0200733 * @font: (nullable): font for getting glyph IDs
Khaled Hosny2fdab782020-12-30 23:44:30 +0200734 * @format: the #hb_buffer_serialize_format_t of the input @buf
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400735 *
Khaled Hosny2fdab782020-12-30 23:44:30 +0200736 * Deserializes glyphs @buffer from textual representation in the format
737 * produced by hb_buffer_serialize_glyphs().
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400738 *
Khaled Hosny2fdab782020-12-30 23:44:30 +0200739 * Return value: %true if @buf is not fully consumed, %false otherwise.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400740 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +0400741 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400742 **/
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500743hb_bool_t
744hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
Simon Cozens57a528a2020-09-18 09:35:05 +0100745 const char *buf,
746 int buf_len, /* -1 means nul-terminated */
747 const char **end_ptr, /* May be NULL */
748 hb_font_t *font, /* May be NULL */
749 hb_buffer_serialize_format_t format)
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500750{
Behdad Esfahbod847794e2013-02-27 17:59:28 -0500751 const char *end;
752 if (!end_ptr)
753 end_ptr = &end;
754 *end_ptr = buf;
Behdad Esfahbode54dd262013-02-27 13:01:02 -0500755
Behdad Esfahbod77e704d2020-10-15 02:02:04 -0600756 buffer->assert_glyphs ();
Behdad Esfahbode54dd262013-02-27 13:01:02 -0500757
Behdad Esfahboda1f4d282020-09-21 16:50:11 -0600758 if (unlikely (hb_object_is_immutable (buffer)))
759 {
Behdad Esfahbod3b641222020-10-09 17:55:21 -0600760 if (end_ptr)
761 *end_ptr = buf;
Behdad Esfahboda1f4d282020-09-21 16:50:11 -0600762 return false;
763 }
764
Behdad Esfahbode54dd262013-02-27 13:01:02 -0500765 if (buf_len == -1)
766 buf_len = strlen (buf);
767
768 if (!buf_len)
769 {
Behdad Esfahbod847794e2013-02-27 17:59:28 -0500770 *end_ptr = buf;
771 return false;
Behdad Esfahbode54dd262013-02-27 13:01:02 -0500772 }
773
774 hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
775
776 if (!font)
777 font = hb_font_get_empty ();
778
779 switch (format)
780 {
781 case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
Simon Cozensc03a2002020-09-18 14:19:17 +0100782 return _hb_buffer_deserialize_text (buffer,
783 buf, buf_len, end_ptr,
784 font);
Behdad Esfahbode54dd262013-02-27 13:01:02 -0500785
786 case HB_BUFFER_SERIALIZE_FORMAT_JSON:
Simon Cozensc03a2002020-09-18 14:19:17 +0100787 return _hb_buffer_deserialize_json (buffer,
788 buf, buf_len, end_ptr,
789 font);
Behdad Esfahbode54dd262013-02-27 13:01:02 -0500790
791 default:
792 case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
793 return false;
794
795 }
Behdad Esfahbodd3e14aa2013-02-27 11:06:36 -0500796}
Behdad Esfahbodbe1c0ab2019-06-18 13:26:03 -0700797
798
Simon Cozensc03a2002020-09-18 14:19:17 +0100799/**
800 * hb_buffer_deserialize_unicode:
801 * @buffer: an #hb_buffer_t buffer.
Khaled Hosny2fdab782020-12-30 23:44:30 +0200802 * @buf: (array length=buf_len): string to deserialize
803 * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
Khaled Hosny5151c2b2020-12-31 00:28:27 +0200804 * @end_ptr: (out) (optional): output pointer to the character after last
Khaled Hosny2fdab782020-12-30 23:44:30 +0200805 * consumed one.
806 * @format: the #hb_buffer_serialize_format_t of the input @buf
Simon Cozensc03a2002020-09-18 14:19:17 +0100807 *
Khaled Hosny2fdab782020-12-30 23:44:30 +0200808 * Deserializes Unicode @buffer from textual representation in the format
809 * produced by hb_buffer_serialize_unicode().
Simon Cozensc03a2002020-09-18 14:19:17 +0100810 *
Khaled Hosny2fdab782020-12-30 23:44:30 +0200811 * Return value: %true if @buf is not fully consumed, %false otherwise.
Simon Cozensc03a2002020-09-18 14:19:17 +0100812 *
813 * Since: 2.7.3
814 **/
815hb_bool_t
816hb_buffer_deserialize_unicode (hb_buffer_t *buffer,
817 const char *buf,
818 int buf_len, /* -1 means nul-terminated */
819 const char **end_ptr, /* May be NULL */
820 hb_buffer_serialize_format_t format)
821{
822 const char *end;
823 if (!end_ptr)
824 end_ptr = &end;
825 *end_ptr = buf;
826
Behdad Esfahbod77e704d2020-10-15 02:02:04 -0600827 buffer->assert_unicode ();
Simon Cozensf56eb402020-09-25 10:06:33 +0100828
829 if (unlikely (hb_object_is_immutable (buffer)))
830 {
Behdad Esfahbod3b641222020-10-09 17:55:21 -0600831 if (end_ptr)
832 *end_ptr = buf;
Simon Cozensf56eb402020-09-25 10:06:33 +0100833 return false;
834 }
835
Simon Cozensc03a2002020-09-18 14:19:17 +0100836 if (buf_len == -1)
837 buf_len = strlen (buf);
838
839 if (!buf_len)
840 {
841 *end_ptr = buf;
842 return false;
843 }
844
845 hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
846
847 hb_font_t* font = hb_font_get_empty ();
848
849 switch (format)
850 {
851 case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
852 return _hb_buffer_deserialize_text (buffer,
853 buf, buf_len, end_ptr,
854 font);
855
856 case HB_BUFFER_SERIALIZE_FORMAT_JSON:
857 return _hb_buffer_deserialize_json (buffer,
858 buf, buf_len, end_ptr,
859 font);
860
861 default:
862 case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
Simon Cozensc03a2002020-09-18 14:19:17 +0100863 return false;
864
865 }
866}
867
868
Behdad Esfahbodbe1c0ab2019-06-18 13:26:03 -0700869#endif