183f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod/* 22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2009,2010 Red Hat, Inc. 3cad3821f3d5b68d490b0728bd37bd57428ec809cBehdad Esfahbod * Copyright © 2011,2012 Google, Inc. 483f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * 583f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * This is part of HarfBuzz, a text shaping library. 683f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * 783f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * Permission is hereby granted, without written agreement and without 883f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 983f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * software and its documentation for any purpose, provided that the 1083f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * above copyright notice and the following two paragraphs appear in 1183f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * all copies of this software. 1283f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * 1383f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1483f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1583f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1683f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1783f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * DAMAGE. 1883f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * 1983f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 2083f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 2183f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 2283f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 2383f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 2483f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * 2583f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod * Red Hat Author(s): Behdad Esfahbod 262409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Google Author(s): Behdad Esfahbod 2783f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod */ 2883f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod 29c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh" 3083f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod 31b8d6183ebc4697a434776cf2aec7857d63a7d881Behdad Esfahbod#include "hb-mutex-private.hh" 32218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod#include "hb-object-private.hh" 33b8d6183ebc4697a434776cf2aec7857d63a7d881Behdad Esfahbod 3434fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbod#include <locale.h> 3534fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbod 36acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 37bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod/* hb_options_t */ 38bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 39bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodhb_options_union_t _hb_options; 40bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 41bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodvoid 42bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod_hb_options_init (void) 43bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod{ 44bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod hb_options_union_t u; 45bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod u.i = 0; 46bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod u.opts.initialized = 1; 47bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 48bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod char *c = getenv ("HB_OPTIONS"); 49bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible"); 50bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 51bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod /* This is idempotent and threadsafe. */ 52bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod _hb_options = u; 53bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod} 54bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 55acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 568e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod/* hb_tag_t */ 578e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 5870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 5970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_tag_from_string: 60a394bb66707184c995fe2d08c80e98220e6ec0b0Khaled Hosny * @str: (array length=len) (element-type uint8_t): 6170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @len: 6270303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 6370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 6470303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 6570303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Return value: 6670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 67b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 6870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 6983f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbodhb_tag_t 7070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbodhb_tag_from_string (const char *str, int len) 7183f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod{ 7283f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod char tag[4]; 7383f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod unsigned int i; 7483f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod 7570303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod if (!str || !len || !*str) 767ff7401c9237cda661869c1cb196d685706ac4e9Behdad Esfahbod return HB_TAG_NONE; 777ff7401c9237cda661869c1cb196d685706ac4e9Behdad Esfahbod 784c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbod if (len < 0 || len > 4) 794c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbod len = 4; 8070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod for (i = 0; i < (unsigned) len && str[i]; i++) 8170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod tag[i] = str[i]; 8283f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod for (; i < 4; i++) 8383f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod tag[i] = ' '; 8483f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod 8507233581c9d953708d3c020907c42b8b89472b89Behdad Esfahbod return HB_TAG_CHAR4 (tag); 8683f34677bcbc6bb194940407b0fcb23575650e3dBehdad Esfahbod} 87acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 8870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 8970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_tag_to_string: 9070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @tag: 91e4d451ee55a57e1231b4076fcd1e87994f6b9528Khaled Hosny * @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t): 9270303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 9370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 9470303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 9501c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.5 9670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 97e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodvoid 98e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodhb_tag_to_string (hb_tag_t tag, char *buf) 99e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{ 100e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod buf[0] = (char) (uint8_t) (tag >> 24); 101e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod buf[1] = (char) (uint8_t) (tag >> 16); 102e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod buf[2] = (char) (uint8_t) (tag >> 8); 103e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod buf[3] = (char) (uint8_t) (tag >> 0); 104e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod} 105e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod 106acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 10739a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod/* hb_direction_t */ 10839a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod 10939a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbodconst char direction_strings[][4] = { 11039a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod "ltr", 11139a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod "rtl", 11239a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod "ttb", 11339a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod "btt" 11439a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod}; 11539a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod 11670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 11770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_direction_from_string: 118a394bb66707184c995fe2d08c80e98220e6ec0b0Khaled Hosny * @str: (array length=len) (element-type uint8_t): 11970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @len: 12070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 12170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 12270303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 12370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Return value: 12470303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 125b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 12670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 12739a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbodhb_direction_t 1284c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbodhb_direction_from_string (const char *str, int len) 12939a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod{ 1304c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbod if (unlikely (!str || !len || !*str)) 13139a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod return HB_DIRECTION_INVALID; 13239a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod 13339a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod /* Lets match loosely: just match the first letter, such that 13439a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod * all of "ltr", "left-to-right", etc work! 13539a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod */ 13639a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod char c = TOLOWER (str[0]); 13739a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod for (unsigned int i = 0; i < ARRAY_LENGTH (direction_strings); i++) 13839a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod if (c == direction_strings[i][0]) 1394bf90f648313e35d21b427a956aa1fe762bae757Behdad Esfahbod return (hb_direction_t) (HB_DIRECTION_LTR + i); 14039a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod 14139a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod return HB_DIRECTION_INVALID; 14239a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod} 14339a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod 14470303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 14570303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_direction_to_string: 14670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @direction: 14770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 14870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 14970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 15070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Return value: (transfer none): 15170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 152b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 15370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 15439a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbodconst char * 15539a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbodhb_direction_to_string (hb_direction_t direction) 15639a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod{ 1574bf90f648313e35d21b427a956aa1fe762bae757Behdad Esfahbod if (likely ((unsigned int) (direction - HB_DIRECTION_LTR) 1584bf90f648313e35d21b427a956aa1fe762bae757Behdad Esfahbod < ARRAY_LENGTH (direction_strings))) 1594bf90f648313e35d21b427a956aa1fe762bae757Behdad Esfahbod return direction_strings[direction - HB_DIRECTION_LTR]; 16039a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod 16139a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod return "invalid"; 16239a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod} 16339a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod 16439a840ae65327b173e6eb1bb291e235a8305d7a1Behdad Esfahbod 1658e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod/* hb_language_t */ 1668e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 1671bc1cb3603167f5da309336f7018c8b0608ac104Behdad Esfahbodstruct hb_language_impl_t { 1683cbdf70e0a92f1c24e16c0d4dcfbec4ac59a77a3Behdad Esfahbod const char s[1]; 1693cbdf70e0a92f1c24e16c0d4dcfbec4ac59a77a3Behdad Esfahbod}; 1703cbdf70e0a92f1c24e16c0d4dcfbec4ac59a77a3Behdad Esfahbod 1718e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbodstatic const char canon_map[256] = { 1728e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1738e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1748e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, 1758e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0, 1768e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 1778e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-', 1788e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 1798e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0 1808e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod}; 1818e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 182f3b170bdd970e31e9dbfed94c07c3cda41269aedBehdad Esfahbodstatic bool 183093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbodlang_equal (hb_language_t v1, 184093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod const void *v2) 1858e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod{ 186c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod const unsigned char *p1 = (const unsigned char *) v1; 187c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod const unsigned char *p2 = (const unsigned char *) v2; 1888e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 189093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod while (*p1 && *p1 == canon_map[*p2]) 190093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod p1++, p2++; 1918e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 192093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod return *p1 == canon_map[*p2]; 1938e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod} 1948e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 1958e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod#if 0 1968e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbodstatic unsigned int 1978e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbodlang_hash (const void *key) 1988e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod{ 1998e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod const unsigned char *p = key; 2008e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod unsigned int h = 0; 2018e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod while (canon_map[*p]) 2028e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod { 2038e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod h = (h << 5) - h + canon_map[*p]; 2048e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod p++; 2058e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod } 2068e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 2078e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod return h; 2088e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod} 2098e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod#endif 2108e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 2118e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 212b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbodstruct hb_language_item_t { 213b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod 214093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod struct hb_language_item_t *next; 215b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod hb_language_t lang; 216b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod 217b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod inline bool operator == (const char *s) const { 218b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod return lang_equal (lang, s); 219b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod } 220b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod 221b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod inline hb_language_item_t & operator = (const char *s) { 222b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod lang = (hb_language_t) strdup (s); 223b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod for (unsigned char *p = (unsigned char *) lang; *p; p++) 224b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod *p = canon_map[*p]; 225b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod 226b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod return *this; 227b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod } 228b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod 229cd361c3cbe4a288e3019b9a029f44e4c5f24436cBehdad Esfahbod void finish (void) { free ((void *) lang); } 230b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod}; 231b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod 232093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 233093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod/* Thread-safe lock-free language list */ 234093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 235093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbodstatic hb_language_item_t *langs; 236093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 23738fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#ifdef HB_USE_ATEXIT 238fb85d618f5883458bacf0ecb0894772291a2d738Chris Petersonstatic 239093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbodvoid free_langs (void) 240093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod{ 241093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod while (langs) { 242093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod hb_language_item_t *next = langs->next; 243093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod langs->finish (); 244093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod free (langs); 245093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod langs = next; 246093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod } 247093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod} 2480082dbeae6c25a7859960b7e791a540ad04246d9jfkthame#endif 249093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 250093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbodstatic hb_language_item_t * 251093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbodlang_find_or_insert (const char *key) 252093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod{ 253093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbodretry: 254093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs); 255093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 256093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod for (hb_language_item_t *lang = first_lang; lang; lang = lang->next) 257093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod if (*lang == key) 258093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod return lang; 259093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 260093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod /* Not found; allocate one. */ 261093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t)); 262093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod if (unlikely (!lang)) 263093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod return NULL; 264093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod lang->next = first_lang; 265093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod *lang = key; 266093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 267093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) { 268675956aca01fc4e005a338af43d1c1f4f938abd1Konstantin Ritt lang->finish (); 269093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod free (lang); 270093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod goto retry; 271093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod } 272093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 27338fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#ifdef HB_USE_ATEXIT 27404aed572f112b96a6033cd6c3df7bdba5e29e93cBehdad Esfahbod if (!first_lang) 27504aed572f112b96a6033cd6c3df7bdba5e29e93cBehdad Esfahbod atexit (free_langs); /* First person registers atexit() callback. */ 276093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod#endif 277093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 278093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod return lang; 279093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod} 280093171cceca63e48e735bbf05a2c11b1b7e95ef1Behdad Esfahbod 281b8d6183ebc4697a434776cf2aec7857d63a7d881Behdad Esfahbod 28270303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 28370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_language_from_string: 2848ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * @str: (array length=len) (element-type uint8_t): a string representing 2858ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * ISO 639 language code 2868ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * @len: length of the @str, or -1 if it is %NULL-terminated. 28770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 2888ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * Converts @str representing an ISO 639 language code to the corresponding 2898ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * #hb_language_t. 29070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 29104f89e8f7dfdb882e8c98afb613cba3f1d02ed7dKhaled Hosny * Return value: (transfer none): 2928ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * The #hb_language_t corresponding to the ISO 639 language code. 29370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 294b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 29570303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 2968e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbodhb_language_t 2974c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbodhb_language_from_string (const char *str, int len) 2988e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod{ 2994c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbod if (!str || !len || !*str) 3001a64f6e19a4b483e278c85e4941107be2f71b0a4Behdad Esfahbod return HB_LANGUAGE_INVALID; 3018e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 302f3159ba5141c2ab0e430e64742972df140f91c43Behdad Esfahbod hb_language_item_t *item = NULL; 30348360ec03b225dfec5f90bc5cb93122203d2dd6bBehdad Esfahbod if (len >= 0) 30448360ec03b225dfec5f90bc5cb93122203d2dd6bBehdad Esfahbod { 305dac86026a6bae5a8a03cfe885bf93f32e5f48614Behdad Esfahbod /* NUL-terminate it. */ 306f3159ba5141c2ab0e430e64742972df140f91c43Behdad Esfahbod char strbuf[64]; 3074c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbod len = MIN (len, (int) sizeof (strbuf) - 1); 308dac86026a6bae5a8a03cfe885bf93f32e5f48614Behdad Esfahbod memcpy (strbuf, str, len); 3094c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbod strbuf[len] = '\0'; 310f3159ba5141c2ab0e430e64742972df140f91c43Behdad Esfahbod item = lang_find_or_insert (strbuf); 3114c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbod } 312f3159ba5141c2ab0e430e64742972df140f91c43Behdad Esfahbod else 313f3159ba5141c2ab0e430e64742972df140f91c43Behdad Esfahbod item = lang_find_or_insert (str); 3148e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 3151a64f6e19a4b483e278c85e4941107be2f71b0a4Behdad Esfahbod return likely (item) ? item->lang : HB_LANGUAGE_INVALID; 3168e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod} 3178e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 31870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 31970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_language_to_string: 3208ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * @language: an #hb_language_t to convert. 32170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 3228ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * See hb_language_from_string(). 32370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 3248ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * Return value: (transfer none): 3258ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * A %NULL-terminated string representing the @language. Must not be freed by 3268ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * the caller. 32770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 328b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 32970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 3308e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbodconst char * 3318e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbodhb_language_to_string (hb_language_t language) 3328e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod{ 3331a64f6e19a4b483e278c85e4941107be2f71b0a4Behdad Esfahbod /* This is actually NULL-safe! */ 3343cbdf70e0a92f1c24e16c0d4dcfbec4ac59a77a3Behdad Esfahbod return language->s; 3358e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod} 3368e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 33770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 33870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_language_get_default: 33970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 34070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 34170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 342351f68f4e01a107f62e4eb3458d7c7ae379939fbBehdad Esfahbod * Return value: (transfer none): 34370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 344b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 34570303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 34634fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbodhb_language_t 34734fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbodhb_language_get_default (void) 34834fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbod{ 3497e7d245b332306949a19c628bacd920717434769Behdad Esfahbod static hb_language_t default_language = HB_LANGUAGE_INVALID; 35034fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbod 3517e7d245b332306949a19c628bacd920717434769Behdad Esfahbod hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language); 3527e7d245b332306949a19c628bacd920717434769Behdad Esfahbod if (unlikely (language == HB_LANGUAGE_INVALID)) { 3537e7d245b332306949a19c628bacd920717434769Behdad Esfahbod language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1); 354d1897a98d8da40cffb57c07099a9a93cfeaacc36Chris Peterson (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language); 35534fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbod } 35634fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbod 35734fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbod return default_language; 35834fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbod} 35934fb5521a5fbb6b95ceff4bbac42a62628bc9f31Behdad Esfahbod 3608e4bb3cacc269ed32187aaaeaa166c64f41a0418Behdad Esfahbod 36100bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod/* hb_script_t */ 36200bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 36370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 36470303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_script_from_iso15924_tag: 3658ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * @tag: an #hb_tag_t representing an ISO 15924 tag. 36670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 3678ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * Converts an ISO 15924 script tag to a corresponding #hb_script_t. 36870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 36970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Return value: 3708ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * An #hb_script_t corresponding to the ISO 15924 tag. 37170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 372b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 37370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 37400bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbodhb_script_t 37500bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbodhb_script_from_iso15924_tag (hb_tag_t tag) 37600bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod{ 377f144a8ea840c6452c1fece2fd988b42a8ea7c5a6Behdad Esfahbod if (unlikely (tag == HB_TAG_NONE)) 378f144a8ea840c6452c1fece2fd988b42a8ea7c5a6Behdad Esfahbod return HB_SCRIPT_INVALID; 379f144a8ea840c6452c1fece2fd988b42a8ea7c5a6Behdad Esfahbod 38000bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod /* Be lenient, adjust case (one capital letter followed by three small letters) */ 3817627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod tag = (tag & 0xDFDFDFDFu) | 0x00202020u; 38200bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 38362879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod switch (tag) { 384d02985ec5a24c659a0a133cc6bc103f1d76bcb29Behdad Esfahbod 385d02985ec5a24c659a0a133cc6bc103f1d76bcb29Behdad Esfahbod /* These graduated from the 'Q' private-area codes, but 386d02985ec5a24c659a0a133cc6bc103f1d76bcb29Behdad Esfahbod * the old code is still aliased by Unicode, and the Qaai 387d02985ec5a24c659a0a133cc6bc103f1d76bcb29Behdad Esfahbod * one in use by ICU. */ 388d02985ec5a24c659a0a133cc6bc103f1d76bcb29Behdad Esfahbod case HB_TAG('Q','a','a','i'): return HB_SCRIPT_INHERITED; 389d02985ec5a24c659a0a133cc6bc103f1d76bcb29Behdad Esfahbod case HB_TAG('Q','a','a','c'): return HB_SCRIPT_COPTIC; 390d02985ec5a24c659a0a133cc6bc103f1d76bcb29Behdad Esfahbod 391d02985ec5a24c659a0a133cc6bc103f1d76bcb29Behdad Esfahbod /* Script variants from http://unicode.org/iso15924/ */ 39262879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_TAG('C','y','r','s'): return HB_SCRIPT_CYRILLIC; 39362879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_TAG('L','a','t','f'): return HB_SCRIPT_LATIN; 39462879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_TAG('L','a','t','g'): return HB_SCRIPT_LATIN; 39562879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_TAG('S','y','r','e'): return HB_SCRIPT_SYRIAC; 39662879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_TAG('S','y','r','j'): return HB_SCRIPT_SYRIAC; 39762879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_TAG('S','y','r','n'): return HB_SCRIPT_SYRIAC; 39862879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod } 39900bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 40000bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod /* If it looks right, just use the tag as a script */ 4017627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod if (((uint32_t) tag & 0xE0E0E0E0u) == 0x40606060u) 40200bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod return (hb_script_t) tag; 40300bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 40400bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod /* Otherwise, return unknown */ 40500bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod return HB_SCRIPT_UNKNOWN; 40600bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod} 40700bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 40870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 40970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_script_from_string: 4108ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * @str: (array length=len) (element-type uint8_t): a string representing an 4118ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * ISO 15924 tag. 4128ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * @len: length of the @str, or -1 if it is %NULL-terminated. 41370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 4148ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * Converts a string @str representing an ISO 15924 script tag to a 4158ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * corresponding #hb_script_t. Shorthand for hb_tag_from_string() then 4168ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * hb_script_from_iso15924_tag(). 41770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 41870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Return value: 4198ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * An #hb_script_t corresponding to the ISO 15924 tag. 42070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 421b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 42270303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 42300bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbodhb_script_t 4248ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosnyhb_script_from_string (const char *str, int len) 42500bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod{ 4268ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny return hb_script_from_iso15924_tag (hb_tag_from_string (str, len)); 42700bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod} 42800bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 42970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 43070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_script_to_iso15924_tag: 4318ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * @script: an #hb_script_ to convert. 43270303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 4338ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * See hb_script_from_iso15924_tag(). 43470303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 4358ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * Return value: 4368ab797c5b86c33eab6ee024471fd3c147325d26aKhaled Hosny * An #hb_tag_t representing an ISO 15924 script tag. 43770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 438b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 43970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 44000bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbodhb_tag_t 44100bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbodhb_script_to_iso15924_tag (hb_script_t script) 44200bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod{ 44362879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod return (hb_tag_t) script; 44400bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod} 44500bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 44670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 44770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_script_get_horizontal_direction: 44870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @script: 44970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 45070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 45170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 45270303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Return value: 45370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 454b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 45570303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 45600bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbodhb_direction_t 45700bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbodhb_script_get_horizontal_direction (hb_script_t script) 45800bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod{ 459fa2673c1ee954ddbbfbfca7cced7b839d7776fc0Behdad Esfahbod /* http://goo.gl/x9ilM */ 46062879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod switch ((hb_tag_t) script) 46162879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod { 462fa2673c1ee954ddbbfbfca7cced7b839d7776fc0Behdad Esfahbod /* Unicode-1.1 additions */ 46362879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_ARABIC: 46462879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_HEBREW: 465fa2673c1ee954ddbbfbfca7cced7b839d7776fc0Behdad Esfahbod 466fa2673c1ee954ddbbfbfca7cced7b839d7776fc0Behdad Esfahbod /* Unicode-3.0 additions */ 46762879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_SYRIAC: 46862879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_THAANA: 46962879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod 47062879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod /* Unicode-4.0 additions */ 47162879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_CYPRIOT: 47262879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod 47350e810cd0e55c25fddb0a2fd0861c51fbf65700eBehdad Esfahbod /* Unicode-4.1 additions */ 47450e810cd0e55c25fddb0a2fd0861c51fbf65700eBehdad Esfahbod case HB_SCRIPT_KHAROSHTHI: 47550e810cd0e55c25fddb0a2fd0861c51fbf65700eBehdad Esfahbod 47662879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod /* Unicode-5.0 additions */ 47762879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_PHOENICIAN: 47862879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_NKO: 47962879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod 48050e810cd0e55c25fddb0a2fd0861c51fbf65700eBehdad Esfahbod /* Unicode-5.1 additions */ 48150e810cd0e55c25fddb0a2fd0861c51fbf65700eBehdad Esfahbod case HB_SCRIPT_LYDIAN: 48250e810cd0e55c25fddb0a2fd0861c51fbf65700eBehdad Esfahbod 48362879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod /* Unicode-5.2 additions */ 48462879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_AVESTAN: 48562879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_IMPERIAL_ARAMAIC: 48662879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: 48762879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: 48862879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_OLD_SOUTH_ARABIAN: 48962879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_OLD_TURKIC: 49062879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_SAMARITAN: 49162879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod 49262879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod /* Unicode-6.0 additions */ 49362879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod case HB_SCRIPT_MANDAIC: 49462879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod 495fa2673c1ee954ddbbfbfca7cced7b839d7776fc0Behdad Esfahbod /* Unicode-6.1 additions */ 496fa2673c1ee954ddbbfbfca7cced7b839d7776fc0Behdad Esfahbod case HB_SCRIPT_MEROITIC_CURSIVE: 497fa2673c1ee954ddbbfbfca7cced7b839d7776fc0Behdad Esfahbod case HB_SCRIPT_MEROITIC_HIEROGLYPHS: 498fa2673c1ee954ddbbfbfca7cced7b839d7776fc0Behdad Esfahbod 499a4a7899cd93fb9d1bc2163a4bbabfa733ee5bd52Behdad Esfahbod /* Unicode-7.0 additions */ 500a4a7899cd93fb9d1bc2163a4bbabfa733ee5bd52Behdad Esfahbod case HB_SCRIPT_MANICHAEAN: 501a4a7899cd93fb9d1bc2163a4bbabfa733ee5bd52Behdad Esfahbod case HB_SCRIPT_MENDE_KIKAKUI: 502a4a7899cd93fb9d1bc2163a4bbabfa733ee5bd52Behdad Esfahbod case HB_SCRIPT_NABATAEAN: 503a4a7899cd93fb9d1bc2163a4bbabfa733ee5bd52Behdad Esfahbod case HB_SCRIPT_OLD_NORTH_ARABIAN: 504a4a7899cd93fb9d1bc2163a4bbabfa733ee5bd52Behdad Esfahbod case HB_SCRIPT_PALMYRENE: 505a4a7899cd93fb9d1bc2163a4bbabfa733ee5bd52Behdad Esfahbod case HB_SCRIPT_PSALTER_PAHLAVI: 506a4a7899cd93fb9d1bc2163a4bbabfa733ee5bd52Behdad Esfahbod 50764a2726e2c6efce4379a7609024ec21eb4b5e4dcBehdad Esfahbod /* Unicode-8.0 additions */ 50864a2726e2c6efce4379a7609024ec21eb4b5e4dcBehdad Esfahbod case HB_SCRIPT_OLD_HUNGARIAN: 50964a2726e2c6efce4379a7609024ec21eb4b5e4dcBehdad Esfahbod 510691086f131cb6c9d97e98730c27673484bf93f87Behdad Esfahbod /* Unicode-9.0 additions */ 511691086f131cb6c9d97e98730c27673484bf93f87Behdad Esfahbod case HB_SCRIPT_ADLAM: 512691086f131cb6c9d97e98730c27673484bf93f87Behdad Esfahbod 51362879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod return HB_DIRECTION_RTL; 51462879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod } 51500bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 51662879eebd9965179af8602ba29ac0a64a739b757Behdad Esfahbod return HB_DIRECTION_LTR; 51700bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod} 51800bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 51900bec2c969555e76c3f84650a1d3c45308e585adBehdad Esfahbod 520218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod/* hb_user_data_array_t */ 521218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod 522218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbodbool 523218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbodhb_user_data_array_t::set (hb_user_data_key_t *key, 524218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod void * data, 52533ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod hb_destroy_func_t destroy, 5267babfe5a7904c26060c5b8441ca1bf23e1444f35Behdad Esfahbod hb_bool_t replace) 527218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod{ 528218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod if (!key) 529218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod return false; 53046df6828513d56cd60467e36cbe45aa06648f488Behdad Esfahbod 53133ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod if (replace) { 53233ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod if (!data && !destroy) { 5330e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbod items.remove (key, lock); 53433ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod return true; 53533ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod } 536218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod } 537218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod hb_user_data_item_t item = {key, data, destroy}; 538ea512f71084296be3bd893f78650def894066de0Behdad Esfahbod bool ret = !!items.replace_or_insert (item, lock, (bool) replace); 53946df6828513d56cd60467e36cbe45aa06648f488Behdad Esfahbod 54046df6828513d56cd60467e36cbe45aa06648f488Behdad Esfahbod return ret; 541218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod} 542218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod 543218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbodvoid * 5447babfe5a7904c26060c5b8441ca1bf23e1444f35Behdad Esfahbodhb_user_data_array_t::get (hb_user_data_key_t *key) 545218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod{ 54680c8855cfeffa028d74a25df884d0e5577c95c6cBehdad Esfahbod hb_user_data_item_t item = {NULL, NULL, NULL}; 54746df6828513d56cd60467e36cbe45aa06648f488Behdad Esfahbod 5480e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbod return items.find (key, &item, lock) ? item.data : NULL; 54945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod} 55046df6828513d56cd60467e36cbe45aa06648f488Behdad Esfahbod 551218e67b9eefa26e2e4fe43f99a84d082b185b1b0Behdad Esfahbod 552c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod/* hb_version */ 553c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod 55470303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 55570303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_version: 55670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @major: (out): Library major version component. 55770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @minor: (out): Library minor version component. 55870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @micro: (out): Library micro version component. 55970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 56070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Returns library version as three integer components. 56170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 562b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 56370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 564c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbodvoid 565c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbodhb_version (unsigned int *major, 566c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod unsigned int *minor, 567c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod unsigned int *micro) 568c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod{ 569c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod *major = HB_VERSION_MAJOR; 570c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod *minor = HB_VERSION_MINOR; 571c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod *micro = HB_VERSION_MICRO; 572c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod} 573c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod 57470303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 57570303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * hb_version_string: 57670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 57770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Returns library version as a string with three components. 57870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 57970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Return value: library version string. 58070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 581b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.2 58270303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 583c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbodconst char * 584c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbodhb_version_string (void) 585c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod{ 586c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod return HB_VERSION_STRING; 587c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod} 588c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod 58970303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod/** 5902b051c6057920c564c13c5d6a3e6dca93446fa12Behdad Esfahbod * hb_version_atleast: 59170303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @major: 59270303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @minor: 59370303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * @micro: 59470303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 59570303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 59670303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 59770303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * Return value: 59870303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod * 59901c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.30 60070303cf23b22647bf641be22c8650310128322a9Behdad Esfahbod **/ 601c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbodhb_bool_t 6022b051c6057920c564c13c5d6a3e6dca93446fa12Behdad Esfahbodhb_version_atleast (unsigned int major, 6032b051c6057920c564c13c5d6a3e6dca93446fa12Behdad Esfahbod unsigned int minor, 6042b051c6057920c564c13c5d6a3e6dca93446fa12Behdad Esfahbod unsigned int micro) 605c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod{ 6062b051c6057920c564c13c5d6a3e6dca93446fa12Behdad Esfahbod return HB_VERSION_ATLEAST (major, minor, micro); 607c78f4485587cc1dee07e772c164a13fde9d2859fBehdad Esfahbod} 60872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 60972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 610b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 611bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod/* hb_feature_t and hb_variation_t */ 61272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 61372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodstatic bool 61472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodparse_space (const char **pp, const char *end) 61572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 61672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod while (*pp < end && ISSPACE (**pp)) 61772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod (*pp)++; 61872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return true; 61972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 62072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 62172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodstatic bool 62272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodparse_char (const char **pp, const char *end, char c) 62372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 62472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_space (pp, end); 62572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 62672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (*pp == end || **pp != c) 62772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return false; 62872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 62972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod (*pp)++; 63072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return true; 63172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 63272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 63372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodstatic bool 63472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodparse_uint (const char **pp, const char *end, unsigned int *pv) 63572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 63672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod char buf[32]; 63772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); 63872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod strncpy (buf, *pp, len); 63972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod buf[len] = '\0'; 64072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 64172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod char *p = buf; 64272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod char *pend = p; 64372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod unsigned int v; 64472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 64572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod /* Intentionally use strtol instead of strtoul, such that 64672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * -1 turns into "big number"... */ 64772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod errno = 0; 64872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod v = strtol (p, &pend, 0); 64972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (errno || p == pend) 65072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return false; 65172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 65272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod *pv = v; 65372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod *pp += pend - p; 65472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return true; 65572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 65672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 65772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodstatic bool 658b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbodparse_float (const char **pp, const char *end, float *pv) 659b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod{ 660b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod char buf[32]; 661b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); 662b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod strncpy (buf, *pp, len); 663b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod buf[len] = '\0'; 664b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 665b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod char *p = buf; 666b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod char *pend = p; 667b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod float v; 668b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 669b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod errno = 0; 670b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod v = strtof (p, &pend); 671b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod if (errno || p == pend) 672b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod return false; 673b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 674b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod *pv = v; 675b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod *pp += pend - p; 676b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod return true; 677b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod} 678b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 679b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbodstatic bool 68072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodparse_bool (const char **pp, const char *end, unsigned int *pv) 68172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 68272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_space (pp, end); 68372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 68472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod const char *p = *pp; 68572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod while (*pp < end && ISALPHA(**pp)) 68672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod (*pp)++; 68772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 68872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod /* CSS allows on/off as aliases 1/0. */ 68972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (*pp - p == 2 || 0 == strncmp (p, "on", 2)) 69072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod *pv = 1; 69172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod else if (*pp - p == 3 || 0 == strncmp (p, "off", 2)) 69272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod *pv = 0; 69372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod else 69472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return false; 69572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 69672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return true; 69772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 69872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 699b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod/* hb_feature_t */ 700b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 70172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodstatic bool 70272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodparse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) 70372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 70472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (parse_char (pp, end, '-')) 70572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod feature->value = 0; 70672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod else { 70772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_char (pp, end, '+'); 70872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod feature->value = 1; 70972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod } 71072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 71172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return true; 71272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 71372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 71472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodstatic bool 715b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbodparse_tag (const char **pp, const char *end, hb_tag_t *tag) 71672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 71772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_space (pp, end); 71872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 71972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod char quote = 0; 72072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 72172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (*pp < end && (**pp == '\'' || **pp == '"')) 72272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod { 72372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod quote = **pp; 72472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod (*pp)++; 72572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod } 72672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 72772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod const char *p = *pp; 72872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod while (*pp < end && ISALNUM(**pp)) 72972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod (*pp)++; 73072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 73172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (p == *pp || *pp - p > 4) 73272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return false; 73372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 734b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod *tag = hb_tag_from_string (p, *pp - p); 73572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 73672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (quote) 73772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod { 73872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod /* CSS expects exactly four bytes. And we only allow quotations for 73972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * CSS compatibility. So, enforce the length. */ 74072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (*pp - p != 4) 74172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return false; 74272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (*pp == end || **pp != quote) 74372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return false; 74472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod (*pp)++; 74572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod } 74672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 74772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return true; 74872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 74972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 75072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodstatic bool 75172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodparse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) 75272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 75372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_space (pp, end); 75472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 75572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod bool has_start; 75672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 75772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod feature->start = 0; 75872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod feature->end = (unsigned int) -1; 75972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 76072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (!parse_char (pp, end, '[')) 76172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return true; 76272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 76372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod has_start = parse_uint (pp, end, &feature->start); 76472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 76572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (parse_char (pp, end, ':')) { 76672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_uint (pp, end, &feature->end); 76772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod } else { 76872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (has_start) 76972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod feature->end = feature->start + 1; 77072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod } 77172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 77272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return parse_char (pp, end, ']'); 77372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 77472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 77572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodstatic bool 77672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodparse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) 77772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 77872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod bool had_equal = parse_char (pp, end, '='); 77972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod bool had_value = parse_uint (pp, end, &feature->value) || 78072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_bool (pp, end, &feature->value); 78172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod /* CSS doesn't use equal-sign between tag and value. 78272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * If there was an equal-sign, then there *must* be a value. 78372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * A value without an eqaul-sign is ok, but not required. */ 78472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return !had_equal || had_value; 78572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 78672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 78772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodstatic bool 78872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodparse_one_feature (const char **pp, const char *end, hb_feature_t *feature) 78972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 79072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return parse_feature_value_prefix (pp, end, feature) && 791b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod parse_tag (pp, end, &feature->tag) && 79272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_feature_indices (pp, end, feature) && 79372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_feature_value_postfix (pp, end, feature) && 79472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod parse_space (pp, end) && 79572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod *pp == end; 79672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 79772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 79872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod/** 79972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * hb_feature_from_string: 80072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * @str: (array length=len) (element-type uint8_t): a string to parse 80172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * @len: length of @str, or -1 if string is %NULL terminated 80272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * @feature: (out): the #hb_feature_t to initialize with the parsed values 80372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * 80472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * Parses a string into a #hb_feature_t. 80572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * 80672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * TODO: document the syntax here. 80772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * 80872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * Return value: 80972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * %true if @str is successfully parsed, %false otherwise. 81072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * 81172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * Since: 0.9.5 81272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod **/ 81372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodhb_bool_t 81472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodhb_feature_from_string (const char *str, int len, 81572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod hb_feature_t *feature) 81672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 81772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod hb_feature_t feat; 81872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 81972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (len < 0) 82072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod len = strlen (str); 82172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 82272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (likely (parse_one_feature (&str, str + len, &feat))) 82372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod { 82472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (feature) 82572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod *feature = feat; 82672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return true; 82772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod } 82872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 82972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (feature) 83072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod memset (feature, 0, sizeof (*feature)); 83172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod return false; 83272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 83372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 83472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod/** 83572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * hb_feature_to_string: 83672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * @feature: an #hb_feature_t to convert 83772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * @buf: (array length=size) (out): output string 83872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * @size: the allocated size of @buf 83972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * 84072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * Converts a #hb_feature_t into a %NULL-terminated string in the format 84172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * understood by hb_feature_from_string(). The client in responsible for 84272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * allocating big enough size for @buf, 128 bytes is more than enough. 84372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * 84472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod * Since: 0.9.5 84572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod **/ 84672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodvoid 84772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbodhb_feature_to_string (hb_feature_t *feature, 84872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod char *buf, unsigned int size) 84972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod{ 85072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (unlikely (!size)) return; 85172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod 85272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod char s[128]; 85372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod unsigned int len = 0; 85472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (feature->value == 0) 85572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod s[len++] = '-'; 85672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod hb_tag_to_string (feature->tag, s + len); 85772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod len += 4; 85872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod while (len && s[len - 1] == ' ') 85972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod len--; 86072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (feature->start != 0 || feature->end != (unsigned int) -1) 86172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod { 86272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod s[len++] = '['; 86372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (feature->start) 86472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); 86572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (feature->end != feature->start + 1) { 86672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod s[len++] = ':'; 86772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (feature->end != (unsigned int) -1) 86872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); 86972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod } 87072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod s[len++] = ']'; 87172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod } 87272364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod if (feature->value > 1) 87372364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod { 87472364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod s[len++] = '='; 87572364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); 87672364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod } 87772364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod assert (len < ARRAY_LENGTH (s)); 87872364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod len = MIN (len, size - 1); 87972364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod memcpy (buf, s, len); 88072364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod buf[len] = '\0'; 88172364103bc9d910d19f23a3764d045af79d076d5Behdad Esfahbod} 882b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 883bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod/* hb_variation_t */ 884b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 885b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbodstatic bool 886bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbodparse_variation_value (const char **pp, const char *end, hb_variation_t *variation) 887b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod{ 888b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod parse_char (pp, end, '='); /* Optional. */ 889bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod return parse_float (pp, end, &variation->value); 890b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod} 891b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 892b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbodstatic bool 893bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbodparse_one_variation (const char **pp, const char *end, hb_variation_t *variation) 894b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod{ 895bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod return parse_tag (pp, end, &variation->tag) && 896bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod parse_variation_value (pp, end, variation) && 897b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod parse_space (pp, end) && 898b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod *pp == end; 899b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod} 900b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 901d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod/** 902d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod * hb_variation_from_string: 903d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod * 904d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod * Since: 1.4.2 905d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod */ 906b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbodhb_bool_t 907bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbodhb_variation_from_string (const char *str, int len, 908bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod hb_variation_t *variation) 909b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod{ 910bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod hb_variation_t var; 911b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 912b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod if (len < 0) 913b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod len = strlen (str); 914b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 915bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod if (likely (parse_one_variation (&str, str + len, &var))) 916b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod { 917bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod if (variation) 918bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod *variation = var; 919b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod return true; 920b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod } 921b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 922bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod if (variation) 923bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod memset (variation, 0, sizeof (*variation)); 924b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod return false; 925b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod} 926b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 927d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod/** 928d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod * hb_variation_to_string: 929d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod * 930d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod * Since: 1.4.2 931d2f249e745a9179943ee39c719b73e1057acbc13Behdad Esfahbod */ 932b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbodvoid 933bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbodhb_variation_to_string (hb_variation_t *variation, 934b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod char *buf, unsigned int size) 935b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod{ 936b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod if (unlikely (!size)) return; 937b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 938b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod char s[128]; 939b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod unsigned int len = 0; 940bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod hb_tag_to_string (variation->tag, s + len); 941b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod len += 4; 942b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod while (len && s[len - 1] == ' ') 943b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod len--; 944b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod s[len++] = '='; 945bb1e19268f02d4aad2240c52852e72afcf0f79adBehdad Esfahbod len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value)); 946b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod 947b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod assert (len < ARRAY_LENGTH (s)); 948b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod len = MIN (len, size - 1); 949b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod memcpy (buf, s, len); 950b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod buf[len] = '\0'; 951b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34eBehdad Esfahbod} 952