Imported Upstream version 0.9.35
[platform/upstream/harfbuzz.git] / src / hb-buffer-serialize.cc
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 }