diff options
author | Owen Taylor <otaylor@redhat.com> | 2003-08-03 21:57:35 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2003-08-03 21:57:35 +0000 |
commit | 2584212cd0976f5f95d9381e829917e7d2a10d28 (patch) | |
tree | 5773e9f6802f8316c5c7463aa55677babe67343c /pango/modules.c | |
parent | 95a8d1788e884b7d8d29d4171a1adc51c61e880e (diff) | |
download | pango-2584212cd0976f5f95d9381e829917e7d2a10d28.tar.gz |
Make PangoEngine{,Lang,Shape} GObjects, and use a GTypeModule-based
Sat Aug 2 23:19:16 2003 Owen Taylor <otaylor@redhat.com>
* pango/pango-engine.[ch] modules/*/*-{fc,win32,x}.c
pango/modules.c pango/break.c pango/pango-context.c
pango/pango-layout.c pango/pango-modules.h
pango/querymodules.c pango/shape.c: Make
PangoEngine{,Lang,Shape} GObjects, and use a
GTypeModule-based module-loading system closely based
on the one used for GtkIMContext and GtkThemeEngine.
* pango/pango-impl-utils.h: OK, I'm tired of typing
in get_type() functions.
* pango/pango-script.[ch] pango/pango-script-table.h
tests/testscript.c tools/gen-script-table.pl: Add port
of script-range code from ICU in preparation for future
use. (#91542)
* tools/gen-script-for-lang.c: Utility program to determine
the script for each fontconfig .orth file.
* docs/tmpl/{scripts.sgml,pango-engine-lang.sgml,
pango-engine-shape.sgml} docs/pango-sections.txt docs/pango-docs.sgml:
Redo to go along with the above changes.
* configure.in: chmod +x tests/runtests.sh
Diffstat (limited to 'pango/modules.c')
-rw-r--r-- | pango/modules.c | 243 |
1 files changed, 179 insertions, 64 deletions
diff --git a/pango/modules.c b/pango/modules.c index d01a8cf8..afbe1169 100644 --- a/pango/modules.c +++ b/pango/modules.c @@ -29,6 +29,14 @@ #include "pango-modules.h" #include "pango-utils.h" +#include "pango-impl-utils.h" + +typedef struct _PangoModule PangoModule; +typedef struct _PangoModuleClass PangoModuleClass; + +#define PANGO_TYPE_MODULE (pango_module_get_type ()) +#define PANGO_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), PANGO_TYPE_MODULE, PangoModule)) +#define PANGO_IS_MODULE(module) (G_TYPE_CHECK_INSTANCE_TYPE ((module), PANGO_TYPE_MODULE)) typedef struct _PangoMapInfo PangoMapInfo; typedef struct _PangoEnginePair PangoEnginePair; @@ -60,16 +68,34 @@ struct _PangoMapInfo struct _PangoEnginePair { PangoEngineInfo info; - gboolean included; - void *load_info; + PangoModule *module; PangoEngine *engine; }; -static GList *maps = NULL; +struct _PangoModule +{ + GTypeModule parent_instance; + + char *path; + GModule *library; -static GSList *builtin_engines = NULL; + void (*list) (PangoEngineInfo **engines, gint *n_engines); + void (*init) (GTypeModule *module); + void (*exit) (void); + PangoEngine *(*create) (const gchar *id); +}; + +struct _PangoModuleClass +{ + GTypeModuleClass parent_class; +}; + +static GList *maps = NULL; static GSList *registered_engines = NULL; static GSList *dlloaded_engines = NULL; +static GHashTable *dlloaded_modules; + +GObjectClass *parent_class; static void build_map (PangoMapInfo *info); static void init_modules (void); @@ -136,56 +162,126 @@ pango_find_map (PangoLanguage *language, return map_info->map; } -static PangoEngine * -pango_engine_pair_get_engine (PangoEnginePair *pair) +static gboolean +pango_module_load (GTypeModule *module) { - if (!pair->engine) + PangoModule *pango_module = PANGO_MODULE (module); + + if (pango_module->path) { - if (pair->included) + pango_module->library = g_module_open (pango_module->path, 0); + if (!pango_module->library) { - PangoIncludedModule *included_module = pair->load_info; - - pair->engine = included_module->load (pair->info.id); + g_warning (g_module_error()); + return FALSE; } - else + + /* extract symbols from the lib */ + if (!g_module_symbol (pango_module->library, "script_engine_init", + (gpointer *)&pango_module->init) || + !g_module_symbol (pango_module->library, "script_engine_exit", + (gpointer *)&pango_module->exit) || + !g_module_symbol (pango_module->library, "script_engine_list", + (gpointer *)&pango_module->list) || + !g_module_symbol (pango_module->library, "script_engine_create", + (gpointer *)&pango_module->create)) { - GModule *module; - char *module_name = pair->load_info; - PangoEngine *(*load) (const gchar *id); - - module = g_module_open (module_name, 0); - if (!module) - { - g_printerr ("Cannot load module %s: %s\n", - module_name, g_module_error()); - return NULL; - } + g_warning (g_module_error()); + g_module_close (pango_module->library); - g_module_symbol (module, "script_engine_load", (gpointer *) &load); - if (!load) - { - g_printerr ("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 FALSE; } + } + + /* call the module's init function to let it */ + /* setup anything it needs to set up. */ + pango_module->init (module); + + return TRUE; +} + +static void +pango_module_unload (GTypeModule *module) +{ + PangoModule *pango_module = PANGO_MODULE (module); + + pango_module->exit(); + + if (pango_module->path) + { + g_module_close (pango_module->library); + pango_module->library = NULL; + pango_module->init = NULL; + pango_module->exit = NULL; + pango_module->list = NULL; + pango_module->create = NULL; + } +} + +/* This only will ever be called if an error occurs during + * initialization + */ +static void +pango_module_finalize (GObject *object) +{ + PangoModule *module = PANGO_MODULE (object); + + g_free (module->path); + + parent_class->finalize (object); +} + +static void +pango_module_class_init (PangoModuleClass *class) +{ + GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class); + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class)); + + module_class->load = pango_module_load; + module_class->unload = pango_module_unload; + + gobject_class->finalize = pango_module_finalize; +} + +static PANGO_DEFINE_TYPE (PangoModule, pango_module, + pango_module_class_init, NULL, + G_TYPE_TYPE_MODULE); + +static PangoEngine * +pango_engine_pair_get_engine (PangoEnginePair *pair) +{ + if (!pair->engine) + { + if (g_type_module_use (G_TYPE_MODULE (pair->module))) + { + pair->engine = pair->module->create (pair->info.id); + g_type_module_unuse (G_TYPE_MODULE (pair->module)); + } + + if (!pair->engine) + g_printerr ("Failed to load Pango module for id: '%s'", pair->info.id); } return pair->engine; } static void -handle_included_module (PangoIncludedModule *module, - GSList **engine_list) +handle_included_module (PangoIncludedModule *included_module, + GSList **engine_list) { + PangoModule *module = g_object_new (PANGO_TYPE_MODULE, NULL); PangoEngineInfo *engine_info; int n_engines; int i; + module->list = included_module->list; + module->init = included_module->init; + module->exit = included_module->exit; + module->create = included_module->create; + module->list (&engine_info, &n_engines); for (i = 0; i < n_engines; i++) @@ -193,14 +289,56 @@ handle_included_module (PangoIncludedModule *module, PangoEnginePair *pair = g_new (PangoEnginePair, 1); pair->info = engine_info[i]; - pair->included = TRUE; - pair->load_info = module; + pair->module = module; pair->engine = NULL; *engine_list = g_slist_prepend (*engine_list, pair); } } +static PangoModule * +find_or_create_module (const char *raw_path) +{ + PangoModule *module; + char *path; + +#if defined(G_OS_WIN32) && defined(LIBDIR) + if (strncmp (raw_path, + LIBDIR "/pango/" MODULE_VERSION "/modules/", + strlen (LIBDIR "/pango/" MODULE_VERSION "/modules/")) == 0) + { + /* This is an entry put there by make install on the + * packager's system. On Windows a prebuilt Pango + * package can be installed in a random + * location. The pango.modules file distributed in + * such a package contains paths from the package + * builder's machine. Replace the path with the real + * one on this machine. */ + path = + g_strconcat (pango_get_lib_subdirectory (), + "\\" MODULE_VERSION "\\modules\\", + raw_path + strlen (LIBDIR "/pango/" MODULE_VERSION "/modules/"), + NULL); + } + else +#endif + { + path = g_strdup (raw_path); + } + + module = g_hash_table_lookup (dlloaded_modules, path); + if (module) + g_free (path); + else + { + module = g_object_new (PANGO_TYPE_MODULE, NULL); + module->path = path; + g_hash_table_insert (dlloaded_modules, path, module); + } + + return module; +} + static gboolean /* Returns true if succeeded, false if failed */ process_module_file (FILE *module_file) { @@ -219,8 +357,6 @@ process_module_file (FILE *module_file) int i; int start, end; - pair->included = FALSE; - p = line_buf->str; if (!pango_skip_space (&p)) @@ -241,29 +377,7 @@ process_module_file (FILE *module_file) switch (i) { case 0: - pair->load_info = g_strdup (tmp_buf->str); -#if defined(G_OS_WIN32) && defined(LIBDIR) - if (strncmp (pair->load_info, - LIBDIR "/pango/" MODULE_VERSION "/modules/", - strlen (LIBDIR "/pango/" MODULE_VERSION "/modules/")) == 0) - { - /* This is an entry put there by make install on the - * packager's system. On Windows a prebuilt Pango - * package can be installed in a random - * location. The pango.modules file distributed in - * such a package contains paths from the package - * builder's machine. Replace the path with the real - * one on this machine. */ - gchar *tem = pair->load_info; - pair->load_info = - g_strconcat (pango_get_lib_subdirectory (), - "\\" MODULE_VERSION "\\modules\\", - tem + strlen (LIBDIR "/pango/" MODULE_VERSION "/modules/"), - NULL); - g_free (tem); - } - -#endif + pair->module = find_or_create_module (tmp_buf->str); break; case 1: pair->info.id = g_strdup (tmp_buf->str); @@ -351,6 +465,8 @@ read_modules (void) char **files; int n; + dlloaded_modules = g_hash_table_new (g_str_hash, g_str_equal); + if (!file_str) file_str = g_build_filename (pango_get_sysconf_subdirectory (), "pango.modules", @@ -520,7 +636,7 @@ build_map (PangoMapInfo *info) init_modules(); - if (!dlloaded_engines && !registered_engines && !builtin_engines) + if (!dlloaded_engines && !registered_engines) { static gboolean no_module_warning = FALSE; if (!no_module_warning) @@ -546,7 +662,6 @@ build_map (PangoMapInfo *info) map_add_engine_list (info, dlloaded_engines, engine_type, render_type); map_add_engine_list (info, registered_engines, engine_type, render_type); - map_add_engine_list (info, builtin_engines, engine_type, render_type); } /** |