diff options
Diffstat (limited to 'pango')
-rw-r--r-- | pango/Makefile.am | 8 | ||||
-rw-r--r-- | pango/break.c | 2 | ||||
-rw-r--r-- | pango/itemize.c | 10 | ||||
-rw-r--r-- | pango/modules.c | 266 | ||||
-rw-r--r-- | pango/modules.h | 31 | ||||
-rw-r--r-- | pango/pango-context.c | 39 | ||||
-rw-r--r-- | pango/pango-layout.c | 17 | ||||
-rw-r--r-- | pango/pangox.c | 42 | ||||
-rw-r--r-- | pango/querymodules.c | 4 |
9 files changed, 243 insertions, 176 deletions
diff --git a/pango/Makefile.am b/pango/Makefile.am index 892ad7ad..e9f663e6 100644 --- a/pango/Makefile.am +++ b/pango/Makefile.am @@ -12,6 +12,7 @@ libpango_la_SOURCES = \ mapping.c \ modules.c \ modules.h \ + module-defs.c \ pango-attributes.c \ pango-context.c \ pango-coverage.c \ @@ -30,7 +31,9 @@ libpangox_la_SOURCES = \ # scheme or the standard libtool scheme. # libpango_la_LDFLAGS = -release $(VERSION) + libpangox_la_LDFLAGS = -release $(VERSION) +libpangox_la_LIBADD = $(INCLUDED_MODULES) pangoincludedir=$(includedir)/pango @@ -47,7 +50,10 @@ pangoinclude_HEADERS = \ pango-types.h \ pangox.h +# +# As a temporary hack, we pull in libpangox here so that we can link +# pango_querymodules_SOURCES = \ querymodules.c -pango_querymodules_LDADD = libpango.la $(GLIB_LIBS) $(FRIBIDI_LIBS) $(UNICODE_LIBS) +pango_querymodules_LDADD = libpangox.la libpango.la $(GLIB_LIBS) $(FRIBIDI_LIBS) $(UNICODE_LIBS) $(X_LIBS) diff --git a/pango/break.c b/pango/break.c index b171b087..70de69ce 100644 --- a/pango/break.c +++ b/pango/break.c @@ -56,7 +56,7 @@ void pango_break (const gchar *text, break; cur = next; - attrs[i].is_white = (wc == ' ' || wc == '\t' || wc == '\n') ? 1 : 0; + attrs[i].is_white = (wc == ' ' || wc == '\t' || wc == '\n' || wc == 0x200b) ? 1 : 0; attrs[i].is_break = i == 0 || attrs[i-1].is_white || attrs[i].is_white; attrs[i].is_char_stop = 1; attrs[i].is_word_stop = (i == 0) || attrs[i-1].is_white; diff --git a/pango/itemize.c b/pango/itemize.c index 71d8e940..27e2c81a 100644 --- a/pango/itemize.c +++ b/pango/itemize.c @@ -200,14 +200,14 @@ add_engines (PangoContext *context, else lang = context->lang; - if (last_lang != lang || - last_lang == 0 || lang == 0 || - strcmp (lang, last_lang) != 0) + if (last_lang != lang && + (last_lang == 0 || lang == 0 || + strcmp (lang, last_lang) != 0)) { lang_map = _pango_find_map (lang, PANGO_ENGINE_TYPE_LANG, - PANGO_RENDER_TYPE_NONE); + PANGO_RENDER_TYPE_NONE); shape_map = _pango_find_map (lang, PANGO_ENGINE_TYPE_SHAPE, - context->render_type); + context->render_type); last_lang = lang; } diff --git a/pango/modules.c b/pango/modules.c index 816acbea..db173e88 100644 --- a/pango/modules.c +++ b/pango/modules.c @@ -31,125 +31,139 @@ typedef struct _PangoMapInfo PangoMapInfo; typedef struct _PangoEnginePair PangoEnginePair; +typedef struct _PangoSubmap PangoSubmap; + +struct _PangoSubmap +{ + gboolean is_leaf; + union { + PangoMapEntry entry; + PangoMapEntry *leaves; + } d; +}; + +struct _PangoMap +{ + gint n_submaps; + PangoSubmap submaps[256]; +}; struct _PangoMapInfo { const gchar *lang; - const gchar *engine_type; - const gchar *render_type; + guint engine_type_id; + guint render_type_id; + PangoMap *map; }; struct _PangoEnginePair { PangoEngineInfo info; - gchar *module; + gboolean included; + void *load_info; PangoEngine *engine; }; +GList *maps; GList *engines; -static PangoMap *build_map (PangoMapInfo *info); -static void read_modules (void); -static guint map_info_hash (const PangoMapInfo *map); -static gboolean map_info_equal (const PangoMapInfo *map_a, - const PangoMapInfo *map_b); +static void build_map (PangoMapInfo *info); +static void init_modules (void); PangoMap * _pango_find_map (const char *lang, - const char *engine_type, - const char *render_type) + guint engine_type_id, + guint render_type_id) { - PangoMapInfo map_info; - PangoMap *map; - - static GHashTable *map_hash = NULL; + GList *tmp_list = maps; + PangoMapInfo *map_info = NULL; + gboolean found_earlier = FALSE; - if (!map_hash) - map_hash = g_hash_table_new ((GHashFunc)map_info_hash, - (GCompareFunc)map_info_equal); + while (tmp_list) + { + map_info = tmp_list->data; + if (map_info->engine_type_id == engine_type_id && + map_info->render_type_id == render_type_id) + { + if (strcmp (map_info->lang, lang) == 0) + break; + else + found_earlier = TRUE; + } - map_info.lang = lang ? lang : "NONE"; - map_info.engine_type = engine_type; - map_info.render_type = render_type; + tmp_list = tmp_list->next; + } - map = g_hash_table_lookup (map_hash, &map_info); - if (!map) + if (!tmp_list) { - PangoMapInfo *new_info = g_new (PangoMapInfo, 1); - new_info->lang = g_strdup (map_info.lang); - new_info->engine_type = g_strdup (engine_type); - new_info->render_type = g_strdup (render_type); + map_info = g_new (PangoMapInfo, 1); + map_info->lang = g_strdup (lang); + map_info->engine_type_id = engine_type_id; + map_info->render_type_id = render_type_id; - map = build_map (new_info); - g_hash_table_insert (map_hash, new_info, map); - } + build_map (map_info); - return map; + maps = g_list_prepend (maps, map_info); + } + else if (found_earlier) + { + /* Move the found map to the beginning of the list + * for speed next time around if we had to do + * any failing strcmps. + */ + if (tmp_list->next) + tmp_list->next->prev = tmp_list->prev; + tmp_list->prev->next = tmp_list->next; + tmp_list->next = maps; + tmp_list->prev = NULL; + maps = tmp_list; + } + + return map_info->map; } -PangoEngine * -_pango_load_engine (const char *id) +static PangoEngine * +pango_engine_pair_get_engine (PangoEnginePair *pair) { - GList *tmp_list; - - read_modules(); - - tmp_list = engines; - while (tmp_list) + if (!pair->engine) { - PangoEnginePair *pair = tmp_list->data; - tmp_list = tmp_list->next; - - if (!strcmp (pair->info.id, id)) + if (pair->included) + { + PangoIncludedModule *included_module = pair->load_info; + + pair->engine = included_module->load (pair->info.id); + } + else { GModule *module; + char *module_name = pair->load_info; PangoEngine *(*load) (const gchar *id); - - if (!pair->engine) + + module = g_module_open (module_name, 0); + if (!module) { - module = g_module_open (pair->module, 0); - if (!module) - { - fprintf(stderr, "Cannot load module %s: %s\n", - pair->module, g_module_error()); - return NULL; - } - - g_module_symbol (module, "script_engine_load", (gpointer)&load); - if (!load) - { - fprintf(stderr, "cannot retrieve script_engine_load from %s: %s\n", - pair->module, g_module_error()); - g_module_close (module); - return NULL; - } - - pair->engine = (*load) (id); + fprintf(stderr, "Cannot load module %s: %s\n", + module_name, g_module_error()); + return NULL; } - - return pair->engine; + + g_module_symbol (module, "script_engine_load", (gpointer)&load); + if (!load) + { + fprintf(stderr, "cannot retrieve script_engine_load from %s: %s\n", + module_name, g_module_error()); + g_module_close (module); + return NULL; + } + + pair->engine = (*load) (pair->info.id); } + } - return NULL; -} - - -static guint -map_info_hash (const PangoMapInfo *map) -{ - return g_str_hash (map->lang) | - g_str_hash (map->engine_type) | - g_str_hash (map->render_type); + return pair->engine; } -static gboolean -map_info_equal (const PangoMapInfo *map_a, const PangoMapInfo *map_b) -{ - return (strcmp (map_a->lang, map_b->lang) == 0 && - strcmp (map_a->engine_type, map_b->engine_type) == 0 && - strcmp (map_a->render_type, map_b->render_type) == 0); -} static char * readline(FILE *file) @@ -176,17 +190,37 @@ readline(FILE *file) } static void +add_included_modules (void) +{ + int i, j; + + for (i = 0; _pango_included_modules[i].list; i++) + { + PangoEngineInfo *engine_info; + int n_engines; + + _pango_included_modules[i].list (&engine_info, &n_engines); + + for (j=0; j < n_engines; j++) + { + PangoEnginePair *pair = g_new (PangoEnginePair, 1); + + pair->info = engine_info[j]; + pair->included = TRUE; + pair->load_info = &_pango_included_modules[i]; + pair->engine = NULL; + + engines = g_list_prepend (engines, pair); + } + } +} + +static void read_modules (void) { FILE *module_file; - static gboolean init = FALSE; char *line; - if (init) - return; - else - init = TRUE; - /* FIXME FIXME FIXME - this is a potential security problem from leaving * pango.modules files scattered around to trojan modules. */ @@ -201,7 +235,6 @@ read_modules (void) } } - engines = NULL; while ((line = readline (module_file))) { PangoEnginePair *pair = g_new (PangoEnginePair, 1); @@ -213,6 +246,8 @@ read_modules (void) int start; int end; + pair->included = FALSE; + p = line; q = line; ranges = NULL; @@ -226,7 +261,7 @@ read_modules (void) switch (i) { case 0: - pair->module = g_strndup (q, p-q); + pair->load_info = g_strndup (q, p-q); break; case 1: pair->info.id = g_strndup (q, p-q); @@ -298,7 +333,6 @@ read_modules (void) engines = g_list_prepend (engines, pair); } - engines = g_list_reverse (engines); } static void @@ -312,16 +346,37 @@ set_entry (PangoMapEntry *entry, gboolean is_exact, PangoEngineInfo *info) } } -static PangoMap * +static void +init_modules (void) +{ + static gboolean init = FALSE; + + if (init) + return; + else + init = TRUE; + + engines = NULL; + + add_included_modules(); + read_modules(); + + engines = g_list_reverse (engines); +} + +static void build_map (PangoMapInfo *info) { GList *tmp_list; int i, j; PangoMap *map; + + char *engine_type = g_quark_to_string (info->engine_type_id); + char *render_type = g_quark_to_string (info->render_type_id); - read_modules(); + init_modules(); - map = g_new (PangoMap, 1); + info->map = map = g_new (PangoMap, 1); for (i=0; i<256; i++) { map->submaps[i].is_leaf = TRUE; @@ -335,8 +390,8 @@ build_map (PangoMapInfo *info) PangoEnginePair *pair = tmp_list->data; tmp_list = tmp_list->next; - if (strcmp (pair->info.engine_type, info->engine_type) == 0 && - strcmp (pair->info.render_type, info->render_type) == 0) + if (strcmp (pair->info.engine_type, engine_type) == 0 && + strcmp (pair->info.render_type, render_type) == 0) { int submap; @@ -403,6 +458,25 @@ build_map (PangoMapInfo *info) } } } +} + +PangoMapEntry * +_pango_map_get_entry (PangoMap *map, + guint32 wc) +{ + PangoSubmap *submap = &map->submaps[wc / 256]; + return submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256]; +} + +PangoEngine * +_pango_map_get_engine (PangoMap *map, + guint32 wc) +{ + PangoSubmap *submap = &map->submaps[wc / 256]; + PangoMapEntry *entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256]; - return map; + if (entry->info) + return pango_engine_pair_get_engine ((PangoEnginePair *)entry->info); + else + return NULL; } diff --git a/pango/modules.h b/pango/modules.h index 972d0892..3b0ca0e6 100644 --- a/pango/modules.h +++ b/pango/modules.h @@ -24,8 +24,9 @@ #ifndef __MODULES_H__ #define __MODULES_H__ +typedef struct _PangoIncludedModule PangoIncludedModule; typedef struct _PangoMap PangoMap; -typedef struct _PangoSubmap PangoSubmap; + typedef struct _PangoMapEntry PangoMapEntry; struct _PangoMapEntry @@ -33,25 +34,21 @@ struct _PangoMapEntry PangoEngineInfo *info; gboolean is_exact; }; - -struct _PangoSubmap +struct _PangoIncludedModule { - gboolean is_leaf; - union { - PangoMapEntry entry; - PangoMapEntry *leaves; - } d; + void (*list) (PangoEngineInfo **engines, int *n_engines); + PangoEngine *(*load) (const char *id); + void (*unload) (PangoEngine *engine); }; -struct _PangoMap -{ - gint n_submaps; - PangoSubmap submaps[256]; -}; +PangoMap * _pango_find_map (const char *lang, + 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); -PangoMap *_pango_find_map (const char *lang, - const char *engine_type, - const char *render_type); -PangoEngine *_pango_load_engine (const char *id); +extern PangoIncludedModule _pango_included_modules[]; #endif /* __MODULES_H__ */ diff --git a/pango/pango-context.c b/pango/pango-context.c index c768c7d5..0c2e3dcf 100644 --- a/pango/pango-context.c +++ b/pango/pango-context.c @@ -43,7 +43,7 @@ static void add_engines (PangoContext *context, gint length, PangoAttrList *attrs, PangoEngineShape **shape_engines, - PangoEngineInfo **lang_engines, + PangoEngineLang **lang_engines, PangoFont **fonts, GSList **extra_attr_lists); @@ -523,7 +523,7 @@ pango_itemize (PangoContext *context, GList *result = NULL; PangoEngineShape **shape_engines; - PangoEngineInfo **lang_engines; + PangoEngineLang **lang_engines; GSList **extra_attr_lists; PangoFont **fonts; @@ -560,7 +560,7 @@ pango_itemize (PangoContext *context, * approach for now. */ shape_engines = g_new0 (PangoEngineShape *, n_chars); - lang_engines = g_new0 (PangoEngineInfo *, n_chars); + lang_engines = g_new0 (PangoEngineLang *, n_chars); fonts = g_new0 (PangoFont *, n_chars); extra_attr_lists = g_new0 (GSList *, n_chars); @@ -594,11 +594,7 @@ pango_itemize (PangoContext *context, item->analysis.level = embedding_levels[i]; item->analysis.shape_engine = shape_engines[i]; - - if (lang_engines[i]) - item->analysis.lang_engine = (PangoEngineLang *)_pango_load_engine (lang_engines[i]->id); - else - item->analysis.lang_engine = NULL; + item->analysis.lang_engine = lang_engines[i]; item->analysis.font = fonts[i]; @@ -676,7 +672,7 @@ add_engines (PangoContext *context, gint length, PangoAttrList *attrs, PangoEngineShape **shape_engines, - PangoEngineInfo **lang_engines, + PangoEngineLang **lang_engines, PangoFont **fonts, GSList **extra_attr_lists) { @@ -685,7 +681,6 @@ add_engines (PangoContext *context, int next_index = 0; GSList *extra_attrs = NULL; gint n_chars; - PangoMap *shape_map = NULL; PangoMap *lang_map = NULL; PangoFontDescription current_desc = { 0 }; @@ -709,9 +704,6 @@ add_engines (PangoContext *context, pos = text; for (i=0; i<n_chars; i++) { - PangoSubmap *submap; - PangoMapEntry *entry; - if (pos - text == next_index) { char *next_lang; @@ -727,12 +719,19 @@ add_engines (PangoContext *context, (lang != next_lang && (lang == NULL || next_lang == NULL || strcmp (lang, next_lang) != 0))) { + static guint engine_type_id = 0; + static guint render_type_id = 0; + lang = next_lang; + + 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); + } - lang_map = _pango_find_map (next_lang, PANGO_ENGINE_TYPE_LANG, - PANGO_RENDER_TYPE_NONE); - shape_map = _pango_find_map (next_lang, PANGO_ENGINE_TYPE_SHAPE, - "PangoRenderX"); + lang_map = _pango_find_map (next_lang, + engine_type_id, render_type_id); } pango_attr_iterator_get_font (iterator, context->font_desc, &next_desc, &extra_attrs); @@ -779,11 +778,7 @@ add_engines (PangoContext *context, pos = unicode_get_utf8 (pos, &wc); - submap = &lang_map->submaps[wc / 256]; - entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256]; - - lang_engines[i] = entry->info; - + lang_engines[i] = (PangoEngineLang *)_pango_map_get_engine (lang_map, wc); fonts[i] = get_font (current_fonts, current_coverages, n_families, wc); /* FIXME: handle reference counting properly on the shapers */ diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 6892ed4e..30a872da 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -1390,8 +1390,9 @@ process_item (PangoLayoutLine *line, int *remaining_width) { PangoGlyphString *glyphs = pango_glyph_string_new (); - PangoRectangle logical_rect; int width; + int length; + int i; if (*remaining_width == 0) return FALSE; @@ -1404,14 +1405,11 @@ process_item (PangoLayoutLine *line, return TRUE; } - /* We special-case the case where the whole item fits. Removing this special - * case would simplify the code, speed up the break case, and wouldn't - * slow things down much for the non-break case. - */ - pango_glyph_string_extents (glyphs, item->analysis.font, NULL, &logical_rect); - width = logical_rect.width; + width =0; + for (i=0; i < glyphs->num_glyphs; i++) + width += glyphs->glyphs[i].geometry.width; - if (logical_rect.width < *remaining_width && !no_break_at_end) + if (width < *remaining_width && !no_break_at_end) { *remaining_width -= width; insert_run (line, item, glyphs); @@ -1420,11 +1418,8 @@ process_item (PangoLayoutLine *line, } else { - int length; int num_chars = item->num_chars; - PangoGlyphUnit *log_widths = g_new (PangoGlyphUnit, item->num_chars); - pango_glyph_string_get_logical_widths (glyphs, text + item->offset, item->length, item->analysis.level, log_widths); /* Shorten the item by one line break diff --git a/pango/pangox.c b/pango/pangox.c index 520ae7fb..c35e614e 100644 --- a/pango/pangox.c +++ b/pango/pangox.c @@ -2081,17 +2081,31 @@ free_coverages_foreach (gpointer key, pango_coverage_unref (value); } +static PangoMap * +pango_x_get_shaper_map (const char *lang) +{ + 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_SHAPE); + render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_X); + } + + return _pango_find_map (lang, engine_type_id, render_type_id); +} + static PangoCoverage * pango_x_font_get_coverage (PangoFont *font, const char *lang) { guint32 ch; PangoMap *shape_map; - PangoSubmap *submap; - PangoMapEntry *entry; PangoCoverage *coverage; PangoCoverage *result; PangoCoverageLevel font_level; + PangoMapEntry *entry; GHashTable *coverage_hash; PangoXFont *xfont = (PangoXFont *)font; @@ -2106,20 +2120,17 @@ pango_x_font_get_coverage (PangoFont *font, coverage_hash = g_hash_table_new (g_str_hash, g_str_equal); - shape_map = _pango_find_map (lang, PANGO_ENGINE_TYPE_SHAPE, - PANGO_RENDER_TYPE_X); + shape_map = pango_x_get_shaper_map (lang); for (ch = 0; ch < 65536; ch++) { - submap = &shape_map->submaps[ch / 256]; - entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[ch % 256]; - + entry = _pango_map_get_entry (shape_map, ch); if (entry->info) { coverage = g_hash_table_lookup (coverage_hash, entry->info->id); if (!coverage) { - PangoEngineShape *engine = (PangoEngineShape *)_pango_load_engine (entry->info->id); + PangoEngineShape *engine = (PangoEngineShape *)_pango_map_get_engine (shape_map, ch); coverage = engine->get_coverage (font, lang); g_hash_table_insert (coverage_hash, entry->info->id, coverage); } @@ -2151,20 +2162,9 @@ pango_x_font_find_shaper (PangoFont *font, guint32 ch) { PangoMap *shape_map = NULL; - PangoSubmap *submap; - PangoMapEntry *entry; - - shape_map = _pango_find_map (lang, PANGO_ENGINE_TYPE_SHAPE, - PANGO_RENDER_TYPE_X); - submap = &shape_map->submaps[ch / 256]; - entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[ch % 256]; - - /* FIXME: check entry->is_exact */ - if (entry->info) - return (PangoEngineShape *)_pango_load_engine (entry->info->id); - else - return NULL; + shape_map = pango_x_get_shaper_map (lang); + return (PangoEngineShape *)_pango_map_get_engine (shape_map, ch); } /* Utility functions */ diff --git a/pango/querymodules.c b/pango/querymodules.c index 8d643f44..9ddddb3d 100644 --- a/pango/querymodules.c +++ b/pango/querymodules.c @@ -58,7 +58,7 @@ query_module (GModule *module, gchar *name) engines[i].ranges[j].langs); } g_print ("\n"); - } + } } else { @@ -83,7 +83,7 @@ int main (int argc, char **argv) else tmp = g_strconcat (cwd, "/", argv[i], NULL); - module = g_module_open (tmp, G_MODULE_BIND_LAZY); + module = g_module_open (tmp, 0); if (module) { query_module (module, tmp); |