diff options
author | Behdad Esfahbod <behdad@gnome.org> | 2007-06-10 00:48:25 +0000 |
---|---|---|
committer | Behdad Esfahbod <behdad@src.gnome.org> | 2007-06-10 00:48:25 +0000 |
commit | 1bc615b0a5863c5680770171f014a1f99c975a9e (patch) | |
tree | e7956b3e611ec5867be06bf721b60333edac3798 /pango/pangocairo-fcfont.c | |
parent | 672cd0f5671ba6f20c76a3b12cfbd4c77c57fb54 (diff) | |
download | pango-1bc615b0a5863c5680770171f014a1f99c975a9e.tar.gz |
Bug 337593 – move glyph extents code (and cache) from pangocairo-*font.c
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.
svn path=/trunk/; revision=2335
Diffstat (limited to 'pango/pangocairo-fcfont.c')
-rw-r--r-- | pango/pangocairo-fcfont.c | 425 |
1 files changed, 56 insertions, 369 deletions
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; } |