15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2009 Red Hat, Inc. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2012 Google, Inc. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This is part of HarfBuzz, a text shaping library. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Red Hat Author(s): Behdad Esfahbod 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-private.hh" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-shaper-private.hh" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-shape-plan-private.hh" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-buffer-private.hh" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-font-private.hh" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static bool 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)parse_space (const char **pp, const char *end) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (*pp < end && ISSPACE (**pp)) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*pp)++; 4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static bool 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)parse_char (const char **pp, const char *end, char c) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_space (pp, end); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*pp == end || **pp != c) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*pp)++; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static bool 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)parse_uint (const char **pp, const char *end, unsigned int *pv) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[32]; 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) strncpy (buf, *pp, len); 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buf[len] = '\0'; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p = buf; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *pend = p; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int v; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /* Intentionally use strtol instead of strtoul, such that 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * -1 turns into "big number"... */ 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) errno = 0; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = strtol (p, &pend, 0); 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (errno || p == pend) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pv = v; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pp += pend - p; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static bool 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)parse_bool (const char **pp, const char *end, unsigned int *pv) 8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles){ 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) parse_space (pp, end); 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const char *p = *pp; 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (*pp < end && ISALPHA(**pp)) 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (*pp)++; 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) /* CSS allows on/off as aliases 1/0. */ 9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (*pp - p == 2 || 0 == strncmp (p, "on", 2)) 9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *pv = 1; 9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) else if (*pp - p == 3 || 0 == strncmp (p, "off", 2)) 9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *pv = 0; 9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) else 9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static bool 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parse_char (pp, end, '-')) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->value = 0; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_char (pp, end, '+'); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->value = 1; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static bool 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_space (pp, end); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) char quote = 0; 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (*pp < end && (**pp == '\'' || **pp == '"')) 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) { 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) quote = **pp; 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (*pp)++; 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const char *p = *pp; 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (*pp < end && ISALNUM(**pp)) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*pp)++; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (p == *pp || *pp - p > 4) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->tag = hb_tag_from_string (p, *pp - p); 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (quote) 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) { 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) /* CSS expects exactly four bytes. And we only allow quotations for 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * CSS compatibility. So, enforce the length. */ 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (*pp - p != 4) 14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (*pp == end || **pp != quote) 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (*pp)++; 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static bool 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_space (pp, end); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool has_start; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->start = 0; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->end = (unsigned int) -1; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parse_char (pp, end, '[')) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_start = parse_uint (pp, end, &feature->start); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parse_char (pp, end, ':')) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_uint (pp, end, &feature->end); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_start) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature->end = feature->start + 1; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return parse_char (pp, end, ']'); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static bool 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool had_equal = parse_char (pp, end, '='); 17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool had_value = parse_uint (pp, end, &feature->value) || 18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) parse_bool (pp, end, &feature->value); 18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) /* CSS doesn't use equal-sign between tag and value. 18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * If there was an equal-sign, then there *must* be a value. 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * A value without an eqaul-sign is ok, but not required. */ 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return !had_equal || had_value; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static bool 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return parse_feature_value_prefix (pp, end, feature) && 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_feature_tag (pp, end, feature) && 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_feature_indices (pp, end, feature) && 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_feature_value_postfix (pp, end, feature) && 19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) parse_space (pp, end) && 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pp == end; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/** 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * hb_feature_from_string: 201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @str: (array length=len): 202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @len: 20303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * @feature: (out) (allow-none): 204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Return value: 208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Since: 1.0 210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) **/ 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_feature_from_string (const char *str, int len, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_feature_t *feature) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) hb_feature_t feat; 21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < 0) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = strlen (str); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (likely (parse_one_feature (&str, str + len, &feat))) 22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) { 22203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (feature) 22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *feature = feat; 22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (feature) 22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) memset (feature, 0, sizeof (*feature)); 22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/** 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * hb_feature_to_string: 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @feature: 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @buf: (array length=size): 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @size: 237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Since: 1.0 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) **/ 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_feature_to_string (hb_feature_t *feature, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *buf, unsigned int size) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (!size)) return; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char s[128]; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int len = 0; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (feature->value == 0) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s[len++] = '-'; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_tag_to_string (feature->tag, s + len); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len += 4; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (len && s[len - 1] == ' ') 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len--; 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (feature->start != 0 || feature->end != (unsigned int) -1) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s[len++] = '['; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (feature->start) 26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (feature->end != feature->start + 1) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s[len++] = ':'; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (feature->end != (unsigned int) -1) 26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s[len++] = ']'; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (feature->value > 1) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s[len++] = '='; 27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert (len < ARRAY_LENGTH (s)); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = MIN (len, size - 1); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy (buf, s, len); 276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buf[len] = '\0'; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char **static_shaper_list; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static inline 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void free_static_shaper_list (void) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free (static_shaper_list); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/** 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * hb_shape_list_shapers: 290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Return value: (transfer none): 294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Since: 1.0 296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) **/ 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char ** 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_shape_list_shapers (void) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)retry: 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (!shaper_list)) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Not found; allocate one. */ 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *)); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (!shaper_list)) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char *nil_shaper_list[] = {NULL}; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nil_shaper_list; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const hb_shaper_pair_t *shapers = _hb_shapers_get (); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int i; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < HB_SHAPERS_COUNT; i++) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shaper_list[i] = shapers[i].name; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shaper_list[i] = NULL; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free (shaper_list); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto retry; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#ifdef HB_USE_ATEXIT 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) atexit (free_static_shaper_list); /* First person registers atexit() callback. */ 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shaper_list; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/** 333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * hb_shape_full: 334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @font: a font. 335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @buffer: a buffer. 336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @features: (array length=num_features): 337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @num_features: 338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @shaper_list: (array zero-terminated=1): 339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Return value: 343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Since: 1.0 345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) **/ 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_shape_full (hb_font_t *font, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_buffer_t *buffer, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const hb_feature_t *features, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int num_features, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char * const *shaper_list) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (!buffer->len)) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_shape_plan_destroy (shape_plan); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (res) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return res; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/** 368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * hb_shape: 369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @font: a font. 370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @buffer: a buffer. 371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @features: (array length=num_features): 372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @num_features: 373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Since: 1.0 377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) **/ 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_shape (hb_font_t *font, 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_buffer_t *buffer, 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const hb_feature_t *features, 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int num_features) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_shape_full (font, buffer, features, num_features, NULL); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 386