summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
Diffstat (limited to 'pango')
-rw-r--r--pango/Makefile.am8
-rw-r--r--pango/break.c2
-rw-r--r--pango/itemize.c10
-rw-r--r--pango/modules.c266
-rw-r--r--pango/modules.h31
-rw-r--r--pango/pango-context.c39
-rw-r--r--pango/pango-layout.c17
-rw-r--r--pango/pangox.c42
-rw-r--r--pango/querymodules.c4
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);