hb-buffer-serialize.cc (26321B)
1 /* 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 27 #include "hb.hh" 28 29 #ifndef HB_NO_BUFFER_SERIALIZE 30 31 #include "hb-buffer.hh" 32 33 34 static const char *_hb_buffer_serialize_formats[] = { 35 "text", 36 "json", 37 nullptr 38 }; 39 40 /** 41 * hb_buffer_serialize_list_formats: 42 * 43 * Returns a list of supported buffer serialization formats. 44 * 45 * Return value: (transfer none): 46 * A string array of buffer serialization formats. Should not be freed. 47 * 48 * Since: 0.9.7 49 **/ 50 const char ** 51 hb_buffer_serialize_list_formats () 52 { 53 return _hb_buffer_serialize_formats; 54 } 55 56 /** 57 * hb_buffer_serialize_format_from_string: 58 * @str: (array length=len) (element-type uint8_t): a string to parse 59 * @len: length of @str, or -1 if string is `NULL` terminated 60 * 61 * 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. 64 * 65 * Return value: 66 * The parsed #hb_buffer_serialize_format_t. 67 * 68 * Since: 0.9.7 69 **/ 70 hb_buffer_serialize_format_t 71 hb_buffer_serialize_format_from_string (const char *str, int len) 72 { 73 /* Upper-case it. */ 74 return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u); 75 } 76 77 /** 78 * hb_buffer_serialize_format_to_string: 79 * @format: an #hb_buffer_serialize_format_t to convert. 80 * 81 * Converts @format to the string corresponding it, or `NULL` if it is not a valid 82 * #hb_buffer_serialize_format_t. 83 * 84 * Return value: (transfer none): 85 * A `NULL` terminated string corresponding to @format. Should not be freed. 86 * 87 * Since: 0.9.7 88 **/ 89 const char * 90 hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) 91 { 92 switch ((unsigned) format) 93 { 94 case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return _hb_buffer_serialize_formats[0]; 95 case HB_BUFFER_SERIALIZE_FORMAT_JSON: return _hb_buffer_serialize_formats[1]; 96 default: 97 case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr; 98 } 99 } 100 101 static unsigned int 102 _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, 103 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) 110 { 111 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr); 112 hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? 113 nullptr : hb_buffer_get_glyph_positions (buffer, nullptr); 114 115 *buf_consumed = 0; 116 hb_position_t x = 0, y = 0; 117 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++ = ','; 128 else 129 *p++ = '['; 130 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++ = '"'; 139 for (char *q = g; *q; q++) 140 { 141 if (unlikely (*q == '"' || *q == '\\')) 142 *p++ = '\\'; 143 *p++ = *q; 144 } 145 *p++ = '"'; 146 } 147 else 148 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); 149 150 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { 151 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster)); 152 } 153 154 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) 155 { 156 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", 157 x+pos[i].x_offset, y+pos[i].y_offset)); 158 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES)) 159 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", 160 pos[i].x_advance, pos[i].y_advance)); 161 } 162 163 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS) 164 { 165 if (info[i].mask & HB_GLYPH_FLAG_DEFINED) 166 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED)); 167 } 168 169 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) 170 { 171 hb_glyph_extents_t extents; 172 if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents)) 173 { 174 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", 175 extents.x_bearing, extents.y_bearing)); 176 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", 177 extents.width, extents.height)); 178 } 179 } 180 181 *p++ = '}'; 182 if (i == end-1) 183 *p++ = ']'; 184 185 unsigned int l = p - b; 186 if (buf_size > l) 187 { 188 hb_memcpy (buf, b, l); 189 buf += l; 190 buf_size -= l; 191 *buf_consumed += l; 192 *buf = '\0'; 193 } else 194 return i - start; 195 196 if (pos && (flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES)) 197 { 198 x += pos[i].x_advance; 199 y += pos[i].y_advance; 200 } 201 } 202 203 return end - start; 204 } 205 206 static unsigned int 207 _hb_buffer_serialize_unicode_json (hb_buffer_t *buffer, 208 unsigned int start, 209 unsigned int end, 210 char *buf, 211 unsigned int buf_size, 212 unsigned int *buf_consumed, 213 hb_buffer_serialize_flags_t flags) 214 { 215 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr); 216 217 *buf_consumed = 0; 218 for (unsigned int i = start; i < end; i++) 219 { 220 char b[1024]; 221 char *p = b; 222 223 if (i) 224 *p++ = ','; 225 else 226 *p++ = '['; 227 228 *p++ = '{'; 229 230 APPEND ("\"u\":"); 231 232 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); 233 234 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { 235 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster)); 236 } 237 238 *p++ = '}'; 239 240 if (i == end-1) 241 *p++ = ']'; 242 243 unsigned int l = p - b; 244 if (buf_size > l) 245 { 246 hb_memcpy (buf, b, l); 247 buf += l; 248 buf_size -= l; 249 *buf_consumed += l; 250 *buf = '\0'; 251 } else 252 return i - start; 253 254 } 255 256 return end - start; 257 } 258 259 static unsigned int 260 _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, 261 unsigned int start, 262 unsigned int end, 263 char *buf, 264 unsigned int buf_size, 265 unsigned int *buf_consumed, 266 hb_font_t *font, 267 hb_buffer_serialize_flags_t flags) 268 { 269 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr); 270 hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? 271 nullptr : hb_buffer_get_glyph_positions (buffer, nullptr); 272 273 *buf_consumed = 0; 274 hb_position_t x = 0, y = 0; 275 for (unsigned int i = start; i < end; i++) 276 { 277 char b[1024]; 278 char *p = b; 279 280 /* In the following code, we know b is large enough that no overflow can happen. */ 281 282 if (i) 283 *p++ = '|'; 284 else 285 *p++ = '['; 286 287 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) 288 { 289 /* TODO Escape delimiters we use. */ 290 hb_font_glyph_to_string (font, info[i].codepoint, p, 128); 291 p += strlen (p); 292 } 293 else 294 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); 295 296 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { 297 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster)); 298 } 299 300 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) 301 { 302 if (x+pos[i].x_offset || y+pos[i].y_offset) 303 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset)); 304 305 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES)) 306 { 307 *p++ = '+'; 308 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance)); 309 if (pos[i].y_advance) 310 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); 311 } 312 } 313 314 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS) 315 { 316 if (info[i].mask & HB_GLYPH_FLAG_DEFINED) 317 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED)); 318 } 319 320 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) 321 { 322 hb_glyph_extents_t extents; 323 if (hb_font_get_glyph_extents(font, info[i].codepoint, &extents)) 324 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)); 325 } 326 327 if (i == end-1) { 328 *p++ = ']'; 329 } 330 331 unsigned int l = p - b; 332 if (buf_size > l) 333 { 334 hb_memcpy (buf, b, l); 335 buf += l; 336 buf_size -= l; 337 *buf_consumed += l; 338 *buf = '\0'; 339 } else 340 return i - start; 341 342 if (pos && (flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES)) 343 { 344 x += pos[i].x_advance; 345 y += pos[i].y_advance; 346 } 347 } 348 349 return end - start; 350 } 351 352 353 static unsigned int 354 _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer, 355 unsigned int start, 356 unsigned int end, 357 char *buf, 358 unsigned int buf_size, 359 unsigned int *buf_consumed, 360 hb_buffer_serialize_flags_t flags) 361 { 362 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr); 363 *buf_consumed = 0; 364 for (unsigned int i = start; i < end; i++) 365 { 366 char b[1024]; 367 char *p = b; 368 369 if (i) 370 *p++ = '|'; 371 else 372 *p++ = '<'; 373 374 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "U+%04X", info[i].codepoint)); 375 376 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { 377 p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster)); 378 } 379 380 if (i == end-1) 381 *p++ = '>'; 382 383 unsigned int l = p - b; 384 if (buf_size > l) 385 { 386 hb_memcpy (buf, b, l); 387 buf += l; 388 buf_size -= l; 389 *buf_consumed += l; 390 *buf = '\0'; 391 } else 392 return i - start; 393 } 394 return end - start; 395 } 396 397 /** 398 * hb_buffer_serialize_glyphs: 399 * @buffer: an #hb_buffer_t buffer. 400 * @start: the first item in @buffer to serialize. 401 * @end: the last item in @buffer to serialize. 402 * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to 403 * write serialized buffer into. 404 * @buf_size: the size of @buf. 405 * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf. 406 * @font: (nullable): the #hb_font_t used to shape this buffer, needed to 407 * read glyph names and extents. If `NULL`, an empty font will be used. 408 * @format: the #hb_buffer_serialize_format_t to use for formatting the output. 409 * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties 410 * to serialize. 411 * 412 * Serializes @buffer into a textual representation of its glyph content, 413 * useful for showing the contents of the buffer, for example during debugging. 414 * There are currently two supported serialization formats: 415 * 416 * ## text 417 * A human-readable, plain text format. 418 * The serialized glyphs will look something like: 419 * 420 * ``` 421 * [uni0651=0@518,0+0|uni0628=0+1897] 422 * ``` 423 * 424 * - The serialized glyphs are delimited with `[` and `]`. 425 * - Glyphs are separated with `|` 426 * - Each glyph starts with glyph name, or glyph index if 427 * #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. Then, 428 * - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, `=` then #hb_glyph_info_t.cluster. 429 * - If #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set, the #hb_glyph_position_t in the format: 430 * - If #hb_glyph_position_t.x_offset and #hb_glyph_position_t.y_offset are not both 0, `@x_offset,y_offset`. Then, 431 * - `+x_advance`, then `,y_advance` if #hb_glyph_position_t.y_advance is not 0. Then, 432 * - If #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set, the #hb_glyph_extents_t in the format `<x_bearing,y_bearing,width,height>` 433 * 434 * ## json 435 * A machine-readable, structured format. 436 * The serialized glyphs will look something like: 437 * 438 * ``` 439 * [{"g":"uni0651","cl":0,"dx":518,"dy":0,"ax":0,"ay":0}, 440 * {"g":"uni0628","cl":0,"dx":0,"dy":0,"ax":1897,"ay":0}] 441 * ``` 442 * 443 * Each glyph is a JSON object, with the following properties: 444 * - `g`: the glyph name or glyph index if 445 * #HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES flag is set. 446 * - `cl`: #hb_glyph_info_t.cluster if 447 * #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set. 448 * - `dx`,`dy`,`ax`,`ay`: #hb_glyph_position_t.x_offset, #hb_glyph_position_t.y_offset, 449 * #hb_glyph_position_t.x_advance and #hb_glyph_position_t.y_advance 450 * respectively, if #HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS is not set. 451 * - `xb`,`yb`,`w`,`h`: #hb_glyph_extents_t.x_bearing, #hb_glyph_extents_t.y_bearing, 452 * #hb_glyph_extents_t.width and #hb_glyph_extents_t.height respectively if 453 * #HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS is set. 454 * 455 * Return value: 456 * The number of serialized items. 457 * 458 * Since: 0.9.7 459 **/ 460 unsigned int 461 hb_buffer_serialize_glyphs (hb_buffer_t *buffer, 462 unsigned int start, 463 unsigned int end, 464 char *buf, 465 unsigned int buf_size, 466 unsigned int *buf_consumed, 467 hb_font_t *font, 468 hb_buffer_serialize_format_t format, 469 hb_buffer_serialize_flags_t flags) 470 { 471 end = hb_clamp (end, start, buffer->len); 472 start = hb_min (start, end); 473 474 unsigned int sconsumed; 475 if (!buf_consumed) 476 buf_consumed = &sconsumed; 477 *buf_consumed = 0; 478 if (buf_size) 479 *buf = '\0'; 480 481 buffer->assert_glyphs (); 482 483 if (!buffer->have_positions) 484 flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS; 485 486 if (unlikely (start == end)) 487 return 0; 488 489 if (!font) 490 font = hb_font_get_empty (); 491 492 switch (format) 493 { 494 case HB_BUFFER_SERIALIZE_FORMAT_TEXT: 495 return _hb_buffer_serialize_glyphs_text (buffer, start, end, 496 buf, buf_size, buf_consumed, 497 font, flags); 498 499 case HB_BUFFER_SERIALIZE_FORMAT_JSON: 500 return _hb_buffer_serialize_glyphs_json (buffer, start, end, 501 buf, buf_size, buf_consumed, 502 font, flags); 503 504 default: 505 case HB_BUFFER_SERIALIZE_FORMAT_INVALID: 506 return 0; 507 508 } 509 } 510 511 /** 512 * hb_buffer_serialize_unicode: 513 * @buffer: an #hb_buffer_t buffer. 514 * @start: the first item in @buffer to serialize. 515 * @end: the last item in @buffer to serialize. 516 * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to 517 * write serialized buffer into. 518 * @buf_size: the size of @buf. 519 * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf. 520 * @format: the #hb_buffer_serialize_format_t to use for formatting the output. 521 * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties 522 * to serialize. 523 * 524 * Serializes @buffer into a textual representation of its content, 525 * when the buffer contains Unicode codepoints (i.e., before shaping). This is 526 * useful for showing the contents of the buffer, for example during debugging. 527 * There are currently two supported serialization formats: 528 * 529 * ## text 530 * A human-readable, plain text format. 531 * The serialized codepoints will look something like: 532 * 533 * ``` 534 * <U+0651=0|U+0628=1> 535 * ``` 536 * 537 * - Glyphs are separated with `|` 538 * - Unicode codepoints are expressed as zero-padded four (or more) 539 * digit hexadecimal numbers preceded by `U+` 540 * - If #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set, the cluster 541 * will be indicated with a `=` then #hb_glyph_info_t.cluster. 542 * 543 * ## json 544 * A machine-readable, structured format. 545 * The serialized codepoints will be a list of objects with the following 546 * properties: 547 * - `u`: the Unicode codepoint as a decimal integer 548 * - `cl`: #hb_glyph_info_t.cluster if 549 * #HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS is not set. 550 * 551 * For example: 552 * 553 * ``` 554 * [{u:1617,cl:0},{u:1576,cl:1}] 555 * ``` 556 * 557 * Return value: 558 * The number of serialized items. 559 * 560 * Since: 2.7.3 561 **/ 562 unsigned int 563 hb_buffer_serialize_unicode (hb_buffer_t *buffer, 564 unsigned int start, 565 unsigned int end, 566 char *buf, 567 unsigned int buf_size, 568 unsigned int *buf_consumed, 569 hb_buffer_serialize_format_t format, 570 hb_buffer_serialize_flags_t flags) 571 { 572 end = hb_clamp (end, start, buffer->len); 573 start = hb_min (start, end); 574 575 unsigned int sconsumed; 576 if (!buf_consumed) 577 buf_consumed = &sconsumed; 578 *buf_consumed = 0; 579 if (buf_size) 580 *buf = '\0'; 581 582 buffer->assert_unicode (); 583 584 if (unlikely (start == end)) 585 return 0; 586 587 switch (format) 588 { 589 case HB_BUFFER_SERIALIZE_FORMAT_TEXT: 590 return _hb_buffer_serialize_unicode_text (buffer, start, end, 591 buf, buf_size, buf_consumed, flags); 592 593 case HB_BUFFER_SERIALIZE_FORMAT_JSON: 594 return _hb_buffer_serialize_unicode_json (buffer, start, end, 595 buf, buf_size, buf_consumed, flags); 596 597 default: 598 case HB_BUFFER_SERIALIZE_FORMAT_INVALID: 599 return 0; 600 601 } 602 } 603 604 static unsigned int 605 _hb_buffer_serialize_invalid (hb_buffer_t *buffer, 606 unsigned int start, 607 unsigned int end, 608 char *buf, 609 unsigned int buf_size, 610 unsigned int *buf_consumed, 611 hb_buffer_serialize_format_t format, 612 hb_buffer_serialize_flags_t flags) 613 { 614 assert (!buffer->len); 615 616 unsigned int sconsumed; 617 if (!buf_consumed) 618 buf_consumed = &sconsumed; 619 if (buf_size < 3) 620 return 0; 621 if (format == HB_BUFFER_SERIALIZE_FORMAT_JSON) { 622 *buf++ = '['; 623 *buf++ = ']'; 624 *buf = '\0'; 625 } else if (format == HB_BUFFER_SERIALIZE_FORMAT_TEXT) { 626 *buf++ = '!'; 627 *buf++ = '!'; 628 *buf = '\0'; 629 } 630 *buf_consumed = 2; 631 return 0; 632 } 633 634 /** 635 * hb_buffer_serialize: 636 * @buffer: an #hb_buffer_t buffer. 637 * @start: the first item in @buffer to serialize. 638 * @end: the last item in @buffer to serialize. 639 * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to 640 * write serialized buffer into. 641 * @buf_size: the size of @buf. 642 * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf. 643 * @font: (nullable): the #hb_font_t used to shape this buffer, needed to 644 * read glyph names and extents. If `NULL`, an empty font will be used. 645 * @format: the #hb_buffer_serialize_format_t to use for formatting the output. 646 * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties 647 * to serialize. 648 * 649 * Serializes @buffer into a textual representation of its content, whether 650 * Unicode codepoints or glyph identifiers and positioning information. This is 651 * useful for showing the contents of the buffer, for example during debugging. 652 * See the documentation of hb_buffer_serialize_unicode() and 653 * hb_buffer_serialize_glyphs() for a description of the output format. 654 * 655 * Return value: 656 * The number of serialized items. 657 * 658 * Since: 2.7.3 659 **/ 660 unsigned int 661 hb_buffer_serialize (hb_buffer_t *buffer, 662 unsigned int start, 663 unsigned int end, 664 char *buf, 665 unsigned int buf_size, 666 unsigned int *buf_consumed, 667 hb_font_t *font, 668 hb_buffer_serialize_format_t format, 669 hb_buffer_serialize_flags_t flags) 670 { 671 switch (buffer->content_type) 672 { 673 674 case HB_BUFFER_CONTENT_TYPE_GLYPHS: 675 return hb_buffer_serialize_glyphs (buffer, start, end, buf, buf_size, 676 buf_consumed, font, format, flags); 677 678 case HB_BUFFER_CONTENT_TYPE_UNICODE: 679 return hb_buffer_serialize_unicode (buffer, start, end, buf, buf_size, 680 buf_consumed, format, flags); 681 682 case HB_BUFFER_CONTENT_TYPE_INVALID: 683 default: 684 return _hb_buffer_serialize_invalid (buffer, start, end, buf, buf_size, 685 buf_consumed, format, flags); 686 } 687 } 688 689 static bool 690 parse_int (const char *pp, const char *end, int32_t *pv) 691 { 692 int v; 693 const char *p = pp; 694 if (unlikely (!hb_parse_int (&p, end, &v, true/* whole buffer */))) 695 return false; 696 697 *pv = v; 698 return true; 699 } 700 701 static bool 702 parse_uint (const char *pp, const char *end, uint32_t *pv) 703 { 704 unsigned int v; 705 const char *p = pp; 706 if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */))) 707 return false; 708 709 *pv = v; 710 return true; 711 } 712 713 static bool 714 parse_hex (const char *pp, const char *end, uint32_t *pv) 715 { 716 unsigned int v; 717 const char *p = pp; 718 if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */, 16))) 719 return false; 720 721 *pv = v; 722 return true; 723 } 724 725 #include "hb-buffer-deserialize-json.hh" 726 #include "hb-buffer-deserialize-text-glyphs.hh" 727 #include "hb-buffer-deserialize-text-unicode.hh" 728 729 /** 730 * hb_buffer_deserialize_glyphs: 731 * @buffer: an #hb_buffer_t buffer. 732 * @buf: (array length=buf_len): string to deserialize 733 * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated 734 * @end_ptr: (out) (optional): output pointer to the character after last 735 * consumed one. 736 * @font: (nullable): font for getting glyph IDs 737 * @format: the #hb_buffer_serialize_format_t of the input @buf 738 * 739 * Deserializes glyphs @buffer from textual representation in the format 740 * produced by hb_buffer_serialize_glyphs(). 741 * 742 * Return value: `true` if the full string was parsed, `false` otherwise. 743 * 744 * Since: 0.9.7 745 **/ 746 hb_bool_t 747 hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, 748 const char *buf, 749 int buf_len, /* -1 means nul-terminated */ 750 const char **end_ptr, /* May be NULL */ 751 hb_font_t *font, /* May be NULL */ 752 hb_buffer_serialize_format_t format) 753 { 754 const char *end; 755 if (!end_ptr) 756 end_ptr = &end; 757 *end_ptr = buf; 758 759 buffer->assert_glyphs (); 760 761 if (unlikely (hb_object_is_immutable (buffer))) 762 { 763 if (end_ptr) 764 *end_ptr = buf; 765 return false; 766 } 767 768 if (buf_len == -1) 769 buf_len = strlen (buf); 770 771 if (!buf_len) 772 { 773 *end_ptr = buf; 774 return false; 775 } 776 777 hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); 778 779 if (!font) 780 font = hb_font_get_empty (); 781 782 switch (format) 783 { 784 case HB_BUFFER_SERIALIZE_FORMAT_TEXT: 785 return _hb_buffer_deserialize_text_glyphs (buffer, 786 buf, buf_len, end_ptr, 787 font); 788 789 case HB_BUFFER_SERIALIZE_FORMAT_JSON: 790 return _hb_buffer_deserialize_json (buffer, 791 buf, buf_len, end_ptr, 792 font); 793 794 default: 795 case HB_BUFFER_SERIALIZE_FORMAT_INVALID: 796 return false; 797 798 } 799 } 800 801 802 /** 803 * hb_buffer_deserialize_unicode: 804 * @buffer: an #hb_buffer_t buffer. 805 * @buf: (array length=buf_len): string to deserialize 806 * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated 807 * @end_ptr: (out) (optional): output pointer to the character after last 808 * consumed one. 809 * @format: the #hb_buffer_serialize_format_t of the input @buf 810 * 811 * Deserializes Unicode @buffer from textual representation in the format 812 * produced by hb_buffer_serialize_unicode(). 813 * 814 * Return value: `true` if the full string was parsed, `false` otherwise. 815 * 816 * Since: 2.7.3 817 **/ 818 hb_bool_t 819 hb_buffer_deserialize_unicode (hb_buffer_t *buffer, 820 const char *buf, 821 int buf_len, /* -1 means nul-terminated */ 822 const char **end_ptr, /* May be NULL */ 823 hb_buffer_serialize_format_t format) 824 { 825 const char *end; 826 if (!end_ptr) 827 end_ptr = &end; 828 *end_ptr = buf; 829 830 buffer->assert_unicode (); 831 832 if (unlikely (hb_object_is_immutable (buffer))) 833 { 834 if (end_ptr) 835 *end_ptr = buf; 836 return false; 837 } 838 839 if (buf_len == -1) 840 buf_len = strlen (buf); 841 842 if (!buf_len) 843 { 844 *end_ptr = buf; 845 return false; 846 } 847 848 hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_UNICODE); 849 850 hb_font_t* font = hb_font_get_empty (); 851 852 switch (format) 853 { 854 case HB_BUFFER_SERIALIZE_FORMAT_TEXT: 855 return _hb_buffer_deserialize_text_unicode (buffer, 856 buf, buf_len, end_ptr, 857 font); 858 859 case HB_BUFFER_SERIALIZE_FORMAT_JSON: 860 return _hb_buffer_deserialize_json (buffer, 861 buf, buf_len, end_ptr, 862 font); 863 864 default: 865 case HB_BUFFER_SERIALIZE_FORMAT_INVALID: 866 return false; 867 868 } 869 } 870 871 872 #endif