1 /* 2 * Copyright 2018 Google, Inc. 3 * 4 * This is part of HarfBuzz, a text shaping library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 * 24 * Google Author(s): Behdad Esfahbod 25 */ 26 27 #include "hb.hh" 28 29 #include "hb-ot-name-table.hh" 30 31 #include "hb-ot-face.hh" 32 #include "hb-utf.hh" 33 34 35 /** 36 * SECTION:hb-ot-name 37 * @title: hb-ot-name 38 * @short_description: OpenType font name information 39 * @include: hb-ot.h 40 * 41 * Functions for fetching name strings from OpenType fonts. 42 **/ 43 44 45 /** 46 * hb_ot_name_list_names: 47 * @face: font face. 48 * @num_entries: (out) (allow-none): number of returned entries. 49 * 50 * Enumerates all available name IDs and language combinations. Returned 51 * array is owned by the @face and should not be modified. It can be 52 * used as long as @face is alive. 53 * 54 * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries. 55 * Since: 2.1.0 56 **/ 57 const hb_ot_name_entry_t * 58 hb_ot_name_list_names (hb_face_t *face, 59 unsigned int *num_entries /* OUT */) 60 { 61 const OT::name_accelerator_t &name = *face->table.name; 62 if (num_entries) *num_entries = name.names.len; 63 return name.names.arrayZ(); 64 } 65 66 67 template <typename in_utf_t, typename out_utf_t> 68 static inline unsigned int 69 hb_ot_name_convert_utf (hb_bytes_t bytes, 70 unsigned int *text_size /* IN/OUT */, 71 typename out_utf_t::codepoint_t *text /* OUT */) 72 { 73 unsigned int src_len = bytes.len / sizeof (typename in_utf_t::codepoint_t); 74 const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ; 75 const typename in_utf_t::codepoint_t *src_end = src + src_len; 76 77 typename out_utf_t::codepoint_t *dst = text; 78 79 hb_codepoint_t unicode; 80 const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; 81 82 if (text_size && *text_size) 83 { 84 (*text_size)--; /* Same room for NUL-termination. */ 85 const typename out_utf_t::codepoint_t *dst_end = text + *text_size; 86 87 while (src < src_end && dst < dst_end) 88 { 89 const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement); 90 typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode); 91 if (dst_next == dst) 92 break; /* Out-of-room. */ 93 94 dst = dst_next; 95 src = src_next; 96 }; 97 98 *text_size = dst - text; 99 *dst = 0; /* NUL-terminate. */ 100 } 101 102 /* Accumulate length of rest. */ 103 unsigned int dst_len = dst - text; 104 while (src < src_end) 105 { 106 src = in_utf_t::next (src, src_end, &unicode, replacement); 107 dst_len += out_utf_t::encode_len (unicode); 108 }; 109 return dst_len; 110 } 111 112 template <typename utf_t> 113 static inline unsigned int 114 hb_ot_name_get_utf (hb_face_t *face, 115 hb_ot_name_id_t name_id, 116 hb_language_t language, 117 unsigned int *text_size /* IN/OUT */, 118 typename utf_t::codepoint_t *text /* OUT */) 119 { 120 const OT::name_accelerator_t &name = *face->table.name; 121 122 if (!language) 123 language = hb_language_from_string ("en", 2); 124 125 unsigned int width; 126 int idx = name.get_index (name_id, language, &width); 127 if (idx != -1) 128 { 129 hb_bytes_t bytes = name.get_name (idx); 130 131 if (width == 2) /* UTF16-BE */ 132 return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text); 133 134 if (width == 1) /* ASCII */ 135 return hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text); 136 } 137 138 if (text_size) 139 { 140 if (*text_size) 141 *text = 0; 142 *text_size = 0; 143 } 144 return 0; 145 } 146 147 /** 148 * hb_ot_name_get_utf8: 149 * @face: font face. 150 * @name_id: OpenType name identifier to fetch. 151 * @language: language to fetch the name for. 152 * @text_size: (inout) (allow-none): input size of @text buffer, and output size of 153 * text written to buffer. 154 * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. 155 * 156 * Fetches a font name from the OpenType 'name' table. 157 * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed. 158 * Returns string in UTF-8 encoding. 159 * 160 * Returns: full length of the requested string, or 0 if not found. 161 * Since: 2.1.0 162 **/ 163 unsigned int 164 hb_ot_name_get_utf8 (hb_face_t *face, 165 hb_ot_name_id_t name_id, 166 hb_language_t language, 167 unsigned int *text_size /* IN/OUT */, 168 char *text /* OUT */) 169 { 170 return hb_ot_name_get_utf<hb_utf8_t> (face, name_id, language, text_size, 171 (hb_utf8_t::codepoint_t *) text); 172 } 173 174 /** 175 * hb_ot_name_get_utf16: 176 * @face: font face. 177 * @name_id: OpenType name identifier to fetch. 178 * @language: language to fetch the name for. 179 * @text_size: (inout) (allow-none): input size of @text buffer, and output size of 180 * text written to buffer. 181 * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. 182 * 183 * Fetches a font name from the OpenType 'name' table. 184 * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed. 185 * Returns string in UTF-16 encoding. 186 * 187 * Returns: full length of the requested string, or 0 if not found. 188 * Since: 2.1.0 189 **/ 190 unsigned int 191 hb_ot_name_get_utf16 (hb_face_t *face, 192 hb_ot_name_id_t name_id, 193 hb_language_t language, 194 unsigned int *text_size /* IN/OUT */, 195 uint16_t *text /* OUT */) 196 { 197 return hb_ot_name_get_utf<hb_utf16_t> (face, name_id, language, text_size, text); 198 } 199 200 /** 201 * hb_ot_name_get_utf32: 202 * @face: font face. 203 * @name_id: OpenType name identifier to fetch. 204 * @language: language to fetch the name for. 205 * @text_size: (inout) (allow-none): input size of @text buffer, and output size of 206 * text written to buffer. 207 * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. 208 * 209 * Fetches a font name from the OpenType 'name' table. 210 * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed. 211 * Returns string in UTF-32 encoding. 212 * 213 * Returns: full length of the requested string, or 0 if not found. 214 * Since: 2.1.0 215 **/ 216 unsigned int 217 hb_ot_name_get_utf32 (hb_face_t *face, 218 hb_ot_name_id_t name_id, 219 hb_language_t language, 220 unsigned int *text_size /* IN/OUT */, 221 uint32_t *text /* OUT */) 222 { 223 return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text); 224 } 225