summaryrefslogtreecommitdiff
path: root/pango/pangocairo-fcfont.c
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@gnome.org>2007-06-10 00:48:25 +0000
committerBehdad Esfahbod <behdad@src.gnome.org>2007-06-10 00:48:25 +0000
commit1bc615b0a5863c5680770171f014a1f99c975a9e (patch)
treee7956b3e611ec5867be06bf721b60333edac3798 /pango/pangocairo-fcfont.c
parent672cd0f5671ba6f20c76a3b12cfbd4c77c57fb54 (diff)
downloadpango-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.c425
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;
}