1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 // This file is available under and governed by the GNU General Public 26 // License version 2 only, as published by the Free Software Foundation. 27 // However, the following notice accompanied the original version of this 28 // file: 29 // 30 /* 31 * Copyright © 2012,2013 Google, Inc. 32 * 33 * This is part of HarfBuzz, a text shaping library. 34 * 35 * Permission is hereby granted, without written agreement and without 36 * license or royalty fees, to use, copy, modify, and distribute this 37 * software and its documentation for any purpose, provided that the 38 * above copyright notice and the following two paragraphs appear in 39 * all copies of this software. 40 * 41 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 42 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 43 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 44 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 45 * DAMAGE. 46 * 47 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 48 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 49 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 50 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 51 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 52 * 53 * Google Author(s): Behdad Esfahbod 54 */ 55 56 #include "hb-buffer-private.hh" 57 58 59 static const char *serialize_formats[] = { 60 "text", 61 "json", 62 NULL 63 }; 64 65 /** 66 * hb_buffer_serialize_list_formats: 67 * 68 * 69 * 70 * Return value: (transfer none): 71 * 72 * Since: 0.9.2 73 **/ 74 const char ** 75 hb_buffer_serialize_list_formats (void) 76 { 77 return serialize_formats; 78 } 79 80 /** 81 * hb_buffer_serialize_format_from_string: 82 * @str: 83 * @len: 84 * 85 * 86 * 87 * Return value: 88 * 89 * Since: 0.9.2 90 **/ 91 hb_buffer_serialize_format_t 92 hb_buffer_serialize_format_from_string (const char *str, int len) 93 { 94 /* Upper-case it. */ 95 return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u); 96 } 97 98 /** 99 * hb_buffer_serialize_format_to_string: 100 * @format: 101 * 102 * 103 * 104 * Return value: 105 * 106 * Since: 0.9.2 107 **/ 108 const char * 109 hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) 110 { 111 switch (format) 112 { 113 case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; 114 case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; 115 default: 116 case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return NULL; 117 } 118 } 119 120 static unsigned int 121 _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, 122 unsigned int start, 123 unsigned int end, 124 char *buf, 125 unsigned int buf_size, 126 unsigned int *buf_consumed, 127 hb_font_t *font, 128 hb_buffer_serialize_flags_t flags) 129 { 130 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); 131 hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? 132 NULL : hb_buffer_get_glyph_positions (buffer, NULL); 133 134 *buf_consumed = 0; 135 for (unsigned int i = start; i < end; i++) 136 { 137 char b[1024]; 138 char *p = b; 139 140 /* In the following code, we know b is large enough that no overflow can happen. */ 141 142 #define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END 143 144 if (i) 145 *p++ = ','; 146 147 *p++ = '{'; 148 149 APPEND ("\"g\":"); 150 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) 151 { 152 char g[128]; 153 hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g)); 154 *p++ = '"'; 155 for (char *q = g; *q; q++) { 156 if (*q == '"') 157 *p++ = '\\'; 158 *p++ = *q; 159 } 160 *p++ = '"'; 161 } 162 else 163 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); 164 165 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { 166 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster)); 167 } 168 169 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) 170 { 171 p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", 172 pos[i].x_offset, pos[i].y_offset); 173 p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", 174 pos[i].x_advance, pos[i].y_advance); 175 } 176 177 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) 178 { 179 hb_glyph_extents_t extents; 180 hb_font_get_glyph_extents(font, info[i].codepoint, &extents); 181 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", 182 extents.x_bearing, extents.y_bearing)); 183 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", 184 extents.width, extents.height)); 185 } 186 187 *p++ = '}'; 188 189 unsigned int l = p - b; 190 if (buf_size > l) 191 { 192 memcpy (buf, b, l); 193 buf += l; 194 buf_size -= l; 195 *buf_consumed += l; 196 *buf = '\0'; 197 } else 198 return i - start; 199 } 200 201 return end - start; 202 } 203 204 static unsigned int 205 _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, 206 unsigned int start, 207 unsigned int end, 208 char *buf, 209 unsigned int buf_size, 210 unsigned int *buf_consumed, 211 hb_font_t *font, 212 hb_buffer_serialize_flags_t flags) 213 { 214 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); 215 hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? 216 NULL : hb_buffer_get_glyph_positions (buffer, NULL); 217 218 *buf_consumed = 0; 219 for (unsigned int i = start; i < end; i++) 220 { 221 char b[1024]; 222 char *p = b; 223 224 /* In the following code, we know b is large enough that no overflow can happen. */ 225 226 if (i) 227 *p++ = '|'; 228 229 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) 230 { 231 hb_font_glyph_to_string (font, info[i].codepoint, p, 128); 232 p += strlen (p); 233 } 234 else 235 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); 236 237 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { 238 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster)); 239 } 240 241 if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) 242 { 243 if (pos[i].x_offset || pos[i].y_offset) 244 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", pos[i].x_offset, pos[i].y_offset)); 245 246 *p++ = '+'; 247 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance)); 248 if (pos[i].y_advance) 249 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); 250 } 251 252 if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) 253 { 254 hb_glyph_extents_t extents; 255 hb_font_get_glyph_extents(font, info[i].codepoint, &extents); 256 p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)); 257 } 258 259 unsigned int l = p - b; 260 if (buf_size > l) 261 { 262 memcpy (buf, b, l); 263 buf += l; 264 buf_size -= l; 265 *buf_consumed += l; 266 *buf = '\0'; 267 } else 268 return i - start; 269 } 270 271 return end - start; 272 } 273 274 /* Returns number of items, starting at start, that were serialized. */ 275 /** 276 * hb_buffer_serialize_glyphs: 277 * @buffer: a buffer. 278 * @start: 279 * @end: 280 * @buf: (array length=buf_size): 281 * @buf_size: 282 * @buf_consumed: (out): 283 * @font: 284 * @format: 285 * @flags: 286 * 287 * 288 * 289 * Return value: 290 * 291 * Since: 0.9.2 292 **/ 293 unsigned int 294 hb_buffer_serialize_glyphs (hb_buffer_t *buffer, 295 unsigned int start, 296 unsigned int end, 297 char *buf, 298 unsigned int buf_size, 299 unsigned int *buf_consumed, /* May be NULL */ 300 hb_font_t *font, /* May be NULL */ 301 hb_buffer_serialize_format_t format, 302 hb_buffer_serialize_flags_t flags) 303 { 304 assert (start <= end && end <= buffer->len); 305 306 unsigned int sconsumed; 307 if (!buf_consumed) 308 buf_consumed = &sconsumed; 309 *buf_consumed = 0; 310 311 assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || 312 buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); 313 314 if (unlikely (start == end)) 315 return 0; 316 317 if (!font) 318 font = hb_font_get_empty (); 319 320 switch (format) 321 { 322 case HB_BUFFER_SERIALIZE_FORMAT_TEXT: 323 return _hb_buffer_serialize_glyphs_text (buffer, start, end, 324 buf, buf_size, buf_consumed, 325 font, flags); 326 327 case HB_BUFFER_SERIALIZE_FORMAT_JSON: 328 return _hb_buffer_serialize_glyphs_json (buffer, start, end, 329 buf, buf_size, buf_consumed, 330 font, flags); 331 332 default: 333 case HB_BUFFER_SERIALIZE_FORMAT_INVALID: 334 return 0; 335 336 } 337 } 338 339 340 static hb_bool_t 341 parse_uint (const char *pp, const char *end, uint32_t *pv) 342 { 343 char buf[32]; 344 unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); 345 strncpy (buf, pp, len); 346 buf[len] = '\0'; 347 348 char *p = buf; 349 char *pend = p; 350 uint32_t v; 351 352 errno = 0; 353 v = strtol (p, &pend, 10); 354 if (errno || p == pend || pend - p != end - pp) 355 return false; 356 357 *pv = v; 358 return true; 359 } 360 361 static hb_bool_t 362 parse_int (const char *pp, const char *end, int32_t *pv) 363 { 364 char buf[32]; 365 unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); 366 strncpy (buf, pp, len); 367 buf[len] = '\0'; 368 369 char *p = buf; 370 char *pend = p; 371 int32_t v; 372 373 errno = 0; 374 v = strtol (p, &pend, 10); 375 if (errno || p == pend || pend - p != end - pp) 376 return false; 377 378 *pv = v; 379 return true; 380 } 381 382 #include "hb-buffer-deserialize-json.hh" 383 #include "hb-buffer-deserialize-text.hh" 384 385 /** 386 * hb_buffer_deserialize_glyphs: 387 * @buffer: a buffer. 388 * @buf: (array length=buf_len): 389 * @buf_len: 390 * @end_ptr: (out): 391 * @font: 392 * @format: 393 * 394 * 395 * 396 * Return value: 397 * 398 * Since: 0.9.2 399 **/ 400 hb_bool_t 401 hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, 402 const char *buf, 403 int buf_len, /* -1 means nul-terminated */ 404 const char **end_ptr, /* May be NULL */ 405 hb_font_t *font, /* May be NULL */ 406 hb_buffer_serialize_format_t format) 407 { 408 const char *end; 409 if (!end_ptr) 410 end_ptr = &end; 411 *end_ptr = buf; 412 413 assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || 414 buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); 415 416 if (buf_len == -1) 417 buf_len = strlen (buf); 418 419 if (!buf_len) 420 { 421 *end_ptr = buf; 422 return false; 423 } 424 425 hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); 426 427 if (!font) 428 font = hb_font_get_empty (); 429 430 switch (format) 431 { 432 case HB_BUFFER_SERIALIZE_FORMAT_TEXT: 433 return _hb_buffer_deserialize_glyphs_text (buffer, 434 buf, buf_len, end_ptr, 435 font); 436 437 case HB_BUFFER_SERIALIZE_FORMAT_JSON: 438 return _hb_buffer_deserialize_glyphs_json (buffer, 439 buf, buf_len, end_ptr, 440 font); 441 442 default: 443 case HB_BUFFER_SERIALIZE_FORMAT_INVALID: 444 return false; 445 446 } 447 }