Home | History | Annotate | Download | only in src
      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-buffer-private.hh"
     28 
     29 
     30 static const char *serialize_formats[] = {
     31   "text",
     32   "json",
     33   NULL
     34 };
     35 
     36 /**
     37  * hb_buffer_serialize_list_formats:
     38  *
     39  *
     40  *
     41  * Return value: (transfer none):
     42  *
     43  * Since: 1.0
     44  **/
     45 const char **
     46 hb_buffer_serialize_list_formats (void)
     47 {
     48   return serialize_formats;
     49 }
     50 
     51 /**
     52  * hb_buffer_serialize_format_from_string:
     53  * @str:
     54  * @len:
     55  *
     56  *
     57  *
     58  * Return value:
     59  *
     60  * Since: 1.0
     61  **/
     62 hb_buffer_serialize_format_t
     63 hb_buffer_serialize_format_from_string (const char *str, int len)
     64 {
     65   /* Upper-case it. */
     66   return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u);
     67 }
     68 
     69 /**
     70  * hb_buffer_serialize_format_to_string:
     71  * @format:
     72  *
     73  *
     74  *
     75  * Return value:
     76  *
     77  * Since: 1.0
     78  **/
     79 const char *
     80 hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
     81 {
     82   switch (format)
     83   {
     84     case HB_BUFFER_SERIALIZE_FORMAT_TEXT:	return serialize_formats[0];
     85     case HB_BUFFER_SERIALIZE_FORMAT_JSON:	return serialize_formats[1];
     86     default:
     87     case HB_BUFFER_SERIALIZE_FORMAT_INVALID:	return NULL;
     88   }
     89 }
     90 
     91 static unsigned int
     92 _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
     93 				  unsigned int start,
     94 				  unsigned int end,
     95 				  char *buf,
     96 				  unsigned int buf_size,
     97 				  unsigned int *buf_consumed,
     98 				  hb_font_t *font,
     99 				  hb_buffer_serialize_flags_t flags)
    100 {
    101   hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
    102   hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
    103 
    104   *buf_consumed = 0;
    105   for (unsigned int i = start; i < end; i++)
    106   {
    107     char b[1024];
    108     char *p = b;
    109 
    110     /* In the following code, we know b is large enough that no overflow can happen. */
    111 
    112 #define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END
    113 
    114     if (i)
    115       *p++ = ',';
    116 
    117     *p++ = '{';
    118 
    119     APPEND ("\"g\":");
    120     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES))
    121     {
    122       char g[128];
    123       hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g));
    124       *p++ = '"';
    125       for (char *q = g; *q; q++) {
    126         if (*q == '"')
    127 	  *p++ = '\\';
    128 	*p++ = *q;
    129       }
    130       *p++ = '"';
    131     }
    132     else
    133       p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
    134 
    135     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
    136       p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
    137     }
    138 
    139     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
    140     {
    141       p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
    142 		     pos[i].x_offset, pos[i].y_offset);
    143       p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
    144 		     pos[i].x_advance, pos[i].y_advance);
    145     }
    146 
    147     *p++ = '}';
    148 
    149     unsigned int l = p - b;
    150     if (buf_size > l)
    151     {
    152       memcpy (buf, b, l);
    153       buf += l;
    154       buf_size -= l;
    155       *buf_consumed += l;
    156       *buf = '\0';
    157     } else
    158       return i - start;
    159   }
    160 
    161   return end - start;
    162 }
    163 
    164 static unsigned int
    165 _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
    166 				  unsigned int start,
    167 				  unsigned int end,
    168 				  char *buf,
    169 				  unsigned int buf_size,
    170 				  unsigned int *buf_consumed,
    171 				  hb_font_t *font,
    172 				  hb_buffer_serialize_flags_t flags)
    173 {
    174   hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
    175   hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
    176 
    177   *buf_consumed = 0;
    178   for (unsigned int i = start; i < end; i++)
    179   {
    180     char b[1024];
    181     char *p = b;
    182 
    183     /* In the following code, we know b is large enough that no overflow can happen. */
    184 
    185     if (i)
    186       *p++ = '|';
    187 
    188     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES))
    189     {
    190       hb_font_glyph_to_string (font, info[i].codepoint, p, 128);
    191       p += strlen (p);
    192     }
    193     else
    194       p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
    195 
    196     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
    197       p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
    198     }
    199 
    200     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
    201     {
    202       if (pos[i].x_offset || pos[i].y_offset)
    203 	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", pos[i].x_offset, pos[i].y_offset));
    204 
    205       *p++ = '+';
    206       p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
    207       if (pos[i].y_advance)
    208 	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
    209     }
    210 
    211     unsigned int l = p - b;
    212     if (buf_size > l)
    213     {
    214       memcpy (buf, b, l);
    215       buf += l;
    216       buf_size -= l;
    217       *buf_consumed += l;
    218       *buf = '\0';
    219     } else
    220       return i - start;
    221   }
    222 
    223   return end - start;
    224 }
    225 
    226 /* Returns number of items, starting at start, that were serialized. */
    227 /**
    228  * hb_buffer_serialize_glyphs:
    229  * @buffer: a buffer.
    230  * @start:
    231  * @end:
    232  * @buf: (array length=buf_size):
    233  * @buf_size:
    234  * @buf_consumed: (out):
    235  * @font:
    236  * @format:
    237  * @flags:
    238  *
    239  *
    240  *
    241  * Return value:
    242  *
    243  * Since: 1.0
    244  **/
    245 unsigned int
    246 hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
    247 			    unsigned int start,
    248 			    unsigned int end,
    249 			    char *buf,
    250 			    unsigned int buf_size,
    251 			    unsigned int *buf_consumed, /* May be NULL */
    252 			    hb_font_t *font, /* May be NULL */
    253 			    hb_buffer_serialize_format_t format,
    254 			    hb_buffer_serialize_flags_t flags)
    255 {
    256   assert (start <= end && end <= buffer->len);
    257 
    258   unsigned int sconsumed;
    259   if (!buf_consumed)
    260     buf_consumed = &sconsumed;
    261   *buf_consumed = 0;
    262 
    263   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
    264 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
    265 
    266   if (unlikely (start == end))
    267     return 0;
    268 
    269   if (!font)
    270     font = hb_font_get_empty ();
    271 
    272   switch (format)
    273   {
    274     case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
    275       return _hb_buffer_serialize_glyphs_text (buffer, start, end,
    276 					       buf, buf_size, buf_consumed,
    277 					       font, flags);
    278 
    279     case HB_BUFFER_SERIALIZE_FORMAT_JSON:
    280       return _hb_buffer_serialize_glyphs_json (buffer, start, end,
    281 					       buf, buf_size, buf_consumed,
    282 					       font, flags);
    283 
    284     default:
    285     case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
    286       return 0;
    287 
    288   }
    289 }
    290 
    291 
    292 static hb_bool_t
    293 parse_uint (const char *pp, const char *end, uint32_t *pv)
    294 {
    295   char buf[32];
    296   unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
    297   strncpy (buf, pp, len);
    298   buf[len] = '\0';
    299 
    300   char *p = buf;
    301   char *pend = p;
    302   uint32_t v;
    303 
    304   errno = 0;
    305   v = strtol (p, &pend, 10);
    306   if (errno || p == pend || pend - p != end - pp)
    307     return false;
    308 
    309   *pv = v;
    310   return true;
    311 }
    312 
    313 static hb_bool_t
    314 parse_int (const char *pp, const char *end, int32_t *pv)
    315 {
    316   char buf[32];
    317   unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
    318   strncpy (buf, pp, len);
    319   buf[len] = '\0';
    320 
    321   char *p = buf;
    322   char *pend = p;
    323   int32_t v;
    324 
    325   errno = 0;
    326   v = strtol (p, &pend, 10);
    327   if (errno || p == pend || pend - p != end - pp)
    328     return false;
    329 
    330   *pv = v;
    331   return true;
    332 }
    333 
    334 #include "hb-buffer-deserialize-json.hh"
    335 #include "hb-buffer-deserialize-text.hh"
    336 
    337 /**
    338  * hb_buffer_deserialize_glyphs:
    339  * @buffer: a buffer.
    340  * @buf: (array length=buf_len):
    341  * @buf_len:
    342  * @end_ptr: (out):
    343  * @font:
    344  * @format:
    345  *
    346  *
    347  *
    348  * Return value:
    349  *
    350  * Since: 1.0
    351  **/
    352 hb_bool_t
    353 hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
    354 			      const char *buf,
    355 			      int buf_len, /* -1 means nul-terminated */
    356 			      const char **end_ptr, /* May be NULL */
    357 			      hb_font_t *font, /* May be NULL */
    358 			      hb_buffer_serialize_format_t format)
    359 {
    360   const char *end;
    361   if (!end_ptr)
    362     end_ptr = &end;
    363   *end_ptr = buf;
    364 
    365   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
    366 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
    367 
    368   if (buf_len == -1)
    369     buf_len = strlen (buf);
    370 
    371   if (!buf_len)
    372   {
    373     *end_ptr = buf;
    374     return false;
    375   }
    376 
    377   hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
    378 
    379   if (!font)
    380     font = hb_font_get_empty ();
    381 
    382   switch (format)
    383   {
    384     case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
    385       return _hb_buffer_deserialize_glyphs_text (buffer,
    386 						 buf, buf_len, end_ptr,
    387 						 font);
    388 
    389     case HB_BUFFER_SERIALIZE_FORMAT_JSON:
    390       return _hb_buffer_deserialize_glyphs_json (buffer,
    391 						 buf, buf_len, end_ptr,
    392 						 font);
    393 
    394     default:
    395     case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
    396       return false;
    397 
    398   }
    399 }
    400