summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rw-r--r--pango/pangocairo-fcfont.c425
-rw-r--r--pango/pangocairo-fcfontmap.c12
-rw-r--r--pango/pangocairo-font.c506
-rw-r--r--pango/pangocairo-fontmap.c16
-rw-r--r--pango/pangocairo-private.h104
-rw-r--r--pango/pangocairo-render.c8
7 files changed, 586 insertions, 505 deletions
diff --git a/ChangeLog b/ChangeLog
index 36c743e9..4d7667fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2007-06-09 Behdad Esfahbod <behdad@gnome.org>
+
+ Bug 337593 – move glyph extents code (and cache) from
+ pangocairo-*font.c into pangocairo-font.c
+
+ * pango/pangocairo-fontmap.c:
+ * pango/pangocairo-fcfontmap.c:
+ Remove per-fontmap renderer. We've not been using it for a while
+ and there is no reason to use it.
+
+ * pango/pangocairo-font.c
+ * pango/pangocairo-fcfont.c:
+ Most most code (including glyph extents caching) from fcfont.c to
+ font.c. Simplifies individual backends a lot. ATSUI and Win32
+ cairo backends should adapt.
+
+ * pango/pangocairo-render.c
+ * pango/pangocairo-private.h:
+ Update to reflect above changes.
+
2007-06-05 Behdad Esfahbod <behdad@gnome.org>
* pango/fonts.c (pango_font_description_merge),
diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c
index 8c44b2a0..b671ebea 100644
--- a/pango/pangocairo-fcfont.c
+++ b/pango/pangocairo-fcfont.c
@@ -21,9 +21,6 @@
#include <config.h>
-#include <math.h>
-#include <stdlib.h>
-
#include <cairo-ft.h>
#include "pango-fontmap.h"
@@ -41,36 +38,12 @@
typedef struct _PangoCairoFcFont PangoCairoFcFont;
typedef struct _PangoCairoFcFontClass PangoCairoFcFontClass;
-typedef struct _GlyphExtentsCacheEntry GlyphExtentsCacheEntry;
-
-#define GLYPH_CACHE_NUM_ENTRIES 256 /* should be power of two */
-#define GLYPH_CACHE_MASK (GLYPH_CACHE_NUM_ENTRIES - 1)
-
-/* An entry in the fixed-size cache for the glyph -> ink_rect mapping.
- * The cache is indexed by the lower N bits of the glyph (see
- * GLYPH_CACHE_NUM_ENTRIES). For scripts with few glyphs,
- * this should provide pretty much instant lookups.
- */
-struct _GlyphExtentsCacheEntry
-{
- PangoGlyph glyph;
- int width;
- PangoRectangle ink_rect;
-};
-
struct _PangoCairoFcFont
{
PangoFcFont font;
+ PangoCairoFontPrivate cf_priv;
- cairo_font_face_t *font_face;
- cairo_scaled_font_t *scaled_font;
- cairo_matrix_t font_matrix;
- cairo_matrix_t ctm;
- cairo_font_options_t *options;
PangoGravity gravity;
-
- PangoRectangle font_extents;
- GlyphExtentsCacheEntry *glyph_extents_cache;
};
struct _PangoCairoFcFontClass
@@ -80,86 +53,33 @@ struct _PangoCairoFcFontClass
GType pango_cairo_fc_font_get_type (void);
-static cairo_font_face_t *pango_cairo_fc_font_get_font_face (PangoCairoFont *font);
-
-/*******************************
- * Utility functions *
- *******************************/
+/********************************
+ * Method implementations *
+ ********************************/
static cairo_font_face_t *
-pango_cairo_fc_font_get_font_face (PangoCairoFont *font)
-{
- PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
- PangoFcFont *fcfont = (PangoFcFont *) (cffont);
-
- if (!cffont->font_face)
- {
- cffont->font_face = cairo_ft_font_face_create_for_pattern (fcfont->font_pattern);
-
- /* Unable to create FT2 cairo scaled font.
- * This means out of memory or a cairo/fontconfig/FreeType bug,
- */
- if (!cffont->font_face)
- return NULL;
- }
-
- return cffont->font_face;
-}
-
-static cairo_scaled_font_t *
-pango_cairo_fc_font_get_scaled_font (PangoCairoFont *font)
+pango_cairo_fc_font_create_font_face (PangoCairoFont *cfont)
{
- PangoCairoFcFont *cffont = (PangoCairoFcFont *)font;
+ PangoFcFont *fcfont = (PangoFcFont *) (cfont);
- if (!cffont->scaled_font)
- {
- cairo_font_face_t *font_face;
-
- font_face = pango_cairo_fc_font_get_font_face (font);
-
- if (!font_face)
- return NULL;
-
- cffont->scaled_font = cairo_scaled_font_create (font_face,
- &cffont->font_matrix,
- &cffont->ctm,
- cffont->options);
-
- /* Unable to create FT2 cairo scaled font.
- * This means out of memory or a cairo/fontconfig/FreeType bug,
- * or a missing font...
- */
- if (!cffont->scaled_font)
- return NULL;
- }
-
- return cffont->scaled_font;
+ return cairo_ft_font_face_create_for_pattern (fcfont->font_pattern);
}
-/********************************
- * Method implementations *
- ********************************/
-
-static gboolean
-pango_cairo_fc_font_install (PangoCairoFont *font,
- cairo_t *cr)
+static PangoFontMetrics *
+pango_cairo_fc_font_create_metrics_for_context (PangoCairoFont *cfont,
+ PangoContext *context)
{
- PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
-
- cairo_set_font_face (cr,
- pango_cairo_fc_font_get_font_face (font));
- cairo_set_font_matrix (cr, &cffont->font_matrix);
- cairo_set_font_options (cr, cffont->options);
+ PangoFcFont *fcfont = (PangoFcFont *) (cfont);
- return TRUE;
+ return pango_fc_font_create_metrics_for_context (fcfont, context);
}
static void
cairo_font_iface_init (PangoCairoFontIface *iface)
{
- iface->install = pango_cairo_fc_font_install;
- iface->get_font_face = pango_cairo_fc_font_get_font_face;
- iface->get_scaled_font = pango_cairo_fc_font_get_scaled_font;
+ iface->create_font_face = pango_cairo_fc_font_create_font_face;
+ iface->create_metrics_for_context = pango_cairo_fc_font_create_metrics_for_context;
+ iface->cf_priv_offset = G_STRUCT_OFFSET (PangoCairoFcFont, cf_priv);
}
G_DEFINE_TYPE_WITH_CODE (PangoCairoFcFont, pango_cairo_fc_font, PANGO_TYPE_FC_FONT,
@@ -170,105 +90,34 @@ pango_cairo_fc_font_finalize (GObject *object)
{
PangoCairoFcFont *cffont = (PangoCairoFcFont *) (object);
- if (cffont->font_face)
- cairo_font_face_destroy (cffont->font_face);
- if (cffont->scaled_font)
- cairo_scaled_font_destroy (cffont->scaled_font);
- if (cffont->options)
- cairo_font_options_destroy (cffont->options);
-
-
- if (cffont->glyph_extents_cache)
- {
- g_free (cffont->glyph_extents_cache);
- }
+ _pango_cairo_font_private_finalize (&cffont->cf_priv);
G_OBJECT_CLASS (pango_cairo_fc_font_parent_class)->finalize (object);
}
-/* This function is cut-and-pasted from pangocairo-fcfont.c - it might be
- * better to add a virtual fcfont->create_context (font).
- */
-static PangoFontMetrics *
-pango_cairo_fc_font_get_metrics (PangoFont *font,
- PangoLanguage *language)
+/* we want get_glyph_extents extremely fast, so we use a small wrapper here
+ * to avoid having to lookup the interface data like we do for get_metrics
+ * in _pango_cairo_font_get_metrics(). */
+static void
+pango_cairo_fc_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
{
- PangoFcFont *fcfont = (PangoFcFont *) (font);
PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
- PangoFcMetricsInfo *info = NULL; /* Quiet gcc */
- GSList *tmp_list;
-
- const char *sample_str = pango_language_get_sample_string (language);
-
- tmp_list = fcfont->metrics_by_lang;
- while (tmp_list)
- {
- info = tmp_list->data;
-
- if (info->sample_str == sample_str) /* We _don't_ need strcmp */
- break;
-
- tmp_list = tmp_list->next;
- }
- if (!tmp_list)
- {
- PangoContext *context;
- int height, shift;
-
- if (!fcfont->fontmap)
- return pango_font_metrics_new ();
-
- info = g_slice_new0 (PangoFcMetricsInfo);
-
- fcfont->metrics_by_lang = g_slist_prepend (fcfont->metrics_by_lang, info);
-
- info->sample_str = sample_str;
-
- context = pango_fc_font_map_create_context (PANGO_FC_FONT_MAP (fcfont->fontmap));
- pango_context_set_language (context, language);
- pango_cairo_context_set_font_options (context, cffont->options);
-
- info->metrics = pango_fc_font_create_metrics_for_context (fcfont, context);
- /* We may actually reuse ascent/descent we got from cairo here. that's
- * in cffont->font_extents.
- */
- height = info->metrics->ascent + info->metrics->descent;
- switch (cffont->gravity)
- {
- default:
- case PANGO_GRAVITY_AUTO:
- case PANGO_GRAVITY_SOUTH:
- break;
- case PANGO_GRAVITY_NORTH:
- info->metrics->ascent = info->metrics->descent;
- break;
- case PANGO_GRAVITY_EAST:
- case PANGO_GRAVITY_WEST:
- {
- int ascent = height / 2;
- if (fcfont->is_hinted)
- ascent = PANGO_UNITS_ROUND (ascent);
- info->metrics->ascent = ascent;
- }
- }
- shift = (height - info->metrics->ascent) - info->metrics->descent;
- info->metrics->descent += shift;
- info->metrics->underline_position -= shift;
- info->metrics->strikethrough_position -= shift;
- info->metrics->ascent = height - info->metrics->descent;
-
- g_object_unref (context);
- }
-
- return pango_font_metrics_ref (info->metrics);
+ _pango_cairo_font_private_get_glyph_extents (&cffont->cf_priv,
+ glyph,
+ ink_rect,
+ logical_rect);
}
static FT_Face
pango_cairo_fc_font_lock_face (PangoFcFont *font)
{
- PangoCairoFont *cfont = (PangoCairoFont *)font;
- cairo_scaled_font_t *scaled_font = pango_cairo_fc_font_get_scaled_font (cfont);
+ PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&cffont->cf_priv);
+
if (G_UNLIKELY (!scaled_font))
return NULL;
@@ -278,8 +127,9 @@ pango_cairo_fc_font_lock_face (PangoFcFont *font)
static void
pango_cairo_fc_font_unlock_face (PangoFcFont *font)
{
- PangoCairoFont *cfont = (PangoCairoFont *)font;
- cairo_scaled_font_t *scaled_font = pango_cairo_fc_font_get_scaled_font (cfont);
+ PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&cffont->cf_priv);
+
if (G_UNLIKELY (!scaled_font))
return;
@@ -287,146 +137,11 @@ pango_cairo_fc_font_unlock_face (PangoFcFont *font)
}
static void
-pango_cairo_fc_font_glyph_extents_cache_init (PangoCairoFcFont *cffont)
-{
- PangoCairoFont *cfont = (PangoCairoFont *)cffont;
- cairo_scaled_font_t *scaled_font = pango_cairo_fc_font_get_scaled_font (cfont);
- cairo_font_extents_t font_extents;
-
- cairo_scaled_font_extents (scaled_font, &font_extents);
-
- cffont->font_extents.x = 0;
- cffont->font_extents.width = 0;
- cffont->font_extents.height = pango_units_from_double (font_extents.ascent + font_extents.descent);
- switch (cffont->gravity)
- {
- default:
- case PANGO_GRAVITY_AUTO:
- case PANGO_GRAVITY_SOUTH:
- cffont->font_extents.y = - pango_units_from_double (font_extents.ascent);
- break;
- case PANGO_GRAVITY_NORTH:
- cffont->font_extents.y = - pango_units_from_double (font_extents.descent);
- break;
- case PANGO_GRAVITY_EAST:
- case PANGO_GRAVITY_WEST:
- {
- PangoFcFont *fcfont = (PangoFcFont *) (cffont);
- int ascent = pango_units_from_double (font_extents.ascent + font_extents.descent) / 2;
- if (fcfont->is_hinted)
- ascent = PANGO_UNITS_ROUND (ascent);
- cffont->font_extents.y = - ascent;
- }
- }
-
- cffont->glyph_extents_cache = g_new0 (GlyphExtentsCacheEntry, GLYPH_CACHE_NUM_ENTRIES);
- /* Make sure all cache entries are invalid initially */
- cffont->glyph_extents_cache[0].glyph = 1; /* glyph 1 cannot happen in bucket 0 */
-}
-
-/* Fills in the glyph extents cache entry
- */
-static void
-compute_glyph_extents (PangoCairoFcFont *cffont,
- PangoGlyph glyph,
- GlyphExtentsCacheEntry *entry)
-{
- cairo_text_extents_t extents;
- cairo_glyph_t cairo_glyph;
-
- cairo_glyph.index = glyph;
- cairo_glyph.x = 0;
- cairo_glyph.y = 0;
-
- cairo_scaled_font_glyph_extents (cffont->scaled_font,
- &cairo_glyph, 1, &extents);
-
- entry->glyph = glyph;
- entry->width = pango_units_from_double (extents.x_advance);
- entry->ink_rect.x = pango_units_from_double (extents.x_bearing);
- entry->ink_rect.y = pango_units_from_double (extents.y_bearing);
- entry->ink_rect.width = pango_units_from_double (extents.width);
- entry->ink_rect.height = pango_units_from_double (extents.height);
-}
-
-static GlyphExtentsCacheEntry *
-pango_cairo_fc_font_get_glyph_extents_cache_entry (PangoCairoFcFont *cffont,
- PangoGlyph glyph)
-{
- GlyphExtentsCacheEntry *entry;
- guint idx;
-
- idx = glyph & GLYPH_CACHE_MASK;
- entry = cffont->glyph_extents_cache + idx;
-
- if (entry->glyph != glyph)
- {
- compute_glyph_extents (cffont, glyph, entry);
- }
-
- return entry;
-}
-
-static void
-pango_cairo_fc_font_get_glyph_extents (PangoFont *font,
- PangoGlyph glyph,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect)
-{
- PangoCairoFcFont *cffont = (PangoCairoFcFont *)font;
- GlyphExtentsCacheEntry *entry;
-
- if (!pango_cairo_fc_font_get_scaled_font ((PangoCairoFont *)cffont))
- {
- /* Get generic unknown-glyph extents. */
- pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect);
- return;
- }
-
- /* We need to initialize the cache here, since we use cffont->font_extents
- */
- if (cffont->glyph_extents_cache == NULL)
- pango_cairo_fc_font_glyph_extents_cache_init (cffont);
-
- if (glyph == PANGO_GLYPH_EMPTY)
- {
- if (ink_rect)
- ink_rect->x = ink_rect->y = ink_rect->width = ink_rect->height = 0;
- if (logical_rect)
- *logical_rect = cffont->font_extents;
- return;
- }
- else if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
- {
- _pango_cairo_get_glyph_extents_missing((PangoCairoFont *)font, glyph, ink_rect, logical_rect);
- return;
- }
-
- entry = pango_cairo_fc_font_get_glyph_extents_cache_entry (cffont, glyph);
-
- if (ink_rect)
- *ink_rect = entry->ink_rect;
- if (logical_rect)
- {
- *logical_rect = cffont->font_extents;
- logical_rect->width = entry->width;
- }
-}
-
-static void
pango_cairo_fc_font_shutdown (PangoFcFont *fcfont)
{
PangoCairoFcFont *cffont = (PangoCairoFcFont *) (fcfont);
- if (cffont->scaled_font)
- {
- cairo_scaled_font_destroy (cffont->scaled_font);
- cffont->scaled_font = NULL;
- }
- if (cffont->font_face)
- {
- cairo_font_face_destroy (cffont->font_face);
- cffont->font_face = NULL;
- }
+
+ _pango_cairo_font_private_finalize (&cffont->cf_priv);
}
static void
@@ -439,7 +154,7 @@ pango_cairo_fc_font_class_init (PangoCairoFcFontClass *class)
object_class->finalize = pango_cairo_fc_font_finalize;
font_class->get_glyph_extents = pango_cairo_fc_font_get_glyph_extents;
- font_class->get_metrics = pango_cairo_fc_font_get_metrics;
+ font_class->get_metrics = _pango_cairo_font_get_metrics;
fc_font_class->lock_face = pango_cairo_fc_font_lock_face;
fc_font_class->unlock_face = pango_cairo_fc_font_unlock_face;
@@ -459,8 +174,7 @@ static double
get_font_size (PangoCairoFcFontMap *cffontmap,
PangoContext *context,
const PangoFontDescription *desc,
- FcPattern *pattern,
- const PangoMatrix *matrix)
+ FcPattern *pattern)
{
double size;
@@ -478,7 +192,7 @@ get_font_size (PangoCairoFcFontMap *cffontmap,
*/
if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
- return size * PANGO_SCALE / pango_matrix_get_font_scale_factor (matrix);
+ return size * PANGO_SCALE / pango_matrix_get_font_scale_factor (pango_context_get_matrix (context));
/* Just in case FC_PIXEL_SIZE got unset between pango_fc_make_pattern()
* and here.
@@ -503,7 +217,7 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
FcPattern *pattern)
{
PangoCairoFcFont *cffont;
- const PangoMatrix *pango_ctm;
+ cairo_matrix_t font_matrix;
FcMatrix *fc_matrix;
double size;
@@ -514,56 +228,29 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
"pattern", pattern,
NULL);
- cffont->gravity = pango_font_description_get_gravity (desc);
-
- /* first apply gravity rotation, then pattern matrix, such that
- * vertical italic text comes out "correct". we don't do anything
- * like baseline adjustment etc though. should be specially
- * handled when we support italic correction. */
- cairo_matrix_init_rotate(&cffont->font_matrix,
- pango_gravity_to_rotation (cffont->gravity));
+ size = get_font_size (cffontmap, context, desc, pattern);
if (FcPatternGetMatrix (pattern,
FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
- {
- cairo_matrix_t matrix;
-
- cairo_matrix_init (&matrix,
- fc_matrix->xx,
- - fc_matrix->yx,
- - fc_matrix->xy,
- fc_matrix->yy,
- 0., 0.);
-
- cairo_matrix_multiply (&cffont->font_matrix,
- &matrix,
- &cffont->font_matrix);
- }
-
- pango_ctm = pango_context_get_matrix (context);
-
- size = get_font_size (cffontmap, context, desc, pattern, pango_ctm);
-
- cairo_matrix_scale (&cffont->font_matrix,
- size / PANGO_SCALE, size / PANGO_SCALE);
-
- if (pango_ctm)
- cairo_matrix_init (&cffont->ctm,
- pango_ctm->xx,
- pango_ctm->yx,
- pango_ctm->xy,
- pango_ctm->yy,
+ cairo_matrix_init (&font_matrix,
+ fc_matrix->xx,
+ - fc_matrix->yx,
+ - fc_matrix->xy,
+ fc_matrix->yy,
0., 0.);
else
- cairo_matrix_init_identity (&cffont->ctm);
+ cairo_matrix_init_identity (&font_matrix);
+ cairo_matrix_scale (&font_matrix,
+ size / PANGO_SCALE, size / PANGO_SCALE);
- cffont->options = cairo_font_options_copy (_pango_cairo_context_get_merged_font_options (context));
+ _pango_cairo_font_private_initialize (&cffont->cf_priv,
+ (PangoCairoFont *) cffont,
+ context,
+ desc,
+ &font_matrix);
- /* fcfont's is_hinted controls metric hinting
- */
- ((PangoFcFont *)(cffont))->is_hinted =
- (cairo_font_options_get_hint_metrics(cffont->options) != CAIRO_HINT_METRICS_OFF);
+ ((PangoFcFont *)(cffont))->is_hinted = _pango_cairo_font_private_is_metrics_hinted (&cffont->cf_priv);
- return (PangoFcFont *) (cffont);
+ return (PangoFcFont *) cffont;
}
diff --git a/pango/pangocairo-fcfontmap.c b/pango/pangocairo-fcfontmap.c
index 5b5c9fb5..bcecb059 100644
--- a/pango/pangocairo-fcfontmap.c
+++ b/pango/pangocairo-fcfontmap.c
@@ -52,23 +52,11 @@ pango_cairo_fc_font_map_get_resolution_cairo (PangoCairoFontMap *cfontmap)
return cffontmap->dpi;
}
-static PangoRenderer *
-pango_cairo_fc_font_map_get_renderer (PangoCairoFontMap *cfontmap)
-{
- PangoCairoFcFontMap *cffontmap = (PangoCairoFcFontMap *) (cfontmap);
-
- if (!cffontmap->renderer)
- cffontmap->renderer = g_object_new (PANGO_TYPE_CAIRO_RENDERER, NULL);
-
- return cffontmap->renderer;
-}
-
static void
cairo_font_map_iface_init (PangoCairoFontMapIface *iface)
{
iface->set_resolution = pango_cairo_fc_font_map_set_resolution;
iface->get_resolution = pango_cairo_fc_font_map_get_resolution_cairo;
- iface->get_renderer = pango_cairo_fc_font_map_get_renderer;
}
G_DEFINE_TYPE_WITH_CODE (PangoCairoFcFontMap, pango_cairo_fc_font_map, PANGO_TYPE_FC_FONT_MAP,
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index 2595c0ef..5f439998 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -29,6 +29,12 @@
PangoCairoWarningHistory _pango_cairo_warning_history = { FALSE };
+#define PANGO_CAIRO_FONT_PRIVATE(font) \
+ ((PangoCairoFontPrivate *) \
+ (font == NULL ? NULL : \
+ G_STRUCT_MEMBER_P (font, \
+ PANGO_CAIRO_FONT_GET_IFACE(PANGO_CAIRO_FONT(font))->cf_priv_offset)))
+
GType
pango_cairo_font_get_type (void)
{
@@ -60,45 +66,86 @@ pango_cairo_font_get_type (void)
return cairo_font_type;
}
-/**
- * _pango_cairo_font_install:
- * @font: a #PangoCairoFont
- * @cr: a #cairo_t
- *
- * Makes @font the current font for rendering in the specified
- * Cairo context.
- **/
-gboolean
-_pango_cairo_font_install (PangoCairoFont *font,
- cairo_t *cr)
+static PangoCairoFontPrivateScaledFontData *
+_pango_cairo_font_private_scaled_font_data_create (void)
+{
+ return g_slice_new (PangoCairoFontPrivateScaledFontData);
+}
+
+static void
+_pango_cairo_font_private_scaled_font_data_destroy (PangoCairoFontPrivateScaledFontData *data)
{
- if (G_UNLIKELY (!PANGO_IS_CAIRO_FONT (font)))
+ cairo_font_options_destroy (data->options);
+ g_slice_free (PangoCairoFontPrivateScaledFontData, data);
+}
+
+cairo_scaled_font_t *
+_pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv)
+{
+ cairo_font_face_t *font_face;
+
+ if (G_LIKELY (cf_priv->scaled_font))
+ return cf_priv->scaled_font;
+
+ /* need to create it */
+
+ if (G_UNLIKELY (cf_priv->data == NULL))
+ {
+ /* we have tried to create and failed before */
+ return NULL;
+ }
+
+ font_face = (* PANGO_CAIRO_FONT_GET_IFACE (cf_priv->cfont)->create_font_face) (cf_priv->cfont);
+ if (G_UNLIKELY (font_face == NULL))
+ goto done;
+
+ cf_priv->scaled_font = cairo_scaled_font_create (font_face,
+ &cf_priv->data->font_matrix,
+ &cf_priv->data->ctm,
+ cf_priv->data->options);
+
+ cairo_font_face_destroy (font_face);
+
+done:
+ _pango_cairo_font_private_scaled_font_data_destroy (cf_priv->data);
+ cf_priv->data = NULL;
+
+ if (G_UNLIKELY (cf_priv->scaled_font == NULL || cairo_scaled_font_status (cf_priv->scaled_font) != CAIRO_STATUS_SUCCESS))
{
- if (!_pango_cairo_warning_history.font_install)
+ PangoFont *font = PANGO_FONT (cf_priv->cfont);
+ static GQuark warned_quark = 0;
+ if (!warned_quark)
+ warned_quark = g_quark_from_static_string ("pangocairo-scaledfont-warned");
+
+ if (!g_object_get_qdata (G_OBJECT (font), warned_quark))
{
- _pango_cairo_warning_history.font_install = TRUE;
- g_warning ("_pango_cairo_font_install called with bad font, expect ugly output");
- cairo_set_font_face (cr, NULL);
+ PangoFontDescription *desc;
+ char *s;
+
+ desc = pango_font_describe (font);
+ s = pango_font_description_to_string (desc);
+ pango_font_description_free (desc);
+
+ g_warning ("failed to create cairo %s, expect ugly output. the offending font is '%s'",
+ font_face ? "scaled font" : "font face",
+ s);
+
+ g_free (s);
+
+ g_object_set_qdata_full (G_OBJECT (font), warned_quark,
+ GINT_TO_POINTER (1), NULL);
}
- return FALSE;
}
- return (* PANGO_CAIRO_FONT_GET_IFACE (font)->install) (font, cr);
+ return cf_priv->scaled_font;
}
-cairo_font_face_t *
-_pango_cairo_font_get_font_face (PangoCairoFont *font)
+static cairo_scaled_font_t *
+_pango_cairo_font_get_scaled_font (PangoFont *cfont)
{
- g_return_val_if_fail (PANGO_IS_CAIRO_FONT (font), NULL);
- /* this function will be removed. don't bother with warning history here */
-
- return (* PANGO_CAIRO_FONT_GET_IFACE (font)->get_font_face) (font);
-}
+ PangoCairoFontPrivate *cf_priv;
-cairo_scaled_font_t *
-_pango_cairo_font_get_scaled_font (PangoCairoFont *font)
-{
- if (G_UNLIKELY (!PANGO_IS_CAIRO_FONT (font)))
+ if (G_UNLIKELY (!PANGO_IS_CAIRO_FONT (cfont)))
{
if (!_pango_cairo_warning_history.font_get_scaled_font)
{
@@ -108,27 +155,126 @@ _pango_cairo_font_get_scaled_font (PangoCairoFont *font)
return NULL;
}
- return (* PANGO_CAIRO_FONT_GET_IFACE (font)->get_scaled_font) (font);
+ cf_priv = PANGO_CAIRO_FONT_PRIVATE (cfont);
+
+ return _pango_cairo_font_private_get_scaled_font (cf_priv);
}
-static void
-_pango_cairo_hex_box_info_destroy (PangoCairoHexBoxInfo *hbi)
+/**
+ * _pango_cairo_font_install:
+ * @font: a #PangoCairoFont
+ * @cr: a #cairo_t
+ *
+ * Makes @font the current font for rendering in the specified
+ * Cairo context.
+ *
+ * Return value: %TRUE if font was installed successfully, %FALSE otherwise.
+ **/
+gboolean
+_pango_cairo_font_install (PangoFont *font,
+ cairo_t *cr)
{
- if (hbi)
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_get_scaled_font (font);
+
+ if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
+ return FALSE;
+
+ cairo_set_scaled_font (cr, scaled_font);
+
+ return TRUE;
+}
+
+
+typedef struct _PangoCairoFontMetricsInfo
+{
+ const char *sample_str;
+ PangoFontMetrics *metrics;
+} PangoCairoFontMetricsInfo;
+
+PangoFontMetrics *
+_pango_cairo_font_get_metrics (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoCairoFont *cfont = (PangoCairoFont *) font;
+ PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (font);
+ PangoCairoFontMetricsInfo *info = NULL; /* Quiet gcc */
+ GSList *tmp_list;
+
+ const char *sample_str = pango_language_get_sample_string (language);
+
+ tmp_list = cf_priv->metrics_by_lang;
+ while (tmp_list)
{
- g_object_unref (hbi->font);
- g_slice_free (PangoCairoHexBoxInfo, hbi);
+ info = tmp_list->data;
+
+ if (info->sample_str == sample_str) /* We _don't_ need strcmp */
+ break;
+
+ tmp_list = tmp_list->next;
}
+
+ if (!tmp_list)
+ {
+ PangoContext *context;
+ cairo_font_options_t *font_options;
+ int height, shift;
+
+ info = g_slice_new0 (PangoCairoFontMetricsInfo);
+
+ cf_priv->metrics_by_lang = g_slist_prepend (cf_priv->metrics_by_lang, info);
+
+ info->sample_str = sample_str;
+
+ context = pango_cairo_font_map_create_context ((PangoCairoFontMap *) pango_font_get_font_map (font));
+ pango_context_set_language (context, language);
+ font_options = cairo_font_options_create ();
+ cairo_scaled_font_get_font_options (_pango_cairo_font_private_get_scaled_font (cf_priv), font_options);
+ pango_cairo_context_set_font_options (context, font_options);
+ cairo_font_options_destroy (font_options);
+
+ info->metrics = (* PANGO_CAIRO_FONT_GET_IFACE (font)->create_metrics_for_context) (cfont, context);
+
+ /* We may actually reuse ascent/descent we got from cairo here. that's
+ * in cf_priv->font_extents.
+ */
+ height = info->metrics->ascent + info->metrics->descent;
+ switch (cf_priv->gravity)
+ {
+ default:
+ case PANGO_GRAVITY_AUTO:
+ case PANGO_GRAVITY_SOUTH:
+ break;
+ case PANGO_GRAVITY_NORTH:
+ info->metrics->ascent = info->metrics->descent;
+ break;
+ case PANGO_GRAVITY_EAST:
+ case PANGO_GRAVITY_WEST:
+ {
+ int ascent = height / 2;
+ if (cf_priv->is_hinted)
+ ascent = PANGO_UNITS_ROUND (ascent);
+ info->metrics->ascent = ascent;
+ }
+ }
+ shift = (height - info->metrics->ascent) - info->metrics->descent;
+ info->metrics->descent += shift;
+ info->metrics->underline_position -= shift;
+ info->metrics->strikethrough_position -= shift;
+ info->metrics->ascent = height - info->metrics->descent;
+
+ g_object_unref (context);
+ }
+
+ return pango_font_metrics_ref (info->metrics);
}
-PangoCairoHexBoxInfo *
-_pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont)
+static PangoCairoFontHexBoxInfo *
+_pango_cairo_font_private_get_hex_box_info (PangoCairoFontPrivate *cf_priv)
{
static const char hexdigits[] = "0123456789ABCDEF";
char c[2] = {0, 0};
PangoFont *mini_font;
- PangoCairoFont *mini_cfont;
- PangoCairoHexBoxInfo *hbi;
+ PangoCairoFontHexBoxInfo *hbi;
/* for metrics hinting */
double scale_x = 1., scale_x_inv = 1., scale_y = 1., scale_y_inv = 1.;
@@ -148,24 +294,20 @@ _pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont)
cairo_matrix_t cairo_ctm;
PangoGravity gravity;
- if (!cfont)
+ if (!cf_priv)
return NULL;
- hbi = (PangoCairoHexBoxInfo *) g_object_get_data (G_OBJECT (cfont), "hex_box_info");
- if (hbi)
- return hbi;
+ if (cf_priv->hbi)
+ return cf_priv->hbi;
- scaled_font = _pango_cairo_font_get_scaled_font (cfont);
- if (!scaled_font)
- {
- g_object_set_data_full (G_OBJECT (cfont), "hex_box_info", NULL, NULL);
- return NULL;
- }
+ scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv);
+ if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
+ return NULL;
+
+ is_hinted = cf_priv->is_hinted;
font_options = cairo_font_options_create ();
- cairo_scaled_font_get_font_options (scaled_font, font_options);
- is_hinted = (cairo_font_options_get_hint_metrics(font_options) != CAIRO_HINT_METRICS_OFF);
- desc = pango_font_describe_with_absolute_size ((PangoFont *)cfont);
+ desc = pango_font_describe_with_absolute_size ((PangoFont *)cf_priv->cfont);
size = pango_font_description_get_size (desc) / (1.*PANGO_SCALE);
gravity = pango_font_description_get_gravity (desc);
@@ -208,7 +350,7 @@ _pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont)
PangoContext *context;
PangoFontMap *fontmap;
- fontmap = pango_font_get_font_map ((PangoFont *)cfont);
+ fontmap = pango_font_get_font_map ((PangoFont *)cf_priv->cfont);
/* we inherit most font properties for the mini font. just
* change family and size. means, you get bold hex digits
@@ -233,8 +375,7 @@ _pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont)
}
}
- pango_font_description_set_absolute_size (desc, mini_size * PANGO_SCALE);
-
+ pango_font_description_set_absolute_size (desc, pango_units_from_double (mini_size));
/* load mini_font */
@@ -251,8 +392,7 @@ _pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont)
cairo_font_options_destroy (font_options);
- mini_cfont = (PangoCairoFont *) mini_font;
- scaled_mini_font = _pango_cairo_font_get_scaled_font (mini_cfont);
+ scaled_mini_font = _pango_cairo_font_get_scaled_font (mini_font);
for (i = 0 ; i < 16 ; i++)
{
@@ -274,8 +414,8 @@ _pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont)
pad = (font_extents.ascent + font_extents.descent) / 43;
pad = MIN (pad, mini_size);
- hbi = g_slice_new (PangoCairoHexBoxInfo);
- hbi->font = mini_font;
+ hbi = g_slice_new (PangoCairoFontHexBoxInfo);
+ hbi->font = (PangoCairoFont *) mini_font;
hbi->rows = rows;
hbi->digit_width = width;
@@ -314,21 +454,114 @@ _pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont)
hbi->box_descent = HINT_Y (hbi->box_descent);
}
- g_object_set_data_full (G_OBJECT (cfont), "hex_box_info", hbi, (GDestroyNotify)_pango_cairo_hex_box_info_destroy);
-
return hbi;
}
+static void
+_pango_cairo_font_hex_box_info_destroy (PangoCairoFontHexBoxInfo *hbi)
+{
+ if (hbi)
+ {
+ g_object_unref (hbi->font);
+ g_slice_free (PangoCairoFontHexBoxInfo, hbi);
+ }
+}
+
+PangoCairoFontHexBoxInfo *
+_pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont)
+{
+ PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (cfont);
+
+ return _pango_cairo_font_private_get_hex_box_info (cf_priv);
+}
+
+void
+_pango_cairo_font_private_initialize (PangoCairoFontPrivate *cf_priv,
+ PangoCairoFont *cfont,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ const cairo_matrix_t *font_matrix)
+{
+ const cairo_font_options_t *font_options;
+ cairo_matrix_t gravity_matrix;
+ const PangoMatrix *pango_ctm;
+
+ cf_priv->cfont = cfont;
+ cf_priv->gravity = pango_font_description_get_gravity (desc);
+
+ cf_priv->data = _pango_cairo_font_private_scaled_font_data_create ();
+
+ /* first apply gravity rotation, then font_matrix, such that
+ * vertical italic text comes out "correct". we don't do anything
+ * like baseline adjustment etc though. should be specially
+ * handled when we support italic correction. */
+ cairo_matrix_init_rotate(&gravity_matrix,
+ pango_gravity_to_rotation (cf_priv->gravity));
+ cairo_matrix_multiply (&cf_priv->data->font_matrix,
+ font_matrix,
+ &gravity_matrix);
+
+ pango_ctm = pango_context_get_matrix (context);
+ if (pango_ctm)
+ cairo_matrix_init (&cf_priv->data->ctm,
+ pango_ctm->xx,
+ pango_ctm->yx,
+ pango_ctm->xy,
+ pango_ctm->yy,
+ 0., 0.);
+ else
+ cairo_matrix_init_identity (&cf_priv->data->ctm);
+
+ font_options = _pango_cairo_context_get_merged_font_options (context);
+ cf_priv->data->options = cairo_font_options_copy (font_options);
+ cf_priv->is_hinted = cairo_font_options_get_hint_metrics (font_options) != CAIRO_HINT_METRICS_OFF;
+
+ cf_priv->scaled_font = NULL;
+ cf_priv->hbi = NULL;
+ cf_priv->glyph_extents_cache = NULL;
+ cf_priv->metrics_by_lang = NULL;
+}
+
+static void
+free_metrics_info (PangoCairoFontMetricsInfo *info)
+{
+ pango_font_metrics_unref (info->metrics);
+ g_slice_free (PangoCairoFontMetricsInfo, info);
+}
+
void
-_pango_cairo_get_glyph_extents_missing (PangoCairoFont *cfont,
- PangoGlyph glyph,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect)
+_pango_cairo_font_private_finalize (PangoCairoFontPrivate *cf_priv)
+{
+ _pango_cairo_font_private_scaled_font_data_destroy (cf_priv->data);
+
+ if (cf_priv->scaled_font)
+ cairo_scaled_font_destroy (cf_priv->scaled_font);
+
+ _pango_cairo_font_hex_box_info_destroy (cf_priv->hbi);
+
+ if (cf_priv->glyph_extents_cache)
+ g_free (cf_priv->glyph_extents_cache);
+
+ g_slist_foreach (cf_priv->metrics_by_lang, (GFunc)free_metrics_info, NULL);
+ g_slist_free (cf_priv->metrics_by_lang);
+}
+
+gboolean
+_pango_cairo_font_private_is_metrics_hinted (PangoCairoFontPrivate *cf_priv)
+{
+ return cf_priv->is_hinted;
+}
+
+static void
+_pango_cairo_font_private_get_glyph_extents_missing (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
{
- PangoCairoHexBoxInfo *hbi;
+ PangoCairoFontHexBoxInfo *hbi;
gint rows, cols;
- hbi = _pango_cairo_font_get_hex_box_info (cfont);
+ hbi = _pango_cairo_font_private_get_hex_box_info (cf_priv);
if (!hbi)
{
pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect);
@@ -355,3 +588,142 @@ _pango_cairo_get_glyph_extents_missing (PangoCairoFont *cfont,
}
}
+#define GLYPH_CACHE_NUM_ENTRIES 256 /* should be power of two */
+#define GLYPH_CACHE_MASK (GLYPH_CACHE_NUM_ENTRIES - 1)
+/* An entry in the fixed-size cache for the glyph->extents mapping.
+ * The cache is indexed by the lower N bits of the glyph (see
+ * GLYPH_CACHE_NUM_ENTRIES). For scripts with few glyphs,
+ * this should provide pretty much instant lookups.
+ */
+struct _PangoCairoFontGlyphExtentsCacheEntry
+{
+ PangoGlyph glyph;
+ int width;
+ PangoRectangle ink_rect;
+};
+
+static gboolean
+_pango_cairo_font_private_glyph_extents_cache_init (PangoCairoFontPrivate *cf_priv)
+{
+ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv);
+ cairo_font_extents_t font_extents;
+
+ if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
+ return FALSE;
+
+ cairo_scaled_font_extents (scaled_font, &font_extents);
+
+ cf_priv->font_extents.x = 0;
+ cf_priv->font_extents.width = 0;
+ cf_priv->font_extents.height = pango_units_from_double (font_extents.ascent + font_extents.descent);
+ switch (cf_priv->gravity)
+ {
+ default:
+ case PANGO_GRAVITY_AUTO:
+ case PANGO_GRAVITY_SOUTH:
+ cf_priv->font_extents.y = - pango_units_from_double (font_extents.ascent);
+ break;
+ case PANGO_GRAVITY_NORTH:
+ cf_priv->font_extents.y = - pango_units_from_double (font_extents.descent);
+ break;
+ case PANGO_GRAVITY_EAST:
+ case PANGO_GRAVITY_WEST:
+ {
+ int ascent = pango_units_from_double (font_extents.ascent + font_extents.descent) / 2;
+ if (cf_priv->is_hinted)
+ ascent = PANGO_UNITS_ROUND (ascent);
+ cf_priv->font_extents.y = - ascent;
+ }
+ }
+
+ cf_priv->glyph_extents_cache = g_new0 (PangoCairoFontGlyphExtentsCacheEntry, GLYPH_CACHE_NUM_ENTRIES);
+ /* Make sure all cache entries are invalid initially */
+ cf_priv->glyph_extents_cache[0].glyph = 1; /* glyph 1 cannot happen in bucket 0 */
+
+ return TRUE;
+}
+
+/* Fills in the glyph extents cache entry
+ */
+static void
+compute_glyph_extents (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph,
+ PangoCairoFontGlyphExtentsCacheEntry *entry)
+{
+ cairo_text_extents_t extents;
+ cairo_glyph_t cairo_glyph;
+
+ cairo_glyph.index = glyph;
+ cairo_glyph.x = 0;
+ cairo_glyph.y = 0;
+
+ cairo_scaled_font_glyph_extents (_pango_cairo_font_private_get_scaled_font (cf_priv),
+ &cairo_glyph, 1, &extents);
+
+ entry->glyph = glyph;
+ entry->width = pango_units_from_double (extents.x_advance);
+ entry->ink_rect.x = pango_units_from_double (extents.x_bearing);
+ entry->ink_rect.y = pango_units_from_double (extents.y_bearing);
+ entry->ink_rect.width = pango_units_from_double (extents.width);
+ entry->ink_rect.height = pango_units_from_double (extents.height);
+}
+
+static PangoCairoFontGlyphExtentsCacheEntry *
+_pango_cairo_font_private_get_glyph_extents_cache_entry (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph)
+{
+ PangoCairoFontGlyphExtentsCacheEntry *entry;
+ guint idx;
+
+ idx = glyph & GLYPH_CACHE_MASK;
+ entry = cf_priv->glyph_extents_cache + idx;
+
+ if (entry->glyph != glyph)
+ {
+ compute_glyph_extents (cf_priv, glyph, entry);
+ }
+
+ return entry;
+}
+
+void
+_pango_cairo_font_private_get_glyph_extents (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoCairoFontGlyphExtentsCacheEntry *entry;
+
+ if (!cf_priv ||
+ (cf_priv->glyph_extents_cache == NULL &&
+ !_pango_cairo_font_private_glyph_extents_cache_init (cf_priv)))
+ {
+ /* Get generic unknown-glyph extents. */
+ pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect);
+ return;
+ }
+
+ if (glyph == PANGO_GLYPH_EMPTY)
+ {
+ if (ink_rect)
+ ink_rect->x = ink_rect->y = ink_rect->width = ink_rect->height = 0;
+ if (logical_rect)
+ *logical_rect = cf_priv->font_extents;
+ return;
+ }
+ else if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ _pango_cairo_font_private_get_glyph_extents_missing(cf_priv, glyph, ink_rect, logical_rect);
+ return;
+ }
+
+ entry = _pango_cairo_font_private_get_glyph_extents_cache_entry (cf_priv, glyph);
+
+ if (ink_rect)
+ *ink_rect = entry->ink_rect;
+ if (logical_rect)
+ {
+ *logical_rect = cf_priv->font_extents;
+ logical_rect->width = entry->width;
+ }
+}
diff --git a/pango/pangocairo-fontmap.c b/pango/pangocairo-fontmap.c
index 57540cd8..e16579e2 100644
--- a/pango/pangocairo-fontmap.c
+++ b/pango/pangocairo-fontmap.c
@@ -181,19 +181,3 @@ pango_cairo_font_map_create_context (PangoCairoFontMap *fontmap)
return context;
}
-
-/**
- * _pango_cairo_font_map_get_renderer:
- * @fontmap: a #PangoCairoFontmap
- *
- * Gets the singleton #PangoCairoRenderer for this fontmap.
- *
- * Return value: the singleton renderer
- **/
-PangoRenderer *
-_pango_cairo_font_map_get_renderer (PangoCairoFontMap *fontmap)
-{
- g_return_val_if_fail (PANGO_IS_CAIRO_FONT_MAP (fontmap), NULL);
-
- return (* PANGO_CAIRO_FONT_MAP_GET_IFACE (fontmap)->get_renderer) (fontmap);
-}
diff --git a/pango/pangocairo-private.h b/pango/pangocairo-private.h
index d739abff..e5a7c382 100644
--- a/pango/pangocairo-private.h
+++ b/pango/pangocairo-private.h
@@ -27,6 +27,7 @@
G_BEGIN_DECLS
+
#define PANGO_CAIRO_FONT_MAP_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PANGO_TYPE_CAIRO_FONT_MAP, PangoCairoFontMapIface))
typedef struct _PangoCairoFontMapIface PangoCairoFontMapIface;
@@ -38,10 +39,8 @@ struct _PangoCairoFontMapIface
void (*set_resolution) (PangoCairoFontMap *fontmap,
double dpi);
double (*get_resolution) (PangoCairoFontMap *fontmap);
- PangoRenderer *(*get_renderer) (PangoCairoFontMap *fontmap);
};
-PangoRenderer *_pango_cairo_font_map_get_renderer (PangoCairoFontMap *cfontmap);
#define PANGO_CAIRO_FONT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PANGO_TYPE_CAIRO_FONT, PangoCairoFontIface))
@@ -49,27 +48,82 @@ PangoRenderer *_pango_cairo_font_map_get_renderer (PangoCairoFontMap *cfontmap);
#define PANGO_CAIRO_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FONT, PangoCairoFont))
#define PANGO_IS_CAIRO_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_CAIRO_FONT))
-typedef struct _PangoCairoFont PangoCairoFont;
-typedef struct _PangoCairoFontIface PangoCairoFontIface;
+typedef struct _PangoCairoFont PangoCairoFont;
+typedef struct _PangoCairoFontIface PangoCairoFontIface;
+typedef struct _PangoCairoFontPrivate PangoCairoFontPrivate;
+typedef struct _PangoCairoFontHexBoxInfo PangoCairoFontHexBoxInfo;
+typedef struct _PangoCairoFontPrivateScaledFontData PangoCairoFontPrivateScaledFontData;
+typedef struct _PangoCairoFontGlyphExtentsCacheEntry PangoCairoFontGlyphExtentsCacheEntry;
+
+struct _PangoCairoFontHexBoxInfo
+{
+ PangoCairoFont *font;
+ int rows;
+ double digit_width;
+ double digit_height;
+ double pad_x;
+ double pad_y;
+ double line_width;
+ double box_descent;
+ double box_height;
+};
+
+struct _PangoCairoFontPrivateScaledFontData
+{
+ cairo_matrix_t font_matrix;
+ cairo_matrix_t ctm;
+ cairo_font_options_t *options;
+};
+
+struct _PangoCairoFontPrivate
+{
+ PangoCairoFont *cfont;
+
+ PangoCairoFontPrivateScaledFontData *data;
+
+ cairo_scaled_font_t *scaled_font;
+ PangoCairoFontHexBoxInfo *hbi;
+
+ gboolean is_hinted;
+ PangoGravity gravity;
+
+ PangoRectangle font_extents;
+ PangoCairoFontGlyphExtentsCacheEntry *glyph_extents_cache;
+
+ GSList *metrics_by_lang;
+};
struct _PangoCairoFontIface
{
GTypeInterface g_iface;
- gboolean (*install) (PangoCairoFont *font,
- cairo_t *cr);
+ cairo_font_face_t *(*create_font_face) (PangoCairoFont *cfont);
+ PangoFontMetrics *(*create_metrics_for_context) (PangoCairoFont *cfont,
+ PangoContext *context);
- cairo_font_face_t *(*get_font_face) (PangoCairoFont *font);
-
- cairo_scaled_font_t *(*get_scaled_font) (PangoCairoFont *font);
+ gssize cf_priv_offset;
};
GType pango_cairo_font_get_type (void);
-gboolean _pango_cairo_font_install (PangoCairoFont *font,
- cairo_t *cr);
-cairo_font_face_t *_pango_cairo_font_get_font_face (PangoCairoFont *font);
-cairo_scaled_font_t *_pango_cairo_font_get_scaled_font (PangoCairoFont *font);
+gboolean _pango_cairo_font_install (PangoFont *font,
+ cairo_t *cr);
+PangoFontMetrics * _pango_cairo_font_get_metrics (PangoFont *font,
+ PangoLanguage *language);
+PangoCairoFontHexBoxInfo *_pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont);
+
+void _pango_cairo_font_private_initialize (PangoCairoFontPrivate *cf_priv,
+ PangoCairoFont *font,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ const cairo_matrix_t *font_matrix);
+void _pango_cairo_font_private_finalize (PangoCairoFontPrivate *cf_priv);
+cairo_scaled_font_t *_pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv);
+gboolean _pango_cairo_font_private_is_metrics_hinted (PangoCairoFontPrivate *cf_priv);
+void _pango_cairo_font_private_get_glyph_extents (PangoCairoFontPrivate *cf_priv,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
#define PANGO_TYPE_CAIRO_RENDERER (pango_cairo_renderer_get_type())
#define PANGO_CAIRO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRenderer))
@@ -79,35 +133,13 @@ typedef struct _PangoCairoRenderer PangoCairoRenderer;
GType pango_cairo_renderer_get_type (void);
-const cairo_font_options_t *_pango_cairo_context_get_merged_font_options (PangoContext *context);
-
-typedef struct _PangoCairoHexBoxInfo PangoCairoHexBoxInfo;
-
-struct _PangoCairoHexBoxInfo
-{
- PangoFont *font;
- int rows;
- double digit_width;
- double digit_height;
- double pad_x;
- double pad_y;
- double line_width;
- double box_descent;
- double box_height;
-};
-
-PangoCairoHexBoxInfo *_pango_cairo_font_get_hex_box_info (PangoCairoFont *font);
+const cairo_font_options_t *_pango_cairo_context_get_merged_font_options (PangoContext *context);
-void _pango_cairo_get_glyph_extents_missing (PangoCairoFont *cfont,
- PangoGlyph glyph,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect);
typedef struct _PangoCairoWarningHistory PangoCairoWarningHistory;
struct _PangoCairoWarningHistory {
- guint font_install : 1;
guint font_get_scaled_font : 1;
};
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
index 4c0baf29..d14d980d 100644
--- a/pango/pangocairo-render.c
+++ b/pango/pangocairo-render.c
@@ -128,7 +128,7 @@ _pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer,
int rows, cols;
char hexbox_string[2] = {0, 0};
double temp_x, temp_y;
- PangoCairoHexBoxInfo *hbi;
+ PangoCairoFontHexBoxInfo *hbi;
gunichar ch;
cairo_save (crenderer->cr);
@@ -136,7 +136,7 @@ _pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer,
hbi = _pango_cairo_font_get_hex_box_info ((PangoCairoFont *)font);
- if (!hbi || !_pango_cairo_font_install ((PangoCairoFont *) (hbi->font), crenderer->cr))
+ if (!hbi || !_pango_cairo_font_install ((PangoFont *)(hbi->font), crenderer->cr))
{
_pango_cairo_renderer_draw_box_glyph (crenderer, gi, cx, cy);
goto done;
@@ -204,7 +204,7 @@ pango_cairo_renderer_draw_glyphs (PangoRenderer *renderer,
if (!crenderer->do_path)
set_color (crenderer, PANGO_RENDER_PART_FOREGROUND);
- if (!_pango_cairo_font_install ((PangoCairoFont *) (font), crenderer->cr))
+ if (!_pango_cairo_font_install (font, crenderer->cr))
{
for (i = 0; i < glyphs->num_glyphs; i++)
{
@@ -455,8 +455,6 @@ acquire_renderer (gboolean *free_renderer)
{
PangoCairoRenderer *renderer;
- /* renderer = _pango_cairo_font_map_get_renderer (PANGO_CAIRO_FONT_MAP (fontmap)); */
-
if (G_LIKELY (G_TRYLOCK (cached_renderer)))
{
if (G_UNLIKELY (!cached_renderer))