From f2c25fd4f7d8a22dcb91461ebb86d1c74565c89b Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 7 May 2009 14:16:01 +0100 Subject: [PATCH] Allow specifying the font for the em conversion Currently, the conversion from em to units is done by using the default font name inside the backend. For actors using their own font/text layout we need a way to specify the font name along with the quantity we wish to transform. --- clutter/clutter-backend.c | 89 ++++++++++++++++++++++++++++++++--------------- clutter/clutter-private.h | 3 +- clutter/clutter-units.c | 47 +++++++++++++++++++++++-- clutter/clutter-units.h | 13 ++++--- 4 files changed, 114 insertions(+), 38 deletions(-) diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c index 3a02e77..35d97fd 100644 --- a/clutter/clutter-backend.c +++ b/clutter/clutter-backend.c @@ -103,55 +103,74 @@ clutter_backend_dispose (GObject *gobject) G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject); } -static inline void -update_units_per_em (ClutterBackend *backend) +static ClutterUnit +get_units_per_em (ClutterBackend *backend, + PangoFontDescription *font_desc) { - ClutterBackendPrivate *priv = backend->priv; - const gchar *font_name; + ClutterUnit units_per_em = -1.0; + gboolean free_font_desc = FALSE; 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')) + if (font_desc == NULL) { - PangoFontDescription *font_desc; - gdouble font_size = 0; + const gchar *font_name = clutter_backend_get_font_name (backend); - font_desc = pango_font_description_from_string (font_name); - if (G_LIKELY (font_desc != NULL)) + if (G_LIKELY (font_name != NULL && *font_name != '\0')) { - gint pango_size; - gboolean is_absolute; + font_desc = pango_font_description_from_string (font_name); + free_font_desc = TRUE; + } + } - 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; + if (font_desc != NULL) + { + gdouble font_size = 0; + gint pango_size; + gboolean is_absolute; - pango_font_description_free (font_desc); - } + pango_size = pango_font_description_get_size (font_desc); + is_absolute = pango_font_description_get_size_is_absolute (font_desc); - /* 10 points at 96 DPI is 12 pixels */ - priv->units_per_em = 1.2f * font_size - * dpi - / 96.0f; + /* "absolute" means "device units" (usually, pixels); otherwise, + * it means logical units (points) + */ + if (is_absolute) + font_size = (gdouble) pango_size / PANGO_SCALE; + else + font_size = (gdouble) pango_size / PANGO_SCALE + * dpi + / 96.0f; + + /* 10 points at 96 DPI is 13.3 pixels */ + units_per_em = (1.2f * font_size) + * dpi + / 96.0f; } else - priv->units_per_em = -1.0f; + units_per_em = -1.0f; + + if (free_font_desc) + pango_font_description_free (font_desc); + + return units_per_em; } static void clutter_backend_real_resolution_changed (ClutterBackend *backend) { - update_units_per_em (backend); + backend->priv->units_per_em = get_units_per_em (backend, NULL); + + CLUTTER_NOTE (BACKEND, "Units per em: %.2f", backend->priv->units_per_em); } static void clutter_backend_real_font_changed (ClutterBackend *backend) { - update_units_per_em (backend); + backend->priv->units_per_em = get_units_per_em (backend, NULL); + + CLUTTER_NOTE (BACKEND, "Units per em: %.2f", backend->priv->units_per_em); } static void @@ -361,7 +380,8 @@ _clutter_backend_init_events (ClutterBackend *backend) } gfloat -_clutter_backend_get_units_per_em (ClutterBackend *backend) +_clutter_backend_get_units_per_em (ClutterBackend *backend, + PangoFontDescription *font_desc) { ClutterBackendPrivate *priv; @@ -369,8 +389,12 @@ _clutter_backend_get_units_per_em (ClutterBackend *backend) priv = backend->priv; - if (G_UNLIKELY (priv->units_per_em < 0)) - update_units_per_em (backend); + /* recompute for the font description, but do not cache the result */ + if (font_desc != NULL) + return get_units_per_em (backend, font_desc); + + if (priv->units_per_em < 0) + priv->units_per_em = get_units_per_em (backend, NULL); return priv->units_per_em; } @@ -603,6 +627,8 @@ clutter_backend_get_font_options (ClutterBackend *backend) cairo_font_options_set_antialias (priv->font_options, CAIRO_ANTIALIAS_DEFAULT); + g_signal_emit (backend, backend_signals[FONT_CHANGED], 0); + return priv->font_options; } @@ -662,7 +688,12 @@ clutter_backend_get_font_name (ClutterBackend *backend) if (G_LIKELY (priv->font_name)) return priv->font_name; + /* if we have never been called then we need to set the + * default font and update everything that relies on the + * ::font-changed signal + */ priv->font_name = g_strdup (DEFAULT_FONT_NAME); + g_signal_emit (backend, backend_signals[FONT_CHANGED], 0); return priv->font_name; } diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index 95b39e3..768ab9d 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -193,7 +193,8 @@ void _clutter_backend_init_events (ClutterBackend *backend); ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend); -gfloat _clutter_backend_get_units_per_em (ClutterBackend *backend); +gfloat _clutter_backend_get_units_per_em (ClutterBackend *backend, + PangoFontDescription *font_desc); void _clutter_feature_init (void); diff --git a/clutter/clutter-units.c b/clutter/clutter-units.c index 1263886..a0ccddc 100644 --- a/clutter/clutter-units.c +++ b/clutter/clutter-units.c @@ -169,11 +169,52 @@ clutter_units_pt (gdouble pt) ClutterUnit clutter_units_em (gdouble em) { - ClutterBackend *backend; + ClutterBackend *backend = clutter_get_default_backend (); - backend = clutter_get_default_backend (); + return em * _clutter_backend_get_units_per_em (backend, NULL); +} + +/** + * clutter_units_em_for_font: + * @font_name: the font name and size + * @em: em to convert + * + * Converts a value in em to #ClutterUnits at the + * current DPI for the given font name. + * + * The @font_name string must be in a format that + * pango_font_description_from_string() can parse, like + * for clutter_text_set_font_name() or clutter_backend_set_font_name(). + * + * Return value: the value in units + * + * Since: 1.0 + */ +ClutterUnit +clutter_units_em_for_font (const gchar *font_name, + gdouble em) +{ + ClutterBackend *backend = clutter_get_default_backend (); - return em * _clutter_backend_get_units_per_em (backend); + if (font_name == NULL || *font_name == '\0') + return em * _clutter_backend_get_units_per_em (backend, NULL); + else + { + PangoFontDescription *font_desc; + gfloat res; + + font_desc = pango_font_description_from_string (font_name); + if (font_desc == NULL) + res = -1.0; + else + { + res = em * _clutter_backend_get_units_per_em (backend, font_desc); + + pango_font_description_free (font_desc); + } + + return res; + } } /** diff --git a/clutter/clutter-units.h b/clutter/clutter-units.h index c2db312..0439df4 100644 --- a/clutter/clutter-units.h +++ b/clutter/clutter-units.h @@ -32,7 +32,8 @@ #define __CLUTTER_UNITS_H__ #include -#include + +#include G_BEGIN_DECLS @@ -192,10 +193,12 @@ typedef float ClutterUnit; */ #define CLUTTER_UNITS_FROM_EM(x) (clutter_units_em (x)) -ClutterUnit clutter_units_mm (gdouble mm); -ClutterUnit clutter_units_pt (gdouble pt); -ClutterUnit clutter_units_em (gdouble em); -ClutterUnit clutter_units_pixels (gint px); +ClutterUnit clutter_units_mm (gdouble mm); +ClutterUnit clutter_units_pt (gdouble pt); +ClutterUnit clutter_units_em (gdouble em); +ClutterUnit clutter_units_em_for_font (const gchar *font_name, + gdouble em); +ClutterUnit clutter_units_pixels (gint px); gint clutter_units_to_pixels (ClutterUnit units); -- 2.7.4