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 }