diff options
-rw-r--r-- | ChangeLog | 32 | ||||
-rw-r--r-- | docs/pango-sections.txt | 6 | ||||
-rw-r--r-- | docs/tmpl/glyphs.sgml | 1 | ||||
-rw-r--r-- | docs/tmpl/opentype.sgml | 78 | ||||
-rw-r--r-- | pango/pango-ot-ruleset.c | 246 | ||||
-rw-r--r-- | pango/pango-ot.h | 26 | ||||
-rw-r--r-- | pango/pangoxft.h | 2 |
7 files changed, 375 insertions, 16 deletions
@@ -1,5 +1,37 @@ 2007-05-14 Behdad Esfahbod <behdad@gnome.org> + Part of Bug 325714 – Pango should respect $LANGUAGE + + * pango/pango-ot.h: + * pango/pango-ot-ruleset.c (pango_ot_ruleset_get_for), + (pango_ot_ruleset_description_hash), + (pango_ot_ruleset_description_equal), + (pango_ot_ruleset_description_copy), + (pango_ot_ruleset_description_free): + Add new engine API: + + PangoOTRulesetDescription + pango_ot_ruleset_get_for() + pango_ot_ruleset_description_hash() + pango_ot_ruleset_description_equal() + pango_ot_ruleset_description_copy() + pango_ot_ruleset_description_free() + + The main addition is pango_ot_ruleset_get_for() that + takes a ruleset description, ie. script/language and list + of GSUB/GPOS features to apply, and returns a ruleset. + It manages all the work to cache rulesets, so modules + don't have to do that anymore. Given that modules do not + deal with just one ruleset anymore (because we want to + respect language, and allow user-selected features), this + makes their life way easier. + + * docs/pango-sections.txt: + * docs/tmpl/opentype.sgml: + Update. + +2007-05-14 Behdad Esfahbod <behdad@gnome.org> + * pango/pango-ot-buffer.c (pango_ot_buffer_get_glyphs), (pango_ot_buffer_output): * pango/pango-ot-ruleset.c (pango_ot_ruleset_substitute), diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt index e016407e..75906ed3 100644 --- a/docs/pango-sections.txt +++ b/docs/pango-sections.txt @@ -940,6 +940,7 @@ PangoOTInfo PangoOTBuffer PangoOTGlyph PangoOTRuleset +PangoOTRulesetDescription PangoOTTableType PangoOTFeatureMap PANGO_OT_ALL_GLYPHS @@ -963,6 +964,7 @@ pango_ot_buffer_set_rtl pango_ot_buffer_set_zero_width_marks pango_ot_buffer_get_glyphs pango_ot_buffer_output +pango_ot_ruleset_get_for pango_ot_ruleset_new pango_ot_ruleset_new_for pango_ot_ruleset_add_feature @@ -970,6 +972,10 @@ pango_ot_ruleset_maybe_add_feature pango_ot_ruleset_maybe_add_features pango_ot_ruleset_substitute pango_ot_ruleset_position +pango_ot_ruleset_description_copy +pango_ot_ruleset_description_equal +pango_ot_ruleset_description_free +pango_ot_ruleset_description_hash pango_ot_tag_from_language pango_ot_tag_from_script pango_ot_tag_to_language diff --git a/docs/tmpl/glyphs.sgml b/docs/tmpl/glyphs.sgml index 2191d7a7..44dff0db 100644 --- a/docs/tmpl/glyphs.sgml +++ b/docs/tmpl/glyphs.sgml @@ -68,7 +68,6 @@ Converts a dimension to device units by ceiling. <para> Rounds a dimension to whole device units, but does not convert it to device units. - </para> @d: a dimension in Pango units. diff --git a/docs/tmpl/opentype.sgml b/docs/tmpl/opentype.sgml index 6c4f7be0..f5a61930 100644 --- a/docs/tmpl/opentype.sgml +++ b/docs/tmpl/opentype.sgml @@ -65,17 +65,38 @@ It contains the following fields. <!-- ##### STRUCT PangoOTRuleset ##### --> <para> -The #PangoOTRuleSet structure holds a +The #PangoOTRuleset structure holds a set of features selected from the tables in an OpenType font. (A feature is an operation such as adjusting glyph positioning that should be applied to a text feature such as a certain -type of accent.) A #PangoOTRuleSet +type of accent.) A #PangoOTRuleset is created with pango_ot_ruleset_new(), features are added to it with pango_ot_ruleset_add_feature(), then it is applied to a #PangoGlyphString with pango_ot_ruleset_shape(). </para> +<!-- ##### STRUCT PangoOTRulesetDescription ##### --> +<para> +The #PangoOTRuleset structure holds all the information needed +to build a complete #PangoOTRuleset from an OpenType font. +The main use of this struct is to act as the key for a per-font +hash of rulesets. The user populates a ruleset description and +gets the ruleset using pango_ot_ruleset_get_for(). +</para> + +@script: a #PangoScript. +@language: a #PangoLanguage. +@static_gsub_features: static map of GSUB features, or %NULL. +@n_static_gsub_features: length of @static_gsub_features, or 0. +@static_gpos_features: static map of GPOS features, or %NULL. +@n_static_gpos_features: length of @static_gpos_features, or 0. +@other_features: map of extra features to add to both GSUB and GPOS, or %NULL. + Unlike the static maps, this pointer need not live beyond + the life of function calls taking this struct. +@n_other_features: length of @other_features, or 0. +@Since: 1.18 + <!-- ##### ENUM PangoOTTableType ##### --> <para> The <type>PangoOTTableType</type> enumeration values are used to @@ -96,6 +117,7 @@ represented as a char array instead of a #PangoOTTag for convenience. @feature_name: feature tag in represented as four-letter ASCII string. @property_bit: the property bit to use for this feature. See pango_ot_ruleset_add_feature() for details. +@Since: 1.18 <!-- ##### MACRO PANGO_OT_ALL_GLYPHS ##### --> <para> @@ -103,6 +125,7 @@ This is used as the property bit in pango_ot_ruleset_add_feature() when a feature should be applied to all glyphs. </para> +@Since: 1.16 <!-- ##### MACRO PANGO_OT_NO_FEATURE ##### --> @@ -114,6 +137,7 @@ automatically skips this value, so no special handling is required by the user. </para> +@Since: 1.18 <!-- ##### MACRO PANGO_OT_NO_SCRIPT ##### --> @@ -126,6 +150,7 @@ taking a script index essentially return if the input script index is this value, so no special handling is required by the user. </para> +@Since: 1.18 <!-- ##### MACRO PANGO_OT_DEFAULT_LANGUAGE ##### --> @@ -141,6 +166,7 @@ pango_ot_info_find_feature() without having to worry about falling back to default language system explicitly. </para> +@Since: 1.16 <!-- ##### MACRO PANGO_OT_TAG_DEFAULT_LANGUAGE ##### --> @@ -152,6 +178,7 @@ pango_ot_info_find_language() as that function falls back to returning default language-system if the requested language tag is not found. </para> +@Since: 1.18 <!-- ##### MACRO PANGO_OT_TAG_DEFAULT_SCRIPT ##### --> @@ -161,6 +188,7 @@ returned as script tag by pango_ot_tag_from_script() if the requested script is not found. </para> +@Since: 1.18 <!-- ##### FUNCTION pango_ot_info_get ##### --> @@ -320,6 +348,16 @@ is not found. @glyphs: +<!-- ##### FUNCTION pango_ot_ruleset_get_for ##### --> +<para> + +</para> + +@info: +@desc: +@Returns: + + <!-- ##### FUNCTION pango_ot_ruleset_new ##### --> <para> @@ -393,6 +431,42 @@ is not found. @buffer: +<!-- ##### FUNCTION pango_ot_ruleset_description_copy ##### --> +<para> + +</para> + +@desc: +@Returns: + + +<!-- ##### FUNCTION pango_ot_ruleset_description_equal ##### --> +<para> + +</para> + +@desc1: +@desc2: +@Returns: + + +<!-- ##### FUNCTION pango_ot_ruleset_description_free ##### --> +<para> + +</para> + +@desc: + + +<!-- ##### FUNCTION pango_ot_ruleset_description_hash ##### --> +<para> + +</para> + +@desc: +@Returns: + + <!-- ##### FUNCTION pango_ot_tag_from_language ##### --> <para> diff --git a/pango/pango-ot-ruleset.c b/pango/pango-ot-ruleset.c index 8efdcff9..7296fa90 100644 --- a/pango/pango-ot-ruleset.c +++ b/pango/pango-ot-ruleset.c @@ -95,6 +95,83 @@ pango_ot_ruleset_finalize (GObject *object) } /** + * pango_ot_ruleset_get_for: + * @info: a #PangoOTInfo. + * @desc: a #PangoOTRulesetDescription. + * + * Returns a ruleset for the given OpenType info and ruleset + * description. The returned ruleset should not be modified. + * + * The static feature map members of @desc should be alive as + * long as @info is. + * + * Return value: the #PangoOTRuleset for @desc. This object will have + * the same lifetime as @info. + * + * Since: 1.18 + **/ +const PangoOTRuleset * +pango_ot_ruleset_get_for (PangoOTInfo *info, + const PangoOTRulesetDescription *desc) +{ + PangoOTRuleset *ruleset; + static GQuark rulesets_quark = 0; + GHashTable *rulesets; + + g_return_val_if_fail (info != NULL, NULL); + g_return_val_if_fail (desc != NULL, NULL); + + if (!rulesets_quark) + rulesets_quark = g_quark_from_string ("pango-info-rulesets"); + + rulesets = g_object_get_qdata (G_OBJECT (info), rulesets_quark); + + if (!rulesets) + { + rulesets = g_hash_table_new_full ((GHashFunc) pango_ot_ruleset_description_hash, + (GEqualFunc) pango_ot_ruleset_description_equal, + (GDestroyNotify) pango_ot_ruleset_description_free, + (GDestroyNotify) g_object_unref); + + g_object_set_qdata_full (G_OBJECT (info), rulesets_quark, rulesets, (GDestroyNotify) g_hash_table_destroy); + } + + ruleset = g_hash_table_lookup (rulesets, desc); + + if (!ruleset) + { + ruleset = pango_ot_ruleset_new_for (info, + desc->script, + desc->language); + + if (desc->n_static_gsub_features) + pango_ot_ruleset_maybe_add_features (ruleset, PANGO_OT_TABLE_GSUB, + desc->static_gsub_features, + desc->n_static_gsub_features); + if (desc->n_static_gpos_features) + pango_ot_ruleset_maybe_add_features (ruleset, PANGO_OT_TABLE_GPOS, + desc->static_gpos_features, + desc->n_static_gpos_features); + + if (desc->n_other_features) + { + pango_ot_ruleset_maybe_add_features (ruleset, PANGO_OT_TABLE_GSUB, + desc->other_features, + desc->n_other_features); + pango_ot_ruleset_maybe_add_features (ruleset, PANGO_OT_TABLE_GPOS, + desc->other_features, + desc->n_other_features); + } + + g_hash_table_insert (rulesets, + pango_ot_ruleset_description_copy (desc), + ruleset); + } + + return ruleset; +} + +/** * pango_ot_ruleset_new: * @info: a #PangoOTInfo. * @@ -108,7 +185,7 @@ pango_ot_ruleset_new (PangoOTInfo *info) { PangoOTRuleset *ruleset; - g_return_val_if_fail (info != NULL, NULL); + g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL); ruleset = g_object_new (PANGO_TYPE_OT_RULESET, NULL); @@ -178,10 +255,14 @@ pango_ot_ruleset_new_for (PangoOTInfo *info, PangoScript script, PangoLanguage *language) { - PangoOTRuleset *ruleset = pango_ot_ruleset_new (info); + PangoOTRuleset *ruleset; PangoOTTag script_tag, language_tag; PangoOTTableType table_type; + g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL); + + ruleset = pango_ot_ruleset_new (info); + script_tag = pango_ot_tag_from_script (script); language_tag = pango_ot_tag_from_language (language); @@ -226,7 +307,7 @@ pango_ot_ruleset_add_feature (PangoOTRuleset *ruleset, PangoOTRule tmp_rule; g_return_if_fail (PANGO_IS_OT_RULESET (ruleset)); - g_return_if_fail (PANGO_IS_OT_INFO (ruleset->info)); + g_return_if_fail (ruleset->info != NULL); if (feature_index == PANGO_OT_NO_FEATURE) return; @@ -269,7 +350,7 @@ pango_ot_ruleset_maybe_add_feature (PangoOTRuleset *ruleset, guint feature_index; g_return_val_if_fail (PANGO_IS_OT_RULESET (ruleset), FALSE); - g_return_val_if_fail (PANGO_IS_OT_INFO (ruleset->info), FALSE); + g_return_val_if_fail (ruleset->info != NULL, FALSE); pango_ot_info_find_feature (ruleset->info, table_type, feature_tag, @@ -304,16 +385,16 @@ pango_ot_ruleset_maybe_add_feature (PangoOTRuleset *ruleset, * * Since: 1.18 **/ -int +guint pango_ot_ruleset_maybe_add_features (PangoOTRuleset *ruleset, PangoOTTableType table_type, const PangoOTFeatureMap *features, - int n_features) + guint n_features) { - int i, n_found_features = 0; + guint i, n_found_features = 0; g_return_val_if_fail (PANGO_IS_OT_RULESET (ruleset), 0); - g_return_val_if_fail (PANGO_IS_OT_INFO (ruleset->info), 0); + g_return_val_if_fail (ruleset->info != NULL, 0); for (i = 0; i < n_features; i++) { @@ -350,7 +431,7 @@ pango_ot_ruleset_substitute (const PangoOTRuleset *ruleset, HB_GSUB gsub = NULL; g_return_if_fail (PANGO_IS_OT_RULESET (ruleset)); - g_return_if_fail (PANGO_IS_OT_INFO (ruleset->info)); + g_return_if_fail (ruleset->info != NULL); for (i = 0; i < ruleset->rules->len; i++) { @@ -394,7 +475,7 @@ pango_ot_ruleset_position (const PangoOTRuleset *ruleset, HB_GPOS gpos = NULL; g_return_if_fail (PANGO_IS_OT_RULESET (ruleset)); - g_return_if_fail (PANGO_IS_OT_INFO (ruleset->info)); + g_return_if_fail (ruleset->info != NULL); for (i = 0; i < ruleset->rules->len; i++) { @@ -422,3 +503,148 @@ pango_ot_ruleset_position (const PangoOTRuleset *ruleset, buffer->applied_gpos = TRUE; } +/* ruleset descriptions */ + +/** + * pango_ot_ruleset_description_hash: + * @desc: a ruleset description + * + * Computes a hash of a #PangoOTRulesetDescription structure suitable + * to be used, for example, as an argument to g_hash_table_new(). + * + * Return value: the hash value. + * + * Since: 1.18 + **/ +guint +pango_ot_ruleset_description_hash (const PangoOTRulesetDescription *desc) +{ + guint hash = 0; + guint i; + + hash ^= desc->script; + hash ^= GPOINTER_TO_UINT (desc->language); + + hash ^= desc->n_static_gsub_features << 8; + hash ^= GPOINTER_TO_UINT (desc->static_gsub_features); + + hash ^= desc->n_static_gpos_features << 12; + hash ^= GPOINTER_TO_UINT (desc->static_gpos_features); + + hash ^= desc->n_other_features << 16; + for (i = 0; i < desc->n_other_features; i++) + { + hash ^= * (guint32 *) desc->other_features[i].feature_name; + hash ^= desc->other_features[i].property_bit; + } + + return hash; +} + +/** + * pango_ot_ruleset_description_equal: + * @desc1: a ruleset description + * @desc2: a ruleset description + * + * Compares two ruleset descriptions for equality. + * Two ruleset descriptions are considered equal if the rulesets + * they describe are provably identical. This means that their + * script, language, and all feature sets should be equal. For static feature + * sets, the array addresses are compared directly, while for other + * features, the list of features is compared one by one. + * (Two ruleset descriptions may result in identical rulesets + * being created, but still compare %FALSE.) + * + * Return value: %TRUE if two ruleset descriptions are identical, + * %FALSE otherwise. + * + * Since: 1.18 + **/ +gboolean +pango_ot_ruleset_description_equal (const PangoOTRulesetDescription *desc1, + const PangoOTRulesetDescription *desc2) +{ + guint i; + +#undef CHECK +#define CHECK(x) if (desc1->x != desc2->x) return FALSE; +#define CHECK_FEATURE_NAME(x) if (*(guint32 *)desc1->x != *(guint32 *)desc2->x) return FALSE + + CHECK (script); + CHECK (language); + + CHECK (static_gsub_features); + CHECK (n_static_gsub_features); + CHECK (static_gpos_features); + CHECK (n_static_gpos_features); + + CHECK (n_other_features); + + for (i = 0; i < desc1->n_other_features; i++) + { + CHECK_FEATURE_NAME (other_features[i].feature_name); + CHECK (other_features[i].property_bit); + } + +#undef CHECK + + return TRUE; +} + +/** + * pango_ot_ruleset_description_copy: + * @desc: ruleset description to copy + * + * Creates a copy of @desc, which should be freed with + * pango_ot_ruleset_description_free(). Primarily used internally + * by pango_ot_ruleset_get_for() to cache rulesets for ruleset + * descriptions. + * + * Return value: the newly allocated #PangoOTRulesetDescription, which + * should be freed with pango_ot_ruleset_description_free(). + * + * Since: 1.18 + **/ +PangoOTRulesetDescription * +pango_ot_ruleset_description_copy (const PangoOTRulesetDescription *desc) +{ + PangoOTRulesetDescription *copy; + + g_return_val_if_fail (desc != NULL, NULL); + + copy = g_slice_new (PangoOTRulesetDescription); + + *copy = *desc; + + if (desc->n_other_features) + { + PangoOTFeatureMap *map = g_new (PangoOTFeatureMap, desc->n_other_features); + memcpy (map, desc->other_features, desc->n_other_features * sizeof (PangoOTFeatureMap)); + copy->other_features = map; + } + else + { + copy->other_features = NULL; + } + + return copy; +} + +/** + * pango_ot_ruleset_description_free: + * @desc: an allocated #PangoOTRulesetDescription + * + * Frees a ruleset description allocated by + * pango_ot_ruleset_description_copy(). + * + * Since: 1.18 + **/ +void +pango_ot_ruleset_description_free (PangoOTRulesetDescription *desc) +{ + g_return_if_fail (desc != NULL); + + free ((gpointer) desc->other_features); + + g_slice_free (PangoOTRulesetDescription, desc); +} diff --git a/pango/pango-ot.h b/pango/pango-ot.h index 7959c6d6..1be9d2c3 100644 --- a/pango/pango-ot.h +++ b/pango/pango-ot.h @@ -39,6 +39,7 @@ typedef struct _PangoOTBuffer PangoOTBuffer; typedef struct _PangoOTGlyph PangoOTGlyph; typedef struct _PangoOTRuleset PangoOTRuleset; typedef struct _PangoOTFeatureMap PangoOTFeatureMap; +typedef struct _PangoOTRulesetDescription PangoOTRulesetDescription; typedef enum { @@ -72,6 +73,18 @@ struct _PangoOTFeatureMap gulong property_bit; }; +struct _PangoOTRulesetDescription { + PangoScript script; + PangoLanguage *language; + const PangoOTFeatureMap *static_gsub_features; + guint n_static_gsub_features; + const PangoOTFeatureMap *static_gpos_features; + guint n_static_gpos_features; + const PangoOTFeatureMap *other_features; + guint n_other_features; +}; + + PangoOTInfo *pango_ot_info_get (FT_Face face); gboolean pango_ot_info_find_script (PangoOTInfo *info, @@ -121,6 +134,8 @@ void pango_ot_buffer_output (const PangoOTBuffer *buffer, void pango_ot_buffer_set_zero_width_marks (PangoOTBuffer *buffer, gboolean zero_width_marks); +const PangoOTRuleset *pango_ot_ruleset_get_for (PangoOTInfo *info, + const PangoOTRulesetDescription *desc); PangoOTRuleset *pango_ot_ruleset_new (PangoOTInfo *info); PangoOTRuleset *pango_ot_ruleset_new_for (PangoOTInfo *info, PangoScript script, @@ -133,10 +148,10 @@ gboolean pango_ot_ruleset_maybe_add_feature (PangoOTRuleset *ruleset, PangoOTTableType table_type, PangoOTTag feature_tag, gulong property_bit); -int pango_ot_ruleset_maybe_add_features (PangoOTRuleset *ruleset, +guint pango_ot_ruleset_maybe_add_features (PangoOTRuleset *ruleset, PangoOTTableType table_type, const PangoOTFeatureMap *features, - int n_features); + guint n_features); void pango_ot_ruleset_substitute (const PangoOTRuleset *ruleset, PangoOTBuffer *buffer); void pango_ot_ruleset_position (const PangoOTRuleset *ruleset, @@ -146,6 +161,13 @@ PangoOTTag pango_ot_tag_from_script (PangoScript script); PangoLanguage* pango_ot_tag_to_language (PangoOTTag language_tag); PangoOTTag pango_ot_tag_from_language (PangoLanguage *language); +guint pango_ot_ruleset_description_hash (const PangoOTRulesetDescription *desc); +gboolean pango_ot_ruleset_description_equal (const PangoOTRulesetDescription *desc1, + const PangoOTRulesetDescription *desc2); +PangoOTRulesetDescription *pango_ot_ruleset_description_copy (const PangoOTRulesetDescription *desc); +void pango_ot_ruleset_description_free (PangoOTRulesetDescription *desc); + + #endif /* PANGO_ENABLE_ENGINE */ G_END_DECLS diff --git a/pango/pangoxft.h b/pango/pangoxft.h index 53387a5a..bb856b18 100644 --- a/pango/pangoxft.h +++ b/pango/pangoxft.h @@ -1,5 +1,5 @@ /* Pango - * pangox.h: + * pangoxft.h: * * Copyright (C) 1999 Red Hat Software * Copyright (C) 2000 SuSE Linux Ltd |