diff --git a/.gitignore b/.gitignore index 1ca16fe5a..1984386e6 100644 --- a/.gitignore +++ b/.gitignore @@ -212,6 +212,7 @@ TAGS /tests/conform/test-conformance-result.xml /tests/conform/test-fixed-size /tests/conform/test-preferred-size +/tests/conform/test-units-cache /tests/micro-bench/test-text-perf /tests/micro-bench/test-text /tests/micro-bench/test-picking diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c index c95ac9bc7..96b22213f 100644 --- a/clutter/clutter-backend.c +++ b/clutter/clutter-backend.c @@ -63,6 +63,7 @@ struct _ClutterBackendPrivate gdouble resolution; gfloat units_per_em; + gint32 units_serial; cairo_font_options_t *font_options; @@ -160,7 +161,10 @@ get_units_per_em (ClutterBackend *backend, static void clutter_backend_real_resolution_changed (ClutterBackend *backend) { - backend->priv->units_per_em = get_units_per_em (backend, NULL); + ClutterBackendPrivate *priv = backend->priv; + + priv->units_per_em = get_units_per_em (backend, NULL); + priv->units_serial += 1; CLUTTER_NOTE (BACKEND, "Units per em: %.2f", backend->priv->units_per_em); } @@ -168,7 +172,10 @@ clutter_backend_real_resolution_changed (ClutterBackend *backend) static void clutter_backend_real_font_changed (ClutterBackend *backend) { - backend->priv->units_per_em = get_units_per_em (backend, NULL); + ClutterBackendPrivate *priv = backend->priv; + + priv->units_per_em = get_units_per_em (backend, NULL); + priv->units_serial += 1; CLUTTER_NOTE (BACKEND, "Units per em: %.2f", backend->priv->units_per_em); } @@ -212,7 +219,9 @@ clutter_backend_init (ClutterBackend *backend) priv = backend->priv = CLUTTER_BACKEND_GET_PRIVATE (backend); priv->resolution = -1.0; + priv->units_per_em = -1.0; + priv->units_serial = 1; } void @@ -721,3 +730,11 @@ clutter_backend_get_font_name (ClutterBackend *backend) return priv->font_name; } + +gint32 +_clutter_backend_get_units_serial (ClutterBackend *backend) +{ + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), 0); + + return backend->priv->units_serial; +} diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index bd6f5dbe2..57ec0481d 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -255,6 +255,8 @@ void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self, void _clutter_run_repaint_functions (void); +gint32 _clutter_backend_get_units_serial (ClutterBackend *backend); + G_END_DECLS #endif /* _HAVE_CLUTTER_PRIVATE_H */ diff --git a/clutter/clutter-units.c b/clutter/clutter-units.c index 595f0a50f..4831fd17d 100644 --- a/clutter/clutter-units.c +++ b/clutter/clutter-units.c @@ -150,12 +150,17 @@ void clutter_units_from_mm (ClutterUnits *units, gfloat mm) { + ClutterBackend *backend; + g_return_if_fail (units != NULL); + backend = clutter_get_default_backend (); + units->unit_type = CLUTTER_UNIT_MM; units->value = mm; units->pixels = units_mm_to_pixels (mm); units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); } /** @@ -171,12 +176,17 @@ void clutter_units_from_cm (ClutterUnits *units, gfloat cm) { + ClutterBackend *backend; + g_return_if_fail (units != NULL); + backend = clutter_get_default_backend (); + units->unit_type = CLUTTER_UNIT_CM; units->value = cm; units->pixels = units_cm_to_pixels (cm); units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); } /** @@ -192,12 +202,17 @@ void clutter_units_from_pt (ClutterUnits *units, gfloat pt) { + ClutterBackend *backend; + g_return_if_fail (units != NULL); + backend = clutter_get_default_backend (); + units->unit_type = CLUTTER_UNIT_POINT; units->value = pt; units->pixels = units_pt_to_pixels (pt); units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); } /** @@ -214,12 +229,17 @@ void clutter_units_from_em (ClutterUnits *units, gfloat em) { + ClutterBackend *backend; + g_return_if_fail (units != NULL); + backend = clutter_get_default_backend (); + units->unit_type = CLUTTER_UNIT_EM; units->value = em; units->pixels = units_em_to_pixels (NULL, em); units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); } /** @@ -237,12 +257,17 @@ clutter_units_from_em_for_font (ClutterUnits *units, const gchar *font_name, gfloat em) { + ClutterBackend *backend; + g_return_if_fail (units != NULL); + backend = clutter_get_default_backend (); + units->unit_type = CLUTTER_UNIT_EM; units->value = em; units->pixels = units_em_to_pixels (font_name, em); units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); } /** @@ -258,12 +283,17 @@ void clutter_units_from_pixels (ClutterUnits *units, gint px) { + ClutterBackend *backend; + g_return_if_fail (units != NULL); + backend = clutter_get_default_backend (); + units->unit_type = CLUTTER_UNIT_PIXEL; units->value = px; units->pixels = px; units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); } /** @@ -353,8 +383,18 @@ clutter_units_free (ClutterUnits *units) gfloat clutter_units_to_pixels (ClutterUnits *units) { + ClutterBackend *backend; + g_return_val_if_fail (units != NULL, 0.0); + /* if the backend settings changed we evict the cached value */ + backend = clutter_get_default_backend (); + if (units->serial != _clutter_backend_get_units_serial (backend)) + units->pixels_set = FALSE; + + if (units->pixels_set) + return units->pixels; + switch (units->unit_type) { case CLUTTER_UNIT_MM: @@ -379,6 +419,7 @@ clutter_units_to_pixels (ClutterUnits *units) } units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); return units->pixels; } @@ -431,6 +472,7 @@ gboolean clutter_units_from_string (ClutterUnits *units, const gchar *str) { + ClutterBackend *backend; ClutterUnitType unit_type; gfloat value; @@ -503,9 +545,12 @@ clutter_units_from_string (ClutterUnits *units, if (*str != '\0') return FALSE; + backend = clutter_get_default_backend (); + units->unit_type = unit_type; units->value = value; units->pixels_set = FALSE; + units->serial = _clutter_backend_get_units_serial (backend); return TRUE; } diff --git a/clutter/clutter-units.h b/clutter/clutter-units.h index e67af95ae..a770d1fec 100644 --- a/clutter/clutter-units.h +++ b/clutter/clutter-units.h @@ -77,11 +77,18 @@ struct _ClutterUnits gfloat value; /* pre-filled by the provided constructors */ + + /* cached pixel value */ gfloat pixels; + + /* whether the :pixels field is set */ guint pixels_set; + /* the serial coming from the backend, used to evict the cache */ + gint32 serial; + /* padding for eventual expansion */ - gint64 __padding_1; + gint32 __padding_1; gint64 __padding_2; }; diff --git a/tests/conform/test-clutter-units.c b/tests/conform/test-clutter-units.c index a685d1ad7..105c454a9 100644 --- a/tests/conform/test-clutter-units.c +++ b/tests/conform/test-clutter-units.c @@ -3,6 +3,29 @@ #include "test-conform-common.h" +void +test_units_cache (TestConformSimpleFixture *fixture, + gconstpointer data) +{ + ClutterUnits units; + ClutterBackend *backend; + gfloat pixels; + gdouble dpi; + + backend = clutter_get_default_backend (); + + dpi = clutter_backend_get_resolution (backend); + + clutter_units_from_em (&units, 1.0); + pixels = clutter_units_to_pixels (&units); + + clutter_backend_set_resolution (backend, dpi + 10); + g_assert_cmpfloat (clutter_units_to_pixels (&units), !=, pixels); + + clutter_backend_set_resolution (backend, dpi); + g_assert_cmpfloat (clutter_units_to_pixels (&units), ==, pixels); +} + void test_units_constructors (TestConformSimpleFixture *fixture, gconstpointer data) diff --git a/tests/conform/test-conform-main.c b/tests/conform/test-conform-main.c index d8d4b1c42..2b2624434 100644 --- a/tests/conform/test-conform-main.c +++ b/tests/conform/test-conform-main.c @@ -167,6 +167,7 @@ main (int argc, char **argv) TEST_CONFORM_SIMPLE ("/units", test_units_constructors); TEST_CONFORM_SIMPLE ("/units", test_units_string); + TEST_CONFORM_SIMPLE ("/units", test_units_cache); TEST_CONFORM_SIMPLE ("/group", test_group_depth_sorting);