hb-shape.cc revision 60cb18a5dea2d30793f89e80995bb729c014864a
115232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod/* 22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2009 Red Hat, Inc. 3e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod * Copyright © 2012 Google, Inc. 415232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * 5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod * This is part of HarfBuzz, a text shaping library. 615232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * 715232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * Permission is hereby granted, without written agreement and without 815232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 915232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * software and its documentation for any purpose, provided that the 1015232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * above copyright notice and the following two paragraphs appear in 1115232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * all copies of this software. 1215232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * 1315232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1415232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1515232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1615232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1715232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * DAMAGE. 1815232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * 1915232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 2015232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 2115232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 2215232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 2315232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 2415232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * 2515232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod 26e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod * Google Author(s): Behdad Esfahbod 2715232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod */ 2815232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod 29c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh" 3015232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod 31027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#include "hb-shaper-private.hh" 325b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod#include "hb-shape-plan-private.hh" 3322da7fd94d6318c52df69d70470a85464ffc533dBehdad Esfahbod#include "hb-buffer-private.hh" 345b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod#include "hb-font-private.hh" 352f50d873680ce0a43b6ec79df1ac946b91f31e63Behdad Esfahbod 3602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod 37e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic void 38e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_space (const char **pp, const char *end) 39e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 40e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod char c; 41e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod while (*pp < end && (c = **pp, ISSPACE (c))) 42e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod (*pp)++; 43e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 44e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 45e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t 46e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_char (const char **pp, const char *end, char c) 47e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 48e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod parse_space (pp, end); 49e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 50e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (*pp == end || **pp != c) 51e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return false; 52e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 53e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod (*pp)++; 54e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return true; 55e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 56e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 57e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t 58e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_uint (const char **pp, const char *end, unsigned int *pv) 59e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 60e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod char buf[32]; 61847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); 62847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod strncpy (buf, *pp, len); 63847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod buf[len] = '\0'; 64e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 65e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod char *p = buf; 66e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod char *pend = p; 67e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod unsigned int v; 68e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 698da51112696ec8641d7dd9184b7ab1dd48458813Behdad Esfahbod /* Intentionally use strtol instead of strtoul, such that 708da51112696ec8641d7dd9184b7ab1dd48458813Behdad Esfahbod * -1 turns into "big number"... */ 71847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod errno = 0; 72e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod v = strtol (p, &pend, 0); 73847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod if (errno || p == pend) 74e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return false; 75e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 76e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod *pv = v; 77e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod *pp += pend - p; 78e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return true; 79e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 80e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 81e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t 8260cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbodparse_bool (const char **pp, const char *end, unsigned int *pv) 8360cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod{ 8460cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod parse_space (pp, end); 8560cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod 8660cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod const char *p = *pp; 8760cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod while (*pp < end && ISALPHA(**pp)) 8860cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod (*pp)++; 8960cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod 9060cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod /* CSS allows on/off as aliases 1/0. */ 9160cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod if (*pp - p == 2 || 0 == strncmp (p, "on", 2)) 9260cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod *pv = 1; 9360cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod else if (*pp - p == 3 || 0 == strncmp (p, "off", 2)) 9460cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod *pv = 0; 9560cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod else 9660cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod return false; 9760cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod 9860cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod return true; 9960cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod} 10060cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod 10160cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbodstatic hb_bool_t 102e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) 103e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 104e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (parse_char (pp, end, '-')) 105e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod feature->value = 0; 106e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod else { 107e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod parse_char (pp, end, '+'); 108e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod feature->value = 1; 109e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod } 110e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 111e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return true; 112e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 113e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 114e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t 115e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) 116e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 1172ee5f665ded86147acedc400153c0b3a90fe07c6Behdad Esfahbod parse_space (pp, end); 1182ee5f665ded86147acedc400153c0b3a90fe07c6Behdad Esfahbod 119e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod const char *p = *pp; 120e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod char c; 121e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 122e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod while (*pp < end && (c = **pp, ISALNUM(c))) 123e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod (*pp)++; 124e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 125f4fe9baefdb7e0ff9946f88b6f4b55738fa30cdfBehdad Esfahbod if (p == *pp || *pp - p > 4) 126e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return false; 127e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 128e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod feature->tag = hb_tag_from_string (p, *pp - p); 129e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return true; 130e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 131e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 132e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t 133e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) 134e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 135e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod parse_space (pp, end); 136e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 137e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod hb_bool_t has_start; 138e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 139e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod feature->start = 0; 140e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod feature->end = (unsigned int) -1; 141e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 142e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (!parse_char (pp, end, '[')) 143e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return true; 144e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 145e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod has_start = parse_uint (pp, end, &feature->start); 146e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 147e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (parse_char (pp, end, ':')) { 148e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod parse_uint (pp, end, &feature->end); 149e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod } else { 150e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (has_start) 151e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod feature->end = feature->start + 1; 152e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod } 153e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 154e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return parse_char (pp, end, ']'); 155e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 156e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 157e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t 158e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) 159e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 160e15fa7a8cffbe6a67b1048d7b87b7df77d8b1686Behdad Esfahbod bool had_equal = parse_char (pp, end, '='); 16160cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod bool had_value = parse_uint (pp, end, &feature->value) || 16260cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod parse_bool (pp, end, &feature->value); 16360cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod /* CSS doesn't use equal-sign between tag and value. 16460cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod * If there was an equal-sign, then there *must* be a value. 165e15fa7a8cffbe6a67b1048d7b87b7df77d8b1686Behdad Esfahbod * A value without an eqaul-sign is ok, but not required. */ 166e15fa7a8cffbe6a67b1048d7b87b7df77d8b1686Behdad Esfahbod return !had_equal || had_value; 167e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 168e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 169e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 170e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t 171e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_one_feature (const char **pp, const char *end, hb_feature_t *feature) 172e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 173e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return parse_feature_value_prefix (pp, end, feature) && 174e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod parse_feature_tag (pp, end, feature) && 175e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod parse_feature_indices (pp, end, feature) && 176e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod parse_feature_value_postfix (pp, end, feature) && 177e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod *pp == end; 178e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 179e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 180288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/** 181288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_feature_from_string: 182288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @str: (array length=len): 183288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @len: 184288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @feature: (out): 185288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 186288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 187288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 188288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Return value: 189288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 190288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0 191288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/ 192e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodhb_bool_t 193e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodhb_feature_from_string (const char *str, int len, 194e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod hb_feature_t *feature) 195e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 196e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (len < 0) 197e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod len = strlen (str); 198e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 199e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod return parse_one_feature (&str, str + len, feature); 200e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 201e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 202288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/** 203288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_feature_to_string: 204288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @feature: 205288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @buf: (array length=size): 206288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @size: 207288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 208288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 209288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 210288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0 211288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/ 212e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodvoid 213e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodhb_feature_to_string (hb_feature_t *feature, 214e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod char *buf, unsigned int size) 215e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 216e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (unlikely (!size)) return; 217e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 218e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod char s[128]; 219e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod unsigned int len = 0; 220e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (feature->value == 0) 221e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod s[len++] = '-'; 222e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod hb_tag_to_string (feature->tag, s + len); 223e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod len += 4; 224e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod while (len && s[len - 1] == ' ') 225e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod len--; 2261c7e55511a870f2689680ca8f977e00879f3b3e3Behdad Esfahbod if (feature->start != 0 || feature->end != (unsigned int) -1) 227e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod { 228e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod s[len++] = '['; 229e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (feature->start) 23038b8b40526a85f33521542e24d1e0c82588efc85Behdad Esfahbod len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->start)); 231e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (feature->end != feature->start + 1) { 232e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod s[len++] = ':'; 233e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (feature->end != (unsigned int) -1) 23438b8b40526a85f33521542e24d1e0c82588efc85Behdad Esfahbod len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->end)); 235e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod } 236e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod s[len++] = ']'; 237e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod } 238e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod if (feature->value > 1) 239e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod { 240e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod s[len++] = '='; 24138b8b40526a85f33521542e24d1e0c82588efc85Behdad Esfahbod len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->value)); 242e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod } 243e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod assert (len < ARRAY_LENGTH (s)); 244e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod len = MIN (len, size - 1); 245e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod memcpy (buf, s, len); 2467235f33f9e5e031622a00a84f4b2e98f16803579Behdad Esfahbod buf[len] = '\0'; 247e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 248e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 249e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 250f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbodstatic const char **static_shaper_list; 251f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod 252e9171af55cc6a402eb20db4ea74c86a0b1e70e85Behdad Esfahbodstatic inline 253f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbodvoid free_static_shaper_list (void) 254f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod{ 255f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod free (static_shaper_list); 256f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod} 2579da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbod 258288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/** 259288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_shape_list_shapers: 260288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 261288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 262288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 263288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Return value: (transfer none): 264288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 265288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0 266288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/ 2679da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbodconst char ** 2689da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbodhb_shape_list_shapers (void) 2699da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbod{ 270f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbodretry: 271f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list); 272f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod 273f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod if (unlikely (!shaper_list)) 274f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod { 275f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod /* Not found; allocate one. */ 276bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *)); 277f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod if (unlikely (!shaper_list)) { 278f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod static const char *nil_shaper_list[] = {NULL}; 279f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod return nil_shaper_list; 280f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod } 281f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod 282bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod const hb_shaper_pair_t *shapers = _hb_shapers_get (); 283f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod unsigned int i; 284bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod for (i = 0; i < HB_SHAPERS_COUNT; i++) 285f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod shaper_list[i] = shapers[i].name; 286f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod shaper_list[i] = NULL; 287f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod 288f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) { 289f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod free (shaper_list); 290f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod goto retry; 291f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod } 292f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod 293f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod#ifdef HAVE_ATEXIT 294f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod atexit (free_static_shaper_list); /* First person registers atexit() callback. */ 295f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod#endif 296f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod } 297f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod 298f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod return shaper_list; 2999da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbod} 30002aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod 301f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod 302288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/** 303288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_shape_full: 304288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @font: a font. 305288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @buffer: a buffer. 306288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @features: (array length=num_features): 307288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @num_features: 308288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @shaper_list: (array zero-terminated=1): 309288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 310288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 311288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 312288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Return value: 313288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 314288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0 315288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/ 31602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbodhb_bool_t 3170501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbodhb_shape_full (hb_font_t *font, 3180501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbod hb_buffer_t *buffer, 3190501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbod const hb_feature_t *features, 3200501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbod unsigned int num_features, 3210501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbod const char * const *shaper_list) 3223286fc0e9adc3f2874c9409e7fdb09e4d2b7dda1Behdad Esfahbod{ 323b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod if (unlikely (!buffer->len)) 324b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod return true; 325b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod 32696fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); 32796fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod 3282f87cebe1062c7007021ebd05c1664e60da80825Behdad Esfahbod hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list); 329c32c096a429da3e64896cf42ff5ab8c775d3c2ecBehdad Esfahbod hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features); 330c32c096a429da3e64896cf42ff5ab8c775d3c2ecBehdad Esfahbod hb_shape_plan_destroy (shape_plan); 33196fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod 33296fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod if (res) 33396fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; 334c32c096a429da3e64896cf42ff5ab8c775d3c2ecBehdad Esfahbod return res; 3353286fc0e9adc3f2874c9409e7fdb09e4d2b7dda1Behdad Esfahbod} 3363ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod 337288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/** 338288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_shape: 339288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @font: a font. 340288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @buffer: a buffer. 341288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @features: (array length=num_features): 342288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @num_features: 343288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 344288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 345288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * 346288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0 347288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/ 3483ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbodvoid 3493ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbodhb_shape (hb_font_t *font, 3503ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod hb_buffer_t *buffer, 3513ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod const hb_feature_t *features, 3523ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod unsigned int num_features) 3533ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod{ 3546bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod hb_shape_full (font, buffer, features, num_features, NULL); 3553ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod} 356