Store the units-per-em inside the Backend

Instead of recomputing the number of units needed to fit in
an em each time clutter_units_em() is called, we can store this
value into the default Backend along with the resolution and
font name. The value should also be updated each time the
resolution and font are changed, to keep it up to date.
This commit is contained in:
Emmanuele Bassi 2009-01-22 11:37:52 +00:00
parent c5aca39c69
commit 355555c1bf
3 changed files with 89 additions and 45 deletions

View File

@ -60,7 +60,8 @@ struct _ClutterBackendPrivate
guint double_click_time;
guint double_click_distance;
ClutterFixed resolution;
gdouble resolution;
gdouble units_per_em;
cairo_font_options_t *font_options;
@ -87,7 +88,9 @@ clutter_backend_dispose (GObject *gobject)
if (clutter_context && clutter_context->events_queue)
{
g_queue_foreach (clutter_context->events_queue, (GFunc) clutter_event_free, NULL);
g_queue_foreach (clutter_context->events_queue,
(GFunc) clutter_event_free,
NULL);
g_queue_free (clutter_context->events_queue);
clutter_context->events_queue = NULL;
}
@ -99,6 +102,57 @@ clutter_backend_dispose (GObject *gobject)
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
}
static inline void
update_units_per_em (ClutterBackend *backend)
{
ClutterBackendPrivate *priv = backend->priv;
const gchar *font_name;
gdouble dpi;
font_name = clutter_backend_get_font_name (backend);
dpi = clutter_backend_get_resolution (backend);
if (G_LIKELY (font_name != NULL && *font_name != '\0'))
{
PangoFontDescription *font_desc;
gdouble font_size = 0;
font_desc = pango_font_description_from_string (font_name);
if (G_LIKELY (font_desc != NULL))
{
gint pango_size;
gboolean is_absolute;
pango_size = pango_font_description_get_size (font_desc);
is_absolute =
pango_font_description_get_size_is_absolute (font_desc);
if (!is_absolute)
font_size = ((gdouble) font_size) / PANGO_SCALE;
pango_font_description_free (font_desc);
}
/* 10 points at 96 DPI is 12 pixels */
priv->units_per_em = 1.2 * font_size
* dpi
/ 96.0;
}
else
priv->units_per_em = -1.0;
}
static void
clutter_backend_real_resolution_changed (ClutterBackend *backend)
{
update_units_per_em (backend);
}
static void
clutter_backend_real_font_changed (ClutterBackend *backend)
{
update_units_per_em (backend);
}
static void
clutter_backend_class_init (ClutterBackendClass *klass)
{
@ -111,7 +165,7 @@ clutter_backend_class_init (ClutterBackendClass *klass)
backend_signals[RESOLUTION_CHANGED] =
g_signal_new (I_("resolution-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterBackendClass, resolution_changed),
NULL, NULL,
clutter_marshal_VOID__VOID,
@ -120,11 +174,14 @@ clutter_backend_class_init (ClutterBackendClass *klass)
backend_signals[FONT_CHANGED] =
g_signal_new (I_("font-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterBackendClass, font_changed),
NULL, NULL,
clutter_marshal_VOID__VOID,
G_TYPE_NONE, 0);
klass->resolution_changed = clutter_backend_real_resolution_changed;
klass->font_changed = clutter_backend_real_font_changed;
}
static void
@ -132,8 +189,10 @@ clutter_backend_init (ClutterBackend *backend)
{
ClutterBackendPrivate *priv;
priv = backend->priv = CLUTTER_BACKEND_GET_PRIVATE(backend);
priv = backend->priv = CLUTTER_BACKEND_GET_PRIVATE (backend);
priv->resolution = -1.0;
priv->units_per_em = -1.0;
}
void
@ -289,14 +348,29 @@ _clutter_backend_init_events (ClutterBackend *backend)
klass->init_events (backend);
}
ClutterUnit
_clutter_backend_get_units_per_em (ClutterBackend *backend)
{
ClutterBackendPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), 0);
priv = backend->priv;
if (G_UNLIKELY (priv->units_per_em < 0))
update_units_per_em (backend);
return priv->units_per_em;
}
/**
* clutter_get_default_backend:
*
* FIXME
* Retrieves the default #ClutterBackend used by Clutter. The
* #ClutterBackend holds backend-specific configuration options.
*
* Return value: the default backend. You should not ref or
* unref the returned object. Applications should not rarely need
* unref the returned object. Applications should rarely need
* to use this.
*
* Since: 0.4
@ -406,19 +480,16 @@ void
clutter_backend_set_resolution (ClutterBackend *backend,
gdouble dpi)
{
ClutterFixed fixed_dpi;
ClutterBackendPrivate *priv;
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
priv = backend->priv;
if (dpi < 0)
dpi = -1.0;
priv = backend->priv;
fixed_dpi = CLUTTER_FLOAT_TO_FIXED (dpi);
if (priv->resolution != fixed_dpi)
priv->resolution = fixed_dpi;
priv->resolution = dpi;
if (CLUTTER_CONTEXT ()->font_map)
cogl_pango_font_map_set_resolution (CLUTTER_CONTEXT ()->font_map, dpi);
@ -443,7 +514,7 @@ clutter_backend_get_resolution (ClutterBackend *backend)
{
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), -1.0);
return CLUTTER_FIXED_TO_FLOAT (backend->priv->resolution);
return backend->priv->resolution;
}
/**

View File

@ -194,6 +194,8 @@ void _clutter_backend_init_events (ClutterBackend *backend);
ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend);
ClutterUnit _clutter_backend_get_units_per_em (ClutterBackend *backend);
void _clutter_feature_init (void);
/* Picking code */

View File

@ -168,39 +168,10 @@ ClutterUnit
clutter_units_em (gdouble em)
{
ClutterBackend *backend;
const gchar *font_name;
gdouble dpi;
ClutterUnit retval = 0;
backend = clutter_get_default_backend ();
dpi = clutter_backend_get_resolution (backend);
font_name = clutter_backend_get_font_name (backend);
if (G_LIKELY ((font_name && *font_name != '\0')))
{
PangoFontDescription *font_desc;
gdouble font_size = 0;
font_desc = pango_font_description_from_string (font_name);
if (G_LIKELY (font_desc != NULL))
{
gint pango_size;
gboolean is_absolute;
pango_size = pango_font_description_get_size (font_desc);
is_absolute =
pango_font_description_get_size_is_absolute (font_desc);
if (!is_absolute)
font_size = ((gdouble) font_size) / PANGO_SCALE;
pango_font_description_free (font_desc);
}
/* 10 points at 96 DPI is 12 pixels */
retval = 1.2 * font_size * dpi / 96.0;
}
return retval;
return em * _clutter_backend_get_units_per_em (backend);
}
static GTypeInfo _info = {