1 | /* Pango |
2 | * pango-ot-info.c: Store tables for OpenType |
3 | * |
4 | * Copyright (C) 2000 Red Hat Software |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Library General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Library General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Library General Public |
17 | * License along with this library; if not, write to the |
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 | * Boston, MA 02111-1307, USA. |
20 | */ |
21 | |
22 | #include "config.h" |
23 | |
24 | #include "pango-ot-private.h" |
25 | |
26 | static void pango_ot_info_finalize (GObject *object); |
27 | |
28 | G_DEFINE_TYPE (PangoOTInfo, pango_ot_info, G_TYPE_OBJECT); |
29 | |
30 | static void |
31 | pango_ot_info_init (PangoOTInfo *self) |
32 | { |
33 | } |
34 | |
35 | static void |
36 | pango_ot_info_class_init (PangoOTInfoClass *klass) |
37 | { |
38 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
39 | |
40 | object_class->finalize = pango_ot_info_finalize; |
41 | } |
42 | |
43 | static void |
44 | pango_ot_info_finalize (GObject *object) |
45 | { |
46 | PangoOTInfo *info = PANGO_OT_INFO (object); |
47 | |
48 | if (info->hb_face) |
49 | hb_face_destroy (face: info->hb_face); |
50 | |
51 | G_OBJECT_CLASS (pango_ot_info_parent_class)->finalize (object); |
52 | } |
53 | |
54 | static void |
55 | pango_ot_info_finalizer (void *object) |
56 | { |
57 | FT_Face face = object; |
58 | PangoOTInfo *info = face->generic.data; |
59 | |
60 | info->face = NULL; |
61 | g_object_unref (object: info); |
62 | } |
63 | |
64 | |
65 | /** |
66 | * pango_ot_info_get: |
67 | * @face: a `FT_Face` |
68 | * |
69 | * Returns the `PangoOTInfo` structure for the given FreeType font face. |
70 | * |
71 | * Return value: (transfer none): the `PangoOTInfo` for @face. |
72 | * This object will have the same lifetime as @face. |
73 | * |
74 | * Since: 1.2 |
75 | */ |
76 | PangoOTInfo * |
77 | pango_ot_info_get (FT_Face face) |
78 | { |
79 | PangoOTInfo *info; |
80 | |
81 | if (G_UNLIKELY (!face)) |
82 | return NULL; |
83 | |
84 | if (G_LIKELY (face->generic.data && face->generic.finalizer == pango_ot_info_finalizer)) |
85 | return face->generic.data; |
86 | else |
87 | { |
88 | if (face->generic.finalizer) |
89 | face->generic.finalizer (face); |
90 | |
91 | info = face->generic.data = g_object_new (PANGO_TYPE_OT_INFO, NULL); |
92 | face->generic.finalizer = pango_ot_info_finalizer; |
93 | |
94 | info->face = face; |
95 | info->hb_face = hb_ft_face_create (ft_face: face, NULL); |
96 | } |
97 | |
98 | return info; |
99 | } |
100 | |
101 | static hb_tag_t |
102 | get_hb_table_type (PangoOTTableType table_type) |
103 | { |
104 | switch (table_type) { |
105 | case PANGO_OT_TABLE_GSUB: return HB_OT_TAG_GSUB; |
106 | case PANGO_OT_TABLE_GPOS: return HB_OT_TAG_GPOS; |
107 | default: return HB_TAG_NONE; |
108 | } |
109 | } |
110 | |
111 | /** |
112 | * pango_ot_info_find_script: |
113 | * @info: a `PangoOTInfo` |
114 | * @table_type: the table type to obtain information about |
115 | * @script_tag: the tag of the script to find |
116 | * @script_index: (out) (optional): location to store the index of the script |
117 | * |
118 | * Finds the index of a script. |
119 | * |
120 | * If not found, tries to find the 'DFLT' and then 'dflt' scripts and |
121 | * return the index of that in @script_index. If none of those is found |
122 | * either, %PANGO_OT_NO_SCRIPT is placed in @script_index. |
123 | * |
124 | * All other functions taking an input script_index parameter know |
125 | * how to handle %PANGO_OT_NO_SCRIPT, so one can ignore the return |
126 | * value of this function completely and proceed, to enjoy the automatic |
127 | * fallback to the 'DFLT'/'dflt' script. |
128 | * |
129 | * Return value: %TRUE if the script was found |
130 | */ |
131 | gboolean |
132 | pango_ot_info_find_script (PangoOTInfo *info, |
133 | PangoOTTableType table_type, |
134 | PangoOTTag script_tag, |
135 | guint *script_index) |
136 | { |
137 | hb_tag_t tt = get_hb_table_type (table_type); |
138 | |
139 | return hb_ot_layout_table_find_script (face: info->hb_face, table_tag: tt, |
140 | script_tag, |
141 | script_index); |
142 | } |
143 | |
144 | /** |
145 | * pango_ot_info_find_language: |
146 | * @info: a `PangoOTInfo` |
147 | * @table_type: the table type to obtain information about |
148 | * @script_index: the index of the script whose languages are searched |
149 | * @language_tag: the tag of the language to find |
150 | * @language_index: (out) (optional): location to store the index of the language |
151 | * @required_feature_index: (out) (optional): location to store the |
152 | * required feature index of the language |
153 | * |
154 | * Finds the index of a language and its required feature index. |
155 | * |
156 | * If the language is not found, sets @language_index to %PANGO_OT_DEFAULT_LANGUAGE |
157 | * and the required feature of the default language system is returned in |
158 | * required_feature_index. For best compatibility with some fonts, also |
159 | * searches the language system tag 'dflt' before falling back to the default |
160 | * language system, but that is transparent to the user. The user can simply |
161 | * ignore the return value of this function to automatically fall back to the |
162 | * default language system. |
163 | * |
164 | * Return value: %TRUE if the language was found |
165 | */ |
166 | gboolean |
167 | pango_ot_info_find_language (PangoOTInfo *info, |
168 | PangoOTTableType table_type, |
169 | guint script_index, |
170 | PangoOTTag language_tag, |
171 | guint *language_index, |
172 | guint *required_feature_index) |
173 | { |
174 | gboolean ret; |
175 | guint l_index; |
176 | hb_tag_t tt = get_hb_table_type (table_type); |
177 | |
178 | ret = hb_ot_layout_script_select_language (face: info->hb_face, |
179 | table_tag: table_type, |
180 | script_index, |
181 | language_count: 1, |
182 | language_tags: &language_tag, |
183 | language_index: &l_index); |
184 | if (language_index) |
185 | *language_index = l_index; |
186 | |
187 | hb_ot_layout_language_get_required_feature_index (face: info->hb_face, table_tag: tt, |
188 | script_index, |
189 | language_index: l_index, |
190 | feature_index: required_feature_index); |
191 | |
192 | return ret; |
193 | } |
194 | |
195 | /** |
196 | * pango_ot_info_find_feature: |
197 | * @info: a `PangoOTInfo` |
198 | * @table_type: the table type to obtain information about |
199 | * @feature_tag: the tag of the feature to find |
200 | * @script_index: the index of the script |
201 | * @language_index: the index of the language whose features are searched, |
202 | * or %PANGO_OT_DEFAULT_LANGUAGE to use the default language of the script |
203 | * @feature_index: (out) (optional): location to store the index of |
204 | * the feature |
205 | * |
206 | * Finds the index of a feature. |
207 | * |
208 | * If the feature is not found, sets @feature_index to PANGO_OT_NO_FEATURE, |
209 | * which is safe to pass to [method@PangoOT.Ruleset.add_feature] and similar |
210 | * functions. |
211 | * |
212 | * In the future, this may set @feature_index to an special value that if |
213 | * used in [method@PangoOT.Ruleset.add_feature] will ask Pango to synthesize |
214 | * the requested feature based on Unicode properties and data. However, this |
215 | * function will still return %FALSE in those cases. So, users may want to |
216 | * ignore the return value of this function in certain cases. |
217 | * |
218 | * Return value: %TRUE if the feature was found |
219 | */ |
220 | gboolean |
221 | pango_ot_info_find_feature (PangoOTInfo *info, |
222 | PangoOTTableType table_type, |
223 | PangoOTTag feature_tag, |
224 | guint script_index, |
225 | guint language_index, |
226 | guint *feature_index) |
227 | { |
228 | hb_tag_t tt = get_hb_table_type (table_type); |
229 | |
230 | return hb_ot_layout_language_find_feature (face: info->hb_face, table_tag: tt, |
231 | script_index, |
232 | language_index, |
233 | feature_tag, |
234 | feature_index); |
235 | } |
236 | |
237 | /** |
238 | * pango_ot_info_list_scripts: |
239 | * @info: a `PangoOTInfo` |
240 | * @table_type: the table type to obtain information about |
241 | * |
242 | * Obtains the list of available scripts. |
243 | * |
244 | * Return value: a newly-allocated zero-terminated |
245 | * array containing the tags of the available scripts |
246 | */ |
247 | PangoOTTag * |
248 | pango_ot_info_list_scripts (PangoOTInfo *info, |
249 | PangoOTTableType table_type) |
250 | { |
251 | hb_tag_t tt = get_hb_table_type (table_type); |
252 | PangoOTTag *result; |
253 | unsigned int count; |
254 | |
255 | count = hb_ot_layout_table_get_script_tags (face: info->hb_face, table_tag: tt, start_offset: 0, NULL, NULL); |
256 | result = g_new (PangoOTTag, count + 1); |
257 | hb_ot_layout_table_get_script_tags (face: info->hb_face, table_tag: tt, start_offset: 0, script_count: &count, script_tags: result); |
258 | result[count] = 0; |
259 | |
260 | return result; |
261 | } |
262 | |
263 | /** |
264 | * pango_ot_info_list_languages: |
265 | * @info: a `PangoOTInfo` |
266 | * @table_type: the table type to obtain information about |
267 | * @script_index: the index of the script to list languages for |
268 | * @language_tag: unused parameter |
269 | * |
270 | * Obtains the list of available languages for a given script. |
271 | * |
272 | * Return value: a newly-allocated zero-terminated |
273 | * array containing the tags of the available languages |
274 | */ |
275 | PangoOTTag * |
276 | pango_ot_info_list_languages (PangoOTInfo *info, |
277 | PangoOTTableType table_type, |
278 | guint script_index, |
279 | PangoOTTag language_tag G_GNUC_UNUSED) |
280 | { |
281 | hb_tag_t tt = get_hb_table_type (table_type); |
282 | PangoOTTag *result; |
283 | unsigned int count; |
284 | |
285 | count = hb_ot_layout_script_get_language_tags (face: info->hb_face, table_tag: tt, script_index, start_offset: 0, NULL, NULL); |
286 | result = g_new (PangoOTTag, count + 1); |
287 | hb_ot_layout_script_get_language_tags (face: info->hb_face, table_tag: tt, script_index, start_offset: 0, language_count: &count, language_tags: result); |
288 | result[count] = 0; |
289 | |
290 | return result; |
291 | } |
292 | |
293 | /** |
294 | * pango_ot_info_list_features: |
295 | * @info: a `PangoOTInfo` |
296 | * @table_type: the table type to obtain information about |
297 | * @tag: unused parameter |
298 | * @script_index: the index of the script to obtain information about |
299 | * @language_index: the index of the language to list features for, or |
300 | * %PANGO_OT_DEFAULT_LANGUAGE, to list features for the default |
301 | * language of the script |
302 | * |
303 | * Obtains the list of features for the given language of the given script. |
304 | * |
305 | * Return value: a newly-allocated zero-terminated |
306 | * array containing the tags of the available features |
307 | */ |
308 | PangoOTTag * |
309 | pango_ot_info_list_features (PangoOTInfo *info, |
310 | PangoOTTableType table_type, |
311 | PangoOTTag tag G_GNUC_UNUSED, |
312 | guint script_index, |
313 | guint language_index) |
314 | { |
315 | hb_tag_t tt = get_hb_table_type (table_type); |
316 | PangoOTTag *result; |
317 | unsigned int count; |
318 | |
319 | count = hb_ot_layout_language_get_feature_tags (face: info->hb_face, table_tag: tt, script_index, language_index, start_offset: 0, NULL, NULL); |
320 | result = g_new (PangoOTTag, count + 1); |
321 | hb_ot_layout_language_get_feature_tags (face: info->hb_face, table_tag: tt, script_index, language_index, start_offset: 0, feature_count: &count, feature_tags: result); |
322 | result[count] = 0; |
323 | |
324 | return result; |
325 | } |
326 | |