QtBase  v6.3.1
hb-common.cc
Go to the documentation of this file.
1 /*
2  * Copyright © 2009,2010 Red Hat, Inc.
3  * Copyright © 2011,2012 Google, Inc.
4  *
5  * This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Red Hat Author(s): Behdad Esfahbod
26  * Google Author(s): Behdad Esfahbod
27  */
28 
29 #include "hb.hh"
30 #include "hb-machinery.hh"
31 
32 #if !defined(HB_NO_SETLOCALE) && (!defined(HAVE_NEWLOCALE) || !defined(HAVE_USELOCALE))
33 #define HB_NO_SETLOCALE 1
34 #endif
35 
36 #ifndef HB_NO_SETLOCALE
37 
38 #include <locale.h>
39 #ifdef HAVE_XLOCALE_H
40 #include <xlocale.h> // Needed on BSD/OS X for uselocale
41 #endif
42 
43 #ifdef WIN32
44 #define hb_locale_t _locale_t
45 #else
46 #define hb_locale_t locale_t
47 #endif
48 #define hb_setlocale setlocale
49 #define hb_uselocale uselocale
50 
51 #else
52 
53 #define hb_locale_t void *
54 #define hb_setlocale(Category, Locale) "C"
55 #define hb_uselocale(Locale) ((hb_locale_t) 0)
56 
57 #endif
58 
69 /* hb_options_t */
70 
72 
73 void
75 {
77  u.i = 0;
78  u.opts.initialized = true;
79 
80  const char *c = getenv ("HB_OPTIONS");
81  if (c)
82  {
83  while (*c)
84  {
85  const char *p = strchr (c, ':');
86  if (!p)
87  p = c + strlen (c);
88 
89 #define OPTION(name, symbol) \
90  if (0 == strncmp (c, name, p - c) && strlen (name) == static_cast<size_t>(p - c)) do { u.opts.symbol = true; } while (0)
91 
92  OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
93 
94 #undef OPTION
95 
96  c = *p ? p + 1 : p;
97  }
98 
99  }
100 
101  /* This is idempotent and threadsafe. */
103 }
104 
105 
106 /* hb_tag_t */
107 
122 hb_tag_t
123 hb_tag_from_string (const char *str, int len)
124 {
125  char tag[4];
126  unsigned int i;
127 
128  if (!str || !len || !*str)
129  return HB_TAG_NONE;
130 
131  if (len < 0 || len > 4)
132  len = 4;
133  for (i = 0; i < (unsigned) len && str[i]; i++)
134  tag[i] = str[i];
135  for (; i < 4; i++)
136  tag[i] = ' ';
137 
138  return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
139 }
140 
151 void
153 {
154  buf[0] = (char) (uint8_t) (tag >> 24);
155  buf[1] = (char) (uint8_t) (tag >> 16);
156  buf[2] = (char) (uint8_t) (tag >> 8);
157  buf[3] = (char) (uint8_t) (tag >> 0);
158 }
159 
160 
161 /* hb_direction_t */
162 
163 const char direction_strings[][4] = {
164  "ltr",
165  "rtl",
166  "ttb",
167  "btt"
168 };
169 
187 hb_direction_from_string (const char *str, int len)
188 {
189  if (unlikely (!str || !len || !*str))
190  return HB_DIRECTION_INVALID;
191 
192  /* Lets match loosely: just match the first letter, such that
193  * all of "ltr", "left-to-right", etc work!
194  */
195  char c = TOLOWER (str[0]);
196  for (unsigned int i = 0; i < ARRAY_LENGTH (direction_strings); i++)
197  if (c == direction_strings[i][0])
198  return (hb_direction_t) (HB_DIRECTION_LTR + i);
199 
200  return HB_DIRECTION_INVALID;
201 }
202 
213 const char *
215 {
216  if (likely ((unsigned int) (direction - HB_DIRECTION_LTR)
219 
220  return "invalid";
221 }
222 
223 
224 /* hb_language_t */
225 
227  const char s[1];
228 };
229 
230 static const char canon_map[256] = {
231  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
232  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
233  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0,
234  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
235  0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
236  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-',
237  0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
238  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
239 };
240 
241 static bool
242 lang_equal (hb_language_t v1,
243  const void *v2)
244 {
245  const unsigned char *p1 = (const unsigned char *) v1;
246  const unsigned char *p2 = (const unsigned char *) v2;
247 
248  while (*p1 && *p1 == canon_map[*p2]) {
249  p1++;
250  p2++;
251  }
252 
253  return *p1 == canon_map[*p2];
254 }
255 
256 #if 0
257 static unsigned int
258 lang_hash (const void *key)
259 {
260  const unsigned char *p = key;
261  unsigned int h = 0;
262  while (canon_map[*p])
263  {
264  h = (h << 5) - h + canon_map[*p];
265  p++;
266  }
267 
268  return h;
269 }
270 #endif
271 
272 
274 
277 
278  bool operator == (const char *s) const
279  { return lang_equal (lang, s); }
280 
282  {
283  /* We can't call strdup(), because we allow custom allocators. */
284  size_t len = strlen(s) + 1;
286  if (likely (lang))
287  {
288  memcpy((unsigned char *) lang, s, len);
289  for (unsigned char *p = (unsigned char *) lang; *p; p++)
290  *p = canon_map[*p];
291  }
292 
293  return *this;
294  }
295 
296  void fini () { hb_free ((void *) lang); }
297 };
298 
299 
300 /* Thread-safe lockfree language list */
301 
303 
304 static inline void
305 free_langs ()
306 {
307 retry:
308  hb_language_item_t *first_lang = langs;
309  if (unlikely (!langs.cmpexch (first_lang, nullptr)))
310  goto retry;
311 
312  while (first_lang) {
313  hb_language_item_t *next = first_lang->next;
314  first_lang->fini ();
315  hb_free (first_lang);
316  first_lang = next;
317  }
318 }
319 
320 static hb_language_item_t *
321 lang_find_or_insert (const char *key)
322 {
323 retry:
324  hb_language_item_t *first_lang = langs;
325 
326  for (hb_language_item_t *lang = first_lang; lang; lang = lang->next)
327  if (*lang == key)
328  return lang;
329 
330  /* Not found; allocate one. */
332  if (unlikely (!lang))
333  return nullptr;
334  lang->next = first_lang;
335  *lang = key;
336  if (unlikely (!lang->lang))
337  {
338  hb_free (lang);
339  return nullptr;
340  }
341 
342  if (unlikely (!langs.cmpexch (first_lang, lang)))
343  {
344  lang->fini ();
345  hb_free (lang);
346  goto retry;
347  }
348 
349  if (!first_lang)
350  hb_atexit (free_langs); /* First person registers atexit() callback. */
351 
352  return lang;
353 }
354 
355 
371 hb_language_from_string (const char *str, int len)
372 {
373  if (!str || !len || !*str)
374  return HB_LANGUAGE_INVALID;
375 
376  hb_language_item_t *item = nullptr;
377  if (len >= 0)
378  {
379  /* NUL-terminate it. */
380  char strbuf[64];
381  len = hb_min (len, (int) sizeof (strbuf) - 1);
382  memcpy (strbuf, str, len);
383  strbuf[len] = '\0';
384  item = lang_find_or_insert (strbuf);
385  }
386  else
387  item = lang_find_or_insert (str);
388 
389  return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
390 }
391 
404 const char *
406 {
407  if (unlikely (!language)) return nullptr;
408 
409  return language->s;
410 }
411 
431 {
432  static hb_atomic_ptr_t <hb_language_t> default_language;
433 
434  hb_language_t language = default_language;
436  {
437  language = hb_language_from_string (hb_setlocale (LC_CTYPE, nullptr), -1);
438  (void) default_language.cmpexch (HB_LANGUAGE_INVALID, language);
439  }
440 
441  return language;
442 }
443 
444 
445 /* hb_script_t */
446 
460 {
461  if (unlikely (tag == HB_TAG_NONE))
462  return HB_SCRIPT_INVALID;
463 
464  /* Be lenient, adjust case (one capital letter followed by three small letters) */
465  tag = (tag & 0xDFDFDFDFu) | 0x00202020u;
466 
467  switch (tag) {
468 
469  /* These graduated from the 'Q' private-area codes, but
470  * the old code is still aliased by Unicode, and the Qaai
471  * one in use by ICU. */
472  case HB_TAG('Q','a','a','i'): return HB_SCRIPT_INHERITED;
473  case HB_TAG('Q','a','a','c'): return HB_SCRIPT_COPTIC;
474 
475  /* Script variants from https://unicode.org/iso15924/ */
476  case HB_TAG('A','r','a','n'): return HB_SCRIPT_ARABIC;
477  case HB_TAG('C','y','r','s'): return HB_SCRIPT_CYRILLIC;
478  case HB_TAG('G','e','o','k'): return HB_SCRIPT_GEORGIAN;
479  case HB_TAG('H','a','n','s'): return HB_SCRIPT_HAN;
480  case HB_TAG('H','a','n','t'): return HB_SCRIPT_HAN;
481  case HB_TAG('J','a','m','o'): return HB_SCRIPT_HANGUL;
482  case HB_TAG('L','a','t','f'): return HB_SCRIPT_LATIN;
483  case HB_TAG('L','a','t','g'): return HB_SCRIPT_LATIN;
484  case HB_TAG('S','y','r','e'): return HB_SCRIPT_SYRIAC;
485  case HB_TAG('S','y','r','j'): return HB_SCRIPT_SYRIAC;
486  case HB_TAG('S','y','r','n'): return HB_SCRIPT_SYRIAC;
487  }
488 
489  /* If it looks right, just use the tag as a script */
490  if (((uint32_t) tag & 0xE0E0E0E0u) == 0x40606060u)
491  return (hb_script_t) tag;
492 
493  /* Otherwise, return unknown */
494  return HB_SCRIPT_UNKNOWN;
495 }
496 
513 hb_script_from_string (const char *str, int len)
514 {
516 }
517 
529 hb_tag_t
531 {
532  return (hb_tag_t) script;
533 }
534 
552 {
553  /* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */
554  switch ((hb_tag_t) script)
555  {
556  /* Unicode-1.1 additions */
557  case HB_SCRIPT_ARABIC:
558  case HB_SCRIPT_HEBREW:
559 
560  /* Unicode-3.0 additions */
561  case HB_SCRIPT_SYRIAC:
562  case HB_SCRIPT_THAANA:
563 
564  /* Unicode-4.0 additions */
565  case HB_SCRIPT_CYPRIOT:
566 
567  /* Unicode-4.1 additions */
569 
570  /* Unicode-5.0 additions */
572  case HB_SCRIPT_NKO:
573 
574  /* Unicode-5.1 additions */
575  case HB_SCRIPT_LYDIAN:
576 
577  /* Unicode-5.2 additions */
578  case HB_SCRIPT_AVESTAN:
584  case HB_SCRIPT_SAMARITAN:
585 
586  /* Unicode-6.0 additions */
587  case HB_SCRIPT_MANDAIC:
588 
589  /* Unicode-6.1 additions */
592 
593  /* Unicode-7.0 additions */
596  case HB_SCRIPT_NABATAEAN:
598  case HB_SCRIPT_PALMYRENE:
600 
601  /* Unicode-8.0 additions */
602  case HB_SCRIPT_HATRAN:
603 
604  /* Unicode-9.0 additions */
605  case HB_SCRIPT_ADLAM:
606 
607  /* Unicode-11.0 additions */
610  case HB_SCRIPT_SOGDIAN:
611 
612  /* Unicode-12.0 additions */
613  case HB_SCRIPT_ELYMAIC:
614 
615  /* Unicode-13.0 additions */
617  case HB_SCRIPT_YEZIDI:
618 
619  /* Unicode-14.0 additions */
621 
622  return HB_DIRECTION_RTL;
623 
624 
625  /* https://github.com/harfbuzz/harfbuzz/issues/1000 */
628  case HB_SCRIPT_RUNIC:
629 
630  return HB_DIRECTION_INVALID;
631  }
632 
633  return HB_DIRECTION_LTR;
634 }
635 
636 
637 /* hb_version */
638 
639 
662 void
663 hb_version (unsigned int *major,
664  unsigned int *minor,
665  unsigned int *micro)
666 {
667  *major = HB_VERSION_MAJOR;
668  *minor = HB_VERSION_MINOR;
669  *micro = HB_VERSION_MICRO;
670 }
671 
681 const char *
683 {
684  return HB_VERSION_STRING;
685 }
686 
701 hb_bool_t
702 hb_version_atleast (unsigned int major,
703  unsigned int minor,
704  unsigned int micro)
705 {
706  return HB_VERSION_ATLEAST (major, minor, micro);
707 }
708 
709 
710 
711 /* hb_feature_t and hb_variation_t */
712 
713 static bool
714 parse_space (const char **pp, const char *end)
715 {
716  while (*pp < end && ISSPACE (**pp))
717  (*pp)++;
718  return true;
719 }
720 
721 static bool
722 parse_char (const char **pp, const char *end, char c)
723 {
724  parse_space (pp, end);
725 
726  if (*pp == end || **pp != c)
727  return false;
728 
729  (*pp)++;
730  return true;
731 }
732 
733 static bool
734 parse_uint (const char **pp, const char *end, unsigned int *pv)
735 {
736  /* Intentionally use hb_parse_int inside instead of hb_parse_uint,
737  * such that -1 turns into "big number"... */
738  int v;
739  if (unlikely (!hb_parse_int (pp, end, &v))) return false;
740 
741  *pv = v;
742  return true;
743 }
744 
745 static bool
746 parse_uint32 (const char **pp, const char *end, uint32_t *pv)
747 {
748  /* Intentionally use hb_parse_int inside instead of hb_parse_uint,
749  * such that -1 turns into "big number"... */
750  int v;
751  if (unlikely (!hb_parse_int (pp, end, &v))) return false;
752 
753  *pv = v;
754  return true;
755 }
756 
757 static bool
758 parse_bool (const char **pp, const char *end, uint32_t *pv)
759 {
760  parse_space (pp, end);
761 
762  const char *p = *pp;
763  while (*pp < end && ISALPHA(**pp))
764  (*pp)++;
765 
766  /* CSS allows on/off as aliases 1/0. */
767  if (*pp - p == 2
768  && TOLOWER (p[0]) == 'o'
769  && TOLOWER (p[1]) == 'n')
770  *pv = 1;
771  else if (*pp - p == 3
772  && TOLOWER (p[0]) == 'o'
773  && TOLOWER (p[1]) == 'f'
774  && TOLOWER (p[2]) == 'f')
775  *pv = 0;
776  else
777  return false;
778 
779  return true;
780 }
781 
782 /* hb_feature_t */
783 
784 static bool
785 parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
786 {
787  if (parse_char (pp, end, '-'))
788  feature->value = 0;
789  else {
790  parse_char (pp, end, '+');
791  feature->value = 1;
792  }
793 
794  return true;
795 }
796 
797 static bool
798 parse_tag (const char **pp, const char *end, hb_tag_t *tag)
799 {
800  parse_space (pp, end);
801 
802  char quote = 0;
803 
804  if (*pp < end && (**pp == '\'' || **pp == '"'))
805  {
806  quote = **pp;
807  (*pp)++;
808  }
809 
810  const char *p = *pp;
811  while (*pp < end && (ISALNUM(**pp) || **pp == '_'))
812  (*pp)++;
813 
814  if (p == *pp || *pp - p > 4)
815  return false;
816 
817  *tag = hb_tag_from_string (p, *pp - p);
818 
819  if (quote)
820  {
821  /* CSS expects exactly four bytes. And we only allow quotations for
822  * CSS compatibility. So, enforce the length. */
823  if (*pp - p != 4)
824  return false;
825  if (*pp == end || **pp != quote)
826  return false;
827  (*pp)++;
828  }
829 
830  return true;
831 }
832 
833 static bool
834 parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
835 {
836  parse_space (pp, end);
837 
838  bool has_start;
839 
840  feature->start = HB_FEATURE_GLOBAL_START;
841  feature->end = HB_FEATURE_GLOBAL_END;
842 
843  if (!parse_char (pp, end, '['))
844  return true;
845 
846  has_start = parse_uint (pp, end, &feature->start);
847 
848  if (parse_char (pp, end, ':') || parse_char (pp, end, ';')) {
849  parse_uint (pp, end, &feature->end);
850  } else {
851  if (has_start)
852  feature->end = feature->start + 1;
853  }
854 
855  return parse_char (pp, end, ']');
856 }
857 
858 static bool
859 parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
860 {
861  bool had_equal = parse_char (pp, end, '=');
862  bool had_value = parse_uint32 (pp, end, &feature->value) ||
863  parse_bool (pp, end, &feature->value);
864  /* CSS doesn't use equal-sign between tag and value.
865  * If there was an equal-sign, then there *must* be a value.
866  * A value without an equal-sign is ok, but not required. */
867  return !had_equal || had_value;
868 }
869 
870 static bool
871 parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
872 {
873  return parse_feature_value_prefix (pp, end, feature) &&
874  parse_tag (pp, end, &feature->tag) &&
875  parse_feature_indices (pp, end, feature) &&
876  parse_feature_value_postfix (pp, end, feature) &&
877  parse_space (pp, end) &&
878  *pp == end;
879 }
880 
930 hb_bool_t
931 hb_feature_from_string (const char *str, int len,
932  hb_feature_t *feature)
933 {
934  hb_feature_t feat;
935 
936  if (len < 0)
937  len = strlen (str);
938 
939  if (likely (parse_one_feature (&str, str + len, &feat)))
940  {
941  if (feature)
942  *feature = feat;
943  return true;
944  }
945 
946  if (feature)
947  memset (feature, 0, sizeof (*feature));
948  return false;
949 }
950 
963 void
965  char *buf, unsigned int size)
966 {
967  if (unlikely (!size)) return;
968 
969  char s[128];
970  unsigned int len = 0;
971  if (feature->value == 0)
972  s[len++] = '-';
973  hb_tag_to_string (feature->tag, s + len);
974  len += 4;
975  while (len && s[len - 1] == ' ')
976  len--;
977  if (feature->start != HB_FEATURE_GLOBAL_START || feature->end != HB_FEATURE_GLOBAL_END)
978  {
979  s[len++] = '[';
980  if (feature->start)
981  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
982  if (feature->end != feature->start + 1) {
983  s[len++] = ':';
984  if (feature->end != HB_FEATURE_GLOBAL_END)
985  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
986  }
987  s[len++] = ']';
988  }
989  if (feature->value > 1)
990  {
991  s[len++] = '=';
992  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
993  }
994  assert (len < ARRAY_LENGTH (s));
995  len = hb_min (len, size - 1);
996  memcpy (buf, s, len);
997  buf[len] = '\0';
998 }
999 
1000 /* hb_variation_t */
1001 
1002 static bool
1003 parse_variation_value (const char **pp, const char *end, hb_variation_t *variation)
1004 {
1005  parse_char (pp, end, '='); /* Optional. */
1006  double v;
1007  if (unlikely (!hb_parse_double (pp, end, &v))) return false;
1008 
1009  variation->value = v;
1010  return true;
1011 }
1012 
1013 static bool
1014 parse_one_variation (const char **pp, const char *end, hb_variation_t *variation)
1015 {
1016  return parse_tag (pp, end, &variation->tag) &&
1017  parse_variation_value (pp, end, variation) &&
1018  parse_space (pp, end) &&
1019  *pp == end;
1020 }
1021 
1042 hb_bool_t
1044  hb_variation_t *variation)
1045 {
1047 
1048  if (len < 0)
1049  len = strlen (str);
1050 
1051  if (likely (parse_one_variation (&str, str + len, &var)))
1052  {
1053  if (variation)
1054  *variation = var;
1055  return true;
1056  }
1057 
1058  if (variation)
1059  memset (variation, 0, sizeof (*variation));
1060  return false;
1061 }
1062 
1063 #ifndef HB_NO_SETLOCALE
1064 
1065 static inline void free_static_C_locale ();
1066 
1067 static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<hb_locale_t>,
1068  hb_C_locale_lazy_loader_t>
1069 {
1070  static hb_locale_t create ()
1071  {
1072  hb_locale_t l = newlocale (LC_ALL_MASK, "C", NULL);
1073  if (!l)
1074  return l;
1075 
1076  hb_atexit (free_static_C_locale);
1077 
1078  return l;
1079  }
1080  static void destroy (hb_locale_t l)
1081  {
1082  freelocale (l);
1083  }
1084  static hb_locale_t get_null ()
1085  {
1086  return (hb_locale_t) 0;
1087  }
1088 } static_C_locale;
1089 
1090 static inline
1091 void free_static_C_locale ()
1092 {
1093  static_C_locale.free_instance ();
1094 }
1095 
1096 static hb_locale_t
1097 get_C_locale ()
1098 {
1099  return static_C_locale.get_unconst ();
1100 }
1101 
1102 #endif
1103 
1116 void
1118  char *buf, unsigned int size)
1119 {
1120  if (unlikely (!size)) return;
1121 
1122  char s[128];
1123  unsigned int len = 0;
1124  hb_tag_to_string (variation->tag, s + len);
1125  len += 4;
1126  while (len && s[len - 1] == ' ')
1127  len--;
1128  s[len++] = '=';
1129 
1130  hb_locale_t oldlocale HB_UNUSED;
1131  oldlocale = hb_uselocale (get_C_locale ());
1132  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
1133  (void) hb_uselocale (oldlocale);
1134 
1135  assert (len < ARRAY_LENGTH (s));
1136  len = hb_min (len, size - 1);
1137  memcpy (buf, s, len);
1138  buf[len] = '\0';
1139 }
1140 
1151 uint8_t
1153 {
1154  return hb_color_get_alpha (color);
1155 }
1156 
1167 uint8_t
1169 {
1170  return hb_color_get_red (color);
1171 }
1172 
1183 uint8_t
1185 {
1186  return hb_color_get_green (color);
1187 }
1188 
1199 uint8_t
1201 {
1202  return hb_color_get_blue (color);
1203 }
1204 
1205 
1206 /* If there is no visibility control, then hb-static.cc will NOT
1207  * define anything. Instead, we get it to define one set in here
1208  * only, so only libharfbuzz.so defines them, not other libs. */
1209 #ifdef HB_NO_VISIBILITY
1210 #undef HB_NO_VISIBILITY
1211 #include "hb-static.cc"
1212 #define HB_NO_VISIBILITY 1
1213 #endif
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 xE2 xB2 x9E xE2 xB2 x9F xD0 xBE xD0 x9E xF0 x90 x90 x84 xF0 x90 x90 xAC xE1 x83 x98 xE1 x83 x94 xE1 x83 x90 xE1 xB2 xBF xE2 xB0 x95 xE2 xB1 x85 xCE xBF xCE x9F xE0 xA8 xA0 xE0 xA8 xB0 xE0 xA9 xA6 Kayah xEA xA4 x8D xEA xA4 x80 Khmer xE1 xA7 xA1 xE1 xA7 xAA xE0 xBB x90 Latin Subscript xE2 x82 x92 xE2 x82 x80 xEA x93 xB3 xF0 x96 xB9 xA1 xF0 x96 xB9 x9B xF0 x96 xB9 xAF xE1 x80 x9D xE1 x80 x84 xE1 x80 x82 no script
Definition: afscript.h:271
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 xE2 xB2 x9E xE2 xB2 x9F xD0 xBE xD0 x9E xF0 x90 x90 x84 xF0 x90 x90 xAC xE1 x83 x98 xE1 x83 x94 xE1 x83 x90 xE1 xB2 xBF xE2 xB0 x95 xE2 xB1 x85 xCE xBF xCE x9F xE0 xA8 xA0 xE0 xA8 xB0 xE0 xA9 xA6 Kayah xEA xA4 x8D xEA xA4 x80 Khmer HB_SCRIPT_INVALID
Definition: afscript.h:199
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 xE2 xB2 x9E xE2 xB2 x9F xD0 xBE xD0 x9E xF0 x90 x90 x84 xF0 x90 x90 xAC HB_SCRIPT_GEORGIAN
Definition: afscript.h:138
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 xE2 xB2 x9E xE2 xB2 x9F HB_SCRIPT_CYRILLIC
Definition: afscript.h:114
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 xE2 xB2 x9E xE2 xB2 x9F xD0 xBE xD0 x9E xF0 x90 x90 x84 xF0 x90 x90 xAC xE1 x83 x98 xE1 x83 x94 xE1 x83 x90 xE1 xB2 xBF xE2 xB0 x95 xE2 xB1 x85 xCE xBF xCE x9F xE0 xA8 xA0 xE0 xA8 xB0 xE0 xA9 xA6 Kayah xEA xA4 x8D xEA xA4 x80 Khmer xE1 xA7 xA1 xE1 xA7 xAA xE0 xBB x90 Latin Subscript xE2 x82 x92 xE2 x82 x80 xEA x93 xB3 xF0 x96 xB9 xA1 xF0 x96 xB9 x9B xF0 x96 xB9 xAF xE1 x80 x9D xE1 x80 x84 xE1 x80 x82 no Old HB_SCRIPT_OLD_TURKIC
Definition: afscript.h:284
xD9 x84 xD8 xAD xD9 x80 HB_SCRIPT_AVESTAN
Definition: afscript.h:53
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 HB_SCRIPT_COPTIC
Definition: afscript.h:102
HB_SCRIPT_ARABIC
Definition: afscript.h:41
QString str
[2]
QPixmap p2
QPixmap p1
[0]
direction
#define NULL
Definition: ftobjs.h:61
hb_tag_t hb_script_to_iso15924_tag(hb_script_t script)
Definition: hb-common.cc:530
void hb_tag_to_string(hb_tag_t tag, char *buf)
Definition: hb-common.cc:152
hb_script_t hb_script_from_string(const char *str, int len)
Definition: hb-common.cc:513
void hb_variation_to_string(hb_variation_t *variation, char *buf, unsigned int size)
Definition: hb-common.cc:1117
hb_direction_t hb_direction_from_string(const char *str, int len)
Definition: hb-common.cc:187
hb_bool_t hb_feature_from_string(const char *str, int len, hb_feature_t *feature)
Definition: hb-common.cc:931
hb_atomic_int_t _hb_options
Definition: hb-common.cc:71
uint8_t() hb_color_get_red(hb_color_t color)
Definition: hb-common.cc:1168
void hb_feature_to_string(hb_feature_t *feature, char *buf, unsigned int size)
Definition: hb-common.cc:964
const char direction_strings[][4]
Definition: hb-common.cc:163
hb_language_t hb_language_from_string(const char *str, int len)
Definition: hb-common.cc:371
const char * hb_language_to_string(hb_language_t language)
Definition: hb-common.cc:405
uint8_t() hb_color_get_blue(hb_color_t color)
Definition: hb-common.cc:1200
uint8_t() hb_color_get_alpha(hb_color_t color)
Definition: hb-common.cc:1152
#define hb_uselocale(Locale)
Definition: hb-common.cc:55
hb_tag_t hb_tag_from_string(const char *str, int len)
Definition: hb-common.cc:123
uint8_t() hb_color_get_green(hb_color_t color)
Definition: hb-common.cc:1184
void _hb_options_init()
Definition: hb-common.cc:74
void hb_version(unsigned int *major, unsigned int *minor, unsigned int *micro)
Definition: hb-common.cc:663
#define hb_setlocale(Category, Locale)
Definition: hb-common.cc:54
const char * hb_version_string()
Definition: hb-common.cc:682
#define hb_locale_t
Definition: hb-common.cc:53
hb_bool_t hb_version_atleast(unsigned int major, unsigned int minor, unsigned int micro)
Definition: hb-common.cc:702
#define OPTION(name, symbol)
hb_language_t hb_language_get_default()
Definition: hb-common.cc:430
hb_direction_t hb_script_get_horizontal_direction(hb_script_t script)
Definition: hb-common.cc:551
const char * hb_direction_to_string(hb_direction_t direction)
Definition: hb-common.cc:214
hb_script_t hb_script_from_iso15924_tag(hb_tag_t tag)
Definition: hb-common.cc:459
hb_bool_t hb_variation_from_string(const char *str, int len, hb_variation_t *variation)
Definition: hb-common.cc:1043
void const void *obj HB_UNUSED
Definition: hb-debug.hh:180
bool hb_parse_int(const char **pp, const char *end, int *pv, bool whole_buffer)
Definition: hb-number.cc:56
bool hb_parse_double(const char **pp, const char *end, double *pv, bool whole_buffer)
Definition: hb-number.cc:73
#define hb_calloc
Definition: hb.hh:236
#define hb_malloc
Definition: hb.hh:235
#define hb_atexit(_)
Definition: hb.hh:452
#define likely(expr)
Definition: hb.hh:250
#define unlikely(expr)
Definition: hb.hh:251
#define hb_free
Definition: hb.hh:238
short next
Definition: keywords.cpp:454
#define ISALNUM(off)
Definition: md4c.c:316
#define ISALPHA(off)
Definition: md4c.c:313
Language language()
Definition: language.cpp:38
PCRE2_SIZE PRIV() strlen(PCRE2_SPTR str)
void
Definition: png.h:1080
#define assert
Definition: qcborcommon_p.h:63
#define ARRAY_LENGTH(a)
Definition: qkmsdevice.cpp:52
GLint GLfloat GLfloat GLfloat v2
GLsizei const GLfloat * v
[13]
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLuint color
[2]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLfloat GLfloat v1
GLfloat GLfloat GLfloat GLfloat h
const GLubyte * c
Definition: qopenglext.h:12701
GLenum GLsizei len
Definition: qopenglext.h:3292
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
#define HB_LANGUAGE_INVALID
Definition: hb-common.h:324
const struct hb_language_impl_t * hb_language_t
Definition: hb-common.h:309
HB_BEGIN_DECLS typedef int hb_bool_t
Definition: hb-common.h:97
#define HB_TAG(c1, c2, c3, c4)
Definition: hb-common.h:169
uint32_t hb_color_t
Definition: hb-common.h:858
hb_script_t
Definition: hb-common.h:506
@ HB_SCRIPT_MEROITIC_CURSIVE
Definition: hb-common.h:616
@ HB_SCRIPT_MANDAIC
Definition: hb-common.h:613
@ HB_SCRIPT_HAN
Definition: hb-common.h:521
@ HB_SCRIPT_CYPRIOT
Definition: hb-common.h:560
@ HB_SCRIPT_RUNIC
Definition: hb-common.h:545
@ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN
Definition: hb-common.h:600
@ HB_SCRIPT_YEZIDI
Definition: hb-common.h:700
@ HB_SCRIPT_UNKNOWN
Definition: hb-common.h:509
@ HB_SCRIPT_OLD_NORTH_ARABIAN
Definition: hb-common.h:640
@ HB_SCRIPT_OLD_UYGHUR
Definition: hb-common.h:706
@ HB_SCRIPT_MANICHAEAN
Definition: hb-common.h:635
@ HB_SCRIPT_LATIN
Definition: hb-common.h:527
@ HB_SCRIPT_ADLAM
Definition: hb-common.h:660
@ HB_SCRIPT_OLD_ITALIC
Definition: hb-common.h:553
@ HB_SCRIPT_HANGUL
Definition: hb-common.h:520
@ HB_SCRIPT_SYRIAC
Definition: hb-common.h:547
@ HB_SCRIPT_INHERITED
Definition: hb-common.h:508
@ HB_SCRIPT_HEBREW
Definition: hb-common.h:522
@ HB_SCRIPT_LYDIAN
Definition: hb-common.h:588
@ HB_SCRIPT_OLD_SOGDIAN
Definition: hb-common.h:683
@ HB_SCRIPT_PHOENICIAN
Definition: hb-common.h:581
@ HB_SCRIPT_MENDE_KIKAKUI
Definition: hb-common.h:636
@ HB_SCRIPT_NABATAEAN
Definition: hb-common.h:639
@ HB_SCRIPT_IMPERIAL_ARAMAIC
Definition: hb-common.h:598
@ HB_SCRIPT_MEROITIC_HIEROGLYPHS
Definition: hb-common.h:617
@ HB_SCRIPT_HATRAN
Definition: hb-common.h:652
@ HB_SCRIPT_PSALTER_PAHLAVI
Definition: hb-common.h:645
@ HB_SCRIPT_OLD_HUNGARIAN
Definition: hb-common.h:654
@ HB_SCRIPT_KHAROSHTHI
Definition: hb-common.h:571
@ HB_SCRIPT_NKO
Definition: hb-common.h:579
@ HB_SCRIPT_SOGDIAN
Definition: hb-common.h:684
@ HB_SCRIPT_THAANA
Definition: hb-common.h:548
@ HB_SCRIPT_OLD_SOUTH_ARABIAN
Definition: hb-common.h:605
@ HB_SCRIPT_HANIFI_ROHINGYA
Definition: hb-common.h:680
@ HB_SCRIPT_PALMYRENE
Definition: hb-common.h:643
@ HB_SCRIPT_ELYMAIC
Definition: hb-common.h:689
@ HB_SCRIPT_SAMARITAN
Definition: hb-common.h:607
@ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI
Definition: hb-common.h:599
@ HB_SCRIPT_CHORASMIAN
Definition: hb-common.h:697
#define HB_FEATURE_GLOBAL_END
Definition: hb-common.h:794
uint32_t hb_tag_t
Definition: hb-common.h:157
#define HB_TAG_NONE
Definition: hb-common.h:187
hb_direction_t
Definition: hb-common.h:229
@ HB_DIRECTION_INVALID
Definition: hb-common.h:230
@ HB_DIRECTION_RTL
Definition: hb-common.h:232
@ HB_DIRECTION_LTR
Definition: hb-common.h:231
#define HB_FEATURE_GLOBAL_START
Definition: hb-common.h:784
#define HB_VERSION_MINOR
Definition: hb-version.h:50
#define HB_VERSION_ATLEAST(major, minor, micro)
Definition: hb-version.h:74
#define HB_VERSION_MAJOR
Definition: hb-version.h:44
#define HB_VERSION_STRING
Definition: hb-version.h:63
#define HB_VERSION_MICRO
Definition: hb-version.h:56
QGraphicsItem * item
void set_relaxed(int v_)
Definition: hb-atomic.hh:149
bool cmpexch(const T *old, T *new_) const
Definition: hb-atomic.hh:171
unsigned int end
Definition: hb-common.h:815
unsigned int start
Definition: hb-common.h:814
hb_tag_t tag
Definition: hb-common.h:812
uint32_t value
Definition: hb-common.h:813
struct hb_language_item_t * next
Definition: hb-common.cc:275
hb_language_t lang
Definition: hb-common.cc:276
hb_language_item_t & operator=(const char *s)
Definition: hb-common.cc:281
bool operator==(const char *s) const
Definition: hb-common.cc:278
static Stored * create()
static void destroy(Stored *p)
static const Stored * get_null()
hb_tag_t tag
Definition: hb-common.h:838
XmlOutput::xml_output tag(const QString &name)
Definition: xmloutput.h:154