summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
Diffstat (limited to 'pango')
-rw-r--r--pango/modules.c301
-rw-r--r--pango/pango-context.c892
-rw-r--r--pango/pango-engine-private.h19
-rw-r--r--pango/pango-engine.c59
-rw-r--r--pango/pango-engine.h17
-rw-r--r--pango/pango-fontmap.c21
-rw-r--r--pango/pango-fontmap.h5
-rw-r--r--pango/pango-fontset.c110
-rw-r--r--pango/pango-fontset.h37
-rw-r--r--pango/pango-modules.h14
-rw-r--r--pango/pango-script-lang-table.h191
-rw-r--r--pango/pango-script.c172
-rw-r--r--pango/pango-script.h6
-rw-r--r--pango/pangofc-fontmap.c1
-rw-r--r--pango/pangowin32-fontmap.c3
-rw-r--r--pango/pangox-fontmap.c44
-rw-r--r--pango/querymodules.c30
17 files changed, 1355 insertions, 567 deletions
diff --git a/pango/modules.c b/pango/modules.c
index 84cffff5..2f11dbdb 100644
--- a/pango/modules.c
+++ b/pango/modules.c
@@ -27,6 +27,7 @@
#include <gmodule.h>
+#include "pango-enum-types.h"
#include "pango-modules.h"
#include "pango-utils.h"
#include "pango-impl-utils.h"
@@ -42,19 +43,15 @@ typedef struct _PangoMapInfo PangoMapInfo;
typedef struct _PangoEnginePair PangoEnginePair;
typedef struct _PangoSubmap PangoSubmap;
-struct _PangoSubmap
+struct _PangoMap
{
- gboolean is_leaf;
- union {
- PangoMapEntry entry;
- PangoMapEntry *leaves;
- } d;
+ GArray *entries;
};
-struct _PangoMap
+struct _PangoMapEntry
{
- gint n_submaps;
- PangoSubmap *submaps;
+ GSList *exact;
+ GSList *fallback;
};
struct _PangoMapInfo
@@ -341,6 +338,21 @@ find_or_create_module (const char *raw_path)
return module;
}
+static PangoScript
+script_from_string (const char *str)
+{
+ static GEnumClass *class = NULL;
+ GEnumValue *value;
+ if (!class)
+ class = g_type_class_ref (PANGO_TYPE_SCRIPT);
+
+ value = g_enum_get_value_by_nick (class, str);
+ if (!value)
+ return PANGO_SCRIPT_INVALID_CODE;
+
+ return value->value;
+}
+
static gboolean /* Returns true if succeeded, false if failed */
process_module_file (FILE *module_file)
{
@@ -351,13 +363,14 @@ process_module_file (FILE *module_file)
while (pango_read_line (module_file, line_buf))
{
PangoEnginePair *pair = g_new (PangoEnginePair, 1);
- PangoEngineRange *range;
- GList *ranges = NULL;
+ PangoEngineScriptInfo *script_info;
+ PangoScript script;
+ GList *scripts = NULL;
GList *tmp_list;
- const char *p, *q;
+ const char *p;
+ char *q;
int i;
- int start, end;
p = line_buf->str;
@@ -391,26 +404,25 @@ process_module_file (FILE *module_file)
pair->info.render_type = g_strdup (tmp_buf->str);
break;
default:
- range = g_new (PangoEngineRange, 1);
- if (sscanf(tmp_buf->str, "%d-%d:", &start, &end) != 2)
+ q = strchr (tmp_buf->str, ':');
+ if (!q)
{
- g_printerr ("Error reading modules file");
have_error = TRUE;
goto error;
}
- q = strchr (tmp_buf->str, ':');
- if (!q)
+ *q = '\0';
+ script = script_from_string (tmp_buf->str);
+ if (script == PANGO_SCRIPT_INVALID_CODE)
{
- g_printerr ( "Error reading modules file");
have_error = TRUE;
goto error;
}
- q++;
- range->start = start;
- range->end = end;
- range->langs = g_strdup (q);
- ranges = g_list_prepend (ranges, range);
+ script_info = g_new (PangoEngineScriptInfo, 1);
+ script_info->script = script;
+ script_info->langs = g_strdup (q + 1);
+
+ scripts = g_list_prepend (scripts, script_info);
}
if (!pango_skip_space (&p))
@@ -421,19 +433,18 @@ process_module_file (FILE *module_file)
if (i<3)
{
- g_printerr ("Error reading modules file");
have_error = TRUE;
goto error;
}
- ranges = g_list_reverse (ranges);
- pair->info.n_ranges = g_list_length (ranges);
- pair->info.ranges = g_new (PangoEngineRange, pair->info.n_ranges);
+ scripts = g_list_reverse (scripts);
+ pair->info.n_scripts = g_list_length (scripts);
+ pair->info.scripts = g_new (PangoEngineScriptInfo, pair->info.n_scripts);
- tmp_list = ranges;
- for (i=0; i<pair->info.n_ranges; i++)
+ tmp_list = scripts;
+ for (i=0; i<pair->info.n_scripts; i++)
{
- pair->info.ranges[i] = *(PangoEngineRange *)tmp_list->data;
+ pair->info.scripts[i] = *(PangoEngineScriptInfo *)tmp_list->data;
tmp_list = tmp_list->next;
}
@@ -442,11 +453,12 @@ process_module_file (FILE *module_file)
dlloaded_engines = g_slist_prepend (dlloaded_engines, pair);
error:
- g_list_foreach (ranges, (GFunc)g_free, NULL);
- g_list_free (ranges);
+ g_list_foreach (scripts, (GFunc)g_free, NULL);
+ g_list_free (scripts);
if (have_error)
{
+ g_printerr ("Error reading Pango modules file\n");
g_free(pair);
break;
}
@@ -497,17 +509,6 @@ read_modules (void)
}
static void
-set_entry (PangoMapEntry *entry, gboolean is_exact, PangoEngineInfo *info)
-{
- if ((is_exact && !entry->is_exact) ||
- !entry->info)
- {
- entry->is_exact = is_exact;
- entry->info = info;
- }
-}
-
-static void
init_modules (void)
{
static gboolean init = FALSE;
@@ -523,90 +524,35 @@ init_modules (void)
read_modules ();
}
-static PangoSubmap *
-map_get_submap (PangoMap *map,
- int index)
-{
- if (index >= map->n_submaps)
- {
- /* Round up to a multiple of 256 */
- int new_n_submaps = (index + 0x100) & ~0xff;
- int i;
-
- map->submaps = g_renew (PangoSubmap, map->submaps, new_n_submaps);
- for (i=map->n_submaps; i<new_n_submaps; i++)
- {
- map->submaps[i].is_leaf = TRUE;
- map->submaps[i].d.entry.info = NULL;
- map->submaps[i].d.entry.is_exact = FALSE;
- }
-
- map->n_submaps = new_n_submaps;
- }
-
- return &map->submaps[index];
-}
-
static void
map_add_engine (PangoMapInfo *info,
PangoEnginePair *pair)
{
- int submap;
- int i, j;
PangoMap *map = info->map;
+ int i;
- for (i=0; i<pair->info.n_ranges; i++)
+ for (i=0; i<pair->info.n_scripts; i++)
{
+ PangoScript script;
+ PangoMapEntry *entry;
gboolean is_exact = FALSE;
- if (pair->info.ranges[i].langs)
+ if (pair->info.scripts[i].langs)
{
- if (pango_language_matches (info->language, pair->info.ranges[i].langs))
+ if (pango_language_matches (info->language, pair->info.scripts[i].langs))
is_exact = TRUE;
}
-
- for (submap = pair->info.ranges[i].start / 256;
- submap <= pair->info.ranges[i].end / 256;
- submap ++)
- {
- PangoSubmap *submap_struct = map_get_submap (map, submap);
- gunichar start;
- gunichar end;
- if (submap == pair->info.ranges[i].start / 256)
- start = pair->info.ranges[i].start % 256;
- else
- start = 0;
-
- if (submap == pair->info.ranges[i].end / 256)
- end = pair->info.ranges[i].end % 256;
- else
- end = 255;
-
- if (submap_struct->is_leaf &&
- start == 0 && end == 255)
- {
- set_entry (&submap_struct->d.entry,
- is_exact, &pair->info);
- }
- else
- {
- if (submap_struct->is_leaf)
- {
- PangoMapEntry old_entry = submap_struct->d.entry;
-
- submap_struct->is_leaf = FALSE;
- submap_struct->d.leaves = g_new (PangoMapEntry, 256);
- for (j=0; j<256; j++)
- submap_struct->d.leaves[j] = old_entry;
- }
-
- for (j=start; j<=end; j++)
- set_entry (&submap_struct->d.leaves[j],
- is_exact, &pair->info);
-
- }
- }
+ script = pair->info.scripts[i].script;
+ if (script >= map->entries->len)
+ g_array_set_size (map->entries, script + 1);
+
+ entry = &g_array_index (map->entries, PangoMapEntry, script);
+
+ if (is_exact)
+ entry->exact = g_slist_prepend (entry->exact, pair);
+ else
+ entry->exact = g_slist_prepend (entry->fallback, pair);
}
}
@@ -662,73 +608,110 @@ build_map (PangoMapInfo *info)
}
info->map = map = g_new (PangoMap, 1);
- map->submaps = NULL;
- map->n_submaps = 0;
-
+ map->entries = g_array_new (FALSE, TRUE, sizeof (PangoMapEntry));
+
map_add_engine_list (info, dlloaded_engines, engine_type, render_type);
map_add_engine_list (info, registered_engines, engine_type, render_type);
}
/**
- * pango_map_get_entry:
+ * pango_map_get_engine:
* @map: a #PangoMap
- * @wc: an ISO-10646 codepoint
+ * @script: a #PangoScript
*
- * Returns the entry in the map for a given codepoint. The entry
- * contains information about the engine that should be used for
- * the codepoint and also whether the engine matches the language
- * tag for which the map was created exactly or just approximately.
+ * Returns the best engine listed in the map for a given script
*
- * Return value: the #PangoMapEntry for the codepoint. This value
- * is owned by the #PangoMap and should not be freed.
+ * Return value: the best engine, if one is listed for the script,
+ * or %NULL. The lookup may cause the engine to be loaded;
+ * once an engine is loaded, it won't be unloaded. If multiple
+ * engines are exact for the script, the choice of which is
+ * returned is arbitrary.
**/
-PangoMapEntry *
-pango_map_get_entry (PangoMap *map,
- guint32 wc)
+PangoEngine *
+pango_map_get_engine (PangoMap *map,
+ PangoScript script)
{
- int i = wc / 256;
-
- if (i < map->n_submaps)
- {
- PangoSubmap *submap = &map->submaps[i];
- return submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256];
- }
+ PangoMapEntry *entry = NULL;
+ PangoMapEntry *common_entry = NULL;
+
+ if (script < map->entries->len)
+ entry = &g_array_index (map->entries, PangoMapEntry, script);
+
+ if (PANGO_SCRIPT_COMMON < map->entries->len)
+ common_entry = &g_array_index (map->entries, PangoMapEntry, PANGO_SCRIPT_COMMON);
+
+ if (entry && entry->exact)
+ return pango_engine_pair_get_engine (entry->exact->data);
+ else if (common_entry && common_entry->exact)
+ return pango_engine_pair_get_engine (common_entry->exact->data);
+ else if (entry && entry->fallback)
+ return pango_engine_pair_get_engine (entry->fallback->data);
+ else if (common_entry && common_entry->fallback)
+ return pango_engine_pair_get_engine (common_entry->fallback->data);
else
+ return NULL;
+}
+
+void
+append_engines (GSList **engine_list,
+ GSList *pair_list)
+{
+ GSList *l;
+
+ for (l = pair_list; l; l = l->next)
{
- static PangoMapEntry default_entry = { NULL, FALSE };
- return &default_entry;
+ PangoEngine *engine = pango_engine_pair_get_engine (l->data);
+ if (engine)
+ *engine_list = g_slist_append (*engine_list, engine);
}
}
/**
- * pango_map_get_engine:
+ * pango_map_get_engines:
* @map: a #PangoMap
- * @wc: an ISO-10646 codepoint
- *
- * Returns the engine listed in the map for a given codepoint.
+ * @script: a #PangoScript
+ * @exact_engines: location to store list of engines that exactly
+ * handle this script.
+ * @fallback_engines: location to store list of engines that approximately
+ * handle this script.
*
- * Return value: the engine, if one is listed for the codepoint,
- * or %NULL. The lookup may cause the engine to be loaded;
- * once an engine is loaded
+ * Finds engines in the map that handle the given script. The returned
+ * lists should be fred with g_slist_free, but the engines in the
+ * lists are owned by GLib and will be kept around permanently, so
+ * they should not be unref'ed.
**/
-PangoEngine *
-pango_map_get_engine (PangoMap *map,
- guint32 wc)
+void
+pango_map_get_engines (PangoMap *map,
+ PangoScript script,
+ GSList **exact_engines,
+ GSList **fallback_engines)
{
- int i = wc / 256;
+ PangoMapEntry *entry = NULL;
+ PangoMapEntry *common_entry = NULL;
+
+ if (script < map->entries->len)
+ entry = &g_array_index (map->entries, PangoMapEntry, script);
+
+ if (PANGO_SCRIPT_COMMON < map->entries->len)
+ common_entry = &g_array_index (map->entries, PangoMapEntry, PANGO_SCRIPT_COMMON);
- if (i < map->n_submaps)
+ if (exact_engines)
{
- PangoSubmap *submap = &map->submaps[i];
- PangoMapEntry *entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256];
-
- if (entry->info)
- return pango_engine_pair_get_engine ((PangoEnginePair *)entry->info);
- else
- return NULL;
+ *exact_engines = NULL;
+ if (entry && entry->exact)
+ append_engines (exact_engines, entry->exact);
+ else if (common_entry && common_entry->exact)
+ append_engines (exact_engines, common_entry->exact);
+ }
+
+ if (fallback_engines)
+ {
+ *fallback_engines = NULL;
+ if (entry && entry->fallback)
+ append_engines (fallback_engines, entry->fallback);
+ else if (common_entry && common_entry->fallback)
+ append_engines (fallback_engines, common_entry->fallback);
}
- else
- return NULL;
}
/**
diff --git a/pango/pango-context.c b/pango/pango-context.c
index 5c19adb9..d6cf6bc9 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -46,15 +46,6 @@ struct _PangoContextClass
};
-static void add_engines (PangoContext *context,
- const gchar *text,
- gint start_index,
- gint length,
- PangoAttrList *attrs,
- PangoAttrIterator *cached_iter,
- gint n_chars,
- PangoAnalysis *analyses);
-
static void pango_context_init (PangoContext *context);
static void pango_context_class_init (PangoContextClass *klass);
static void pango_context_finalize (GObject *object);
@@ -360,299 +351,700 @@ pango_context_get_base_dir (PangoContext *context)
return context->base_dir;
}
-/**
- * pango_itemize:
- * @context: a structure holding information that affects
- the itemization process.
- * @text: the text to itemize.
- * @start_index: first byte in @text to process
- * @length: the number of bytes (not characters) to process
- * after @start_index.
- * This must be >= 0.
- * @attrs: the set of attributes that apply to @text.
- * @cached_iter: Cached attribute iterator, or NULL
- *
- * Breaks a piece of text into segments with consistent
- * directional level and shaping engine. Each byte of @text will
- * be contained in exactly one of the items in the returned list;
- * the generated list of items will be in logical order (the start
- * offsets of the items are ascending).
- *
- * @cached_iter should be an iterator over @attrs currently positioned at a
- * range before or containing @start_index; @cached_iter will be advanced to
- * the range covering the position just after @start_index + @length.
- * (i.e. if itemizing in a loop, just keep passing in the same @cached_iter).
- *
- * Return value: a GList of PangoItem structures.
- */
-GList *
-pango_itemize (PangoContext *context,
- const char *text,
- int start_index,
- int length,
- PangoAttrList *attrs,
- PangoAttrIterator *cached_iter)
+/**********************************************************************/
+
+static gboolean
+advance_attr_iterator_to (PangoAttrIterator *iterator,
+ int start_index)
{
- gunichar *text_ucs4;
- long n_chars, i;
- guint8 *embedding_levels;
- PangoDirection base_dir;
+ int start_range, end_range;
+
+ pango_attr_iterator_range (iterator, &start_range, &end_range);
+
+ while (start_index >= end_range)
+ {
+ if (!pango_attr_iterator_next (iterator))
+ return FALSE;
+ pango_attr_iterator_range (iterator, &start_range, &end_range);
+ }
+
+ if (start_range > start_index)
+ g_warning ("In pango_itemize(), the cached iterator passed in "
+ "had already moved beyond the start_index");
+
+ return TRUE;
+}
+
+/***************************************************************************
+ * We cache the results of character,fontset => font,shaper in a hash table
+ ***************************************************************************/
+
+typedef struct {
+ GHashTable *hash;
+} ShaperFontCache;
+
+typedef struct {
+ PangoEngineShape *shape_engine;
+ PangoFont *font;
+} ShaperFontElement;
+
+static void
+shaper_font_cache_destroy (ShaperFontCache *cache)
+{
+ g_hash_table_destroy (cache->hash);
+ g_free (cache);
+}
+
+static void
+shaper_font_element_destroy (ShaperFontElement *element)
+{
+ if (element->font)
+ g_object_unref (element->font);
+ g_free (element);
+}
+
+static ShaperFontCache *
+get_shaper_font_cache (PangoFontset *fontset)
+{
+ ShaperFontCache *cache;
+
+ static GQuark cache_quark = 0;
+ if (!cache_quark)
+ cache_quark = g_quark_from_static_string ("pango-shaper-font-cache");
+
+ cache = g_object_get_qdata (G_OBJECT (fontset), cache_quark);
+ if (!cache)
+ {
+ cache = g_new (ShaperFontCache, 1);
+ cache->hash = g_hash_table_new_full (g_direct_hash, NULL,
+ NULL, (GDestroyNotify)shaper_font_element_destroy);
+
+ g_object_set_qdata_full (G_OBJECT (fontset), cache_quark,
+ cache, (GDestroyNotify)shaper_font_cache_destroy);
+ }
+
+ return cache;
+}
+
+static gboolean
+shaper_font_cache_get (ShaperFontCache *cache,
+ gunichar wc,
+ PangoEngineShape **shape_engine,
+ PangoFont **font)
+{
+ ShaperFontElement *element;
+
+ element = g_hash_table_lookup (cache->hash, GUINT_TO_POINTER (wc));
+ if (element)
+ {
+ *shape_engine = element->shape_engine;
+ *font = element->font;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void
+shaper_font_cache_insert (ShaperFontCache *cache,
+ gunichar wc,
+ PangoEngineShape *shape_engine,
+ PangoFont *font)
+{
+ ShaperFontElement *element = g_new (ShaperFontElement, 1);
+ element->shape_engine = shape_engine;
+ element->font = font;
+
+ g_hash_table_insert (cache->hash, GUINT_TO_POINTER (wc), element);
+}
+
+/**********************************************************************/
+
+typedef enum {
+ EMBEDDING_CHANGED = 1 << 0,
+ SCRIPT_CHANGED = 1 << 1,
+ LANG_CHANGED = 1 << 2,
+ FONT_CHANGED = 1 << 3,
+ DERIVED_LANG_CHANGED = 1 << 4
+} ChangedFlags;
+
+typedef struct _ItemizeState ItemizeState;
+
+struct _ItemizeState
+{
+ PangoContext *context;
+ const char *text;
+ const char *end;
+
+ const char *run_start;
+ const char *run_end;
+
+ GList *result;
PangoItem *item;
- const char *p;
- const char *next;
- GList *result = NULL;
- PangoAnalysis *analyses;
+ guint8 *embedding_levels;
+ int embedding_end_offset;
+ const char *embedding_end;
+ guint8 embedding;
- g_return_val_if_fail (context != NULL, NULL);
- g_return_val_if_fail (start_index >= 0, NULL);
- g_return_val_if_fail (length >= 0, NULL);
- g_return_val_if_fail (length == 0 || text != NULL, NULL);
+ PangoAttrIterator *attr_iter;
+ gboolean free_attr_iter;
+ const char *attr_end;
+ PangoFontDescription *font_desc;
+ PangoLanguage *lang;
+ GSList *extra_attrs;
+ gboolean copy_extra_attrs;
- if (length == 0)
- return NULL;
+ ChangedFlags changed;
+
+ PangoScriptIter *script_iter;
+ const char *script_end;
+ PangoScript script;
- base_dir = context->base_dir;
+ PangoLanguage *derived_lang;
+ PangoEngineLang *lang_engine;
+
+ PangoFontset *current_fonts;
+ ShaperFontCache *cache;
+
+ GSList *exact_engines;
+ GSList *fallback_engines;
+};
- if (length == 0)
- return NULL;
+static void
+update_embedding_end (ItemizeState *state)
+{
+ state->embedding = state->embedding_levels[state->embedding_end_offset];
+ while (state->embedding_end < state->end &&
+ state->embedding_levels[state->embedding_end_offset] == state->embedding)
+ {
+ state->embedding_end_offset++;
+ state->embedding_end = g_utf8_next_char (state->embedding_end);
+ }
+
+ state->changed |= EMBEDDING_CHANGED;
+}
+
+static void
+update_attr_iterator (ItemizeState *state)
+{
+ PangoLanguage *old_lang;
+ int end_index;
+
+ pango_attr_iterator_range (state->attr_iter, NULL, &end_index);
+ if (end_index < state->end - state->text)
+ state->attr_end = state->text + end_index;
+ else
+ state->attr_end = state->end;
+
+ old_lang = state->lang;
+ state->font_desc = pango_font_description_copy_static (state->context->font_desc);
+ pango_attr_iterator_get_font (state->attr_iter, state->font_desc,
+ &state->lang, &state->extra_attrs);
+ state->copy_extra_attrs = FALSE;
+
+ state->changed |= FONT_CHANGED;
+ if (state->lang != old_lang)
+ state->changed |= LANG_CHANGED;
+}
+static void
+update_end (ItemizeState *state)
+{
+ state->run_end = state->embedding_end;
+ if (state->attr_end < state->run_end)
+ state->run_end = state->attr_end;
+ if (state->script_end < state->run_end)
+ state->run_end = state->script_end;
+}
+
+static void
+itemize_state_init (ItemizeState *state,
+ PangoContext *context,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter)
+{
+ PangoDirection base_dir;
+ gunichar *text_ucs4;
+ long n_chars;
+
+ state->context = context;
+ state->text = text;
+ state->end = text + start_index + length;
+
+ state->result = NULL;
+ state->item = NULL;
+
+ state->run_start = text + start_index;
+
/* First, apply the bidirectional algorithm to break
* the text into directional runs.
*/
- text_ucs4 = g_utf8_to_ucs4_fast (text + start_index, length, &n_chars);
-
- embedding_levels = g_new (guint8, n_chars);
+ base_dir = context->base_dir;
+ text_ucs4 = g_utf8_to_ucs4_fast (text + start_index, length, &n_chars);
+ state->embedding_levels = g_new (guint8, n_chars);
pango_log2vis_get_embedding_levels (text_ucs4, n_chars, &base_dir,
- embedding_levels);
-
- /* Storing ranges would be more efficient, but also more
- * complicated... we take the simple approach for now.
+ state->embedding_levels);
+ g_free (text_ucs4);
+
+ state->embedding_end_offset = 0;
+ state->embedding_end = text + start_index;
+ update_embedding_end (state);
+
+ /* Initialize the attribute iterator
*/
+ if (cached_iter)
+ {
+ state->attr_iter = cached_iter;
+ state->free_attr_iter = FALSE;
+ }
+ else
+ {
+ state->attr_iter = pango_attr_list_get_iterator (attrs);
+ state->free_attr_iter = TRUE;
+ }
- analyses = g_new0 (PangoAnalysis, n_chars);
+ advance_attr_iterator_to (state->attr_iter, start_index);
+ update_attr_iterator (state);
- /* Now, fill in the appropriate shapers, language engines and fonts for
- * each character.
+ /* Initialize the script iterator
*/
+ state->script_iter = pango_script_iter_new (text + start_index, length);
+ pango_script_iter_get_range (state->script_iter, NULL,
+ &state->script_end, &state->script);
+
+ update_end (state);
+
+ state->derived_lang = NULL;
+ state->lang_engine = NULL;
+ state->current_fonts = NULL;
+ state->cache = NULL;
+ state->exact_engines = NULL;
+ state->fallback_engines = NULL;
+
+ state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED | FONT_CHANGED;
+}
- add_engines (context, text, start_index, length, attrs,
- cached_iter,
- n_chars,
- analyses);
+static gboolean
+itemize_state_next (ItemizeState *state)
+{
+ if (state->run_end == state->end)
+ return FALSE;
- /* Make a GList of PangoItems out of the above results
- */
+ state->changed = 0;
+
+ state->run_start = state->run_end;
- item = NULL;
- p = text + start_index;
- for (i=0; i<n_chars; i++)
+ if (state->run_end == state->embedding_end)
{
- PangoAnalysis *analysis = &analyses[i];
- PangoAnalysis *last_analysis = i > 0 ? &analyses[i-1] : 0;
-
- next = g_utf8_next_char (p);
-
- if (i == 0 ||
- text_ucs4[i] == '\t' || text_ucs4[i-1] == '\t' ||
- embedding_levels[i] != embedding_levels[i-1] ||
- analysis->shape_engine != last_analysis->shape_engine ||
- analysis->lang_engine != last_analysis->lang_engine ||
- analysis->font != last_analysis->font ||
- analysis->language != last_analysis->language ||
- analysis->extra_attrs != last_analysis->extra_attrs)
+ update_embedding_end (state);
+ }
+
+ if (state->run_end == state->attr_end)
+ {
+ pango_attr_iterator_next (state->attr_iter);
+ update_attr_iterator (state);
+ }
+
+ if (state->run_end == state->script_end)
+ {
+ pango_script_iter_next (state->script_iter);
+ pango_script_iter_get_range (state->script_iter, NULL,
+ &state->script_end, &state->script);
+ state->changed |= SCRIPT_CHANGED;
+ }
+
+ update_end (state);
+
+ return TRUE;
+}
+
+static GSList *
+copy_attr_slist (GSList *attr_slist)
+{
+ GSList *new_list = NULL;
+ GSList *l;
+
+ for (l = attr_slist; l; l = l->next)
+ new_list = g_slist_prepend (new_list, pango_attribute_copy (l->data));
+
+ return g_slist_reverse (new_list);
+}
+
+static void
+itemize_state_fill_shaper (ItemizeState *state,
+ PangoEngineShape *shape_engine,
+ PangoFont *font)
+{
+ GList *l;
+
+ for (l = state->result; l; l = l->next)
+ {
+ PangoItem *item = l->data;
+ if (item->analysis.shape_engine)
+ break;
+ item->analysis.font = g_object_ref (font);
+ item->analysis.shape_engine = shape_engine;
+ }
+}
+
+static void
+itemize_state_add_character (ItemizeState *state,
+ PangoEngineShape *shape_engine,
+ PangoFont *font,
+ gboolean force_break,
+ const char *pos)
+{
+ if (state->item)
+ {
+ if (!force_break &&
+ state->item->analysis.lang_engine == state->lang_engine &&
+ state->item->analysis.shape_engine == shape_engine &&
+ state->item->analysis.font == font)
{
- /* assert that previous item got at least one char */
- g_assert (item == NULL || item->length > 0);
- g_assert (item == NULL || item->num_chars > 0);
-
- item = pango_item_new ();
- item->offset = p - text;
- item->num_chars = 0;
- item->analysis.level = embedding_levels[i];
-
- item->analysis.shape_engine = analysis->shape_engine;
- item->analysis.lang_engine = analysis->lang_engine;
-
- item->analysis.font = analysis->font;
- item->analysis.language = analysis->language;
-
- /* Copy the extra attribute list if necessary */
- if (analysis->extra_attrs && i != 0 && analysis->extra_attrs == last_analysis->extra_attrs)
- {
- GSList *tmp_list = analysis->extra_attrs;
- GSList *new_list = NULL;
- while (tmp_list)
- {
- new_list = g_slist_prepend (new_list,
- pango_attribute_copy (tmp_list->data));
- tmp_list = tmp_list->next;
- }
- item->analysis.extra_attrs = g_slist_reverse (new_list);
- }
- else
- item->analysis.extra_attrs = analysis->extra_attrs;
-
- result = g_list_prepend (result, item);
+ state->item->num_chars++;
+ return;
}
- else
- g_object_unref (analysis->font);
- item->length = (next - text) - item->offset;
- item->num_chars++;
- p = next;
- }
+ state->item->length = (pos - state->text) - state->item->offset;
- g_free (analyses);
- g_free (embedding_levels);
- g_free (text_ucs4);
+ if (!state->item->analysis.shape_engine && shape_engine)
+ {
+ itemize_state_fill_shaper (state, shape_engine, font);
+ }
+ else if (state->item->analysis.shape_engine && !shape_engine)
+ {
+ font = state->item->analysis.font;
+ shape_engine = state->item->analysis.shape_engine;
+ }
+ }
+
+ state->item = pango_item_new ();
+ state->item->offset = pos - state->text;
+ state->item->length = 0;
+ state->item->num_chars = 1;
+ state->item->analysis.shape_engine = shape_engine;
+ state->item->analysis.lang_engine = state->lang_engine;
+
+ if (font)
+ g_object_ref (font);
+ state->item->analysis.font = font;
+
+ state->item->analysis.level = state->embedding;
+ state->item->analysis.language = state->derived_lang;
- return g_list_reverse (result);
+ if (state->copy_extra_attrs)
+ {
+ state->item->analysis.extra_attrs = copy_attr_slist (state->extra_attrs);
+ }
+ else
+ {
+ state->item->analysis.extra_attrs = state->extra_attrs;
+ state->copy_extra_attrs = TRUE;
+ }
+
+ state->result = g_list_prepend (state->result, state->item);
+}
+
+static void
+get_engines (PangoContext *context,
+ PangoLanguage *lang,
+ PangoScript script,
+ GSList **exact_engines,
+ GSList **fallback_engines)
+{
+ const char *engine_type = pango_font_map_get_shape_engine_type (context->font_map);
+ PangoMap *shaper_map = pango_find_map (lang,
+ g_quark_from_string (PANGO_ENGINE_TYPE_SHAPE),
+ g_quark_from_string (engine_type));
+ pango_map_get_engines (shaper_map, script,
+ exact_engines, fallback_engines);
}
+typedef struct {
+ PangoLanguage *lang;
+ gunichar wc;
+ GSList *engines;
+ PangoEngineShape *shape_engine;
+ PangoFont *font;
+} GetShaperFontInfo;
+
static gboolean
-advance_iterator_to (PangoAttrIterator *iterator,
- int start_index)
+get_shaper_and_font_foreach (PangoFontset *fontset,
+ PangoFont *font,
+ gpointer data)
{
- int start_range, end_range;
-
- pango_attr_iterator_range (iterator, &start_range, &end_range);
+ GetShaperFontInfo *info = data;
+ GSList *l;
- while (start_index >= end_range)
+ for (l = info->engines; l; l = l->next)
{
- if (!pango_attr_iterator_next (iterator))
- return FALSE;
- pango_attr_iterator_range (iterator, &start_range, &end_range);
+ PangoEngineShape *engine = l->data;
+ PangoCoverageLevel level;
+
+ level = _pango_engine_shape_covers (engine, font,
+ info->lang, info->wc);
+ if (level != PANGO_COVERAGE_NONE)
+ {
+ info->shape_engine = engine;
+ info->font = g_object_ref (font);
+ return TRUE;
+ }
}
- if (start_range > start_index)
- g_warning ("In pango_itemize(), the cached iterator passed in "
- "had already moved beyond the start_index");
+ return FALSE;
+}
- return TRUE;
+static gboolean
+get_shaper_and_font (ItemizeState *state,
+ gunichar wc,
+ PangoEngineShape **shape_engine,
+ PangoFont **font)
+{
+ GetShaperFontInfo info;
+
+ if (shaper_font_cache_get (state->cache, wc, shape_engine, font))
+ return *shape_engine != NULL;
+
+ if (!state->exact_engines && !state->fallback_engines)
+ get_engines (state->context, state->derived_lang, state->script,
+ &state->exact_engines, &state->fallback_engines);
+
+ info.lang = state->derived_lang;
+ info.wc = wc;
+ info.shape_engine = NULL;
+ info.font = NULL;
+
+ info.engines = state->exact_engines;
+ pango_fontset_foreach (state->current_fonts, get_shaper_and_font_foreach, &info);
+ if (info.shape_engine)
+ {
+ *shape_engine = info.shape_engine;
+ *font = info.font;
+
+ shaper_font_cache_insert (state->cache, wc, *shape_engine, *font);
+
+ return TRUE;
+ }
+
+ info.engines = state->fallback_engines;
+ pango_fontset_foreach (state->current_fonts, get_shaper_and_font_foreach, &info);
+
+ *shape_engine = info.shape_engine;
+ *font = info.font;
+
+ shaper_font_cache_insert (state->cache, wc, *shape_engine, *font);
+
+ return *shape_engine != NULL;
}
static void
-add_engines (PangoContext *context,
- const gchar *text,
- gint start_index,
- gint length,
- PangoAttrList *attrs,
- PangoAttrIterator *cached_iter,
- gint n_chars,
- PangoAnalysis *analyses)
-{
- const char *pos;
- PangoLanguage *language = NULL;
- int next_index;
- GSList *extra_attrs = NULL;
- PangoMap *lang_map = NULL;
- PangoFontDescription *current_desc = NULL;
- PangoFontset *current_fonts = NULL;
- PangoAttrIterator *iterator;
- gboolean first_iteration = TRUE;
- gunichar wc;
- int i = 0;
+itemize_state_reset_shape_engines (ItemizeState *state)
+{
+ g_slist_free (state->exact_engines);
+ state->exact_engines = NULL;
+ g_slist_free (state->fallback_engines);
+ state->fallback_engines = NULL;
+}
- if (cached_iter)
- iterator = cached_iter;
+static PangoLanguage *
+compute_derived_language (PangoLanguage *lang,
+ PangoScript script)
+{
+ PangoLanguage *derived_lang;
+
+ /* Make sure the language tag is consistent with the derived
+ * script. There is no point in marking up a section of
+ * Arabic text with the "en" language tag.
+ */
+ if (lang && pango_language_includes_script (lang, script))
+ derived_lang = lang;
else
- iterator = pango_attr_list_get_iterator (attrs);
+ {
+ derived_lang = pango_script_get_sample_language (script);
+ if (!derived_lang)
+ derived_lang = lang;
+ }
- advance_iterator_to (iterator, start_index);
-
- pango_attr_iterator_range (iterator, NULL, &next_index);
+ return derived_lang;
+}
+
+static PangoMap *
+get_lang_map (PangoLanguage *lang)
+{
+ static guint engine_type_id = 0;
+ static guint render_type_id = 0;
- pos = text + start_index;
- for (i=0; i<n_chars; i++)
+ if (engine_type_id == 0)
{
- PangoAnalysis *analysis = &analyses[i];
-
- if (first_iteration || pos - text == next_index)
- {
- PangoLanguage *next_language;
- PangoFontDescription *next_desc = pango_font_description_copy_static (context->font_desc);
-
- first_iteration = FALSE;
-
- /* Only advance the iterator if we've exhausted a range,
- * not on the first iteration.
- */
- if (pos - text == next_index)
- {
- pango_attr_iterator_next (iterator);
- pango_attr_iterator_range (iterator, NULL, &next_index);
- }
-
- pango_attr_iterator_get_font (iterator, next_desc, &next_language, &extra_attrs);
-
- if (!next_language)
- next_language = context->language;
-
- if (i == 0 || language != next_language)
- {
- static guint engine_type_id = 0;
- static guint render_type_id = 0;
-
- if (engine_type_id == 0)
- {
- engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_LANG);
- render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_NONE);
- }
+ engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_LANG);
+ render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_NONE);
+ }
- lang_map = pango_find_map (next_language,
- engine_type_id, render_type_id);
- }
-
- if (i == 0 ||
- language != next_language ||
- !pango_font_description_equal (current_desc, next_desc))
- {
- pango_font_description_free (current_desc);
- current_desc = next_desc;
- language = next_language;
-
- if (current_fonts)
- g_object_unref (current_fonts);
-
- current_fonts = pango_font_map_load_fontset (context->font_map,
- context,
- current_desc,
- language);
- }
- else
- pango_font_description_free (next_desc);
- }
-
- wc = g_utf8_get_char (pos);
- pos = g_utf8_next_char (pos);
-
- analysis->lang_engine = (PangoEngineLang *)pango_map_get_engine (lang_map, wc);
- analysis->font = pango_fontset_get_font (current_fonts, wc);
- analysis->language = language;
+ return pango_find_map (lang, engine_type_id, render_type_id);
+}
+
+static void
+itemize_state_update_for_new_run (ItemizeState *state)
+{
+ if (state->changed & (SCRIPT_CHANGED | LANG_CHANGED))
+ {
+ PangoLanguage *old_derived_lang = state->derived_lang;
+ state->derived_lang = compute_derived_language (state->lang, state->script);
+ if (old_derived_lang != state->derived_lang)
+ state->changed |= DERIVED_LANG_CHANGED;
+ }
- /* FIXME: handle reference counting properly on the shapers */
- if (analysis->font)
- analysis->shape_engine = pango_font_find_shaper (analysis->font, language, wc);
+ if ((state->changed & DERIVED_LANG_CHANGED) || !state->lang_engine)
+ {
+ PangoMap *lang_map = get_lang_map (state->derived_lang);
+ state->lang_engine = (PangoEngineLang *)pango_map_get_engine (lang_map, state->script);
+ }
+
+ if (state->changed & (SCRIPT_CHANGED | DERIVED_LANG_CHANGED))
+ itemize_state_reset_shape_engines (state);
+
+ if (state->changed & (FONT_CHANGED | DERIVED_LANG_CHANGED) &&
+ state->current_fonts)
+ {
+ g_object_unref (state->current_fonts);
+ state->current_fonts = NULL;
+ state->cache = NULL;
+ }
+
+ if (!state->current_fonts)
+ {
+ state->current_fonts = pango_font_map_load_fontset (state->context->font_map,
+ state->context,
+ state->font_desc,
+ state->derived_lang);
+ state->cache = get_shaper_font_cache (state->current_fonts);
+ }
+}
+
+static void
+itemize_state_process_run (ItemizeState *state)
+{
+ const char *p;
+ gboolean last_was_tab = FALSE;
+
+ itemize_state_update_for_new_run (state);
+
+ for (p = state->run_start;
+ p < state->run_end;
+ p = g_utf8_next_char (p))
+ {
+ gunichar wc = g_utf8_get_char (p);
+ gboolean is_tab = wc == '\t';
+ PangoEngineShape *shape_engine;
+ PangoFont *font;
+
+ if (!g_unichar_isgraph (wc))
+ {
+ shape_engine = NULL;
+ font = NULL;
+ }
else
- analysis->shape_engine = NULL;
+ get_shaper_and_font (state, wc, &shape_engine, &font);
+
+ itemize_state_add_character (state,
+ shape_engine, font,
+ is_tab || last_was_tab,
+ p);
- if (analysis->shape_engine == NULL)
- analysis->shape_engine = _pango_get_fallback_shaper ();
+ last_was_tab = is_tab;
+ }
+
+ /* Finish the final item from the current segment */
+ state->item->length = (p - state->text) - state->item->offset;
+ if (!state->item->analysis.shape_engine)
+ {
+ PangoEngineShape *shape_engine;
+ PangoFont *font;
- analysis->extra_attrs = extra_attrs;
+ if (!get_shaper_and_font (state, ' ', &shape_engine, &font))
+ {
+ shape_engine = _pango_get_fallback_shaper ();
+ font = NULL;
+ }
+
+ itemize_state_fill_shaper (state, shape_engine, font);
}
+ state->item = NULL;
+}
+
+static void
+itemize_state_finish (ItemizeState *state)
+{
+ g_free (state->embedding_levels);
+ if (state->free_attr_iter)
+ pango_attr_iterator_destroy (state->attr_iter);
+ pango_script_iter_free (state->script_iter);
+ pango_font_description_free (state->font_desc);
+
+ itemize_state_reset_shape_engines (state);
+ if (state->current_fonts)
+ g_object_unref (state->current_fonts);
+}
+
+/**
+ * pango_itemize:
+ * @context: a structure holding information that affects
+ the itemization process.
+ * @text: the text to itemize.
+ * @start_index: first byte in @text to process
+ * @length: the number of bytes (not characters) to process
+ * after @start_index.
+ * This must be >= 0.
+ * @attrs: the set of attributes that apply to @text.
+ * @cached_iter: Cached attribute iterator, or NULL
+ *
+ * Breaks a piece of text into segments with consistent
+ * directional level and shaping engine. Each byte of @text will
+ * be contained in exactly one of the items in the returned list;
+ * the generated list of items will be in logical order (the start
+ * offsets of the items are ascending).
+ *
+ * @cached_iter should be an iterator over @attrs currently positioned at a
+ * range before or containing @start_index; @cached_iter will be advanced to
+ * the range covering the position just after @start_index + @length.
+ * (i.e. if itemizing in a loop, just keep passing in the same @cached_iter).
+ *
+ * Return value: a GList of PangoItem structures.
+ */
+GList *
+pango_itemize (PangoContext *context,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter)
+{
+ ItemizeState state;
+
+ g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (start_index >= 0, NULL);
+ g_return_val_if_fail (length >= 0, NULL);
+ g_return_val_if_fail (length == 0 || text != NULL, NULL);
- g_assert (pos - text == start_index + length);
+ if (length == 0)
+ return NULL;
- if (current_desc)
- pango_font_description_free (current_desc);
- if (current_fonts)
- g_object_unref (current_fonts);
+ itemize_state_init (&state, context, text, start_index, length,
+ attrs, cached_iter);
- if (iterator != cached_iter)
- pango_attr_iterator_destroy (iterator);
+ do
+ itemize_state_process_run (&state);
+ while (itemize_state_next (&state));
+
+ itemize_state_finish (&state);
+
+ return g_list_reverse (state.result);
}
/**
diff --git a/pango/pango-engine-private.h b/pango/pango-engine-private.h
index 2e4a3573..d56a092f 100644
--- a/pango/pango-engine-private.h
+++ b/pango/pango-engine-private.h
@@ -27,15 +27,16 @@
G_BEGIN_DECLS
-void _pango_engine_shape_shape (PangoEngineShape *engine,
- PangoFont *font,
- const char *text,
- int length,
- PangoAnalysis *analysis,
- PangoGlyphString *glyphs);
-PangoCoverage *_pango_engine_shape_get_coverage (PangoEngineShape *engine,
- PangoFont *font,
- PangoLanguage *language);
+void _pango_engine_shape_shape (PangoEngineShape *engine,
+ PangoFont *font,
+ const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs);
+PangoCoverageLevel _pango_engine_shape_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *language,
+ gunichar wc);
PangoEngineShape *_pango_get_fallback_shaper (void);
diff --git a/pango/pango-engine.c b/pango/pango-engine.c
index 844a534d..d421a1ac 100644
--- a/pango/pango-engine.c
+++ b/pango/pango-engine.c
@@ -31,18 +31,25 @@ PANGO_DEFINE_TYPE_ABSTRACT (PangoEngineLang, pango_engine_lang,
NULL, NULL,
PANGO_TYPE_ENGINE);
-static PangoCoverage *
-pango_engine_shape_real_get_coverage (PangoEngineShape *engine,
- PangoFont *font,
- PangoLanguage *language)
+static PangoCoverageLevel
+pango_engine_shape_real_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *language,
+ gunichar wc)
{
- return pango_font_get_coverage (font, language);
+
+ PangoCoverage *coverage = pango_font_get_coverage (font, language);
+ PangoCoverageLevel result = pango_coverage_get (coverage, wc);
+
+ pango_coverage_unref (coverage);
+
+ return result;
}
void
pango_engine_shape_class_init (PangoEngineShapeClass *class)
{
- class->get_coverage = pango_engine_shape_real_get_coverage;
+ class->covers = pango_engine_shape_real_covers;
}
PANGO_DEFINE_TYPE_ABSTRACT (PangoEngineShape, pango_engine_shape,
@@ -70,17 +77,19 @@ _pango_engine_shape_shape (PangoEngineShape *engine,
glyphs);
}
-PangoCoverage *
-_pango_engine_shape_get_coverage (PangoEngineShape *engine,
- PangoFont *font,
- PangoLanguage *language)
+PangoCoverageLevel
+_pango_engine_shape_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *language,
+ gunichar wc)
{
- g_return_val_if_fail (PANGO_IS_ENGINE_SHAPE (engine), NULL);
- g_return_val_if_fail (PANGO_IS_FONT (font), NULL);
+ g_return_val_if_fail (PANGO_IS_ENGINE_SHAPE (engine), PANGO_COVERAGE_NONE);
+ g_return_val_if_fail (PANGO_IS_FONT (font), PANGO_COVERAGE_NONE);
- return PANGO_ENGINE_SHAPE_GET_CLASS (engine)->get_coverage (engine,
- font,
- language);
+ return PANGO_ENGINE_SHAPE_GET_CLASS (engine)->covers (engine,
+ font,
+ language,
+ wc);
}
/* No extra fields needed */
@@ -124,25 +133,19 @@ fallback_engine_shape (PangoEngineShape *engine,
}
}
-static PangoCoverage*
-fallback_engine_get_coverage (PangoEngineShape *engine,
- PangoFont *font,
- PangoLanguage *lang)
+static PangoCoverageLevel
+fallback_engine_covers (PangoEngineShape *engine,
+ PangoFont *font,
+ PangoLanguage *lang,
+ gunichar wc)
{
- PangoCoverage *result = pango_coverage_new ();
-
- /* We return an empty coverage (this function won't get
- * called, but if it is, empty coverage will keep
- * it from being used).
- */
-
- return result;
+ return PANGO_COVERAGE_NONE;
}
static void
fallback_engine_class_init (PangoEngineShapeClass *class)
{
- class->get_coverage = fallback_engine_get_coverage;
+ class->covers = fallback_engine_covers;
class->script_shape = fallback_engine_shape;
}
diff --git a/pango/pango-engine.h b/pango/pango-engine.h
index 1aa429de..253d85c7 100644
--- a/pango/pango-engine.h
+++ b/pango/pango-engine.h
@@ -26,6 +26,7 @@
#include <pango/pango-item.h>
#include <pango/pango-font.h>
#include <pango/pango-glyph.h>
+#include <pango/pango-script.h>
G_BEGIN_DECLS
@@ -182,20 +183,20 @@ struct _PangoEngineShapeClass
int length,
PangoAnalysis *analysis,
PangoGlyphString *glyphs);
- PangoCoverage *(*get_coverage) (PangoEngineShape *engine,
+ PangoCoverageLevel (*covers) (PangoEngineShape *engine,
PangoFont *font,
- PangoLanguage *language);
+ PangoLanguage *language,
+ gunichar wc);
};
GType pango_engine_shape_get_type (void) G_GNUC_CONST;
typedef struct _PangoEngineInfo PangoEngineInfo;
-typedef struct _PangoEngineRange PangoEngineRange;
+typedef struct _PangoEngineScriptInfo PangoEngineScriptInfo;
-struct _PangoEngineRange
+struct _PangoEngineScriptInfo
{
- guint32 start;
- guint32 end;
+ PangoScript script;
gchar *langs;
};
@@ -204,8 +205,8 @@ struct _PangoEngineInfo
gchar *id;
gchar *engine_type;
gchar *render_type;
- PangoEngineRange *ranges;
- gint n_ranges;
+ PangoEngineScriptInfo *scripts;
+ gint n_scripts;
};
/**
diff --git a/pango/pango-fontmap.c b/pango/pango-fontmap.c
index c3b62694..ba373369 100644
--- a/pango/pango-fontmap.c
+++ b/pango/pango-fontmap.c
@@ -249,3 +249,24 @@ pango_font_map_real_load_fontset (PangoFontMap *fontmap,
return PANGO_FONTSET (fonts);
}
+
+/**
+ * pango_font_map_get_shape_engine_type:
+ * @fontmap: a #PangoFontmap
+ *
+ * Returns the render ID for shape engines for this fontmap.
+ * See the <structfield>render_type</structfield> field of
+ * #PangoEngineInfo.
+ *
+ * Return value: the ID string for shape engines for
+ * this fontmap. Owned by Pango, should not be modified
+ * or freed.
+ **/
+const char *
+pango_font_map_get_shape_engine_type (PangoFontMap *fontmap)
+{
+ g_return_val_if_fail (PANGO_IS_FONT_MAP (fontmap), NULL);
+
+ return PANGO_FONT_MAP_GET_CLASS (fontmap)->shape_engine_type;
+}
+
diff --git a/pango/pango-fontmap.h b/pango/pango-fontmap.h
index ddf7d173..5fc5d78f 100644
--- a/pango/pango-fontmap.h
+++ b/pango/pango-fontmap.h
@@ -46,7 +46,6 @@ void pango_font_map_list_families (PangoFontMap *fontma
PangoFontFamily ***families,
int *n_families);
-
#ifdef PANGO_ENABLE_BACKEND
#define PANGO_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONT_MAP, PangoFontMapClass))
@@ -76,6 +75,8 @@ struct _PangoFontMapClass
PangoContext *context,
const PangoFontDescription *desc,
PangoLanguage *language);
+
+ const char *shape_engine_type;
/*< private >*/
@@ -86,6 +87,8 @@ struct _PangoFontMapClass
void (*_pango_reserved4) (void);
};
+const char *pango_font_map_get_shape_engine_type (PangoFontMap *fontmap);
+
#endif /* PANGO_ENABLE_BACKEND */
G_END_DECLS
diff --git a/pango/pango-fontset.c b/pango/pango-fontset.c
index 7ba883d1..1f639376 100644
--- a/pango/pango-fontset.c
+++ b/pango/pango-fontset.c
@@ -26,45 +26,20 @@
#include "pango-types.h"
#include "pango-font.h"
#include "pango-fontset.h"
+#include "pango-impl-utils.h"
#include "pango-utils.h"
-static void pango_fontset_class_init (PangoFontsetClass *class);
static PangoFontMetrics *pango_fontset_real_get_metrics (PangoFontset *fontset);
-GType
-pango_fontset_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontsetClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_fontset_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoFontset),
- 0, /* n_preallocs */
- NULL /* init */
- };
-
- object_type = g_type_register_static (G_TYPE_OBJECT,
- "PangoFontset",
- &object_info, 0);
- }
-
- return object_type;
-}
-
static void
pango_fontset_class_init (PangoFontsetClass *class)
{
class->get_metrics = pango_fontset_real_get_metrics;
}
+PANGO_DEFINE_TYPE_ABSTRACT (PangoFontset, pango_fontset,
+ pango_fontset_class_init, NULL, G_TYPE_OBJECT);
+
/**
* pango_fontset_get_font:
* @fontset: a #PangoFontset
@@ -81,7 +56,7 @@ pango_fontset_get_font (PangoFontset *fontset,
guint wc)
{
- g_return_val_if_fail (fontset != NULL, NULL);
+ g_return_val_if_fail (PANGO_IS_FONTSET (fontset), NULL);
return PANGO_FONTSET_GET_CLASS (fontset)->get_font (fontset, wc);
}
@@ -98,11 +73,30 @@ pango_fontset_get_font (PangoFontset *fontset,
PangoFontMetrics *
pango_fontset_get_metrics (PangoFontset *fontset)
{
- g_return_val_if_fail (fontset != NULL, NULL);
+ g_return_val_if_fail (PANGO_IS_FONTSET (fontset), NULL);
return PANGO_FONTSET_GET_CLASS (fontset)->get_metrics (fontset);
}
+/**
+ * pango_fontset_foreach:
+ * @fontset: a #PangoFontset
+ * @func: Callback function
+ * @data: data to pass to the callback function
+ *
+ * Iterate through all the fonts in a fontset, calling @func for
+ * each one. If @func returns TRUE, that stops the iteration.
+ **/
+void
+pango_fontset_foreach (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data)
+{
+ g_return_if_fail (PANGO_IS_FONTSET (fontset));
+ g_return_if_fail (func != NULL);
+
+ PANGO_FONTSET_GET_CLASS (fontset)->foreach (fontset, func, data);
+}
static PangoFontMetrics *
pango_fontset_real_get_metrics (PangoFontset *fontset)
@@ -175,13 +169,15 @@ pango_fontset_real_get_metrics (PangoFontset *fontset)
#define PANGO_IS_FONTSET_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONTSET_SIMPLE))
#define PANGO_FONTSET_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONTSET_SIMPLE, PangoFontsetSimpleClass))
-static void pango_fontset_simple_class_init (PangoFontsetSimpleClass *class);
static void pango_fontset_simple_finalize (GObject *object);
static void pango_fontset_simple_init (PangoFontsetSimple *fontset);
static PangoFontMetrics *pango_fontset_simple_get_metrics (PangoFontset *fontset);
static PangoLanguage * pango_fontset_simple_get_language (PangoFontset *fontset);
static PangoFont * pango_fontset_simple_get_font (PangoFontset *fontset,
guint wc);
+static void pango_fontset_simple_foreach (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data);
struct _PangoFontsetSimple
{
@@ -218,34 +214,6 @@ pango_fontset_simple_new (PangoLanguage *language)
return fontset;
}
-GType
-pango_fontset_simple_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontsetSimpleClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_fontset_simple_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoFontsetSimple),
- 0, /* n_preallocs */
- (GInstanceInitFunc) pango_fontset_simple_init,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONTSET,
- "PangoFontsetSimple",
- &object_info, 0);
- }
-
- return object_type;
-}
-
static void
pango_fontset_simple_class_init (PangoFontsetSimpleClass *class)
{
@@ -258,6 +226,7 @@ pango_fontset_simple_class_init (PangoFontsetSimpleClass *class)
fontset_class->get_font = pango_fontset_simple_get_font;
fontset_class->get_metrics = pango_fontset_simple_get_metrics;
fontset_class->get_language = pango_fontset_simple_get_language;
+ fontset_class->foreach = pango_fontset_simple_foreach;
}
static void
@@ -268,6 +237,10 @@ pango_fontset_simple_init (PangoFontsetSimple *fontset)
fontset->language = NULL;
}
+PANGO_DEFINE_TYPE (PangoFontsetSimple, pango_fontset_simple,
+ pango_fontset_simple_class_init, pango_fontset_simple_init,
+ PANGO_TYPE_FONTSET);
+
static void
pango_fontset_simple_finalize (GObject *object)
{
@@ -379,3 +352,20 @@ pango_fontset_simple_get_font (PangoFontset *fontset,
font = g_ptr_array_index(simple->fonts, result);
return g_object_ref (font);
}
+
+static void
+pango_fontset_simple_foreach (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data)
+{
+ PangoFontsetSimple *simple = PANGO_FONTSET_SIMPLE (fontset);
+ int i;
+
+ for (i = 0; i < simple->fonts->len; i++)
+ {
+ if ((*func) (fontset,
+ g_ptr_array_index (simple->fonts, i),
+ data))
+ return;
+ }
+}
diff --git a/pango/pango-fontset.h b/pango/pango-fontset.h
index 8a118328..49cc6006 100644
--- a/pango/pango-fontset.h
+++ b/pango/pango-fontset.h
@@ -41,9 +41,27 @@ GType pango_fontset_get_type (void) G_GNUC_CONST;
typedef struct _PangoFontset PangoFontset;
-PangoFont * pango_fontset_get_font (PangoFontset *fontset,
- guint wc);
-PangoFontMetrics *pango_fontset_get_metrics (PangoFontset *fontset);
+/**
+ * PangoFontsetForeachFunc
+ * @fontset: a #PangoFontset
+ * @font: a font from @fontset
+ * @data: callback data
+ *
+ * A callback function used by pango_fontset_foreach() when enumerating
+ * the fonts in a fontset.
+ *
+ * Returns: if %TRUE, stop iteration and return immediatlehy.
+ **/
+typedef gboolean (*PangoFontsetForeachFunc) (PangoFontset *fontset,
+ PangoFont *font,
+ gpointer data);
+
+PangoFont * pango_fontset_get_font (PangoFontset *fontset,
+ guint wc);
+PangoFontMetrics *pango_fontset_get_metrics (PangoFontset *fontset);
+void pango_fontset_foreach (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data);
#ifdef PANGO_ENABLE_BACKEND
@@ -64,11 +82,14 @@ struct _PangoFontsetClass
/*< public >*/
- PangoFont * (*get_font) (PangoFontset *fontset,
- guint wc);
-
- PangoFontMetrics *(*get_metrics) (PangoFontset *fontset);
- PangoLanguage * (*get_language) (PangoFontset *fontset);
+ PangoFont * (*get_font) (PangoFontset *fontset,
+ guint wc);
+
+ PangoFontMetrics *(*get_metrics) (PangoFontset *fontset);
+ PangoLanguage * (*get_language) (PangoFontset *fontset);
+ void (*foreach) (PangoFontset *fontset,
+ PangoFontsetForeachFunc func,
+ gpointer data);
/*< private >*/
diff --git a/pango/pango-modules.h b/pango/pango-modules.h
index c0bb5c9a..5dbcfe9f 100644
--- a/pango/pango-modules.h
+++ b/pango/pango-modules.h
@@ -31,12 +31,6 @@ G_BEGIN_DECLS
typedef struct _PangoMap PangoMap;
typedef struct _PangoMapEntry PangoMapEntry;
-struct _PangoMapEntry
-{
- PangoEngineInfo *info;
- gboolean is_exact;
-};
-
typedef struct _PangoIncludedModule PangoIncludedModule;
struct _PangoIncludedModule
@@ -51,10 +45,12 @@ struct _PangoIncludedModule
PangoMap * pango_find_map (PangoLanguage *language,
guint engine_type_id,
guint render_type_id);
-PangoMapEntry *pango_map_get_entry (PangoMap *map,
- guint32 wc);
PangoEngine * pango_map_get_engine (PangoMap *map,
- guint32 wc);
+ PangoScript script);
+void pango_map_get_engines (PangoMap *map,
+ PangoScript script,
+ GSList **exact_engines,
+ GSList **fallback_engines);
void pango_module_register (PangoIncludedModule *module);
#endif /* PANGO_ENABLE_BACKEND */
diff --git a/pango/pango-script-lang-table.h b/pango/pango-script-lang-table.h
new file mode 100644
index 00000000..e3f0b783
--- /dev/null
+++ b/pango/pango-script-lang-table.h
@@ -0,0 +1,191 @@
+/* pango-script-lang-table.h: Generated by gen-script-for-lang.c
+ *
+ * Date: 15 September 2003
+ * Source: fontconfig-2.2.0
+ *
+ * Do not edit.
+ */
+typedef struct {
+ const char lang[6];
+ PangoScript scripts[3];
+} PangoScriptForLang;
+
+PangoScriptForLang pango_script_for_lang[] = {
+ { "aa", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ab", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "af", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "am", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ar", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ast", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ava", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ay", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "az", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE } },
+ { "ba", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bam", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "be", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bg", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bh", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bho", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bin", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bn", { PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bo", { PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "br", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bs", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "bua", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ca", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ce", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ch", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "chm", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "chr", { PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "co", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "cs", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "cu", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "cv", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE } },
+ { "cy", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "da", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "de", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "dz", { PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "el", { PANGO_SCRIPT_GREEK, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "en", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "eo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "es", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "et", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "eu", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fa", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fj", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fr", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ful", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fur", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "fy", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ga", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gd", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gez", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gu", { PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "gv", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ha", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "haw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "he", { PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "hi", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ho", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "hr", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "hu", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "hy", { PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ia", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ibo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "id", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ie", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ik", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "io", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "is", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "it", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "iu", { PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ja", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_HIRAGANA, PANGO_SCRIPT_KATAKANA } },
+ { "ka", { PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kaa", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ki", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "km", { PANGO_SCRIPT_KHMER, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kn", { PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ko", { PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE } },
+ { "kok", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ks", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ku", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE } },
+ { "kum", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kv", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "kw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ky", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "la", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lb", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lez", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lo", { PANGO_SCRIPT_LAO, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lt", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "lv", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mg", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mh", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ml", { PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mn", { PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE } },
+ { "mr", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "mt", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "my", { PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "nb", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ne", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "nl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "nn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "no", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ny", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "oc", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "om", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "or", { PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "os", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "pl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "pt", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "rm", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ro", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ru", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sa", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sah", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sco", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "se", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sel", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sh", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "si", { PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sk", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sm", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sma", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "smj", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "smn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sms", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "so", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sq", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sr", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sv", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "sw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "syr", { PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ta", { PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "te", { PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tg", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "th", { PANGO_SCRIPT_THAI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ti-er", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ti-et", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tig", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tl", { PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "to", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tr", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ts", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tt", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "tyv", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ug", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "uk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ur", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "uz", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "ven", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "vi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "vo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "vot", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "wa", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "wen", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "wo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "xh", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "yap", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "yi", { PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "yo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-cn", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-hk", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-mo", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-sg", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zh-tw", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+ { "zu", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } },
+};
diff --git a/pango/pango-script.c b/pango/pango-script.c
index 39a95641..10acfc90 100644
--- a/pango/pango-script.c
+++ b/pango/pango-script.c
@@ -341,3 +341,175 @@ pango_script_iter_next (PangoScriptIter *iter)
return TRUE;
}
+
+/**********************************************************
+ * End of code from ICU
+ **********************************************************/
+
+#include "pango-script-lang-table.h"
+
+static int
+script_for_lang_compare (gconstpointer key,
+ gconstpointer member)
+{
+ const char *lang = key;
+ const PangoScriptForLang *script_for_lang = member;
+
+ return strcmp (lang,
+ pango_language_to_string (script_for_lang->lang));
+}
+
+/**
+ * pango_language_includes_script:
+ * @language: a PangoLanguage
+ * @script: a #PangoScript
+ *
+ * Determines if @script is one of the scripts used to
+ * write @language. The returned value is conservative;
+ * if nothing is known about the language tag @language,
+ * %TRUE will be returned, since, as far as Pango knows,
+ * @script might be used to write @language.
+ *
+ * This routine is used in Pango's itemization process when
+ * determining if a supplied language tag is relevant to
+ * a particular section of text. It probably is not useful for
+ * applications in most circumstances.
+ *
+ * Return value: %TRUE if @script is one of the scripts used
+ * to write @language, or if nothing is known about @language.
+ **/
+gboolean
+pango_language_includes_script (PangoLanguage *language,
+ PangoScript script)
+{
+ PangoScriptForLang *script_for_lang;
+ int j;
+
+ g_return_val_if_fail (language != NULL, FALSE);
+
+ /* This bsearch could be optimized to occur only once if
+ * we store the pointer to the PangoScriptForLang in the
+ * same block as the string value for the PangoLanguage.
+ */
+ script_for_lang = bsearch (pango_language_to_string (language),
+ pango_script_for_lang,
+ sizeof (PangoScriptForLang),
+ G_N_ELEMENTS (pango_script_for_lang),
+ script_for_lang_compare);
+ if (!script_for_lang)
+ return TRUE;
+
+ for (j = 0; j < G_N_ELEMENTS (script_for_lang->scripts); j++)
+ if (script_for_lang->scripts[j] == script)
+ return TRUE;
+
+ return FALSE;
+}
+
+/**
+ * pango_script_get_sample_language:
+ * @script: a #PangoScript
+ *
+ * Given a script, finds a language tag that is reasonably
+ * representative of that script. This will usually be the
+ * most widely spoken or used language written in that script:
+ * for instance, the sample language for %PANGO_SCRIPT_CYRILLIC
+ * is <literal>ru</literal> (Russian), the sample lanugage
+ * for %PANGO_SCRIPT_ARABIC is <literal>ar</literal>.
+ *
+ * For some
+ * scripts, no sample language will be returned because there
+ * is no language that is sufficiently representative. The best
+ * example of this is %PANGO_SCRIPT_HAN, where various different
+ * variants of written Chinese, Japanese, and Korean all use
+ * significantly different sets of Han characters and forms
+ * of shared characters. No sample language can be provided
+ * for many historical scripts as well.
+ *
+ * Return value: a #PangoLanguage that is representative
+ * of the script, or %NULL if no such language exists.
+ **/
+PangoLanguage *
+pango_script_get_sample_language (PangoScript script)
+{
+ /* Note that in the following, we want
+ * pango_language_includes_script() for the sample language
+ * to include the script, so alternate orthographies
+ * (Shavian for English, Osmanya for Somali, etc), typically
+ * have no sample language
+ */
+ const char sample_languages[][4] = {
+ "", /* PANGO_SCRIPT_COMMON */
+ "", /* PANGO_SCRIPT_INHERITED */
+ "ar", /* PANGO_SCRIPT_ARABIC */
+ "hy", /* PANGO_SCRIPT_ARMENIAN */
+ "bn", /* PANGO_SCRIPT_BENGALI */
+ /* Used primarily in Taiwan, but not part of the standard
+ * zh-tw orthography */
+ "", /* PANGO_SCRIPT_BOPOMOFO */
+ "chr", /* PANGO_SCRIPT_CHEROKEE */
+ "cop", /* PANGO_SCRIPT_COPTIC */
+ "ru", /* PANGO_SCRIPT_CYRILLIC */
+ /* Deseret was used to write English */
+ "", /* PANGO_SCRIPT_DESERET */
+ "hi", /* PANGO_SCRIPT_DEVANAGARI */
+ "am", /* PANGO_SCRIPT_ETHIOPIC */
+ "ka", /* PANGO_SCRIPT_GEORGIAN */
+ "", /* PANGO_SCRIPT_GOTHIC */
+ "el", /* PANGO_SCRIPT_GREEK */
+ "gu", /* PANGO_SCRIPT_GUJARATI */
+ "pa", /* PANGO_SCRIPT_GURMUKHI */
+ "", /* PANGO_SCRIPT_HAN */
+ "ko", /* PANGO_SCRIPT_HANGUL */
+ "he", /* PANGO_SCRIPT_HEBREW */
+ "ja", /* PANGO_SCRIPT_HIRAGANA */
+ "kn", /* PANGO_SCRIPT_KANNADA */
+ "ja", /* PANGO_SCRIPT_KATAKANA */
+ "km", /* PANGO_SCRIPT_KHMER */
+ "lo", /* PANGO_SCRIPT_LAO */
+ "en", /* PANGO_SCRIPT_LATIN */
+ "ml", /* PANGO_SCRIPT_MALAYALAM */
+ "mn", /* PANGO_SCRIPT_MONGOLIAN */
+ "my", /* PANGO_SCRIPT_MYANMAR */
+ /* Ogham was used to write old Irish */
+ "", /* PANGO_SCRIPT_OGHAM */
+ "", /* PANGO_SCRIPT_OLD_ITALIC */
+ "or", /* PANGO_SCRIPT_ORIYA */
+ "", /* PANGO_SCRIPT_RUNIC */
+ "si", /* PANGO_SCRIPT_SINHALA */
+ "syr", /* PANGO_SCRIPT_SYRIAC */
+ "ta", /* PANGO_SCRIPT_TAMIL */
+ "te", /* PANGO_SCRIPT_TELUGU */
+ "dv", /* PANGO_SCRIPT_THAANA */
+ "th", /* PANGO_SCRIPT_THAI */
+ "bo", /* PANGO_SCRIPT_TIBETAN */
+ "iu", /* PANGO_SCRIPT_CANADIAN_ABORIGINAL */
+ "", /* PANGO_SCRIPT_YI */
+ "tl", /* PANGO_SCRIPT_TAGALOG */
+ /* There are no ISO-636 language codes for the following
+ * Phillipino languages/scripts */
+ "", /* PANGO_SCRIPT_HANUNOO */
+ "", /* PANGO_SCRIPT_BUHID */
+ "", /* PANGO_SCRIPT_TAGBANWA */
+
+ "", /* PANGO_SCRIPT_BRAILLE */
+ "", /* PANGO_SCRIPT_CYPRIOT */
+ "", /* PANGO_SCRIPT_LIMBU */
+ /* Used for Somali (so) in the past */
+ "", /* PANGO_SCRIPT_OSMANYA */
+ /* The Shavian alphabet was designed for English */
+ "", /* PANGO_SCRIPT_SHAVIAN */
+ "", /* PANGO_SCRIPT_LINEAR_B */
+ "", /* PANGO_SCRIPT_TAI_LE */
+ "uga", /* PANGO_SCRIPT_UGARITIC */
+ };
+
+ g_return_val_if_fail (script >= 0, NULL);
+ g_return_val_if_fail (script < G_N_ELEMENTS (sample_languages), NULL);
+ const char *sample_language = sample_languages[script];
+
+ if (!sample_language[0])
+ return NULL;
+ else
+ return pango_language_from_string (sample_language);
+}
diff --git a/pango/pango-script.h b/pango/pango-script.h
index 6c03c89b..cc7e2c80 100644
--- a/pango/pango-script.h
+++ b/pango/pango-script.h
@@ -25,6 +25,8 @@
#include <glib.h>
+#include <pango/pango-types.h>
+
G_BEGIN_DECLS
/**
@@ -106,6 +108,10 @@ void pango_script_iter_get_range (PangoScriptIter *iter,
gboolean pango_script_iter_next (PangoScriptIter *iter);
void pango_script_iter_free (PangoScriptIter *iter);
+PangoLanguage *pango_script_get_sample_language (PangoScript script);
+gboolean pango_language_includes_script (PangoLanguage *language,
+ PangoScript script);
+
G_END_DECLS
#endif /* __PANGO_SCRIPT_H__ */
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index ab8837f1..7567a4ca 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -201,6 +201,7 @@ pango_fc_font_map_class_init (PangoFontMapClass *class)
class->load_font = pango_fc_font_map_load_font;
class->load_fontset = pango_fc_font_map_load_fontset;
class->list_families = pango_fc_font_map_list_families;
+ class->shape_engine_type = PANGO_RENDER_TYPE_FC;
#ifdef INSTANCE_PRIVATE_DATA_WORKS
g_type_class_add_private (object_class, sizeof (PangoFontMapClass));
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index adcb6b97..fd6b05d5 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -187,7 +187,8 @@ pango_win32_font_map_class_init (PangoFontMapClass *class)
object_class->finalize = pango_win32_font_map_finalize;
class->load_font = pango_win32_font_map_load_font;
class->list_families = pango_win32_font_map_list_families;
-
+ class->shape_engine_type = PANGO_RENDER_TYPE_WIN32;
+
pango_win32_get_dc ();
}
diff --git a/pango/pangox-fontmap.c b/pango/pangox-fontmap.c
index ca6615ec..09fbfcc9 100644
--- a/pango/pangox-fontmap.c
+++ b/pango/pangox-fontmap.c
@@ -220,6 +220,7 @@ pango_x_font_map_class_init (PangoFontMapClass *class)
object_class->finalize = pango_x_font_map_finalize;
class->load_font = pango_x_font_map_load_font;
class->list_families = pango_x_font_map_list_families;
+ class->shape_engine_type = PANGO_RENDER_TYPE_X;
}
/*
@@ -1527,7 +1528,6 @@ pango_x_face_get_coverage (PangoXFace *xface,
PangoXFont *xfont;
PangoXFontMap *xfontmap = NULL; /* Quiet gcc */
PangoCoverage *result = NULL;
- GHashTable *coverage_hash;
Atom atom = None;
if (xface)
@@ -1553,42 +1553,28 @@ pango_x_face_get_coverage (PangoXFace *xface,
if (!result)
{
- guint32 ch;
PangoMap *shape_map;
- PangoCoverage *coverage;
- PangoCoverageLevel font_level;
- PangoMapEntry *map_entry;
-
+ PangoEngineShape *engine;
+ gunichar wc;
+
result = pango_coverage_new ();
- coverage_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
shape_map = pango_x_get_shaper_map (language);
+ engine = (PangoEngineShape *)pango_map_get_engine (shape_map, PANGO_SCRIPT_COMMON);
- for (ch = 0; ch < 65536; ch++)
+ for (wc = 0; wc < 65536; wc++)
{
- map_entry = pango_map_get_entry (shape_map, ch);
- if (map_entry->info)
- {
- coverage = g_hash_table_lookup (coverage_hash, map_entry->info->id);
- if (!coverage)
- {
- PangoEngineShape *engine = (PangoEngineShape *)pango_map_get_engine (shape_map, ch);
- coverage = _pango_engine_shape_get_coverage (engine, font, language);
- g_hash_table_insert (coverage_hash, map_entry->info->id, coverage);
- }
-
- font_level = pango_coverage_get (coverage, ch);
- if (font_level == PANGO_COVERAGE_EXACT && !map_entry->is_exact)
- font_level = PANGO_COVERAGE_APPROXIMATE;
-
- if (font_level != PANGO_COVERAGE_NONE)
- pango_coverage_set (result, ch, font_level);
- }
+ PangoCoverageLevel level;
+
+ level = _pango_engine_shape_covers (engine, font, language, wc);
+ if (level != PANGO_COVERAGE_NONE)
+ pango_coverage_set (result, wc, level);
}
- g_hash_table_foreach (coverage_hash, free_coverages_foreach, NULL);
- g_hash_table_destroy (coverage_hash);
+ return result;
+
+
+ result = _pango_engine_shape_get_coverage (engine, font, language);
if (atom)
pango_x_store_cached_coverage (xfontmap, atom, result);
diff --git a/pango/querymodules.c b/pango/querymodules.c
index 0bec2a11..8ea48b7a 100644
--- a/pango/querymodules.c
+++ b/pango/querymodules.c
@@ -27,6 +27,7 @@
#include "pango-context.h"
#include "pango-utils.h"
#include "pango-engine.h"
+#include "pango-enum-types.h"
#include <errno.h>
#include <string.h>
@@ -98,6 +99,24 @@ escape_string (const char *str)
g_module_symbol (module, name, (gpointer *)&location)
#endif
+static const char *
+script_from_string (PangoScript script)
+{
+ static GEnumClass *class = NULL;
+ GEnumValue *value;
+ if (!class)
+ class = g_type_class_ref (PANGO_TYPE_SCRIPT);
+
+ value = g_enum_get_value (class, script);
+ if (!value)
+ {
+ g_warning ("Engine reported invalid script value %d\n", script);
+ return script_from_string (PANGO_SCRIPT_INVALID_CODE);
+ }
+
+ return value->value_nick;
+}
+
void
query_module (const char *dir, const char *name)
{
@@ -151,14 +170,13 @@ query_module (const char *dir, const char *name)
engines[i].id, engines[i].engine_type, engines[i].render_type);
g_free (quoted_path);
- for (j=0; j < engines[i].n_ranges; j++)
+ for (j=0; j < engines[i].n_scripts; j++)
{
if (j != 0)
g_printf (" ");
- g_printf ("%d-%d:%s",
- engines[i].ranges[j].start,
- engines[i].ranges[j].end,
- engines[i].ranges[j].langs);
+ g_printf ("%s:%s",
+ script_from_string (engines[i].scripts[j].script),
+ engines[i].scripts[j].langs);
}
g_printf ("\n");
}
@@ -179,6 +197,8 @@ int main (int argc, char **argv)
int i;
char *path;
+ g_type_init ();
+
g_printf ("# Pango Modules file\n"
"# Automatically generated file, do not edit\n"
"#\n");