gfx/harfbuzz/src/hb-buffer-serialize.cc

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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

mercurial