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