diff options
author | Owen Taylor <otaylor@redhat.com> | 2000-07-21 13:59:36 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2000-07-21 13:59:36 +0000 |
commit | a084f42c0e920e2ac91383b8d98ff54f339d17ac (patch) | |
tree | cd2ae4cd9d49439019d4dddda005c02523d26c89 /pango | |
parent | 1f53784fdae609da25c593d9b99ba830c6513298 (diff) | |
download | pango-a084f42c0e920e2ac91383b8d98ff54f339d17ac.tar.gz |
Free buffer strings.
Fri Jul 21 09:59:10 2000 Owen Taylor <otaylor@redhat.com>
* pango/modules.c (process_module_file): Free buffer strings.
* pango/pangox-fontmap.c (pango_x_real_get_coverage_win): Add
caching of coverage maps on a persistant subwindow of the
root window. This window contains a property for
each "lang|xlfd,xlfd" which is the result of pango_coverage_to_bytes.
* pango/pango-context.c (pango_context_finalize): Free
the font description.
* pango/pango-coverage.c (pango_coverage_to/from_bytes): Added
functions to covert a PangoCoverage structure too and
from a flat block of bytes.
* configure.in (X_LIBS): Add a check to detect fribidi being
compiled against glib-1.2.x.
Diffstat (limited to 'pango')
-rw-r--r-- | pango/modules.c | 7 | ||||
-rw-r--r-- | pango/pango-attributes.c | 2 | ||||
-rw-r--r-- | pango/pango-context.c | 6 | ||||
-rw-r--r-- | pango/pango-coverage.c | 146 | ||||
-rw-r--r-- | pango/pango-coverage.h | 8 | ||||
-rw-r--r-- | pango/pangox-fontmap.c | 352 |
6 files changed, 487 insertions, 34 deletions
diff --git a/pango/modules.c b/pango/modules.c index cad34866..c31e4d3c 100644 --- a/pango/modules.c +++ b/pango/modules.c @@ -301,11 +301,14 @@ process_module_file (FILE *module_file) if (have_error) { g_free(pair); - return FALSE; + break; } } - return TRUE; + g_string_free (line_buf, TRUE); + g_string_free (tmp_buf, TRUE); + + return !have_error; } static void diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index a688cab6..23cfd8b1 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -19,6 +19,8 @@ * Boston, MA 02111-1307, USA. */ +#include <string.h> + #include <pango/pango-attributes.h> struct _PangoAttrList diff --git a/pango/pango-context.c b/pango/pango-context.c index 11e1ecbc..cf6d3b42 100644 --- a/pango/pango-context.c +++ b/pango/pango-context.c @@ -19,8 +19,10 @@ * Boston, MA 02111-1307, USA. */ -#include <pango/pango-context.h> +#include <string.h> + #include <fribidi/fribidi.h> +#include <pango/pango-context.h> #include "iconv.h" #include "pango-modules.h" @@ -125,6 +127,8 @@ pango_context_finalize (GObject *object) g_slist_foreach (context->font_maps, (GFunc)g_object_unref, NULL); g_slist_free (context->font_maps); + + pango_font_description_free (context->font_desc); G_OBJECT_CLASS (parent_class)->finalize (object); } diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c index 1e090f41..6a031fb3 100644 --- a/pango/pango-coverage.c +++ b/pango/pango-coverage.c @@ -341,4 +341,150 @@ void pango_coverage_max (PangoCoverage *coverage, } } +#define PANGO_COVERAGE_MAGIC 0xc89dbd5e + +/** + * pango_coverage_to_bytes: + * @coverage: a #PangoCoverage + * @bytes: location to store result (must be freed with g_free()) + * @n_bytes: location to store size of result + * + * Convert a PangoCoverage structure into a flat binary format + **/ +void +pango_coverage_to_bytes (PangoCoverage *coverage, + guchar **bytes, + int *n_bytes) +{ + int i, j; + int size = 8 + 4 * coverage->n_blocks; + guchar *data; + int offset; + + for (i=0; i<coverage->n_blocks; i++) + { + if (coverage->blocks[i].data) + size += 64; + } + + data = g_malloc (size); + + *(guint32 *)&data[0] = g_htonl (PANGO_COVERAGE_MAGIC); /* Magic */ + *(guint32 *)&data[4] = g_htonl (coverage->n_blocks); + offset = 8; + + for (i=0; i<coverage->n_blocks; i++) + { + guint32 header_val; + + /* Check for solid blocks. This is a sort of random place + * to do the optimization, but we care most about getting + * it right when storing it somewhere persistant. + */ + if (coverage->blocks[i].data != NULL) + { + guchar *data = coverage->blocks[i].data; + guchar first_val = data[0]; + + for (j = 1 ; j < 64; j++) + if (data[j] != first_val) + break; + + if (j == 64) + { + g_free (data); + coverage->blocks[i].data = NULL; + coverage->blocks[i].level = first_val & 0x3; + } + } + + if (coverage->blocks[i].data != NULL) + header_val = (guint32)-1; + else + header_val = coverage->blocks[i].level; + + *(guint32 *)&data[offset] = g_htonl (header_val); + offset += 4; + + if (coverage->blocks[i].data) + { + memcpy (data + offset, coverage->blocks[i].data, 64); + offset += 64; + } + } + + *bytes = data; + *n_bytes = size; +} + +static guint32 +pango_coverage_get_uint32 (guchar **ptr) +{ + guint32 val; + + memcpy (&val, *ptr, 4); + *ptr += 4; + + return g_ntohl (val); +} + +/** + * pango_coverage_from_bytes: + * @bytes: binary data representing a #PangoCoverage + * @n_bytes: the size of @bytes in bytes + * + * Convert data generated from pango_converage_to_bytes() back + * to a #PangoCoverage + * + * Return value: a newly allocated #PangoCoverage, or NULL if + * the data was invalid. + **/ +PangoCoverage * +pango_coverage_from_bytes (guchar *bytes, + int n_bytes) +{ + PangoCoverage *coverage = g_new0 (PangoCoverage, 1); + guchar *ptr = bytes; + int i; + + coverage->ref_count = 1; + + if (n_bytes < 8) + goto error; + + if (pango_coverage_get_uint32 (&ptr) != PANGO_COVERAGE_MAGIC) + goto error; + + coverage->n_blocks = pango_coverage_get_uint32 (&ptr); + coverage->blocks = g_new0 (PangoBlockInfo, coverage->n_blocks); + + for (i = 0; i < coverage->n_blocks; i++) + { + guint val; + + if (ptr + 4 > bytes + n_bytes) + goto error; + + val = pango_coverage_get_uint32 (&ptr); + if (val == (guint32)-1) + { + if (ptr + 64 > bytes + n_bytes) + goto error; + + coverage->blocks[i].data = g_new (guchar, 64); + memcpy (coverage->blocks[i].data, ptr, 64); + ptr += 64; + } + else + coverage->blocks[i].level = val; + } + + return coverage; + + error: + + pango_coverage_unref (coverage); + return NULL; +} + diff --git a/pango/pango-coverage.h b/pango/pango-coverage.h index d51c4bc0..a10eb4cb 100644 --- a/pango/pango-coverage.h +++ b/pango/pango-coverage.h @@ -49,6 +49,12 @@ void pango_coverage_set (PangoCoverage *coverage, void pango_coverage_max (PangoCoverage *coverage, PangoCoverage *other); +void pango_coverage_to_bytes (PangoCoverage *coverage, + guchar **bytes, + int *n_bytes); +PangoCoverage *pango_coverage_from_bytes (guchar *bytes, + int n_bytes); + #ifdef __cplusplus } #endif /* __cplusplus */ @@ -56,3 +62,5 @@ void pango_coverage_max (PangoCoverage *coverage, #endif /* __PANGO_COVERAGE_H__ */ + + diff --git a/pango/pangox-fontmap.c b/pango/pangox-fontmap.c index 007e3ad1..34a0cc3f 100644 --- a/pango/pangox-fontmap.c +++ b/pango/pangox-fontmap.c @@ -25,6 +25,8 @@ #include <string.h> #include <errno.h> +#include <X11/Xatom.h> + #include "pango-fontmap.h" #include "pango-utils.h" #include "pangox-private.h" @@ -84,6 +86,8 @@ struct _PangoXFontMap int n_fonts; double resolution; /* (points / pixel) * PANGO_SCALE */ + + Window coverage_win; }; struct _PangoXFontMapClass @@ -547,6 +551,270 @@ pango_x_font_map_load_font (PangoFontMap *fontmap, return result; } + +/************************ + * Coverage Map Caching * + ************************/ + +/* We need to be robust against errors accessing the coverage + * cache window, since it is not our window. So we temporarily + * set this error handler while accessing it. The error_occured + * global allows us to tell whether an error occured for + * XChangeProperty + */ +static gboolean error_occured; + +static int +ignore_error (Display *d, XErrorEvent *e) +{ + return 0; +} + +/* Retrieve the coverage window for the given display. + * We look for a property on the root window, and then + * check that the window that property points to also + * has the same property pointing to itself. The second + * check allows us to make sure that a stale property + * isn't just pointing to some other apps window + */ +static Window +pango_x_real_get_coverage_win (Display *display) +{ + Atom type; + int format; + gulong n_items; + gulong bytes_after; + Atom *data; + Window retval = None; + int (*old_handler) (Display *, XErrorEvent *); + + Atom coverage_win_atom = XInternAtom (display, + "PANGO_COVERAGE_WIN", + False); + + XGetWindowProperty (display, + DefaultRootWindow (display), + coverage_win_atom, + 0, 4, + False, XA_WINDOW, + &type, &format, &n_items, &bytes_after, + (guchar **)&data); + + if (type == XA_WINDOW) + { + if (format == 32 && n_items == 1 && bytes_after == 0) + retval = *data; + + XFree (data); + } + + old_handler= XSetErrorHandler (ignore_error); + + if (XGetWindowProperty (display, + retval, + coverage_win_atom, + 0, 4, + False, XA_WINDOW, + &type, &format, &n_items, &bytes_after, + (guchar **)&data) == Success && + type == XA_WINDOW) + { + if (format != 32 || n_items != 1 || bytes_after != 0 || + *data != retval) + retval = None; + + XFree (data); + } + else + retval = None; + + XSync (display, False); + XSetErrorHandler (old_handler); + + return retval; +} + +/* Find or create the peristant window for caching font coverage + * information. + * + * To assure atomic creation, we first look for the window, then if we + * don't find it, grab the server, look for it again, and then if that + * still didn't find it, create it and ungrab. + */ +static Window +pango_x_get_coverage_win (PangoXFontMap *xfontmap) +{ + if (!xfontmap->coverage_win) + xfontmap->coverage_win = pango_x_real_get_coverage_win (xfontmap->display); + + if (!xfontmap->coverage_win) + { + Display *persistant_display; + + persistant_display = XOpenDisplay (DisplayString (xfontmap->display)); + if (!persistant_display) + { + g_warning ("Cannot create or retrieve display for font coverage cache"); + return None; + } + + XGrabServer (persistant_display); + + xfontmap->coverage_win = pango_x_real_get_coverage_win (xfontmap->display); + if (!xfontmap->coverage_win) + { + XSetWindowAttributes attr; + + attr.override_redirect = True; + + XSetCloseDownMode (persistant_display, RetainPermanent); + + xfontmap->coverage_win = + XCreateWindow (persistant_display, + DefaultRootWindow (persistant_display), + -100, -100, 10, 10, 0, 0, + InputOnly, CopyFromParent, + CWOverrideRedirect, &attr); + + XChangeProperty (persistant_display, + DefaultRootWindow (persistant_display), + XInternAtom (persistant_display, + "PANGO_COVERAGE_WIN", + FALSE), + XA_WINDOW, + 32, PropModeReplace, + (guchar *)&xfontmap->coverage_win, 1); + + + XChangeProperty (persistant_display, + xfontmap->coverage_win, + XInternAtom (persistant_display, + "PANGO_COVERAGE_WIN", + FALSE), + XA_WINDOW, + 32, PropModeReplace, + (guchar *)&xfontmap->coverage_win, 1); + } + + XUngrabServer (persistant_display); + + XSync (persistant_display, False); + XCloseDisplay (persistant_display); + } + + return xfontmap->coverage_win; +} + +/* Find the cached value for the coverage map on the + * coverage cache window, if it exists. *atom is set + * to the interned value of str for later use in storing + * the property if the lookup fails + */ +static PangoCoverage * +pango_x_get_cached_coverage (PangoXFontMap *xfontmap, + const char *str, + Atom *atom) +{ + int (*old_handler) (Display *, XErrorEvent *); + Window coverage_win; + PangoCoverage *result = NULL; + + Atom type; + int format; + int tries = 5; + gulong n_items; + gulong bytes_after; + guchar *data; + + *atom = XInternAtom (xfontmap->display, str, False); + + while (tries--) + { + coverage_win = pango_x_get_coverage_win (xfontmap); + + if (!coverage_win) + return NULL; + + old_handler= XSetErrorHandler (ignore_error); + + if (XGetWindowProperty (xfontmap->display, + coverage_win, *atom, + 0, G_MAXLONG, + False, XA_STRING, + &type, &format, &n_items, &bytes_after, + &data) == Success + && type == XA_STRING) + { + if (format == 8 && bytes_after == 0) + result = pango_coverage_from_bytes (data, n_items); + + XSetErrorHandler (old_handler); + XFree (data); + break; + } + else + { + /* Window disappeared out from under us */ + XSetErrorHandler (old_handler); + xfontmap->coverage_win = None; + } + + } + + return result; +} + +/* Store the given coverage map on the coverage cache window. + * atom is the intern'ed value of the string that identifies + * the cache entry. + */ +static void +pango_x_store_cached_coverage (PangoXFontMap *xfontmap, + Atom atom, + PangoCoverage *coverage) +{ + int (*old_handler) (Display *, XErrorEvent *); + guchar *bytes; + gint size; + + int tries = 5; + + pango_coverage_to_bytes (coverage, &bytes, &size); + + while (tries--) + { + Window coverage_win = pango_x_get_coverage_win (xfontmap); + + if (!coverage_win) + break; + + old_handler = XSetErrorHandler (ignore_error); + error_occured = False; + + XChangeProperty (xfontmap->display, + coverage_win, + atom, + XA_STRING, + 8, PropModeReplace, + bytes, size); + + XSync (xfontmap->display, False); + XSetErrorHandler (old_handler); + + if (!error_occured) + break; + else + { + /* Window disappeared out from under us */ + XSetErrorHandler (old_handler); + xfontmap->coverage_win = None; + } + } + + g_free (bytes); +} + + static void pango_x_font_map_read_alias_file (PangoXFontMap *xfontmap, const char *filename) @@ -1090,39 +1358,57 @@ pango_x_font_entry_get_coverage (PangoXFontEntry *entry, PangoFont *font, const char *lang) { - guint32 ch; - PangoMap *shape_map; - PangoCoverage *coverage; - PangoCoverage *result; - PangoCoverageLevel font_level; - PangoMapEntry *map_entry; + PangoXFont *xfont; + PangoXFontMap *xfontmap = NULL; /* Quiet gcc */ + PangoCoverage *result = NULL; GHashTable *coverage_hash; + Atom atom = None; if (entry) - if (entry->coverage) - { - pango_coverage_ref (entry->coverage); - return entry->coverage; - } - - result = pango_coverage_new (); - - coverage_hash = g_hash_table_new (g_str_hash, g_str_equal); - - shape_map = pango_x_get_shaper_map (lang); + { + if (entry->coverage) + { + pango_coverage_ref (entry->coverage); + return entry->coverage; + } + + xfont = (PangoXFont *)font; + + xfontmap = (PangoXFontMap *)pango_x_font_map_for_display (xfont->display); + if (entry->xlfd) + { + char *str = g_strconcat (lang ? lang : "*", "|", entry->xlfd, NULL); + result = pango_x_get_cached_coverage (xfontmap, str, &atom); + g_free (str); + } + } - for (ch = 0; ch < 65536; ch++) + if (!result) { - map_entry = pango_map_get_entry (shape_map, ch); - if (map_entry->info) + guint32 ch; + PangoMap *shape_map; + PangoCoverage *coverage; + PangoCoverageLevel font_level; + PangoMapEntry *map_entry; + + result = pango_coverage_new (); + + coverage_hash = g_hash_table_new (g_str_hash, g_str_equal); + + shape_map = pango_x_get_shaper_map (lang); + + for (ch = 0; ch < 65536; ch++) { - coverage = g_hash_table_lookup (coverage_hash, map_entry->info->id); - if (!coverage) + map_entry = pango_map_get_entry (shape_map, ch); + if (map_entry->info) { - PangoEngineShape *engine = (PangoEngineShape *)pango_map_get_engine (shape_map, ch); - coverage = engine->get_coverage (font, lang); - g_hash_table_insert (coverage_hash, map_entry->info->id, coverage); - } + coverage = g_hash_table_lookup (coverage_hash, map_entry->info->id); + if (!coverage) + { + PangoEngineShape *engine = (PangoEngineShape *)pango_map_get_engine (shape_map, ch); + coverage = engine->get_coverage (font, lang); + 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) @@ -1130,18 +1416,22 @@ pango_x_font_entry_get_coverage (PangoXFontEntry *entry, if (font_level != PANGO_COVERAGE_NONE) pango_coverage_set (result, ch, font_level); + } } - } - - g_hash_table_foreach (coverage_hash, free_coverages_foreach, NULL); - g_hash_table_destroy (coverage_hash); + + g_hash_table_foreach (coverage_hash, free_coverages_foreach, NULL); + g_hash_table_destroy (coverage_hash); + if (atom) + pango_x_store_cached_coverage (xfontmap, atom, result); + } + if (entry) { entry->coverage = result; pango_coverage_ref (result); } - + return result; } |