src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape.cc
changeset 48274 51772bf1fb0c
parent 47216 71c04702a3d5
child 50826 f5b95be8b6e2
equal deleted inserted replaced
48273:e2065f7505eb 48274:51772bf1fb0c
    43  * which are sequences of Unicode characters that use the same font and have
    43  * which are sequences of Unicode characters that use the same font and have
    44  * the same text direction, script and language. After shaping the buffer
    44  * the same text direction, script and language. After shaping the buffer
    45  * contains the output glyphs and their positions.
    45  * contains the output glyphs and their positions.
    46  **/
    46  **/
    47 
    47 
    48 static bool
       
    49 parse_space (const char **pp, const char *end)
       
    50 {
       
    51   while (*pp < end && ISSPACE (**pp))
       
    52     (*pp)++;
       
    53   return true;
       
    54 }
       
    55 
       
    56 static bool
       
    57 parse_char (const char **pp, const char *end, char c)
       
    58 {
       
    59   parse_space (pp, end);
       
    60 
       
    61   if (*pp == end || **pp != c)
       
    62     return false;
       
    63 
       
    64   (*pp)++;
       
    65   return true;
       
    66 }
       
    67 
       
    68 static bool
       
    69 parse_uint (const char **pp, const char *end, unsigned int *pv)
       
    70 {
       
    71   char buf[32];
       
    72   unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
       
    73   strncpy (buf, *pp, len);
       
    74   buf[len] = '\0';
       
    75 
       
    76   char *p = buf;
       
    77   char *pend = p;
       
    78   unsigned int v;
       
    79 
       
    80   /* Intentionally use strtol instead of strtoul, such that
       
    81    * -1 turns into "big number"... */
       
    82   errno = 0;
       
    83   v = strtol (p, &pend, 0);
       
    84   if (errno || p == pend)
       
    85     return false;
       
    86 
       
    87   *pv = v;
       
    88   *pp += pend - p;
       
    89   return true;
       
    90 }
       
    91 
       
    92 static bool
       
    93 parse_bool (const char **pp, const char *end, unsigned int *pv)
       
    94 {
       
    95   parse_space (pp, end);
       
    96 
       
    97   const char *p = *pp;
       
    98   while (*pp < end && ISALPHA(**pp))
       
    99     (*pp)++;
       
   100 
       
   101   /* CSS allows on/off as aliases 1/0. */
       
   102   if (*pp - p == 2 || 0 == strncmp (p, "on", 2))
       
   103     *pv = 1;
       
   104   else if (*pp - p == 3 || 0 == strncmp (p, "off", 2))
       
   105     *pv = 0;
       
   106   else
       
   107     return false;
       
   108 
       
   109   return true;
       
   110 }
       
   111 
       
   112 static bool
       
   113 parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
       
   114 {
       
   115   if (parse_char (pp, end, '-'))
       
   116     feature->value = 0;
       
   117   else {
       
   118     parse_char (pp, end, '+');
       
   119     feature->value = 1;
       
   120   }
       
   121 
       
   122   return true;
       
   123 }
       
   124 
       
   125 static bool
       
   126 parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
       
   127 {
       
   128   parse_space (pp, end);
       
   129 
       
   130   char quote = 0;
       
   131 
       
   132   if (*pp < end && (**pp == '\'' || **pp == '"'))
       
   133   {
       
   134     quote = **pp;
       
   135     (*pp)++;
       
   136   }
       
   137 
       
   138   const char *p = *pp;
       
   139   while (*pp < end && ISALNUM(**pp))
       
   140     (*pp)++;
       
   141 
       
   142   if (p == *pp || *pp - p > 4)
       
   143     return false;
       
   144 
       
   145   feature->tag = hb_tag_from_string (p, *pp - p);
       
   146 
       
   147   if (quote)
       
   148   {
       
   149     /* CSS expects exactly four bytes.  And we only allow quotations for
       
   150      * CSS compatibility.  So, enforce the length. */
       
   151      if (*pp - p != 4)
       
   152        return false;
       
   153     if (*pp == end || **pp != quote)
       
   154       return false;
       
   155     (*pp)++;
       
   156   }
       
   157 
       
   158   return true;
       
   159 }
       
   160 
       
   161 static bool
       
   162 parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
       
   163 {
       
   164   parse_space (pp, end);
       
   165 
       
   166   bool has_start;
       
   167 
       
   168   feature->start = 0;
       
   169   feature->end = (unsigned int) -1;
       
   170 
       
   171   if (!parse_char (pp, end, '['))
       
   172     return true;
       
   173 
       
   174   has_start = parse_uint (pp, end, &feature->start);
       
   175 
       
   176   if (parse_char (pp, end, ':')) {
       
   177     parse_uint (pp, end, &feature->end);
       
   178   } else {
       
   179     if (has_start)
       
   180       feature->end = feature->start + 1;
       
   181   }
       
   182 
       
   183   return parse_char (pp, end, ']');
       
   184 }
       
   185 
       
   186 static bool
       
   187 parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
       
   188 {
       
   189   bool had_equal = parse_char (pp, end, '=');
       
   190   bool had_value = parse_uint (pp, end, &feature->value) ||
       
   191                    parse_bool (pp, end, &feature->value);
       
   192   /* CSS doesn't use equal-sign between tag and value.
       
   193    * If there was an equal-sign, then there *must* be a value.
       
   194    * A value without an eqaul-sign is ok, but not required. */
       
   195   return !had_equal || had_value;
       
   196 }
       
   197 
       
   198 
       
   199 static bool
       
   200 parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
       
   201 {
       
   202   return parse_feature_value_prefix (pp, end, feature) &&
       
   203          parse_feature_tag (pp, end, feature) &&
       
   204          parse_feature_indices (pp, end, feature) &&
       
   205          parse_feature_value_postfix (pp, end, feature) &&
       
   206          parse_space (pp, end) &&
       
   207          *pp == end;
       
   208 }
       
   209 
       
   210 /**
       
   211  * hb_feature_from_string:
       
   212  * @str: (array length=len) (element-type uint8_t): a string to parse
       
   213  * @len: length of @str, or -1 if string is %NULL terminated
       
   214  * @feature: (out): the #hb_feature_t to initialize with the parsed values
       
   215  *
       
   216  * Parses a string into a #hb_feature_t.
       
   217  *
       
   218  * TODO: document the syntax here.
       
   219  *
       
   220  * Return value:
       
   221  * %true if @str is successfully parsed, %false otherwise.
       
   222  *
       
   223  * Since: 0.9.5
       
   224  **/
       
   225 hb_bool_t
       
   226 hb_feature_from_string (const char *str, int len,
       
   227                         hb_feature_t *feature)
       
   228 {
       
   229   hb_feature_t feat;
       
   230 
       
   231   if (len < 0)
       
   232     len = strlen (str);
       
   233 
       
   234   if (likely (parse_one_feature (&str, str + len, &feat)))
       
   235   {
       
   236     if (feature)
       
   237       *feature = feat;
       
   238     return true;
       
   239   }
       
   240 
       
   241   if (feature)
       
   242     memset (feature, 0, sizeof (*feature));
       
   243   return false;
       
   244 }
       
   245 
       
   246 /**
       
   247  * hb_feature_to_string:
       
   248  * @feature: an #hb_feature_t to convert
       
   249  * @buf: (array length=size) (out): output string
       
   250  * @size: the allocated size of @buf
       
   251  *
       
   252  * Converts a #hb_feature_t into a %NULL-terminated string in the format
       
   253  * understood by hb_feature_from_string(). The client in responsible for
       
   254  * allocating big enough size for @buf, 128 bytes is more than enough.
       
   255  *
       
   256  * Since: 0.9.5
       
   257  **/
       
   258 void
       
   259 hb_feature_to_string (hb_feature_t *feature,
       
   260                       char *buf, unsigned int size)
       
   261 {
       
   262   if (unlikely (!size)) return;
       
   263 
       
   264   char s[128];
       
   265   unsigned int len = 0;
       
   266   if (feature->value == 0)
       
   267     s[len++] = '-';
       
   268   hb_tag_to_string (feature->tag, s + len);
       
   269   len += 4;
       
   270   while (len && s[len - 1] == ' ')
       
   271     len--;
       
   272   if (feature->start != 0 || feature->end != (unsigned int) -1)
       
   273   {
       
   274     s[len++] = '[';
       
   275     if (feature->start)
       
   276       len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
       
   277     if (feature->end != feature->start + 1) {
       
   278       s[len++] = ':';
       
   279       if (feature->end != (unsigned int) -1)
       
   280         len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
       
   281     }
       
   282     s[len++] = ']';
       
   283   }
       
   284   if (feature->value > 1)
       
   285   {
       
   286     s[len++] = '=';
       
   287     len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
       
   288   }
       
   289   assert (len < ARRAY_LENGTH (s));
       
   290   len = MIN (len, size - 1);
       
   291   memcpy (buf, s, len);
       
   292   buf[len] = '\0';
       
   293 }
       
   294 
       
   295 
       
   296 static const char **static_shaper_list;
    48 static const char **static_shaper_list;
   297 
    49 
   298 #ifdef HB_USE_ATEXIT
    50 #ifdef HB_USE_ATEXIT
   299 static
    51 static
   300 void free_static_shaper_list (void)
    52 void free_static_shaper_list (void)
   322   if (unlikely (!shaper_list))
    74   if (unlikely (!shaper_list))
   323   {
    75   {
   324     /* Not found; allocate one. */
    76     /* Not found; allocate one. */
   325     shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
    77     shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
   326     if (unlikely (!shaper_list)) {
    78     if (unlikely (!shaper_list)) {
   327       static const char *nil_shaper_list[] = {NULL};
    79       static const char *nil_shaper_list[] = {nullptr};
   328       return nil_shaper_list;
    80       return nil_shaper_list;
   329     }
    81     }
   330 
    82 
   331     const hb_shaper_pair_t *shapers = _hb_shapers_get ();
    83     const hb_shaper_pair_t *shapers = _hb_shapers_get ();
   332     unsigned int i;
    84     unsigned int i;
   333     for (i = 0; i < HB_SHAPERS_COUNT; i++)
    85     for (i = 0; i < HB_SHAPERS_COUNT; i++)
   334       shaper_list[i] = shapers[i].name;
    86       shaper_list[i] = shapers[i].name;
   335     shaper_list[i] = NULL;
    87     shaper_list[i] = nullptr;
   336 
    88 
   337     if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) {
    89     if (!hb_atomic_ptr_cmpexch (&static_shaper_list, nullptr, shaper_list)) {
   338       free (shaper_list);
    90       free (shaper_list);
   339       goto retry;
    91       goto retry;
   340     }
    92     }
   341 
    93 
   342 #ifdef HB_USE_ATEXIT
    94 #ifdef HB_USE_ATEXIT
   360  *
   112  *
   361  * See hb_shape() for details. If @shaper_list is not %NULL, the specified
   113  * See hb_shape() for details. If @shaper_list is not %NULL, the specified
   362  * shapers will be used in the given order, otherwise the default shapers list
   114  * shapers will be used in the given order, otherwise the default shapers list
   363  * will be used.
   115  * will be used.
   364  *
   116  *
   365  * Return value: %FALSE if all shapers failed, %TRUE otherwise
   117  * Return value: false if all shapers failed, true otherwise
   366  *
   118  *
   367  * Since: 0.9.2
   119  * Since: 0.9.2
   368  **/
   120  **/
   369 hb_bool_t
   121 hb_bool_t
   370 hb_shape_full (hb_font_t          *font,
   122 hb_shape_full (hb_font_t          *font,
   403 hb_shape (hb_font_t           *font,
   155 hb_shape (hb_font_t           *font,
   404           hb_buffer_t         *buffer,
   156           hb_buffer_t         *buffer,
   405           const hb_feature_t  *features,
   157           const hb_feature_t  *features,
   406           unsigned int         num_features)
   158           unsigned int         num_features)
   407 {
   159 {
   408   hb_shape_full (font, buffer, features, num_features, NULL);
   160   hb_shape_full (font, buffer, features, num_features, nullptr);
   409 }
   161 }