summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
Diffstat (limited to 'pango')
-rw-r--r--pango/modules.c7
-rw-r--r--pango/pango-attributes.c2
-rw-r--r--pango/pango-context.c6
-rw-r--r--pango/pango-coverage.c146
-rw-r--r--pango/pango-coverage.h8
-rw-r--r--pango/pangox-fontmap.c352
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;
}