From e027843cb0d411d3f3943820d7a0687a1d7fdc27 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 19 May 2024 18:41:59 -0400 Subject: [PATCH] css: Add a way to resolve css images This will be needed to separate out computed and used values for css image values. --- gtk/gtkcssimage.c | 46 ++++++++++-- gtk/gtkcssimageconic.c | 52 +++++++++++++- gtk/gtkcssimagefallback.c | 71 +++++++++++++++++- gtk/gtkcssimageicontheme.c | 68 +++++++++++++++++- gtk/gtkcssimageiconthemeprivate.h | 2 +- gtk/gtkcssimagelinear.c | 74 ++++++++++++++++--- gtk/gtkcssimageprivate.h | 13 ++-- gtk/gtkcssimageradial.c | 59 +++++++++++++++ gtk/gtkcssimagerecolor.c | 115 ++++++++++++++++++------------ gtk/gtkcssimagerecolorprivate.h | 5 +- gtk/gtkcssimagescaled.c | 39 ++++++++++ 11 files changed, 469 insertions(+), 75 deletions(-) diff --git a/gtk/gtkcssimage.c b/gtk/gtkcssimage.c index 854275c77c..a613f17703 100644 --- a/gtk/gtkcssimage.c +++ b/gtk/gtkcssimage.c @@ -120,6 +120,20 @@ gtk_css_image_real_is_computed (GtkCssImage *image) return FALSE; } +static gboolean +gtk_css_image_real_contains_current_color (GtkCssImage *image) +{ + return FALSE; +} + +static GtkCssImage * +gtk_css_image_real_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color) +{ + return g_object_ref (image); +} + static void _gtk_css_image_class_init (GtkCssImageClass *klass) { @@ -133,6 +147,8 @@ _gtk_css_image_class_init (GtkCssImageClass *klass) klass->is_dynamic = gtk_css_image_real_is_dynamic; klass->get_dynamic_image = gtk_css_image_real_get_dynamic_image; klass->is_computed = gtk_css_image_real_is_computed; + klass->contains_current_color = gtk_css_image_real_contains_current_color; + klass->resolve = gtk_css_image_real_resolve; } static void @@ -239,11 +255,11 @@ _gtk_css_image_equal (GtkCssImage *image1, return klass->equal (image1, image2); } -void -_gtk_css_image_draw (GtkCssImage *image, - cairo_t *cr, - double width, - double height) +static void +gtk_css_image_draw (GtkCssImage *image, + cairo_t *cr, + double width, + double height) { GtkSnapshot *snapshot; GskRenderNode *node; @@ -497,7 +513,7 @@ _gtk_css_image_get_surface (GtkCssImage *image, surface_height); cr = cairo_create (result); - _gtk_css_image_draw (image, cr, surface_width, surface_height); + gtk_css_image_draw (image, cr, surface_width, surface_height); cairo_destroy (cr); return result; @@ -588,3 +604,21 @@ gtk_css_image_is_computed (GtkCssImage *image) return klass->is_computed (image); } + +gboolean +gtk_css_image_contains_current_color (GtkCssImage *image) +{ + GtkCssImageClass *klass = GTK_CSS_IMAGE_GET_CLASS (image); + + return klass->contains_current_color (image); +} + +GtkCssImage * +gtk_css_image_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color) +{ + GtkCssImageClass *klass = GTK_CSS_IMAGE_GET_CLASS (image); + + return klass->resolve (image, context, current_color); +} diff --git a/gtk/gtkcssimageconic.c b/gtk/gtkcssimageconic.c index d48bfcc30a..4f1a290f70 100644 --- a/gtk/gtkcssimageconic.c +++ b/gtk/gtkcssimageconic.c @@ -363,7 +363,7 @@ gtk_css_image_conic_compute (GtkCssImage *image, copy->hue_interp = self->hue_interp; copy->n_stops = self->n_stops; - copy->color_stops = g_malloc (sizeof (GtkCssImageConicColorStop) * copy->n_stops); + copy->color_stops = g_new (GtkCssImageConicColorStop, self->n_stops); for (i = 0; i < self->n_stops; i++) { const GtkCssImageConicColorStop *stop = &self->color_stops[i]; @@ -544,6 +544,54 @@ gtk_css_image_conic_is_computed (GtkCssImage *image) return computed; } +static gboolean +gtk_css_image_conic_contains_current_color (GtkCssImage *image) +{ + GtkCssImageConic *self = GTK_CSS_IMAGE_CONIC (image); + + for (guint i = 0; i < self->n_stops; i ++) + { + const GtkCssImageConicColorStop *stop = &self->color_stops[i]; + + if (gtk_css_value_contains_current_color (stop->color)) + return TRUE; + } + + return FALSE; +} + +static GtkCssImage * +gtk_css_image_conic_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color) +{ + GtkCssImageConic *self = GTK_CSS_IMAGE_CONIC (image); + GtkCssImageConic *resolved; + + if (!gtk_css_image_conic_contains_current_color (image)) + return g_object_ref (image); + + resolved = g_object_new (GTK_TYPE_CSS_IMAGE_CONIC, NULL); + + resolved->center = gtk_css_value_ref (self->center); + resolved->rotation = gtk_css_value_ref (self->rotation); + + resolved->n_stops = self->n_stops; + resolved->color_stops = g_new (GtkCssImageConicColorStop, self->n_stops); + + for (guint i = 0; i < self->n_stops; i++) + { + if (self->color_stops[i].offset) + resolved->color_stops[i].offset = gtk_css_value_ref (self->color_stops[i].offset); + else + resolved->color_stops[i].offset = NULL; + + resolved->color_stops[i].color = gtk_css_color_value_resolve (self->color_stops[i].color, context, current_color); + } + + return GTK_CSS_IMAGE (resolved); +} + static void gtk_css_image_conic_class_init (GtkCssImageConicClass *klass) { @@ -557,6 +605,8 @@ gtk_css_image_conic_class_init (GtkCssImageConicClass *klass) image_class->equal = gtk_css_image_conic_equal; image_class->transition = gtk_css_image_conic_transition; image_class->is_computed = gtk_css_image_conic_is_computed; + image_class->contains_current_color = gtk_css_image_conic_contains_current_color; + image_class->resolve = gtk_css_image_conic_resolve; object_class->dispose = gtk_css_image_conic_dispose; } diff --git a/gtk/gtkcssimagefallback.c b/gtk/gtkcssimagefallback.c index c1d8deb2ac..f081d318fa 100644 --- a/gtk/gtkcssimagefallback.c +++ b/gtk/gtkcssimagefallback.c @@ -72,7 +72,10 @@ gtk_css_image_fallback_snapshot (GtkCssImage *image, { if (fallback->color) { - const GdkRGBA *color = gtk_css_color_value_get_rgba (fallback->color); + const GdkRGBA *color; + + color = gtk_css_color_value_get_rgba (fallback->color); + if (!gdk_rgba_is_clear (color)) gtk_snapshot_append_color (snapshot, color, &GRAPHENE_RECT_INIT (0, 0, width, height)); @@ -301,6 +304,70 @@ gtk_css_image_fallback_is_computed (GtkCssImage *image) return TRUE; } +static gboolean +gtk_css_image_fallback_contains_current_color (GtkCssImage *image) +{ + GtkCssImageFallback *fallback = GTK_CSS_IMAGE_FALLBACK (image); + + if (fallback->used < 0) + { + guint i; + + if (fallback->color && !fallback->images) + return gtk_css_value_contains_current_color (fallback->color); + + for (i = 0; i < fallback->n_images; i++) + { + if (gtk_css_image_contains_current_color (fallback->images[i])) + return TRUE; + } + } + + return FALSE; +} + +static GtkCssImage * +gtk_css_image_fallback_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color) +{ + GtkCssImageFallback *fallback = GTK_CSS_IMAGE_FALLBACK (image); + GtkCssImageFallback *resolved; + int i; + + if (fallback->used < 0) + { + GtkCssValue *resolved_color = NULL; + + if (fallback->color) + resolved_color = gtk_css_color_value_resolve (fallback->color, context, current_color); + + /* image($color) that didn't change */ + if (resolved_color && !fallback->images && resolved_color == fallback->color) + return g_object_ref (image); + + resolved = g_object_new (_gtk_css_image_fallback_get_type (), NULL); + resolved->n_images = fallback->n_images; + resolved->images = g_new (GtkCssImage *, fallback->n_images); + for (i = 0; i < fallback->n_images; i++) + { + resolved->images[i] = g_object_ref (fallback->images[i]); + + if (gtk_css_image_is_invalid (resolved->images[i])) + continue; + + if (resolved->used < 0) + resolved->used = i; + } + + resolved->color = resolved_color; + + return GTK_CSS_IMAGE (resolved); + } + else + return GTK_CSS_IMAGE (g_object_ref (image)); +} + static void _gtk_css_image_fallback_class_init (GtkCssImageFallbackClass *klass) { @@ -316,6 +383,8 @@ _gtk_css_image_fallback_class_init (GtkCssImageFallbackClass *klass) image_class->print = gtk_css_image_fallback_print; image_class->equal = gtk_css_image_fallback_equal; image_class->is_computed = gtk_css_image_fallback_is_computed; + image_class->contains_current_color = gtk_css_image_fallback_contains_current_color; + image_class->resolve = gtk_css_image_fallback_resolve; object_class->dispose = gtk_css_image_fallback_dispose; } diff --git a/gtk/gtkcssimageicontheme.c b/gtk/gtkcssimageicontheme.c index c5679512ac..85fbe0c5fd 100644 --- a/gtk/gtkcssimageicontheme.c +++ b/gtk/gtkcssimageicontheme.c @@ -29,6 +29,8 @@ #include "gtkstyleproviderprivate.h" #include "gtksymbolicpaintable.h" #include "gtkiconthemeprivate.h" +#include "gtkcsscolorvalueprivate.h" +#include "gtkcsspalettevalueprivate.h" G_DEFINE_TYPE (GtkCssImageIconTheme, _gtk_css_image_icon_theme, GTK_TYPE_CSS_IMAGE) @@ -50,6 +52,7 @@ gtk_css_image_icon_theme_snapshot (GtkCssImage *image, double icon_width, icon_height; int size; double x, y; + GdkRGBA colors[4]; size = floor (MIN (width, height)); if (size <= 0) @@ -89,11 +92,15 @@ gtk_css_image_icon_theme_snapshot (GtkCssImage *image, gtk_snapshot_save (snapshot); gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y)); } + + for (guint i = 0; i < 4; i++) + colors[i] = *gtk_css_color_value_get_rgba (icon_theme->colors[i]); + gtk_symbolic_paintable_snapshot_symbolic (GTK_SYMBOLIC_PAINTABLE (icon), snapshot, icon_width, icon_height, - icon_theme->colors, + colors, G_N_ELEMENTS (icon_theme->colors)); if (x != 0 || y != 0) gtk_snapshot_restore (snapshot); @@ -146,6 +153,7 @@ gtk_css_image_icon_theme_compute (GtkCssImage *image, GtkCssImageIconTheme *copy; GtkSettings *settings; GdkDisplay *display; + const char *names[4] = { NULL, "success", "warning", "error" }; copy = g_object_new (GTK_TYPE_CSS_IMAGE_ICON_THEME, NULL); copy->name = g_strdup (icon_theme->name); @@ -154,7 +162,18 @@ gtk_css_image_icon_theme_compute (GtkCssImage *image, copy->icon_theme = gtk_icon_theme_get_for_display (display); copy->serial = gtk_icon_theme_get_serial (copy->icon_theme); copy->scale = gtk_style_provider_get_scale (context->provider); - gtk_css_style_lookup_symbolic_colors (context->style, copy->colors); + + for (guint i = 0; i < 4; i++) + { + GtkCssValue *color = NULL; + + if (names[i]) + color = gtk_css_palette_value_get_color (context->style->core->icon_palette, names[i]); + if (color) + copy->colors[i] = gtk_css_value_ref (color); + else + copy->colors[i] = gtk_css_value_ref (context->style->core->color); + } return GTK_CSS_IMAGE (copy); } @@ -180,10 +199,52 @@ gtk_css_image_icon_theme_dispose (GObject *object) icon_theme->name = NULL; g_clear_object (&icon_theme->cached_icon); + g_clear_pointer (&icon_theme->colors[0], gtk_css_value_unref); + g_clear_pointer (&icon_theme->colors[1], gtk_css_value_unref); + g_clear_pointer (&icon_theme->colors[2], gtk_css_value_unref); + g_clear_pointer (&icon_theme->colors[3], gtk_css_value_unref); G_OBJECT_CLASS (_gtk_css_image_icon_theme_parent_class)->dispose (object); } +static gboolean +gtk_css_image_icon_theme_contains_current_color (GtkCssImage *image) +{ + GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (image); + + for (guint i = 0; i < 4; i++) + { + if (!icon_theme->colors[i] || + gtk_css_value_contains_current_color (icon_theme->colors[i])) + return TRUE; + } + + return FALSE; +} + +static GtkCssImage * +gtk_css_image_icon_theme_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current) +{ + GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (image); + GtkCssImageIconTheme *copy; + + if (!gtk_css_image_icon_theme_contains_current_color (image)) + return g_object_ref (image); + + copy = g_object_new (GTK_TYPE_CSS_IMAGE_ICON_THEME, NULL); + copy->name = g_strdup (icon_theme->name); + copy->icon_theme = icon_theme->icon_theme; + copy->serial = icon_theme->serial; + copy->scale = icon_theme->scale; + + for (guint i = 0; i < 4; i++) + copy->colors[i] = gtk_css_color_value_resolve (icon_theme->colors[i], context, current); + + return GTK_CSS_IMAGE (copy); +} + static void _gtk_css_image_icon_theme_class_init (GtkCssImageIconThemeClass *klass) { @@ -196,7 +257,8 @@ _gtk_css_image_icon_theme_class_init (GtkCssImageIconThemeClass *klass) image_class->print = gtk_css_image_icon_theme_print; image_class->compute = gtk_css_image_icon_theme_compute; image_class->equal = gtk_css_image_icon_theme_equal; - + image_class->contains_current_color = gtk_css_image_icon_theme_contains_current_color; + image_class->resolve = gtk_css_image_icon_theme_resolve; object_class->dispose = gtk_css_image_icon_theme_dispose; } diff --git a/gtk/gtkcssimageiconthemeprivate.h b/gtk/gtkcssimageiconthemeprivate.h index 613c49e1d2..8f04c86a07 100644 --- a/gtk/gtkcssimageiconthemeprivate.h +++ b/gtk/gtkcssimageiconthemeprivate.h @@ -39,7 +39,7 @@ struct _GtkCssImageIconTheme GtkCssImage parent; GtkIconTheme *icon_theme; - GdkRGBA colors[4]; + GtkCssValue *colors[4]; int serial; int scale; char *name; diff --git a/gtk/gtkcssimagelinear.c b/gtk/gtkcssimagelinear.c index 046299801c..3ae0e8cd1c 100644 --- a/gtk/gtkcssimagelinear.c +++ b/gtk/gtkcssimagelinear.c @@ -134,10 +134,10 @@ gtk_css_image_linear_compute_start_point (double angle_in_degrees, } static void -gtk_css_image_linear_snapshot (GtkCssImage *image, - GtkSnapshot *snapshot, - double width, - double height) +gtk_css_image_linear_snapshot (GtkCssImage *image, + GtkSnapshot *snapshot, + double width, + double height) { GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image); GskColorStop *stops; @@ -188,12 +188,16 @@ gtk_css_image_linear_snapshot (GtkCssImage *image, if (start == end) { - /* repeating gradients with all color stops sharing the same offset - * get the color of the last color stop */ + /* Repeating gradients with all color stops sharing the same offset + * get the color of the last color stop + */ const GtkCssImageLinearColorStop *stop = &linear->color_stops[linear->n_stops - 1]; + const GdkRGBA *color; + + color = gtk_css_color_value_get_rgba (stop->color); gtk_snapshot_append_color (snapshot, - gtk_css_color_value_get_rgba (stop->color), + color, &GRAPHENE_RECT_INIT (0, 0, width, height)); return; } @@ -236,8 +240,9 @@ gtk_css_image_linear_snapshot (GtkCssImage *image, offset += step; - stops[last].offset = (offset - start) / (end - start); stops[last].color = *gtk_css_color_value_get_rgba (stop->color); + + stops[last].offset = (offset - start) / (end - start); } offset = pos; @@ -742,6 +747,57 @@ gtk_css_image_linear_is_computed (GtkCssImage *image) return computed; } +static gboolean +gtk_css_image_linear_contains_current_color (GtkCssImage *image) +{ + GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image); + + for (guint i = 0; i < linear->n_stops; i ++) + { + const GtkCssImageLinearColorStop *stop = &linear->color_stops[i]; + + if (gtk_css_value_contains_current_color (stop->color)) + return TRUE; + } + + return FALSE; +} + +static GtkCssImage * +gtk_css_image_linear_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color) +{ + GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image); + GtkCssImageLinear *copy; + guint i; + + copy = g_object_new (GTK_TYPE_CSS_IMAGE_LINEAR, NULL); + copy->repeating = linear->repeating; + copy->side = linear->side; + + if (linear->angle) + copy->angle = gtk_css_value_ref (linear->angle); + + copy->n_stops = linear->n_stops; + copy->color_stops = g_new (GtkCssImageLinearColorStop, copy->n_stops); + + for (i = 0; i < linear->n_stops; i++) + { + const GtkCssImageLinearColorStop *stop = &linear->color_stops[i]; + GtkCssImageLinearColorStop *scopy = ©->color_stops[i]; + + scopy->color = gtk_css_color_value_resolve (stop->color, context, current_color); + + if (stop->offset) + scopy->offset = gtk_css_value_ref (stop->offset); + else + scopy->offset = NULL; + } + + return GTK_CSS_IMAGE (copy); +} + static void _gtk_css_image_linear_class_init (GtkCssImageLinearClass *klass) { @@ -755,6 +811,8 @@ _gtk_css_image_linear_class_init (GtkCssImageLinearClass *klass) image_class->equal = gtk_css_image_linear_equal; image_class->transition = gtk_css_image_linear_transition; image_class->is_computed = gtk_css_image_linear_is_computed; + image_class->contains_current_color = gtk_css_image_linear_contains_current_color; + image_class->resolve = gtk_css_image_linear_resolve; object_class->dispose = gtk_css_image_linear_dispose; } diff --git a/gtk/gtkcssimageprivate.h b/gtk/gtkcssimageprivate.h index fd6b27f4ec..afb324c7f8 100644 --- a/gtk/gtkcssimageprivate.h +++ b/gtk/gtkcssimageprivate.h @@ -91,6 +91,10 @@ struct _GtkCssImageClass void (* print) (GtkCssImage *image, GString *string); gboolean (* is_computed) (GtkCssImage *image); + gboolean (* contains_current_color) (GtkCssImage *image); + GtkCssImage *( * resolve) (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color); }; GType _gtk_css_image_get_type (void) G_GNUC_CONST; @@ -112,10 +116,6 @@ GtkCssImage * _gtk_css_image_transition (GtkCssImage * guint property_id, double progress); -void _gtk_css_image_draw (GtkCssImage *image, - cairo_t *cr, - double width, - double height); void gtk_css_image_snapshot (GtkCssImage *image, GtkSnapshot *snapshot, double width, @@ -142,6 +142,11 @@ cairo_surface_t * int surface_height); gboolean gtk_css_image_is_computed (GtkCssImage *image) G_GNUC_PURE; +gboolean gtk_css_image_contains_current_color (GtkCssImage *image) G_GNUC_PURE; + +GtkCssImage * gtk_css_image_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color); G_END_DECLS diff --git a/gtk/gtkcssimageradial.c b/gtk/gtkcssimageradial.c index 3cd5afe7de..5cbe25d126 100644 --- a/gtk/gtkcssimageradial.c +++ b/gtk/gtkcssimageradial.c @@ -748,6 +748,63 @@ gtk_css_image_radial_is_computed (GtkCssImage *image) return computed; } + +static gboolean +gtk_css_image_radial_contains_current_color (GtkCssImage *image) +{ + GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image); + + for (guint i = 0; i < radial->n_stops; i ++) + { + const GtkCssImageRadialColorStop *stop = &radial->color_stops[i]; + + if (gtk_css_value_contains_current_color (stop->color)) + return TRUE; + } + + return FALSE; +} + +static GtkCssImage * +gtk_css_image_radial_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color) +{ + GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image); + GtkCssImageRadial *copy; + + copy = g_object_new (GTK_TYPE_CSS_IMAGE_RADIAL, NULL); + copy->repeating = radial->repeating; + copy->circle = radial->circle; + copy->size = radial->size; + + copy->position = gtk_css_value_ref (radial->position); + + if (radial->sizes[0]) + copy->sizes[0] = gtk_css_value_ref (radial->sizes[0]); + + if (radial->sizes[1]) + copy->sizes[1] = gtk_css_value_ref (radial->sizes[1]); + + copy->n_stops = radial->n_stops; + copy->color_stops = g_new (GtkCssImageRadialColorStop, copy->n_stops); + + for (guint i = 0; i < radial->n_stops; i++) + { + const GtkCssImageRadialColorStop *stop = &radial->color_stops[i]; + GtkCssImageRadialColorStop *scopy = ©->color_stops[i]; + + scopy->color = gtk_css_color_value_resolve (stop->color, context, current_color); + + if (stop->offset) + scopy->offset = gtk_css_value_ref (stop->offset); + else + scopy->offset = NULL; + } + + return GTK_CSS_IMAGE (copy); +} + static void _gtk_css_image_radial_class_init (GtkCssImageRadialClass *klass) { @@ -761,6 +818,8 @@ _gtk_css_image_radial_class_init (GtkCssImageRadialClass *klass) image_class->transition = gtk_css_image_radial_transition; image_class->equal = gtk_css_image_radial_equal; image_class->is_computed = gtk_css_image_radial_is_computed; + image_class->contains_current_color = gtk_css_image_radial_contains_current_color; + image_class->resolve = gtk_css_image_radial_resolve; object_class->dispose = gtk_css_image_radial_dispose; } diff --git a/gtk/gtkcssimagerecolor.c b/gtk/gtkcssimagerecolor.c index 04ebd302f4..8534930916 100644 --- a/gtk/gtkcssimagerecolor.c +++ b/gtk/gtkcssimagerecolor.c @@ -55,43 +55,13 @@ gtk_css_image_recolor_dispose (GObject *object) GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (object); g_clear_pointer (&recolor->palette, gtk_css_value_unref); + g_clear_pointer (&recolor->color, gtk_css_value_unref); g_clear_object (&recolor->file); g_clear_object (&recolor->texture); G_OBJECT_CLASS (_gtk_css_image_recolor_parent_class)->dispose (object); } -static void -lookup_symbolic_colors (GtkCssStyle *style, - GtkCssValue *palette, - GdkRGBA *color_out, - GdkRGBA *success_out, - GdkRGBA *warning_out, - GdkRGBA *error_out) -{ - GtkCssValue *lookup; - - *color_out = *gtk_css_color_value_get_rgba (style->core->color); - - lookup = gtk_css_palette_value_get_color (palette, "success"); - if (lookup) - *success_out = *gtk_css_color_value_get_rgba (lookup); - else - *success_out = *color_out; - - lookup = gtk_css_palette_value_get_color (palette, "warning"); - if (lookup) - *warning_out = *gtk_css_color_value_get_rgba (lookup); - else - *warning_out = *color_out; - - lookup = gtk_css_palette_value_get_color (palette, "error"); - if (lookup) - *error_out = *gtk_css_color_value_get_rgba (lookup); - else - *error_out = *color_out; -} - static void gtk_css_image_recolor_load_texture (GtkCssImageRecolor *recolor, GError **error) @@ -127,21 +97,22 @@ gtk_css_image_recolor_load_texture (GtkCssImageRecolor *recolor, } static GtkCssImage * -gtk_css_image_recolor_load (GtkCssImageRecolor *recolor, - GtkCssStyle *style, - GtkCssValue *palette, - int scale, - GError **gerror) +gtk_css_image_recolor_load (GtkCssImageRecolor *recolor, + GtkCssComputeContext *context, + GtkCssValue *palette, + int scale, + GError **gerror) { GError *local_error = NULL; GtkCssImageRecolor *image; image = g_object_new (GTK_TYPE_CSS_IMAGE_RECOLOR, NULL); - lookup_symbolic_colors (style, palette, &image->color, &image->success, &image->warning, &image->error); - gtk_css_image_recolor_load_texture (recolor, &local_error); - image->file = g_object_ref (recolor->file); + image->palette = gtk_css_value_ref (palette); + image->color = gtk_css_value_ref (context->style->core->color); + + gtk_css_image_recolor_load_texture (recolor, &local_error); if (recolor->texture) image->texture = g_object_ref (recolor->texture); @@ -172,16 +143,34 @@ gtk_css_image_recolor_snapshot (GtkCssImage *image, double height) { GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (image); - const GdkRGBA *fg = &recolor->color; - const GdkRGBA *sc = &recolor->success; - const GdkRGBA *wc = &recolor->warning; - const GdkRGBA *ec = &recolor->error; + const GdkRGBA *fg, *sc, *wc, *ec; + const GtkCssValue *color; graphene_matrix_t matrix; graphene_vec4_t offset; if (recolor->texture == NULL) return; + fg = gtk_css_color_value_get_rgba (recolor->color); + + color = gtk_css_palette_value_get_color (recolor->palette, "success"); + if (color) + sc = gtk_css_color_value_get_rgba (color); + else + sc = fg; + + color = gtk_css_palette_value_get_color (recolor->palette, "warning"); + if (color) + wc = gtk_css_color_value_get_rgba (color); + else + wc = fg; + + color = gtk_css_palette_value_get_color (recolor->palette, "error"); + if (color) + ec = gtk_css_color_value_get_rgba (color); + else + ec = fg; + graphene_matrix_init_from_float (&matrix, (float[16]) { sc->red - fg->red, sc->green - fg->green, sc->blue - fg->blue, 0, @@ -218,7 +207,7 @@ gtk_css_image_recolor_compute (GtkCssImage *image, else palette = gtk_css_value_ref (context->style->core->icon_palette); - img = gtk_css_image_recolor_load (recolor, context->style, palette, scale, &error); + img = gtk_css_image_recolor_load (recolor, context, palette, scale, &error); if (error) { @@ -267,7 +256,7 @@ gtk_css_image_recolor_parse_arg (GtkCssParser *parser, static gboolean gtk_css_image_recolor_parse (GtkCssImage *image, - GtkCssParser *parser) + GtkCssParser *parser) { if (!gtk_css_parser_has_function (parser, "-gtk-recolor")) { @@ -309,8 +298,38 @@ gtk_css_image_recolor_is_computed (GtkCssImage *image) { GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (image); - return recolor->texture && - (!recolor->palette || gtk_css_value_is_computed (recolor->palette)); + return recolor->texture && gtk_css_value_is_computed (recolor->palette); +} + +static gboolean +gtk_css_image_recolor_contains_current_color (GtkCssImage *image) +{ + GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (image); + + if (!recolor->palette || !recolor->color) + return TRUE; + + return gtk_css_value_contains_current_color (recolor->palette) || + gtk_css_value_contains_current_color (recolor->color); +} + +static GtkCssImage * +gtk_css_image_recolor_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color) +{ + GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (image); + GtkCssImageRecolor *img; + + img = g_object_new (GTK_TYPE_CSS_IMAGE_RECOLOR, NULL); + + img->palette = gtk_css_palette_value_resolve (recolor->palette, context, current_color); + img->color = gtk_css_color_value_resolve (recolor->color, context, current_color); + img->file = g_object_ref (recolor->file); + if (recolor->texture) + img->texture = g_object_ref (recolor->texture); + + return GTK_CSS_IMAGE (img); } static void @@ -326,6 +345,8 @@ _gtk_css_image_recolor_class_init (GtkCssImageRecolorClass *klass) image_class->parse = gtk_css_image_recolor_parse; image_class->print = gtk_css_image_recolor_print; image_class->is_computed = gtk_css_image_recolor_is_computed; + image_class->contains_current_color = gtk_css_image_recolor_contains_current_color; + image_class->resolve = gtk_css_image_recolor_resolve; object_class->dispose = gtk_css_image_recolor_dispose; } diff --git a/gtk/gtkcssimagerecolorprivate.h b/gtk/gtkcssimagerecolorprivate.h index 309d3eeb45..02f3a74d7c 100644 --- a/gtk/gtkcssimagerecolorprivate.h +++ b/gtk/gtkcssimagerecolorprivate.h @@ -39,12 +39,9 @@ struct _GtkCssImageRecolor GtkCssImage parent; GFile *file; + GtkCssValue *color; GtkCssValue *palette; GdkTexture *texture; - GdkRGBA color; - GdkRGBA success; - GdkRGBA warning; - GdkRGBA error; }; struct _GtkCssImageRecolorClass diff --git a/gtk/gtkcssimagescaled.c b/gtk/gtkcssimagescaled.c index 273ab99359..d55e0cfcc4 100644 --- a/gtk/gtkcssimagescaled.c +++ b/gtk/gtkcssimagescaled.c @@ -208,6 +208,43 @@ gtk_css_image_scaled_is_computed (GtkCssImage *image) gtk_css_image_is_computed (self->images[0]); } +static gboolean +gtk_css_image_scaled_contains_current_color (GtkCssImage *image) +{ + GtkCssImageScaled *self = GTK_CSS_IMAGE_SCALED (image); + + for (guint i = 0; i < self->n_images; i++) + { + if (gtk_css_image_contains_current_color (self->images[i])) + return TRUE; + } + + return FALSE; +} + +static GtkCssImage * +gtk_css_image_scaled_resolve (GtkCssImage *image, + GtkCssComputeContext *context, + GtkCssValue *current_color) +{ + GtkCssImageScaled *self = GTK_CSS_IMAGE_SCALED (image); + GtkCssImageScaled *res; + + res = g_object_new (GTK_TYPE_CSS_IMAGE_SCALED, NULL); + + res->n_images = self->n_images; + res->images = g_new (GtkCssImage *, self->n_images); + res->scales = g_new (int, self->n_images); + + for (guint i = 0; i < self->n_images; i++) + { + res->images[i] = gtk_css_image_resolve (self->images[i], context, current_color); + res->scales[i] = self->scales[i]; + } + + return GTK_CSS_IMAGE (res); +} + static void _gtk_css_image_scaled_class_init (GtkCssImageScaledClass *klass) { @@ -222,6 +259,8 @@ _gtk_css_image_scaled_class_init (GtkCssImageScaledClass *klass) image_class->compute = gtk_css_image_scaled_compute; image_class->print = gtk_css_image_scaled_print; image_class->is_computed = gtk_css_image_scaled_is_computed; + image_class->contains_current_color = gtk_css_image_scaled_contains_current_color; + image_class->resolve = gtk_css_image_scaled_resolve; object_class->dispose = gtk_css_image_scaled_dispose; }