summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog32
-rw-r--r--docs/pango-sections.txt6
-rw-r--r--docs/tmpl/glyphs.sgml1
-rw-r--r--docs/tmpl/opentype.sgml78
-rw-r--r--pango/pango-ot-ruleset.c246
-rw-r--r--pango/pango-ot.h26
-rw-r--r--pango/pangoxft.h2
7 files changed, 375 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index f9100ac4..e621947c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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