diff --git a/gtk/gtkstyleset.h b/gtk/gtkstyleset.h index 8b8750c588..f81881a596 100644 --- a/gtk/gtkstyleset.h +++ b/gtk/gtkstyleset.h @@ -106,6 +106,9 @@ void gtk_style_set_merge (GtkStyleSet *set, gboolean gtk_symbolic_color_resolve (GtkSymbolicColor *color, GtkStyleSet *style_set, GdkColor *resolved_color); +gboolean gtk_gradient_resolve (GtkGradient *gradient, + GtkStyleSet *style_set, + cairo_pattern_t **resolved_gradient); G_END_DECLS diff --git a/gtk/gtksymboliccolor.c b/gtk/gtksymboliccolor.c index 9b9386b4cd..5710218102 100644 --- a/gtk/gtksymboliccolor.c +++ b/gtk/gtksymboliccolor.c @@ -22,6 +22,9 @@ #include "gtkstyleset.h" #include "gtkintl.h" +G_DEFINE_BOXED_TYPE (GtkGradient, gtk_gradient, + gtk_gradient_ref, gtk_gradient_unref) + /* Symbolic colors */ typedef enum { COLOR_TYPE_LITERAL, @@ -55,6 +58,26 @@ struct GtkSymbolicColor }; }; +typedef struct ColorStop ColorStop; + +struct ColorStop +{ + gdouble offset; + GtkSymbolicColor *color; +}; + +struct GtkGradient +{ + gdouble x0; + gdouble y0; + gdouble x1; + gdouble y1; + + GArray *stops; + + guint ref_count; +}; + GtkSymbolicColor * gtk_symbolic_color_new_literal (GdkColor *color) { @@ -240,3 +263,112 @@ gtk_symbolic_color_get_type (void) return type; } + +/* GtkGradient */ +GtkGradient * +gtk_gradient_new_linear (gdouble x0, + gdouble y0, + gdouble x1, + gdouble y1) +{ + GtkGradient *gradient; + + gradient = g_slice_new (GtkGradient); + gradient->stops = g_array_new (FALSE, FALSE, sizeof (ColorStop)); + + gradient->x0 = x0; + gradient->y0 = y0; + gradient->x1 = x1; + gradient->y1 = y1; + + gradient->ref_count = 1; + + return gradient; +} + +void +gtk_gradient_add_color_stop (GtkGradient *gradient, + gdouble offset, + GtkSymbolicColor *color) +{ + ColorStop stop; + + g_return_if_fail (gradient != NULL); + + stop.offset = offset; + stop.color = gtk_symbolic_color_ref (color); + + g_array_append_val (gradient->stops, stop); +} + +GtkGradient * +gtk_gradient_ref (GtkGradient *gradient) +{ + g_return_val_if_fail (gradient != NULL, NULL); + + gradient->ref_count++; + + return gradient; +} + +void +gtk_gradient_unref (GtkGradient *gradient) +{ + g_return_if_fail (gradient != NULL); + + gradient->ref_count--; + + if (gradient->ref_count == 0) + { + guint i; + + for (i = 0; i < gradient->stops->len; i++) + { + ColorStop *stop; + + stop = &g_array_index (gradient->stops, ColorStop, i); + gtk_symbolic_color_unref (stop->color); + } + + g_array_free (gradient->stops, TRUE); + g_slice_free (GtkGradient, gradient); + } +} + +gboolean +gtk_gradient_resolve (GtkGradient *gradient, + GtkStyleSet *style_set, + cairo_pattern_t **resolved_gradient) +{ + cairo_pattern_t *pattern; + guint i; + + g_return_val_if_fail (gradient != NULL, FALSE); + g_return_val_if_fail (GTK_IS_STYLE_SET (style_set), FALSE); + g_return_val_if_fail (resolved_gradient != NULL, FALSE); + + pattern = cairo_pattern_create_linear (gradient->x0, gradient->y0, + gradient->x1, gradient->y1); + + for (i = 0; i < gradient->stops->len; i++) + { + ColorStop *stop; + GdkColor color; + + stop = &g_array_index (gradient->stops, ColorStop, i); + + if (!gtk_symbolic_color_resolve (stop->color, style_set, &color)) + { + cairo_pattern_destroy (pattern); + return FALSE; + } + + cairo_pattern_add_color_stop_rgb (pattern, stop->offset, + color.red / 65535., + color.green / 65535., + color.blue / 65535.); + } + + *resolved_gradient = pattern; + return TRUE; +} diff --git a/gtk/gtksymboliccolor.h b/gtk/gtksymboliccolor.h index 8b3608bf21..aedd2aa28e 100644 --- a/gtk/gtksymboliccolor.h +++ b/gtk/gtksymboliccolor.h @@ -26,11 +26,13 @@ G_BEGIN_DECLS /* Dummy typedefs */ typedef struct GtkSymbolicColor GtkSymbolicColor; -typedef struct GtkSymbolicColorMap GtkSymbolicColorMap; +typedef struct GtkGradient GtkGradient; #define GTK_TYPE_SYMBOLIC_COLOR (gtk_symbolic_color_get_type ()) +#define GTK_TYPE_GRADIENT (gtk_gradient_get_type ()) GType gtk_symbolic_color_get_type (void) G_GNUC_CONST; +GType gtk_gradient_get_type (void) G_GNUC_CONST; GtkSymbolicColor * gtk_symbolic_color_new_literal (GdkColor *color); GtkSymbolicColor * gtk_symbolic_color_new_name (const gchar *name); @@ -43,6 +45,18 @@ GtkSymbolicColor * gtk_symbolic_color_new_mix (GtkSymbolicColor *color1, GtkSymbolicColor * gtk_symbolic_color_ref (GtkSymbolicColor *color); void gtk_symbolic_color_unref (GtkSymbolicColor *color); +GtkGradient * gtk_gradient_new_linear (gdouble x0, + gdouble y0, + gdouble x1, + gdouble y1); + +void gtk_gradient_add_color_stop (GtkGradient *gradient, + gdouble offset, + GtkSymbolicColor *color); + +GtkGradient * gtk_gradient_ref (GtkGradient *gradient); +void gtk_gradient_unref (GtkGradient *gradient); + G_END_DECLS #endif /* __GTK_SYMBOLIC_COLOR_H__ */