1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/harfbuzz/src/hb-buffer-serialize.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,399 @@ 1.4 +/* 1.5 + * Copyright © 2012,2013 Google, Inc. 1.6 + * 1.7 + * This is part of HarfBuzz, a text shaping library. 1.8 + * 1.9 + * Permission is hereby granted, without written agreement and without 1.10 + * license or royalty fees, to use, copy, modify, and distribute this 1.11 + * software and its documentation for any purpose, provided that the 1.12 + * above copyright notice and the following two paragraphs appear in 1.13 + * all copies of this software. 1.14 + * 1.15 + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1.16 + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1.17 + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1.18 + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1.19 + * DAMAGE. 1.20 + * 1.21 + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 1.22 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 1.23 + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 1.24 + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 1.25 + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 1.26 + * 1.27 + * Google Author(s): Behdad Esfahbod 1.28 + */ 1.29 + 1.30 +#include "hb-buffer-private.hh" 1.31 + 1.32 + 1.33 +static const char *serialize_formats[] = { 1.34 + "text", 1.35 + "json", 1.36 + NULL 1.37 +}; 1.38 + 1.39 +/** 1.40 + * hb_buffer_serialize_list_formats: 1.41 + * 1.42 + * 1.43 + * 1.44 + * Return value: (transfer none): 1.45 + * 1.46 + * Since: 1.0 1.47 + **/ 1.48 +const char ** 1.49 +hb_buffer_serialize_list_formats (void) 1.50 +{ 1.51 + return serialize_formats; 1.52 +} 1.53 + 1.54 +/** 1.55 + * hb_buffer_serialize_format_from_string: 1.56 + * @str: 1.57 + * @len: 1.58 + * 1.59 + * 1.60 + * 1.61 + * Return value: 1.62 + * 1.63 + * Since: 1.0 1.64 + **/ 1.65 +hb_buffer_serialize_format_t 1.66 +hb_buffer_serialize_format_from_string (const char *str, int len) 1.67 +{ 1.68 + /* Upper-case it. */ 1.69 + return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020); 1.70 +} 1.71 + 1.72 +/** 1.73 + * hb_buffer_serialize_format_to_string: 1.74 + * @format: 1.75 + * 1.76 + * 1.77 + * 1.78 + * Return value: 1.79 + * 1.80 + * Since: 1.0 1.81 + **/ 1.82 +const char * 1.83 +hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) 1.84 +{ 1.85 + switch (format) 1.86 + { 1.87 + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; 1.88 + case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; 1.89 + default: 1.90 + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return NULL; 1.91 + } 1.92 +} 1.93 + 1.94 +static unsigned int 1.95 +_hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, 1.96 + unsigned int start, 1.97 + unsigned int end, 1.98 + char *buf, 1.99 + unsigned int buf_size, 1.100 + unsigned int *buf_consumed, 1.101 + hb_font_t *font, 1.102 + hb_buffer_serialize_flags_t flags) 1.103 +{ 1.104 + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); 1.105 + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); 1.106 + 1.107 + *buf_consumed = 0; 1.108 + for (unsigned int i = start; i < end; i++) 1.109 + { 1.110 + char b[1024]; 1.111 + char *p = b; 1.112 + 1.113 + /* In the following code, we know b is large enough that no overflow can happen. */ 1.114 + 1.115 +#define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END 1.116 + 1.117 + if (i) 1.118 + *p++ = ','; 1.119 + 1.120 + *p++ = '{'; 1.121 + 1.122 + APPEND ("\"g\":"); 1.123 + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) 1.124 + { 1.125 + char g[128]; 1.126 + hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g)); 1.127 + *p++ = '"'; 1.128 + for (char *q = g; *q; q++) { 1.129 + if (*q == '"') 1.130 + *p++ = '\\'; 1.131 + *p++ = *q; 1.132 + } 1.133 + *p++ = '"'; 1.134 + } 1.135 + else 1.136 + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); 1.137 + 1.138 + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { 1.139 + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster)); 1.140 + } 1.141 + 1.142 + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) 1.143 + { 1.144 + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", 1.145 + pos[i].x_offset, pos[i].y_offset); 1.146 + p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", 1.147 + pos[i].x_advance, pos[i].y_advance); 1.148 + } 1.149 + 1.150 + *p++ = '}'; 1.151 + 1.152 + unsigned int l = p - b; 1.153 + if (buf_size > l) 1.154 + { 1.155 + memcpy (buf, b, l); 1.156 + buf += l; 1.157 + buf_size -= l; 1.158 + *buf_consumed += l; 1.159 + *buf = '\0'; 1.160 + } else 1.161 + return i - start; 1.162 + } 1.163 + 1.164 + return end - start; 1.165 +} 1.166 + 1.167 +static unsigned int 1.168 +_hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, 1.169 + unsigned int start, 1.170 + unsigned int end, 1.171 + char *buf, 1.172 + unsigned int buf_size, 1.173 + unsigned int *buf_consumed, 1.174 + hb_font_t *font, 1.175 + hb_buffer_serialize_flags_t flags) 1.176 +{ 1.177 + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); 1.178 + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL); 1.179 + 1.180 + *buf_consumed = 0; 1.181 + for (unsigned int i = start; i < end; i++) 1.182 + { 1.183 + char b[1024]; 1.184 + char *p = b; 1.185 + 1.186 + /* In the following code, we know b is large enough that no overflow can happen. */ 1.187 + 1.188 + if (i) 1.189 + *p++ = '|'; 1.190 + 1.191 + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES)) 1.192 + { 1.193 + hb_font_glyph_to_string (font, info[i].codepoint, p, 128); 1.194 + p += strlen (p); 1.195 + } 1.196 + else 1.197 + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint)); 1.198 + 1.199 + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) { 1.200 + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster)); 1.201 + } 1.202 + 1.203 + if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) 1.204 + { 1.205 + if (pos[i].x_offset || pos[i].y_offset) 1.206 + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", pos[i].x_offset, pos[i].y_offset)); 1.207 + 1.208 + *p++ = '+'; 1.209 + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance)); 1.210 + if (pos[i].y_advance) 1.211 + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); 1.212 + } 1.213 + 1.214 + unsigned int l = p - b; 1.215 + if (buf_size > l) 1.216 + { 1.217 + memcpy (buf, b, l); 1.218 + buf += l; 1.219 + buf_size -= l; 1.220 + *buf_consumed += l; 1.221 + *buf = '\0'; 1.222 + } else 1.223 + return i - start; 1.224 + } 1.225 + 1.226 + return end - start; 1.227 +} 1.228 + 1.229 +/* Returns number of items, starting at start, that were serialized. */ 1.230 +/** 1.231 + * hb_buffer_serialize_glyphs: 1.232 + * @buffer: a buffer. 1.233 + * @start: 1.234 + * @end: 1.235 + * @buf: (array length=buf_size): 1.236 + * @buf_size: 1.237 + * @buf_consumed: (out): 1.238 + * @font: 1.239 + * @format: 1.240 + * @flags: 1.241 + * 1.242 + * 1.243 + * 1.244 + * Return value: 1.245 + * 1.246 + * Since: 1.0 1.247 + **/ 1.248 +unsigned int 1.249 +hb_buffer_serialize_glyphs (hb_buffer_t *buffer, 1.250 + unsigned int start, 1.251 + unsigned int end, 1.252 + char *buf, 1.253 + unsigned int buf_size, 1.254 + unsigned int *buf_consumed, /* May be NULL */ 1.255 + hb_font_t *font, /* May be NULL */ 1.256 + hb_buffer_serialize_format_t format, 1.257 + hb_buffer_serialize_flags_t flags) 1.258 +{ 1.259 + assert (start <= end && end <= buffer->len); 1.260 + 1.261 + unsigned int sconsumed; 1.262 + if (!buf_consumed) 1.263 + buf_consumed = &sconsumed; 1.264 + *buf_consumed = 0; 1.265 + 1.266 + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || 1.267 + buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); 1.268 + 1.269 + if (unlikely (start == end)) 1.270 + return 0; 1.271 + 1.272 + if (!font) 1.273 + font = hb_font_get_empty (); 1.274 + 1.275 + switch (format) 1.276 + { 1.277 + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: 1.278 + return _hb_buffer_serialize_glyphs_text (buffer, start, end, 1.279 + buf, buf_size, buf_consumed, 1.280 + font, flags); 1.281 + 1.282 + case HB_BUFFER_SERIALIZE_FORMAT_JSON: 1.283 + return _hb_buffer_serialize_glyphs_json (buffer, start, end, 1.284 + buf, buf_size, buf_consumed, 1.285 + font, flags); 1.286 + 1.287 + default: 1.288 + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: 1.289 + return 0; 1.290 + 1.291 + } 1.292 +} 1.293 + 1.294 + 1.295 +static hb_bool_t 1.296 +parse_uint (const char *pp, const char *end, uint32_t *pv) 1.297 +{ 1.298 + char buf[32]; 1.299 + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); 1.300 + strncpy (buf, pp, len); 1.301 + buf[len] = '\0'; 1.302 + 1.303 + char *p = buf; 1.304 + char *pend = p; 1.305 + uint32_t v; 1.306 + 1.307 + errno = 0; 1.308 + v = strtol (p, &pend, 10); 1.309 + if (errno || p == pend || pend - p != end - pp) 1.310 + return false; 1.311 + 1.312 + *pv = v; 1.313 + return true; 1.314 +} 1.315 + 1.316 +static hb_bool_t 1.317 +parse_int (const char *pp, const char *end, int32_t *pv) 1.318 +{ 1.319 + char buf[32]; 1.320 + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); 1.321 + strncpy (buf, pp, len); 1.322 + buf[len] = '\0'; 1.323 + 1.324 + char *p = buf; 1.325 + char *pend = p; 1.326 + int32_t v; 1.327 + 1.328 + errno = 0; 1.329 + v = strtol (p, &pend, 10); 1.330 + if (errno || p == pend || pend - p != end - pp) 1.331 + return false; 1.332 + 1.333 + *pv = v; 1.334 + return true; 1.335 +} 1.336 + 1.337 +#include "hb-buffer-deserialize-json.hh" 1.338 +#include "hb-buffer-deserialize-text.hh" 1.339 + 1.340 +/** 1.341 + * hb_buffer_deserialize_glyphs: 1.342 + * @buffer: a buffer. 1.343 + * @buf: (array length=buf_len): 1.344 + * @buf_len: 1.345 + * @end_ptr: (out): 1.346 + * @font: 1.347 + * @format: 1.348 + * 1.349 + * 1.350 + * 1.351 + * Return value: 1.352 + * 1.353 + * Since: 1.0 1.354 + **/ 1.355 +hb_bool_t 1.356 +hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, 1.357 + const char *buf, 1.358 + int buf_len, /* -1 means nul-terminated */ 1.359 + const char **end_ptr, /* May be NULL */ 1.360 + hb_font_t *font, /* May be NULL */ 1.361 + hb_buffer_serialize_format_t format) 1.362 +{ 1.363 + const char *end; 1.364 + if (!end_ptr) 1.365 + end_ptr = &end; 1.366 + *end_ptr = buf; 1.367 + 1.368 + assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || 1.369 + buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); 1.370 + 1.371 + if (buf_len == -1) 1.372 + buf_len = strlen (buf); 1.373 + 1.374 + if (!buf_len) 1.375 + { 1.376 + *end_ptr = buf; 1.377 + return false; 1.378 + } 1.379 + 1.380 + hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); 1.381 + 1.382 + if (!font) 1.383 + font = hb_font_get_empty (); 1.384 + 1.385 + switch (format) 1.386 + { 1.387 + case HB_BUFFER_SERIALIZE_FORMAT_TEXT: 1.388 + return _hb_buffer_deserialize_glyphs_text (buffer, 1.389 + buf, buf_len, end_ptr, 1.390 + font); 1.391 + 1.392 + case HB_BUFFER_SERIALIZE_FORMAT_JSON: 1.393 + return _hb_buffer_deserialize_glyphs_json (buffer, 1.394 + buf, buf_len, end_ptr, 1.395 + font); 1.396 + 1.397 + default: 1.398 + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: 1.399 + return false; 1.400 + 1.401 + } 1.402 +}