• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 **
hb_buffer_serialize_list_formats(void)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
hb_buffer_serialize_format_from_string(const char * str,int len)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 *
hb_buffer_serialize_format_to_string(hb_buffer_serialize_format_t format)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
_hb_buffer_serialize_glyphs_json(hb_buffer_t * buffer,unsigned int start,unsigned int end,char * buf,unsigned int buf_size,unsigned int * buf_consumed,hb_font_t * font,hb_buffer_serialize_flags_t flags)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
_hb_buffer_serialize_glyphs_text(hb_buffer_t * buffer,unsigned int start,unsigned int end,char * buf,unsigned int buf_size,unsigned int * buf_consumed,hb_font_t * font,hb_buffer_serialize_flags_t flags)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
hb_buffer_serialize_glyphs(hb_buffer_t * buffer,unsigned int start,unsigned int end,char * buf,unsigned int buf_size,unsigned int * buf_consumed,hb_font_t * font,hb_buffer_serialize_format_t format,hb_buffer_serialize_flags_t flags)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
parse_uint(const char * pp,const char * end,uint32_t * pv)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
parse_int(const char * pp,const char * end,int32_t * pv)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
hb_buffer_deserialize_glyphs(hb_buffer_t * buffer,const char * buf,int buf_len,const char ** end_ptr,hb_font_t * font,hb_buffer_serialize_format_t format)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