diff options
Diffstat (limited to 'pango')
-rw-r--r-- | pango/modules.c | 301 | ||||
-rw-r--r-- | pango/pango-context.c | 892 | ||||
-rw-r--r-- | pango/pango-engine-private.h | 19 | ||||
-rw-r--r-- | pango/pango-engine.c | 59 | ||||
-rw-r--r-- | pango/pango-engine.h | 17 | ||||
-rw-r--r-- | pango/pango-fontmap.c | 21 | ||||
-rw-r--r-- | pango/pango-fontmap.h | 5 | ||||
-rw-r--r-- | pango/pango-fontset.c | 110 | ||||
-rw-r--r-- | pango/pango-fontset.h | 37 | ||||
-rw-r--r-- | pango/pango-modules.h | 14 | ||||
-rw-r--r-- | pango/pango-script-lang-table.h | 191 | ||||
-rw-r--r-- | pango/pango-script.c | 172 | ||||
-rw-r--r-- | pango/pango-script.h | 6 | ||||
-rw-r--r-- | pango/pangofc-fontmap.c | 1 | ||||
-rw-r--r-- | pango/pangowin32-fontmap.c | 3 | ||||
-rw-r--r-- | pango/pangox-fontmap.c | 44 | ||||
-rw-r--r-- | pango/querymodules.c | 30 |
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"); |