QtBase  v6.3.1
hb-buffer-serialize.cc
Go to the documentation of this file.
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.hh"
28 
29 #ifndef HB_NO_BUFFER_SERIALIZE
30 
31 #include "hb-buffer.hh"
32 
33 
34 static const char *serialize_formats[] = {
35  "text",
36  "json",
37  nullptr
38 };
39 
50 const char **
52 {
53  return serialize_formats;
54 }
55 
72 {
73  /* Upper-case it. */
74  return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020u);
75 }
76 
89 const char *
91 {
92  switch ((unsigned) format)
93  {
94  case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0];
95  case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1];
96  default:
97  case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr;
98  }
99 }
100 
101 static unsigned int
102 _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
103  unsigned int start,
104  unsigned int end,
105  char *buf,
106  unsigned int buf_size,
107  unsigned int *buf_consumed,
108  hb_font_t *font,
110 {
113  nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
114 
115  *buf_consumed = 0;
116  hb_position_t x = 0, y = 0;
117  for (unsigned int i = start; i < end; i++)
118  {
119  char b[1024];
120  char *p = b;
121 
122  /* In the following code, we know b is large enough that no overflow can happen. */
123 
124 #define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END
125 
126  if (i)
127  *p++ = ',';
128  else
129  *p++ = '[';
130 
131  *p++ = '{';
132 
133  APPEND ("\"g\":");
135  {
136  char g[128];
137  hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g));
138  *p++ = '"';
139  for (char *q = g; *q; q++)
140  {
141  if (unlikely (*q == '"' || *q == '\\'))
142  *p++ = '\\';
143  *p++ = *q;
144  }
145  *p++ = '"';
146  }
147  else
148  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
149 
151  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
152  }
153 
155  {
156  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
157  x+pos[i].x_offset, y+pos[i].y_offset));
159  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
160  pos[i].x_advance, pos[i].y_advance));
161  }
162 
164  {
166  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED));
167  }
168 
170  {
171  hb_glyph_extents_t extents;
172  hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
173  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
174  extents.x_bearing, extents.y_bearing));
175  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
176  extents.width, extents.height));
177  }
178 
179  *p++ = '}';
180  if (i == end-1)
181  *p++ = ']';
182 
183  unsigned int l = p - b;
184  if (buf_size > l)
185  {
186  memcpy (buf, b, l);
187  buf += l;
188  buf_size -= l;
189  *buf_consumed += l;
190  *buf = '\0';
191  } else
192  return i - start;
193 
195  {
196  x += pos[i].x_advance;
197  y += pos[i].y_advance;
198  }
199  }
200 
201  return end - start;
202 }
203 
204 static unsigned int
205 _hb_buffer_serialize_unicode_json (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,
212 {
214 
215  *buf_consumed = 0;
216  for (unsigned int i = start; i < end; i++)
217  {
218  char b[1024];
219  char *p = b;
220 
221  if (i)
222  *p++ = ',';
223  else
224  *p++ = '[';
225 
226  *p++ = '{';
227 
228  APPEND ("\"u\":");
229 
230  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
231 
233  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
234  }
235 
236  *p++ = '}';
237 
238  if (i == end-1)
239  *p++ = ']';
240 
241  unsigned int l = p - b;
242  if (buf_size > l)
243  {
244  memcpy (buf, b, l);
245  buf += l;
246  buf_size -= l;
247  *buf_consumed += l;
248  *buf = '\0';
249  } else
250  return i - start;
251 
252  }
253 
254  return end - start;
255 }
256 
257 static unsigned int
258 _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
259  unsigned int start,
260  unsigned int end,
261  char *buf,
262  unsigned int buf_size,
263  unsigned int *buf_consumed,
264  hb_font_t *font,
266 {
269  nullptr : hb_buffer_get_glyph_positions (buffer, nullptr);
270 
271  *buf_consumed = 0;
272  hb_position_t x = 0, y = 0;
273  for (unsigned int i = start; i < end; i++)
274  {
275  char b[1024];
276  char *p = b;
277 
278  /* In the following code, we know b is large enough that no overflow can happen. */
279 
280  if (i)
281  *p++ = '|';
282  else
283  *p++ = '[';
284 
286  {
287  /* TODO Escape delimiters we use. */
288  hb_font_glyph_to_string (font, info[i].codepoint, p, 128);
289  p += strlen (p);
290  }
291  else
292  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
293 
295  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
296  }
297 
299  {
300  if (x+pos[i].x_offset || y+pos[i].y_offset)
301  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset));
302 
304  {
305  *p++ = '+';
306  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
307  if (pos[i].y_advance)
308  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
309  }
310  }
311 
313  {
315  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
316  }
317 
319  {
320  hb_glyph_extents_t extents;
321  hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
322  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
323  }
324 
325  if (i == end-1) {
326  *p++ = ']';
327  }
328 
329  unsigned int l = p - b;
330  if (buf_size > l)
331  {
332  memcpy (buf, b, l);
333  buf += l;
334  buf_size -= l;
335  *buf_consumed += l;
336  *buf = '\0';
337  } else
338  return i - start;
339 
341  {
342  x += pos[i].x_advance;
343  y += pos[i].y_advance;
344  }
345  }
346 
347  return end - start;
348 }
349 
350 
351 static unsigned int
352 _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
353  unsigned int start,
354  unsigned int end,
355  char *buf,
356  unsigned int buf_size,
357  unsigned int *buf_consumed,
359 {
361  *buf_consumed = 0;
362  for (unsigned int i = start; i < end; i++)
363  {
364  char b[1024];
365  char *p = b;
366 
367  if (i)
368  *p++ = '|';
369  else
370  *p++ = '<';
371 
372  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "U+%04X", info[i].codepoint));
373 
375  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
376  }
377 
378  if (i == end-1)
379  *p++ = '>';
380 
381  unsigned int l = p - b;
382  if (buf_size > l)
383  {
384  memcpy (buf, b, l);
385  buf += l;
386  buf_size -= l;
387  *buf_consumed += l;
388  *buf = '\0';
389  } else
390  return i - start;
391  }
392  return end - start;
393 }
394 
458 unsigned int
460  unsigned int start,
461  unsigned int end,
462  char *buf,
463  unsigned int buf_size,
464  unsigned int *buf_consumed,
465  hb_font_t *font,
468 {
469  end = hb_clamp (end, start, buffer->len);
470  start = hb_min (start, end);
471 
472  unsigned int sconsumed;
473  if (!buf_consumed)
474  buf_consumed = &sconsumed;
475  *buf_consumed = 0;
476  if (buf_size)
477  *buf = '\0';
478 
479  buffer->assert_glyphs ();
480 
481  if (!buffer->have_positions)
483 
484  if (unlikely (start == end))
485  return 0;
486 
487  if (!font)
488  font = hb_font_get_empty ();
489 
490  switch (format)
491  {
493  return _hb_buffer_serialize_glyphs_text (buffer, start, end,
494  buf, buf_size, buf_consumed,
495  font, flags);
496 
498  return _hb_buffer_serialize_glyphs_json (buffer, start, end,
499  buf, buf_size, buf_consumed,
500  font, flags);
501 
502  default:
504  return 0;
505 
506  }
507 }
508 
560 unsigned int
562  unsigned int start,
563  unsigned int end,
564  char *buf,
565  unsigned int buf_size,
566  unsigned int *buf_consumed,
569 {
570  end = hb_clamp (end, start, buffer->len);
571  start = hb_min (start, end);
572 
573  unsigned int sconsumed;
574  if (!buf_consumed)
575  buf_consumed = &sconsumed;
576  *buf_consumed = 0;
577  if (buf_size)
578  *buf = '\0';
579 
580  buffer->assert_unicode ();
581 
582  if (unlikely (start == end))
583  return 0;
584 
585  switch (format)
586  {
588  return _hb_buffer_serialize_unicode_text (buffer, start, end,
589  buf, buf_size, buf_consumed, flags);
590 
592  return _hb_buffer_serialize_unicode_json (buffer, start, end,
593  buf, buf_size, buf_consumed, flags);
594 
595  default:
597  return 0;
598 
599  }
600 }
601 
602 static unsigned int
603 _hb_buffer_serialize_invalid (hb_buffer_t *buffer,
604  unsigned int start,
605  unsigned int end,
606  char *buf,
607  unsigned int buf_size,
608  unsigned int *buf_consumed,
611 {
612  assert (!buffer->len);
613 
614  unsigned int sconsumed;
615  if (!buf_consumed)
616  buf_consumed = &sconsumed;
617  if (buf_size < 3)
618  return 0;
620  *buf++ = '[';
621  *buf++ = ']';
622  *buf = '\0';
623  } else if (format == HB_BUFFER_SERIALIZE_FORMAT_TEXT) {
624  *buf++ = '!';
625  *buf++ = '!';
626  *buf = '\0';
627  }
628  *buf_consumed = 2;
629  return 0;
630 }
631 
658 unsigned int
660  unsigned int start,
661  unsigned int end,
662  char *buf,
663  unsigned int buf_size,
664  unsigned int *buf_consumed,
665  hb_font_t *font,
668 {
669  switch (buffer->content_type)
670  {
671 
673  return hb_buffer_serialize_glyphs (buffer, start, end, buf, buf_size,
674  buf_consumed, font, format, flags);
675 
677  return hb_buffer_serialize_unicode (buffer, start, end, buf, buf_size,
678  buf_consumed, format, flags);
679 
681  default:
682  return _hb_buffer_serialize_invalid (buffer, start, end, buf, buf_size,
683  buf_consumed, format, flags);
684  }
685 }
686 
687 static bool
688 parse_int (const char *pp, const char *end, int32_t *pv)
689 {
690  int v;
691  const char *p = pp;
692  if (unlikely (!hb_parse_int (&p, end, &v, true/* whole buffer */)))
693  return false;
694 
695  *pv = v;
696  return true;
697 }
698 
699 static bool
700 parse_uint (const char *pp, const char *end, uint32_t *pv)
701 {
702  unsigned int v;
703  const char *p = pp;
704  if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */)))
705  return false;
706 
707  *pv = v;
708  return true;
709 }
710 
711 static bool
712 parse_hex (const char *pp, const char *end, uint32_t *pv)
713 {
714  unsigned int v;
715  const char *p = pp;
716  if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */, 16)))
717  return false;
718 
719  *pv = v;
720  return true;
721 }
722 
725 
743 hb_bool_t
745  const char *buf,
746  int buf_len, /* -1 means nul-terminated */
747  const char **end_ptr, /* May be NULL */
748  hb_font_t *font, /* May be NULL */
750 {
751  const char *end;
752  if (!end_ptr)
753  end_ptr = &end;
754  *end_ptr = buf;
755 
756  buffer->assert_glyphs ();
757 
758  if (unlikely (hb_object_is_immutable (buffer)))
759  {
760  if (end_ptr)
761  *end_ptr = buf;
762  return false;
763  }
764 
765  if (buf_len == -1)
766  buf_len = strlen (buf);
767 
768  if (!buf_len)
769  {
770  *end_ptr = buf;
771  return false;
772  }
773 
775 
776  if (!font)
777  font = hb_font_get_empty ();
778 
779  switch (format)
780  {
782  return _hb_buffer_deserialize_text (buffer,
783  buf, buf_len, end_ptr,
784  font);
785 
787  return _hb_buffer_deserialize_json (buffer,
788  buf, buf_len, end_ptr,
789  font);
790 
791  default:
793  return false;
794 
795  }
796 }
797 
798 
815 hb_bool_t
817  const char *buf,
818  int buf_len, /* -1 means nul-terminated */
819  const char **end_ptr, /* May be NULL */
821 {
822  const char *end;
823  if (!end_ptr)
824  end_ptr = &end;
825  *end_ptr = buf;
826 
827  buffer->assert_unicode ();
828 
829  if (unlikely (hb_object_is_immutable (buffer)))
830  {
831  if (end_ptr)
832  *end_ptr = buf;
833  return false;
834  }
835 
836  if (buf_len == -1)
837  buf_len = strlen (buf);
838 
839  if (!buf_len)
840  {
841  *end_ptr = buf;
842  return false;
843  }
844 
846 
848 
849  switch (format)
850  {
852  return _hb_buffer_deserialize_text (buffer,
853  buf, buf_len, end_ptr,
854  font);
855 
857  return _hb_buffer_deserialize_json (buffer,
858  buf, buf_len, end_ptr,
859  font);
860 
861  default:
863  return false;
864 
865  }
866 }
867 
868 
869 #endif
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
QString str
[2]
unsigned int hb_buffer_serialize_unicode(hb_buffer_t *buffer, unsigned int start, unsigned int end, char *buf, unsigned int buf_size, unsigned int *buf_consumed, hb_buffer_serialize_format_t format, hb_buffer_serialize_flags_t flags)
const char * hb_buffer_serialize_format_to_string(hb_buffer_serialize_format_t format)
hb_bool_t hb_buffer_deserialize_unicode(hb_buffer_t *buffer, const char *buf, int buf_len, const char **end_ptr, hb_buffer_serialize_format_t format)
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)
const char ** hb_buffer_serialize_list_formats()
hb_buffer_serialize_format_t hb_buffer_serialize_format_from_string(const char *str, int len)
#define APPEND(s)
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)
unsigned int hb_buffer_serialize(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)
void hb_buffer_set_content_type(hb_buffer_t *buffer, hb_buffer_content_type_t content_type)
Definition: hb-buffer.cc:818
hb_glyph_position_t * hb_buffer_get_glyph_positions(hb_buffer_t *buffer, unsigned int *length)
Definition: hb-buffer.cc:1433
hb_glyph_info_t * hb_buffer_get_glyph_infos(hb_buffer_t *buffer, unsigned int *length)
Definition: hb-buffer.cc:1404
hb_tag_t hb_tag_from_string(const char *str, int len)
Definition: hb-common.cc:123
void hb_font_glyph_to_string(hb_font_t *font, hb_codepoint_t glyph, char *s, unsigned int size)
Definition: hb-font.cc:1584
hb_font_t * hb_font_get_empty()
Definition: hb-font.cc:1783
hb_bool_t hb_font_get_glyph_extents(hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents)
Definition: hb-font.cc:1224
bool hb_parse_int(const char **pp, const char *end, int *pv, bool whole_buffer)
Definition: hb-number.cc:56
bool hb_parse_uint(const char **pp, const char *end, unsigned *pv, bool whole_buffer, int base)
Definition: hb-number.cc:64
#define unlikely(expr)
Definition: hb.hh:251
backing_store_ptr info
[4]
Definition: jmemsys.h:161
PCRE2_SIZE PRIV() strlen(PCRE2_SPTR str)
#define assert
Definition: qcborcommon_p.h:63
#define ARRAY_LENGTH(a)
Definition: qkmsdevice.cpp:52
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLuint GLuint end
GLenum GLuint buffer
GLenum GLuint GLenum GLsizei const GLchar * buf
GLbitfield flags
GLuint start
GLboolean GLboolean g
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint GLsizei GLsizei GLenum format
GLint y
GLenum GLsizei len
Definition: qopenglext.h:3292
GLdouble GLdouble GLdouble GLdouble q
Definition: qopenglext.h:259
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
@ HB_GLYPH_FLAG_DEFINED
Definition: hb-buffer.h:155
hb_buffer_serialize_flags_t
Definition: hb-buffer.h:591
@ HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS
Definition: hb-buffer.h:593
@ HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS
Definition: hb-buffer.h:596
@ HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES
Definition: hb-buffer.h:598
@ HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS
Definition: hb-buffer.h:594
@ HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES
Definition: hb-buffer.h:595
@ HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS
Definition: hb-buffer.h:597
hb_buffer_serialize_format_t
Definition: hb-buffer.h:612
@ HB_BUFFER_SERIALIZE_FORMAT_INVALID
Definition: hb-buffer.h:615
@ HB_BUFFER_SERIALIZE_FORMAT_JSON
Definition: hb-buffer.h:614
@ HB_BUFFER_SERIALIZE_FORMAT_TEXT
Definition: hb-buffer.h:613
@ HB_BUFFER_CONTENT_TYPE_GLYPHS
Definition: hb-buffer.h:284
@ HB_BUFFER_CONTENT_TYPE_UNICODE
Definition: hb-buffer.h:283
@ HB_BUFFER_CONTENT_TYPE_INVALID
Definition: hb-buffer.h:282
HB_BEGIN_DECLS typedef int hb_bool_t
Definition: hb-common.h:97
int32_t hb_position_t
Definition: hb-common.h:115
hb_position_t x_bearing
Definition: hb-font.h:141
hb_position_t y_bearing
Definition: hb-font.h:142
hb_position_t height
Definition: hb-font.h:144
hb_position_t width
Definition: hb-font.h:143