1 /* Pango
2  * pango-ot-ruleset.c: Shaping using OpenType features
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_ruleset_finalize   (GObject        *object);
27 
28 /**
29  * PangoOTRuleset:
30  *
31  * The `PangoOTRuleset` structure holds a set of features selected
32  * from the tables in an OpenType font.
33  *
34  * A feature is an operation such as adjusting glyph positioning
35  * that should be applied to a text feature such as a certain
36  * type of accent.
37  *
38  * A `PangoOTRuleset` is created with [ctor@PangoOT.Ruleset.new],
39  * features are added to it with [method@PangoOT.Ruleset.add_feature],
40  * then it is applied to a `PangoGlyphString` with
41  * [method@PangoOT.Ruleset.position].
42  */
43 G_DEFINE_TYPE (PangoOTRuleset, pango_ot_ruleset, G_TYPE_OBJECT);
44 
45 static void
pango_ot_ruleset_class_init(PangoOTRulesetClass * klass)46 pango_ot_ruleset_class_init (PangoOTRulesetClass *klass)
47 {
48   GObjectClass *object_class = G_OBJECT_CLASS (klass);
49 
50   object_class->finalize = pango_ot_ruleset_finalize;
51 }
52 
53 static void
pango_ot_ruleset_init(PangoOTRuleset * ruleset)54 pango_ot_ruleset_init (PangoOTRuleset *ruleset)
55 {
56 }
57 
58 static void
pango_ot_ruleset_finalize(GObject * object)59 pango_ot_ruleset_finalize (GObject *object)
60 {
61   G_OBJECT_CLASS (pango_ot_ruleset_parent_class)->finalize (object);
62 }
63 
64 /**
65  * pango_ot_ruleset_get_for_description:
66  * @info: a `PangoOTInfo`
67  * @desc: a `PangoOTRulesetDescription`
68  *
69  * Returns a ruleset for the given OpenType info and ruleset
70  * description.
71  *
72  * Rulesets are created on demand using
73  * [ctor@PangoOT.Ruleset.new_from_description].
74  * The returned ruleset should not be modified or destroyed.
75  *
76  * The static feature map members of @desc should be alive as
77  * long as @info is.
78  *
79  * Return value: the `PangoOTRuleset` for @desc. This object will have
80  *   the same lifetime as @info.
81  *
82  * Since: 1.18
83  */
84 const PangoOTRuleset *
pango_ot_ruleset_get_for_description(PangoOTInfo * info,const PangoOTRulesetDescription * desc)85 pango_ot_ruleset_get_for_description (PangoOTInfo                     *info,
86 				      const PangoOTRulesetDescription *desc)
87 {
88   static PangoOTRuleset *ruleset; /* MT-safe */
89 
90   if (g_once_init_enter (&ruleset))
91     g_once_init_leave (&ruleset, g_object_new (PANGO_TYPE_OT_RULESET, NULL));
92 
93   return ruleset;
94 }
95 
96 /**
97  * pango_ot_ruleset_new:
98  * @info: a `PangoOTInfo`
99  *
100  * Creates a new `PangoOTRuleset` for the given OpenType info.
101  *
102  * Return value: the newly allocated `PangoOTRuleset`
103  */
104 PangoOTRuleset *
pango_ot_ruleset_new(PangoOTInfo * info)105 pango_ot_ruleset_new (PangoOTInfo *info)
106 {
107   return g_object_new (PANGO_TYPE_OT_RULESET, NULL);
108 }
109 
110 /**
111  * pango_ot_ruleset_new_for:
112  * @info: a `PangoOTInfo`
113  * @script: a `PangoScript`
114  * @language: a `PangoLanguage`
115  *
116  * Creates a new `PangoOTRuleset` for the given OpenType info, script, and
117  * language.
118  *
119  * This function is part of a convenience scheme that highly simplifies
120  * using a `PangoOTRuleset` to represent features for a specific pair of script
121  * and language.  So one can use this function passing in the script and
122  * language of interest, and later try to add features to the ruleset by just
123  * specifying the feature name or tag, without having to deal with finding
124  * script, language, or feature indices manually.
125  *
126  * In addition to what [ctor@PangoOT.Ruleset.new] does, this function will:
127  *
128  * * Find the `PangoOTTag` script and language tags associated with
129  *   @script and @language using [func@PangoOT.tag_from_script] and
130  *   [func@PangoOT.tag_from_language],
131  *
132  * * For each of table types %PANGO_OT_TABLE_GSUB and %PANGO_OT_TABLE_GPOS,
133  *   find the script index of the script tag found and the language
134  *   system index of the language tag found in that script system, using
135  *   [method@PangoOT.Info.find_script] and [method@PangoOT.Info.find_language],
136  *
137  * * For found language-systems, if they have required feature index,
138  *   add that feature to the ruleset using [method@PangoOT.Ruleset.add_feature],
139  *
140  * * Remember found script and language indices for both table types,
141  *   and use them in future [method@PangoOT.Ruleset.maybe_add_feature] and
142  *   [method@PangoOT.Ruleset.maybe_add_features].
143  *
144  * Because of the way return values of [method@PangoOT.Info.find_script] and
145  * [method@PangoOT.Info.find_language] are ignored, this function automatically
146  * finds and uses the 'DFLT' script and the default language-system.
147  *
148  * Return value: the newly allocated `PangoOTRuleset`
149  *
150  * Since: 1.18
151  */
152 PangoOTRuleset *
pango_ot_ruleset_new_for(PangoOTInfo * info,PangoScript script,PangoLanguage * language)153 pango_ot_ruleset_new_for (PangoOTInfo       *info,
154 			  PangoScript        script,
155 			  PangoLanguage     *language)
156 {
157   return g_object_new (PANGO_TYPE_OT_RULESET, NULL);
158 }
159 
160 /**
161  * pango_ot_ruleset_new_from_description:
162  * @info: a `PangoOTInfo`
163  * @desc: a `PangoOTRulesetDescription`
164  *
165  * Creates a new `PangoOTRuleset` for the given OpenType info and
166  * matching the given ruleset description.
167  *
168  * This is a convenience function that calls [ctor@PangoOT.Ruleset.new_for]
169  * and adds the static GSUB/GPOS features to the resulting ruleset,
170  * followed by adding other features to both GSUB and GPOS.
171  *
172  * The static feature map members of @desc should be alive as
173  * long as @info is.
174  *
175  * Return value: the newly allocated `PangoOTRuleset`
176  *
177  * Since: 1.18
178  */
179 PangoOTRuleset *
pango_ot_ruleset_new_from_description(PangoOTInfo * info,const PangoOTRulesetDescription * desc)180 pango_ot_ruleset_new_from_description (PangoOTInfo                     *info,
181 				       const PangoOTRulesetDescription *desc)
182 {
183   return g_object_new (PANGO_TYPE_OT_RULESET, NULL);
184 }
185 
186 /**
187  * pango_ot_ruleset_add_feature:
188  * @ruleset: a `PangoOTRuleset`
189  * @table_type: the table type to add a feature to
190  * @feature_index: the index of the feature to add
191  * @property_bit: the property bit to use for this feature. Used to
192  *   identify the glyphs that this feature should be applied to, or
193  *   %PANGO_OT_ALL_GLYPHS if it should be applied to all glyphs.
194  *
195  * Adds a feature to the ruleset.
196  */
197 void
pango_ot_ruleset_add_feature(PangoOTRuleset * ruleset,PangoOTTableType table_type,guint feature_index,gulong property_bit)198 pango_ot_ruleset_add_feature (PangoOTRuleset   *ruleset,
199 			      PangoOTTableType  table_type,
200 			      guint             feature_index,
201 			      gulong            property_bit)
202 {
203 }
204 
205 /**
206  * pango_ot_ruleset_maybe_add_feature:
207  * @ruleset: a `PangoOTRuleset`
208  * @table_type: the table type to add a feature to
209  * @feature_tag: the tag of the feature to add
210  * @property_bit: the property bit to use for this feature. Used to
211  *   identify the glyphs that this feature should be applied to, or
212  *   %PANGO_OT_ALL_GLYPHS if it should be applied to all glyphs.
213  *
214  * This is a convenience function that first tries to find the feature
215  * using [method@PangoOT.Info.find_feature] and the ruleset script and
216  * language passed to [ctor@PangoOT.Ruleset.new_for] and if the feature
217  * is found, adds it to the ruleset.
218  *
219  * If @ruleset was not created using [ctor@PangoOT.Ruleset.new_for],
220  * this function does nothing.
221  *
222  * Return value: %TRUE if the feature was found and added to ruleset,
223  *   %FALSE otherwise
224  *
225  * Since: 1.18
226  */
227 gboolean
pango_ot_ruleset_maybe_add_feature(PangoOTRuleset * ruleset,PangoOTTableType table_type,PangoOTTag feature_tag,gulong property_bit)228 pango_ot_ruleset_maybe_add_feature (PangoOTRuleset          *ruleset,
229 				    PangoOTTableType         table_type,
230 				    PangoOTTag               feature_tag,
231 				    gulong                   property_bit)
232 {
233   return FALSE;
234 }
235 
236 /**
237  * pango_ot_ruleset_maybe_add_features:
238  * @ruleset: a `PangoOTRuleset`
239  * @table_type: the table type to add features to
240  * @features: array of feature name and property bits to add
241  * @n_features: number of feature records in @features array
242  *
243  * This is a convenience function that for each feature in the feature map
244  * array @features converts the feature name to a `PangoOTTag` feature tag
245  * using PANGO_OT_TAG_MAKE() and calls [method@PangoOT.Ruleset.maybe_add_feature]
246  * on it.
247  *
248  * Return value: The number of features in @features that were found
249  *   and added to @ruleset
250  *
251  * Since: 1.18
252  */
253 guint
pango_ot_ruleset_maybe_add_features(PangoOTRuleset * ruleset,PangoOTTableType table_type,const PangoOTFeatureMap * features,guint n_features)254 pango_ot_ruleset_maybe_add_features (PangoOTRuleset          *ruleset,
255 				     PangoOTTableType         table_type,
256 				     const PangoOTFeatureMap *features,
257 				     guint                    n_features)
258 {
259   return 0;
260 }
261 
262 /**
263  * pango_ot_ruleset_get_feature_count:
264  * @ruleset: a `PangoOTRuleset`
265  * @n_gsub_features: (out) (optional): location to store number of GSUB features
266  * @n_gpos_features: (out) (optional): location to store number of GPOS features
267  *
268  * Gets the number of GSUB and GPOS features in the ruleset.
269  *
270  * Return value: Total number of features in the @ruleset
271  *
272  * Since: 1.18
273  */
274 guint
pango_ot_ruleset_get_feature_count(const PangoOTRuleset * ruleset,guint * n_gsub_features,guint * n_gpos_features)275 pango_ot_ruleset_get_feature_count (const PangoOTRuleset   *ruleset,
276 				    guint                  *n_gsub_features,
277 				    guint                  *n_gpos_features)
278 {
279   return 0;
280 }
281 
282 /**
283  * pango_ot_ruleset_substitute:
284  * @ruleset: a `PangoOTRuleset`
285  * @buffer: a `PangoOTBuffer`
286  *
287  * Performs the OpenType GSUB substitution on @buffer using
288  * the features in @ruleset.
289  *
290  * Since: 1.4
291  */
292 void
pango_ot_ruleset_substitute(const PangoOTRuleset * ruleset,PangoOTBuffer * buffer)293 pango_ot_ruleset_substitute  (const PangoOTRuleset *ruleset,
294 			      PangoOTBuffer        *buffer)
295 {
296 }
297 
298 /**
299  * pango_ot_ruleset_position:
300  * @ruleset: a `PangoOTRuleset`
301  * @buffer: a `PangoOTBuffer`
302  *
303  * Performs the OpenType GPOS positioning on @buffer using
304  * the features in @ruleset.
305  *
306  * Since: 1.4
307  */
308 void
pango_ot_ruleset_position(const PangoOTRuleset * ruleset,PangoOTBuffer * buffer)309 pango_ot_ruleset_position (const PangoOTRuleset *ruleset,
310 			   PangoOTBuffer        *buffer)
311 {
312 }
313 
314 
315 /* ruleset descriptions */
316 
317 /**
318  * pango_ot_ruleset_description_hash:
319  * @desc: a ruleset description
320  *
321  * Computes a hash of a `PangoOTRulesetDescription` structure suitable
322  * to be used, for example, as an argument to g_hash_table_new().
323  *
324  * Return value: the hash value
325  *
326  * Since: 1.18
327  */
328 guint
pango_ot_ruleset_description_hash(const PangoOTRulesetDescription * desc)329 pango_ot_ruleset_description_hash  (const PangoOTRulesetDescription *desc)
330 {
331   return 0;
332 }
333 
334 /**
335  * pango_ot_ruleset_description_equal:
336  * @desc1: a ruleset description
337  * @desc2: a ruleset description
338  *
339  * Compares two ruleset descriptions for equality.
340  *
341  * Two ruleset descriptions are considered equal if the rulesets
342  * they describe are provably identical. This means that their
343  * script, language, and all feature sets should be equal.
344  *
345  * For static feature sets, the array addresses are compared directly,
346  * while for other features, the list of features is compared one by
347  * one.(Two ruleset descriptions may result in identical rulesets
348  * being created, but still compare %FALSE.)
349  *
350  * Return value: %TRUE if two ruleset descriptions are identical,
351  *   %FALSE otherwise
352  *
353  * Since: 1.18
354  **/
355 gboolean
pango_ot_ruleset_description_equal(const PangoOTRulesetDescription * desc1,const PangoOTRulesetDescription * desc2)356 pango_ot_ruleset_description_equal (const PangoOTRulesetDescription *desc1,
357 				    const PangoOTRulesetDescription *desc2)
358 {
359   return TRUE;
360 }
361 
G_DEFINE_BOXED_TYPE(PangoOTRulesetDescription,pango_ot_ruleset_description,pango_ot_ruleset_description_copy,pango_ot_ruleset_description_free)362 G_DEFINE_BOXED_TYPE (PangoOTRulesetDescription, pango_ot_ruleset_description,
363                      pango_ot_ruleset_description_copy,
364                      pango_ot_ruleset_description_free)
365 
366 /**
367  * pango_ot_ruleset_description_copy:
368  * @desc: ruleset description to copy
369  *
370  * Creates a copy of @desc, which should be freed with
371  * [method@PangoOT.RulesetDescription.free].
372  *
373  * Primarily used internally by [func@PangoOT.Ruleset.get_for_description]
374  * to cache rulesets for ruleset descriptions.
375  *
376  * Return value: the newly allocated `PangoOTRulesetDescription`
377  *
378  * Since: 1.18
379  */
380 PangoOTRulesetDescription *
381 pango_ot_ruleset_description_copy  (const PangoOTRulesetDescription *desc)
382 {
383   PangoOTRulesetDescription *copy;
384 
385   g_return_val_if_fail (desc != NULL, NULL);
386 
387   copy = g_slice_new (PangoOTRulesetDescription);
388 
389   *copy = *desc;
390 
391   return copy;
392 }
393 
394 /**
395  * pango_ot_ruleset_description_free:
396  * @desc: an allocated `PangoOTRulesetDescription`
397  *
398  * Frees a ruleset description allocated by
399  * pango_ot_ruleset_description_copy().
400  *
401  * Since: 1.18
402  */
403 void
pango_ot_ruleset_description_free(PangoOTRulesetDescription * desc)404 pango_ot_ruleset_description_free (PangoOTRulesetDescription *desc)
405 {
406   g_slice_free (PangoOTRulesetDescription, desc);
407 }
408