diff options
author | Benjamin Otte <otte@redhat.com> | 2015-01-18 20:24:27 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2015-01-20 06:30:19 +0100 |
commit | 1c3dd5d46bd2e33bc7bf43b28d9c57c69a1199dd (patch) | |
tree | 92a25cec00c67870622b0df332f2b98faf9facba | |
parent | ebb64c2288aff6bd70d349771cc564d36b2f27b0 (diff) | |
download | gtk+-1c3dd5d46bd2e33bc7bf43b28d9c57c69a1199dd.tar.gz |
render: Move code for rendering builtin images
Also, make it have a generic entry point with
gtk_css_image_builtin_draw().
The only feature lost so is the drawing of shadows for spinners, but
that will come back later.
-rw-r--r-- | gtk/gtkcssimagebuiltin.c | 794 | ||||
-rw-r--r-- | gtk/gtkcssimagebuiltinprivate.h | 25 | ||||
-rw-r--r-- | gtk/gtkrender.c | 818 |
3 files changed, 976 insertions, 661 deletions
diff --git a/gtk/gtkcssimagebuiltin.c b/gtk/gtkcssimagebuiltin.c index 7f72ce1a34..ba31ec14c6 100644 --- a/gtk/gtkcssimagebuiltin.c +++ b/gtk/gtkcssimagebuiltin.c @@ -21,15 +21,728 @@ #include "gtkcssimagebuiltinprivate.h" +#include "gtkhslaprivate.h" +#include "gtkrenderprivate.h" + +#include <math.h> + +#include "fallback-c89.c" + G_DEFINE_TYPE (GtkCssImageBuiltin, gtk_css_image_builtin, GTK_TYPE_CSS_IMAGE) static GtkCssImage *the_one_true_image; static void -gtk_css_image_builtin_draw (GtkCssImage *image, - cairo_t *cr, - double width, - double height) +gtk_css_image_builtin_draw_check (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + GtkStateFlags state, + const GdkRGBA * fg_color, + const GdkRGBA * bg_color, + const GdkRGBA * border_color, + int border_width) +{ + gint x, y, exterior_size, interior_size, thickness, pad; + + exterior_size = MIN (width, height); + + if (exterior_size % 2 == 0) /* Ensure odd */ + exterior_size -= 1; + + /* FIXME: thickness */ + thickness = 1; + pad = thickness + MAX (1, (exterior_size - 2 * thickness) / 9); + interior_size = MAX (1, exterior_size - 2 * pad); + + if (interior_size < 7) + { + interior_size = 7; + pad = MAX (0, (exterior_size - interior_size) / 2); + } + + x = - (1 + exterior_size - (gint) width) / 2; + y = - (1 + exterior_size - (gint) height) / 2; + + if (border_width > 0) + { + cairo_set_line_width (cr, border_width); + + cairo_rectangle (cr, x + 0.5, y + 0.5, exterior_size - 1, exterior_size - 1); + gdk_cairo_set_source_rgba (cr, bg_color); + cairo_fill_preserve (cr); + + gdk_cairo_set_source_rgba (cr, border_color); + cairo_stroke (cr); + } + + gdk_cairo_set_source_rgba (cr, fg_color); + + if (state & GTK_STATE_FLAG_INCONSISTENT) + { + int line_thickness = MAX (1, (3 + interior_size * 2) / 7); + + cairo_rectangle (cr, + x + pad, + y + pad + (1 + interior_size - line_thickness) / 2, + interior_size, + line_thickness); + cairo_fill (cr); + } + else + { + if (state & GTK_STATE_FLAG_CHECKED) + { + cairo_translate (cr, + x + pad, y + pad); + + cairo_scale (cr, interior_size / 7., interior_size / 7.); + + cairo_rectangle (cr, 0, 0, 7, 7); + cairo_clip (cr); + + cairo_move_to (cr, 7.0, 0.0); + cairo_line_to (cr, 7.5, 1.0); + cairo_curve_to (cr, 5.3, 2.0, + 4.3, 4.0, + 3.5, 7.0); + cairo_curve_to (cr, 3.0, 5.7, + 1.3, 4.7, + 0.0, 4.7); + cairo_line_to (cr, 0.2, 3.5); + cairo_curve_to (cr, 1.1, 3.5, + 2.3, 4.3, + 3.0, 5.0); + cairo_curve_to (cr, 1.0, 3.9, + 2.4, 4.1, + 3.2, 4.9); + cairo_curve_to (cr, 3.5, 3.1, + 5.2, 2.0, + 7.0, 0.0); + + cairo_fill (cr); + } + } +} + +static void +gtk_css_image_builtin_draw_option (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + GtkStateFlags state, + const GdkRGBA * fg_color, + const GdkRGBA * bg_color, + const GdkRGBA * border_color, + int border_width) +{ + gint x, y, exterior_size, interior_size, thickness, pad; + + exterior_size = MIN (width, height); + + if (exterior_size % 2 == 0) /* Ensure odd */ + exterior_size -= 1; + + x = - (1 + exterior_size - width) / 2; + y = - (1 + exterior_size - height) / 2; + + if (border_width > 0) + { + cairo_set_line_width (cr, border_width); + + cairo_new_sub_path (cr); + cairo_arc (cr, + x + exterior_size / 2., + y + exterior_size / 2., + (exterior_size - 1) / 2., + 0, 2 * G_PI); + + gdk_cairo_set_source_rgba (cr, bg_color); + cairo_fill_preserve (cr); + + gdk_cairo_set_source_rgba (cr, border_color); + cairo_stroke (cr); + } + + gdk_cairo_set_source_rgba (cr, fg_color); + + /* FIXME: thickness */ + thickness = 1; + + if (state & GTK_STATE_FLAG_INCONSISTENT) + { + gint line_thickness; + + pad = thickness + MAX (1, (exterior_size - 2 * thickness) / 9); + interior_size = MAX (1, exterior_size - 2 * pad); + + if (interior_size < 7) + { + interior_size = 7; + pad = MAX (0, (exterior_size - interior_size) / 2); + } + + line_thickness = MAX (1, (3 + interior_size * 2) / 7); + + cairo_rectangle (cr, + x + pad, + y + pad + (interior_size - line_thickness) / 2., + interior_size, + line_thickness); + cairo_fill (cr); + } + if (state & GTK_STATE_FLAG_CHECKED) + { + pad = thickness + MAX (1, 2 * (exterior_size - 2 * thickness) / 9); + interior_size = MAX (1, exterior_size - 2 * pad); + + if (interior_size < 5) + { + interior_size = 7; + pad = MAX (0, (exterior_size - interior_size) / 2); + } + + cairo_new_sub_path (cr); + cairo_arc (cr, + x + pad + interior_size / 2., + y + pad + interior_size / 2., + interior_size / 2., + 0, 2 * G_PI); + cairo_fill (cr); + } +} + +static void +gtk_css_image_builtin_draw_arrow (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + const GdkRGBA * color) +{ + double line_width; + double size; + + size = MIN (width, height); + + cairo_translate (cr, width / 2.0 + size / 4.0, height / 2.0); + + line_width = size / 3.0 / sqrt (2); + cairo_set_line_width (cr, line_width); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + + cairo_scale (cr, + (size / (size + line_width)), + (size / (size + line_width))); + + cairo_move_to (cr, -size / 2.0, -size / 2.0); + cairo_rel_line_to (cr, size / 2.0, size / 2.0); + cairo_rel_line_to (cr, - size / 2.0, size / 2.0); + + gdk_cairo_set_source_rgba (cr, color); + cairo_stroke (cr); +} + +static void +gtk_css_image_builtin_draw_expander (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + GtkStateFlags state, + GtkCssImageBuiltinType image_type, + const GdkRGBA * fg_color, + const GdkRGBA * border_color) +{ + double vertical_overshoot; + int diameter; + double radius; + double interp; /* interpolation factor for center position */ + double x_double_horz, y_double_horz; + double x_double_vert, y_double_vert; + double x_double, y_double; + gdouble angle; + gint line_width; + gboolean is_rtl; + gdouble progress; + + is_rtl = (state & GTK_STATE_FLAG_DIR_RTL); + line_width = 1; + progress = (state & GTK_STATE_FLAG_CHECKED) ? 1 : 0; + + if (image_type != GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL) + { + if (is_rtl) + angle = (G_PI) - ((G_PI / 2) * progress); + else + angle = (G_PI / 2) * progress; + } + else + { + if (is_rtl) + angle = (G_PI / 2) + ((G_PI / 2) * progress); + else + angle = (G_PI / 2) - ((G_PI / 2) * progress); + } + + interp = progress; + + /* Compute distance that the stroke extends beyonds the end + * of the triangle we draw. + */ + vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8)); + + /* For odd line widths, we end the vertical line of the triangle + * at a half pixel, so we round differently. + */ + if (line_width % 2 == 1) + vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5; + else + vertical_overshoot = ceil (vertical_overshoot); + + /* Adjust the size of the triangle we draw so that the entire stroke fits + */ + diameter = (gint) MAX (3, width - 2 * vertical_overshoot); + + /* If the line width is odd, we want the diameter to be even, + * and vice versa, so force the sum to be odd. This relationship + * makes the point of the triangle look right. + */ + diameter -= (1 - (diameter + line_width) % 2); + + radius = diameter / 2.; + + /* Adjust the center so that the stroke is properly aligned with + * the pixel grid. The center adjustment is different for the + * horizontal and vertical orientations. For intermediate positions + * we interpolate between the two. + */ + x_double_vert = floor ((width / 2) - (radius + line_width) / 2.) + (radius + line_width) / 2.; + y_double_vert = (height / 2) - 0.5; + + x_double_horz = (width / 2) - 0.5; + y_double_horz = floor ((height / 2) - (radius + line_width) / 2.) + (radius + line_width) / 2.; + + x_double = x_double_vert * (1 - interp) + x_double_horz * interp; + y_double = y_double_vert * (1 - interp) + y_double_horz * interp; + + cairo_translate (cr, x_double, y_double); + cairo_rotate (cr, angle); + + cairo_move_to (cr, - radius / 2., - radius); + cairo_line_to (cr, radius / 2., 0); + cairo_line_to (cr, - radius / 2., radius); + cairo_close_path (cr); + + cairo_set_line_width (cr, line_width); + + gdk_cairo_set_source_rgba (cr, fg_color); + + cairo_fill_preserve (cr); + + gdk_cairo_set_source_rgba (cr, border_color); + cairo_stroke (cr); +} + +static void +color_shade (const GdkRGBA *color, + gdouble factor, + GdkRGBA *color_return) +{ + GtkHSLA hsla; + + _gtk_hsla_init_from_rgba (&hsla, color); + _gtk_hsla_shade (&hsla, &hsla, factor); + _gdk_rgba_init_from_hsla (color_return, &hsla); +} + +static void +render_dot (cairo_t *cr, + const GdkRGBA *lighter, + const GdkRGBA *darker, + gdouble x, + gdouble y, + gdouble size) +{ + size = CLAMP ((gint) size, 2, 3); + + if (size == 2) + { + gdk_cairo_set_source_rgba (cr, lighter); + cairo_rectangle (cr, x, y, 1, 1); + cairo_rectangle (cr, x + 1, y + 1, 1, 1); + cairo_fill (cr); + } + else if (size == 3) + { + gdk_cairo_set_source_rgba (cr, lighter); + cairo_rectangle (cr, x, y, 2, 1); + cairo_rectangle (cr, x, y, 1, 2); + cairo_fill (cr); + + gdk_cairo_set_source_rgba (cr, darker); + cairo_rectangle (cr, x + 1, y + 1, 2, 1); + cairo_rectangle (cr, x + 2, y, 1, 2); + cairo_fill (cr); + } +} + +static void +add_path_line (cairo_t *cr, + gdouble x1, + gdouble y1, + gdouble x2, + gdouble y2) +{ + /* Adjust endpoints */ + if (y1 == y2) + { + y1 += 0.5; + y2 += 0.5; + x2 += 1; + } + else if (x1 == x2) + { + x1 += 0.5; + x2 += 0.5; + y2 += 1; + } + + cairo_move_to (cr, x1, y1); + cairo_line_to (cr, x2, y2); +} + +void +gtk_css_image_builtin_draw_grip (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + GtkJunctionSides sides, + const GdkRGBA *bg_color) +{ + GdkRGBA lighter, darker; + + cairo_set_line_width (cr, 1.0); + + color_shade (bg_color, 0.7, &darker); + color_shade (bg_color, 1.3, &lighter); + + /* reduce confusing values to a meaningful state */ + if ((sides & (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMRIGHT)) == (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMRIGHT)) + sides &= ~GTK_JUNCTION_CORNER_TOPLEFT; + + if ((sides & (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMLEFT)) == (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMLEFT)) + sides &= ~GTK_JUNCTION_CORNER_TOPRIGHT; + + if (sides == 0) + sides = GTK_JUNCTION_CORNER_BOTTOMRIGHT; + + /* align drawing area to the connected side */ + if (sides == GTK_JUNCTION_LEFT) + { + if (height < width) + width = height; + } + else if (sides == GTK_JUNCTION_CORNER_TOPLEFT) + { + if (width < height) + height = width; + else if (height < width) + width = height; + } + else if (sides == GTK_JUNCTION_CORNER_BOTTOMLEFT) + { + /* make it square, aligning to bottom left */ + if (width < height) + { + cairo_translate (cr, 0, height - width); + height = width; + } + else if (height < width) + width = height; + } + else if (sides == GTK_JUNCTION_RIGHT) + { + /* aligning to right */ + if (height < width) + { + cairo_translate (cr, width - height, 0); + width = height; + } + } + else if (sides == GTK_JUNCTION_CORNER_TOPRIGHT) + { + if (width < height) + height = width; + else if (height < width) + { + cairo_translate (cr, width - height, 0); + width = height; + } + } + else if (sides == GTK_JUNCTION_CORNER_BOTTOMRIGHT) + { + /* make it square, aligning to bottom right */ + if (width < height) + { + cairo_translate (cr, 0, height - width); + height = width; + } + else if (height < width) + { + cairo_translate (cr, width - height, 0); + width = height; + } + } + else if (sides == GTK_JUNCTION_TOP) + { + if (width < height) + height = width; + } + else if (sides == GTK_JUNCTION_BOTTOM) + { + /* align to bottom */ + if (width < height) + { + cairo_translate (cr, 0, height - width); + height = width; + } + } + else + g_assert_not_reached (); + + if (sides == GTK_JUNCTION_LEFT || + sides == GTK_JUNCTION_RIGHT) + { + gint xi; + + xi = 0; + + while (xi < width) + { + gdk_cairo_set_source_rgba (cr, &lighter); + add_path_line (cr, 0, 0, 0, height); + cairo_stroke (cr); + xi++; + + gdk_cairo_set_source_rgba (cr, &darker); + add_path_line (cr, xi, 0, xi, height); + cairo_stroke (cr); + xi += 2; + } + } + else if (sides == GTK_JUNCTION_TOP || + sides == GTK_JUNCTION_BOTTOM) + { + gint yi; + + yi = 0; + + while (yi < height) + { + gdk_cairo_set_source_rgba (cr, &lighter); + add_path_line (cr, 0, yi, width, yi); + cairo_stroke (cr); + yi++; + + gdk_cairo_set_source_rgba (cr, &darker); + add_path_line (cr, 0, yi, width, yi); + cairo_stroke (cr); + yi += 2; + } + } + else if (sides == GTK_JUNCTION_CORNER_TOPLEFT) + { + gint xi, yi; + + xi = width; + yi = height; + + while (xi > 3) + { + gdk_cairo_set_source_rgba (cr, &darker); + add_path_line (cr, xi, 0, 0, yi); + cairo_stroke (cr); + + --xi; + --yi; + + add_path_line (cr, xi, 0, 0, yi); + cairo_stroke (cr); + + --xi; + --yi; + + gdk_cairo_set_source_rgba (cr, &lighter); + add_path_line (cr, xi, 0, 0, yi); + cairo_stroke (cr); + + xi -= 3; + yi -= 3; + } + } + else if (sides == GTK_JUNCTION_CORNER_TOPRIGHT) + { + gint xi, yi; + + xi = 0; + yi = height; + + while (xi < (width - 3)) + { + gdk_cairo_set_source_rgba (cr, &lighter); + add_path_line (cr, xi, 0, width, yi); + cairo_stroke (cr); + + ++xi; + --yi; + + gdk_cairo_set_source_rgba (cr, &darker); + add_path_line (cr, xi, 0, width, yi); + cairo_stroke (cr); + + ++xi; + --yi; + + add_path_line (cr, xi, 0, width, yi); + cairo_stroke (cr); + + xi += 3; + yi -= 3; + } + } + else if (sides == GTK_JUNCTION_CORNER_BOTTOMLEFT) + { + gint xi, yi; + + xi = width; + yi = 0; + + while (xi > 3) + { + gdk_cairo_set_source_rgba (cr, &darker); + add_path_line (cr, 0, yi, xi, height); + cairo_stroke (cr); + + --xi; + ++yi; + + add_path_line (cr, 0, yi, xi, height); + cairo_stroke (cr); + + --xi; + ++yi; + + gdk_cairo_set_source_rgba (cr, &lighter); + add_path_line (cr, 0, yi, xi, height); + cairo_stroke (cr); + + xi -= 3; + yi += 3; + } + } + else if (sides == GTK_JUNCTION_CORNER_BOTTOMRIGHT) + { + gint xi, yi; + + xi = 0; + yi = 0; + + while (xi < (width - 3)) + { + gdk_cairo_set_source_rgba (cr, &lighter); + add_path_line (cr, xi, height, width, yi); + cairo_stroke (cr); + + ++xi; + ++yi; + + gdk_cairo_set_source_rgba (cr, &darker); + add_path_line (cr, xi, height, width, yi); + cairo_stroke (cr); + + ++xi; + ++yi; + + add_path_line (cr, xi, height, width, yi); + cairo_stroke (cr); + + xi += 3; + yi += 3; + } + } +} + +void +gtk_css_image_builtin_draw_pane_separator (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + const GdkRGBA *bg_color) +{ + GdkRGBA lighter, darker; + gint xx, yy; + + cairo_set_line_width (cr, 1.0); + + color_shade (bg_color, 0.7, &darker); + color_shade (bg_color, 1.3, &lighter); + + if (width > height) + for (xx = width / 2 - 15; xx <= width / 2 + 15; xx += 5) + render_dot (cr, &lighter, &darker, xx, height / 2 - 1, 3); + else + for (yy = height / 2 - 15; yy <= height / 2 + 15; yy += 5) + render_dot (cr, &lighter, &darker, width / 2 - 1, yy, 3); +} + +void +gtk_css_image_builtin_draw_handle (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + const GdkRGBA *bg_color) +{ + GdkRGBA lighter, darker; + gint xx, yy; + + cairo_set_line_width (cr, 1.0); + + color_shade (bg_color, 0.7, &darker); + color_shade (bg_color, 1.3, &lighter); + + for (yy = 0; yy < height; yy += 3) + for (xx = 0; xx < width; xx += 6) + { + render_dot (cr, &lighter, &darker, xx, yy, 2); + render_dot (cr, &lighter, &darker, xx + 3, yy + 1, 2); + } +} + +static void +gtk_css_image_builtin_draw_spinner (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + const GdkRGBA *color) +{ + gdouble radius; + + radius = MIN (width / 2, height / 2); + + cairo_save (cr); + cairo_translate (cr, width / 2, height / 2); + + gdk_cairo_set_source_rgba (cr, color); + gtk_render_paint_spinner (cr, radius, -1); + + cairo_restore (cr); +} + +static void +gtk_css_image_builtin_real_draw (GtkCssImage *image, + cairo_t *cr, + double width, + double height) { /* It's a builtin image, other code will draw things */ } @@ -99,7 +812,7 @@ gtk_css_image_builtin_class_init (GtkCssImageBuiltinClass *klass) GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); - image_class->draw = gtk_css_image_builtin_draw; + image_class->draw = gtk_css_image_builtin_real_draw; image_class->parse = gtk_css_image_builtin_parse; image_class->print = gtk_css_image_builtin_print; image_class->compute = gtk_css_image_builtin_compute; @@ -125,3 +838,74 @@ gtk_css_image_builtin_new (void) return the_one_true_image; } +void +gtk_css_image_builtin_draw (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + GtkCssImageBuiltinType image_type, + GtkStateFlags state, + GtkJunctionSides sides, + const GdkRGBA * fg_color, + const GdkRGBA * bg_color, + const GdkRGBA * border_color, + int border_width) +{ + switch (image_type) + { + default: + g_assert_not_reached (); + break; + case GTK_CSS_IMAGE_BUILTIN_NONE: + break; + case GTK_CSS_IMAGE_BUILTIN_CHECK: + gtk_css_image_builtin_draw_check (image, cr, + width, height, + state, + fg_color, bg_color, + border_color, border_width); + break; + case GTK_CSS_IMAGE_BUILTIN_OPTION: + gtk_css_image_builtin_draw_option (image, cr, + width, height, + state, + fg_color, bg_color, + border_color, border_width); + break; + case GTK_CSS_IMAGE_BUILTIN_ARROW: + gtk_css_image_builtin_draw_arrow (image, cr, + width, height, + fg_color); + break; + case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL: + case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL: + gtk_css_image_builtin_draw_expander (image, cr, + width, height, + state, + image_type, + fg_color, border_color); + break; + case GTK_CSS_IMAGE_BUILTIN_GRIP: + gtk_css_image_builtin_draw_grip (image, cr, + width, height, + sides, + bg_color); + break; + case GTK_CSS_IMAGE_BUILTIN_PANE_SEPARATOR: + gtk_css_image_builtin_draw_pane_separator (image, cr, + width, height, + bg_color); + break; + case GTK_CSS_IMAGE_BUILTIN_HANDLE: + gtk_css_image_builtin_draw_handle (image, cr, + width, height, + bg_color); + break; + case GTK_CSS_IMAGE_BUILTIN_SPINNER: + gtk_css_image_builtin_draw_spinner (image, cr, + width, height, + fg_color); + break; + } +} + diff --git a/gtk/gtkcssimagebuiltinprivate.h b/gtk/gtkcssimagebuiltinprivate.h index 294a83b8d5..1ad6174822 100644 --- a/gtk/gtkcssimagebuiltinprivate.h +++ b/gtk/gtkcssimagebuiltinprivate.h @@ -25,6 +25,19 @@ G_BEGIN_DECLS +typedef enum { + GTK_CSS_IMAGE_BUILTIN_NONE, + GTK_CSS_IMAGE_BUILTIN_CHECK, + GTK_CSS_IMAGE_BUILTIN_OPTION, + GTK_CSS_IMAGE_BUILTIN_ARROW, + GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL, + GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL, + GTK_CSS_IMAGE_BUILTIN_GRIP, + GTK_CSS_IMAGE_BUILTIN_PANE_SEPARATOR, + GTK_CSS_IMAGE_BUILTIN_HANDLE, + GTK_CSS_IMAGE_BUILTIN_SPINNER +} GtkCssImageBuiltinType; + #define GTK_TYPE_CSS_IMAGE_BUILTIN (gtk_css_image_builtin_get_type ()) #define GTK_CSS_IMAGE_BUILTIN(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_IMAGE_BUILTIN, GtkCssImageBuiltin)) #define GTK_CSS_IMAGE_BUILTIN_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_IMAGE_BUILTIN, GtkCssImageBuiltinClass)) @@ -49,6 +62,18 @@ GType gtk_css_image_builtin_get_type (void) G_GNUC_CONST; GtkCssImage * gtk_css_image_builtin_new (void); +void gtk_css_image_builtin_draw (GtkCssImage *image, + cairo_t *cr, + double width, + double height, + GtkCssImageBuiltinType image_type, + GtkStateFlags state, + GtkJunctionSides sides, + const GdkRGBA *fg_color, + const GdkRGBA *bg_color, + const GdkRGBA *border_color, + int border_width); + G_END_DECLS #endif /* __GTK_CSS_IMAGE_BUILTIN_PRIVATE_H__ */ diff --git a/gtk/gtkrender.c b/gtk/gtkrender.c index ea264abfdc..15b2a8b30e 100644 --- a/gtk/gtkrender.c +++ b/gtk/gtkrender.c @@ -94,112 +94,42 @@ gtk_do_render_check (GtkStyleContext *context, gdouble width, gdouble height) { - const GdkRGBA *fg_color, *bg_color; - GtkStateFlags flags; - gint exterior_size, interior_size, thickness, pad; GtkBorderStyle border_style; - GtkBorder border; gint border_width; if (render_icon_image (context, cr, x, y, width, height)) return; - flags = gtk_style_context_get_state (context); - cairo_save (cr); - - fg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)); - bg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR)); - border.top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100); - border.right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100); - border.bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100); - border.left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100); border_style = _gtk_css_border_style_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_STYLE)); - - border_width = MIN (MIN (border.top, border.bottom), - MIN (border.left, border.right)); - exterior_size = MIN (width, height); - - if (exterior_size % 2 == 0) /* Ensure odd */ - exterior_size -= 1; - - /* FIXME: thickness */ - thickness = 1; - pad = thickness + MAX (1, (exterior_size - 2 * thickness) / 9); - interior_size = MAX (1, exterior_size - 2 * pad); - - if (interior_size < 7) - { - interior_size = 7; - pad = MAX (0, (exterior_size - interior_size) / 2); - } - - x -= (1 + exterior_size - (gint) width) / 2; - y -= (1 + exterior_size - (gint) height) / 2; - if (border_style == GTK_BORDER_STYLE_SOLID) { - const GdkRGBA *border_color; + GtkBorder border; - cairo_set_line_width (cr, border_width); - border_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)); + border.top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100); + border.right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100); + border.bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100); + border.left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100); - cairo_rectangle (cr, x + 0.5, y + 0.5, exterior_size - 1, exterior_size - 1); - gdk_cairo_set_source_rgba (cr, bg_color); - cairo_fill_preserve (cr); - - gdk_cairo_set_source_rgba (cr, border_color); - cairo_stroke (cr); - } - - gdk_cairo_set_source_rgba (cr, fg_color); - - if (flags & GTK_STATE_FLAG_INCONSISTENT) - { - int line_thickness = MAX (1, (3 + interior_size * 2) / 7); - - cairo_rectangle (cr, - x + pad, - y + pad + (1 + interior_size - line_thickness) / 2, - interior_size, - line_thickness); - cairo_fill (cr); + border_width = MIN (MIN (border.top, border.bottom), + MIN (border.left, border.right)); } else { - if (flags & GTK_STATE_FLAG_CHECKED) - { - cairo_translate (cr, - x + pad, y + pad); - - cairo_scale (cr, interior_size / 7., interior_size / 7.); - - cairo_rectangle (cr, 0, 0, 7, 7); - cairo_clip (cr); - - cairo_move_to (cr, 7.0, 0.0); - cairo_line_to (cr, 7.5, 1.0); - cairo_curve_to (cr, 5.3, 2.0, - 4.3, 4.0, - 3.5, 7.0); - cairo_curve_to (cr, 3.0, 5.7, - 1.3, 4.7, - 0.0, 4.7); - cairo_line_to (cr, 0.2, 3.5); - cairo_curve_to (cr, 1.1, 3.5, - 2.3, 4.3, - 3.0, 5.0); - cairo_curve_to (cr, 1.0, 3.9, - 2.4, 4.1, - 3.2, 4.9); - cairo_curve_to (cr, 3.5, 3.1, - 5.2, 2.0, - 7.0, 0.0); - - cairo_fill (cr); - } + border_width = 0; } - cairo_restore (cr); + cairo_translate (cr, x, y); + + gtk_css_image_builtin_draw (_gtk_css_image_value_get_image (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ICON_SOURCE)), + cr, + width, height, + GTK_CSS_IMAGE_BUILTIN_OPTION, + gtk_style_context_get_state (context), + gtk_style_context_get_junction_sides (context), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)), + border_width); } /** @@ -253,106 +183,42 @@ gtk_do_render_option (GtkStyleContext *context, gdouble width, gdouble height) { - GtkStateFlags flags; - const GdkRGBA *fg_color, *bg_color; - gint exterior_size, interior_size, pad, thickness, border_width; GtkBorderStyle border_style; - GtkBorder border; + gint border_width; if (render_icon_image (context, cr, x, y, width, height)) return; - flags = gtk_style_context_get_state (context); - - cairo_save (cr); - - fg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)); - bg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR)); - border.top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100); - border.right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100); - border.bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100); - border.left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100); border_style = _gtk_css_border_style_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_STYLE)); - - exterior_size = MIN (width, height); - border_width = MIN (MIN (border.top, border.bottom), - MIN (border.left, border.right)); - - if (exterior_size % 2 == 0) /* Ensure odd */ - exterior_size -= 1; - - x -= (1 + exterior_size - width) / 2; - y -= (1 + exterior_size - height) / 2; - if (border_style == GTK_BORDER_STYLE_SOLID) { - const GdkRGBA *border_color; - - cairo_set_line_width (cr, border_width); - border_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)); + GtkBorder border; - cairo_new_sub_path (cr); - cairo_arc (cr, - x + exterior_size / 2., - y + exterior_size / 2., - (exterior_size - 1) / 2., - 0, 2 * G_PI); + border.top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100); + border.right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100); + border.bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100); + border.left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100); - gdk_cairo_set_source_rgba (cr, bg_color); - cairo_fill_preserve (cr); - - gdk_cairo_set_source_rgba (cr, border_color); - cairo_stroke (cr); + border_width = MIN (MIN (border.top, border.bottom), + MIN (border.left, border.right)); } - - gdk_cairo_set_source_rgba (cr, fg_color); - - /* FIXME: thickness */ - thickness = 1; - - if (flags & GTK_STATE_FLAG_INCONSISTENT) + else { - gint line_thickness; - - pad = thickness + MAX (1, (exterior_size - 2 * thickness) / 9); - interior_size = MAX (1, exterior_size - 2 * pad); - - if (interior_size < 7) - { - interior_size = 7; - pad = MAX (0, (exterior_size - interior_size) / 2); - } - - line_thickness = MAX (1, (3 + interior_size * 2) / 7); - - cairo_rectangle (cr, - x + pad, - y + pad + (interior_size - line_thickness) / 2., - interior_size, - line_thickness); - cairo_fill (cr); + border_width = 0; } - if (flags & GTK_STATE_FLAG_CHECKED) - { - pad = thickness + MAX (1, 2 * (exterior_size - 2 * thickness) / 9); - interior_size = MAX (1, exterior_size - 2 * pad); - if (interior_size < 5) - { - interior_size = 7; - pad = MAX (0, (exterior_size - interior_size) / 2); - } - - cairo_new_sub_path (cr); - cairo_arc (cr, - x + pad + interior_size / 2., - y + pad + interior_size / 2., - interior_size / 2., - 0, 2 * G_PI); - cairo_fill (cr); - } + cairo_translate (cr, x, y); - cairo_restore (cr); + gtk_css_image_builtin_draw (_gtk_css_image_value_get_image (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ICON_SOURCE)), + cr, + width, height, + GTK_CSS_IMAGE_BUILTIN_CHECK, + gtk_style_context_get_state (context), + gtk_style_context_get_junction_sides (context), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)), + border_width); } /** @@ -404,36 +270,44 @@ gtk_do_render_arrow (GtkStyleContext *context, gdouble y, gdouble size) { - double line_width; - const GdkRGBA *color; + GtkBorderStyle border_style; + gint border_width; if (render_icon_image (context, cr, x, y, size, size)) return; - cairo_save (cr); + border_style = _gtk_css_border_style_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_STYLE)); + if (border_style == GTK_BORDER_STYLE_SOLID) + { + GtkBorder border; - line_width = size / 3.0 / sqrt (2); - cairo_set_line_width (cr, line_width); - cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + border.top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100); + border.right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100); + border.bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100); + border.left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100); + + border_width = MIN (MIN (border.top, border.bottom), + MIN (border.left, border.right)); + } + else + { + border_width = 0; + } cairo_translate (cr, x + size / 2.0, y + size / 2.0); cairo_rotate (cr, angle - G_PI_2); - cairo_translate (cr, size / 4.0, 0); - - cairo_scale (cr, - (size / (size + line_width)), - (size / (size + line_width))); - - cairo_move_to (cr, -size / 2.0, -size / 2.0); - cairo_rel_line_to (cr, size / 2.0, size / 2.0); - cairo_rel_line_to (cr, - size / 2.0, size / 2.0); - - color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)); - gdk_cairo_set_source_rgba (cr, color); - cairo_stroke (cr); - - cairo_restore (cr); + cairo_translate (cr, - size / 2.0, - size / 2.0); + + gtk_css_image_builtin_draw (_gtk_css_image_value_get_image (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ICON_SOURCE)), + cr, + size, size, + GTK_CSS_IMAGE_BUILTIN_ARROW, + gtk_style_context_get_state (context), + gtk_style_context_get_junction_sides (context), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)), + border_width); } /** @@ -479,18 +353,6 @@ gtk_render_arrow (GtkStyleContext *context, cairo_restore (cr); } -static void -color_shade (const GdkRGBA *color, - gdouble factor, - GdkRGBA *color_return) -{ - GtkHSLA hsla; - - _gtk_hsla_init_from_rgba (&hsla, color); - _gtk_hsla_shade (&hsla, &hsla, factor); - _gdk_rgba_init_from_hsla (color_return, &hsla); -} - /** * gtk_render_background: * @context: a #GtkStyleContext @@ -586,107 +448,44 @@ gtk_do_render_expander (GtkStyleContext *context, gdouble width, gdouble height) { - GtkStateFlags flags; - const GdkRGBA *outline_color, *fg_color; - double vertical_overshoot; - int diameter; - double radius; - double interp; /* interpolation factor for center position */ - double x_double_horz, y_double_horz; - double x_double_vert, y_double_vert; - double x_double, y_double; - gdouble angle; - gint line_width; - gboolean is_rtl; - gdouble progress; + GtkBorderStyle border_style; + gint border_width; if (render_icon_image (context, cr, x, y, width, height)) return; - cairo_save (cr); - flags = gtk_style_context_get_state (context); - - fg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)); - outline_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)); + border_style = _gtk_css_border_style_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_STYLE)); + if (border_style == GTK_BORDER_STYLE_SOLID) + { + GtkBorder border; - is_rtl = (gtk_style_context_get_state (context) & GTK_STATE_FLAG_DIR_RTL); - line_width = 1; - progress = (flags & GTK_STATE_FLAG_CHECKED) ? 1 : 0; + border.top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100); + border.right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100); + border.bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100); + border.left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100); - if (!gtk_style_context_has_class (context, GTK_STYLE_CLASS_HORIZONTAL)) - { - if (is_rtl) - angle = (G_PI) - ((G_PI / 2) * progress); - else - angle = (G_PI / 2) * progress; + border_width = MIN (MIN (border.top, border.bottom), + MIN (border.left, border.right)); } else { - if (is_rtl) - angle = (G_PI / 2) + ((G_PI / 2) * progress); - else - angle = (G_PI / 2) - ((G_PI / 2) * progress); + border_width = 0; } - interp = progress; - - /* Compute distance that the stroke extends beyonds the end - * of the triangle we draw. - */ - vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8)); - - /* For odd line widths, we end the vertical line of the triangle - * at a half pixel, so we round differently. - */ - if (line_width % 2 == 1) - vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5; - else - vertical_overshoot = ceil (vertical_overshoot); - - /* Adjust the size of the triangle we draw so that the entire stroke fits - */ - diameter = (gint) MAX (3, width - 2 * vertical_overshoot); - - /* If the line width is odd, we want the diameter to be even, - * and vice versa, so force the sum to be odd. This relationship - * makes the point of the triangle look right. - */ - diameter -= (1 - (diameter + line_width) % 2); - - radius = diameter / 2.; - - /* Adjust the center so that the stroke is properly aligned with - * the pixel grid. The center adjustment is different for the - * horizontal and vertical orientations. For intermediate positions - * we interpolate between the two. - */ - x_double_vert = floor ((x + width / 2) - (radius + line_width) / 2.) + (radius + line_width) / 2.; - y_double_vert = (y + height / 2) - 0.5; - - x_double_horz = (x + width / 2) - 0.5; - y_double_horz = floor ((y + height / 2) - (radius + line_width) / 2.) + (radius + line_width) / 2.; - - x_double = x_double_vert * (1 - interp) + x_double_horz * interp; - y_double = y_double_vert * (1 - interp) + y_double_horz * interp; - - cairo_translate (cr, x_double, y_double); - cairo_rotate (cr, angle); - - cairo_move_to (cr, - radius / 2., - radius); - cairo_line_to (cr, radius / 2., 0); - cairo_line_to (cr, - radius / 2., radius); - cairo_close_path (cr); - - cairo_set_line_width (cr, line_width); - - gdk_cairo_set_source_rgba (cr, fg_color); - - cairo_fill_preserve (cr); - - gdk_cairo_set_source_rgba (cr, outline_color); - cairo_stroke (cr); + cairo_translate (cr, x, y); - cairo_restore (cr); + gtk_css_image_builtin_draw (_gtk_css_image_value_get_image (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ICON_SOURCE)), + cr, + width, height, + gtk_style_context_has_class (context, "horizontal") + ? GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL + : GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL, + gtk_style_context_get_state (context), + gtk_style_context_get_junction_sides (context), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)), + border_width); } /** @@ -1228,62 +1027,6 @@ gtk_render_extension (GtkStyleContext *context, } static void -render_dot (cairo_t *cr, - const GdkRGBA *lighter, - const GdkRGBA *darker, - gdouble x, - gdouble y, - gdouble size) -{ - size = CLAMP ((gint) size, 2, 3); - - if (size == 2) - { - gdk_cairo_set_source_rgba (cr, lighter); - cairo_rectangle (cr, x, y, 1, 1); - cairo_rectangle (cr, x + 1, y + 1, 1, 1); - cairo_fill (cr); - } - else if (size == 3) - { - gdk_cairo_set_source_rgba (cr, lighter); - cairo_rectangle (cr, x, y, 2, 1); - cairo_rectangle (cr, x, y, 1, 2); - cairo_fill (cr); - - gdk_cairo_set_source_rgba (cr, darker); - cairo_rectangle (cr, x + 1, y + 1, 2, 1); - cairo_rectangle (cr, x + 2, y, 1, 2); - cairo_fill (cr); - } -} - -static void -add_path_line (cairo_t *cr, - gdouble x1, - gdouble y1, - gdouble x2, - gdouble y2) -{ - /* Adjust endpoints */ - if (y1 == y2) - { - y1 += 0.5; - y2 += 0.5; - x2 += 1; - } - else if (x1 == x2) - { - x1 += 0.5; - x2 += 0.5; - y2 += 1; - } - - cairo_move_to (cr, x1, y1); - cairo_line_to (cr, x2, y2); -} - -static void gtk_do_render_handle (GtkStyleContext *context, cairo_t *cr, gdouble x, @@ -1291,10 +1034,9 @@ gtk_do_render_handle (GtkStyleContext *context, gdouble width, gdouble height) { - const GdkRGBA *bg_color; - GdkRGBA lighter, darker; - GtkJunctionSides sides; - gint xx, yy; + GtkCssImageBuiltinType type; + GtkBorderStyle border_style; + gint border_width; gtk_render_background (context, cr, x, y, width, height); gtk_render_frame (context, cr, x, y, width, height); @@ -1302,282 +1044,43 @@ gtk_do_render_handle (GtkStyleContext *context, if (render_icon_image (context, cr, x, y, width, height)) return; - cairo_save (cr); - - cairo_set_line_width (cr, 1.0); - sides = gtk_style_context_get_junction_sides (context); - bg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR)); - - color_shade (bg_color, 0.7, &darker); - color_shade (bg_color, 1.3, &lighter); - - if (gtk_style_context_has_class (context, GTK_STYLE_CLASS_GRIP)) + border_style = _gtk_css_border_style_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_STYLE)); + if (border_style == GTK_BORDER_STYLE_SOLID) { - /* reduce confusing values to a meaningful state */ - if ((sides & (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMRIGHT)) == (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMRIGHT)) - sides &= ~GTK_JUNCTION_CORNER_TOPLEFT; - - if ((sides & (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMLEFT)) == (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMLEFT)) - sides &= ~GTK_JUNCTION_CORNER_TOPRIGHT; - - if (sides == 0) - sides = GTK_JUNCTION_CORNER_BOTTOMRIGHT; - - /* align drawing area to the connected side */ - if (sides == GTK_JUNCTION_LEFT) - { - if (height < width) - width = height; - } - else if (sides == GTK_JUNCTION_CORNER_TOPLEFT) - { - if (width < height) - height = width; - else if (height < width) - width = height; - } - else if (sides == GTK_JUNCTION_CORNER_BOTTOMLEFT) - { - /* make it square, aligning to bottom left */ - if (width < height) - { - y += (height - width); - height = width; - } - else if (height < width) - width = height; - } - else if (sides == GTK_JUNCTION_RIGHT) - { - /* aligning to right */ - if (height < width) - { - x += (width - height); - width = height; - } - } - else if (sides == GTK_JUNCTION_CORNER_TOPRIGHT) - { - if (width < height) - height = width; - else if (height < width) - { - x += (width - height); - width = height; - } - } - else if (sides == GTK_JUNCTION_CORNER_BOTTOMRIGHT) - { - /* make it square, aligning to bottom right */ - if (width < height) - { - y += (height - width); - height = width; - } - else if (height < width) - { - x += (width - height); - width = height; - } - } - else if (sides == GTK_JUNCTION_TOP) - { - if (width < height) - height = width; - } - else if (sides == GTK_JUNCTION_BOTTOM) - { - /* align to bottom */ - if (width < height) - { - y += (height - width); - height = width; - } - } - else - g_assert_not_reached (); - - if (sides == GTK_JUNCTION_LEFT || - sides == GTK_JUNCTION_RIGHT) - { - gint xi; - - xi = x; - - while (xi < x + width) - { - gdk_cairo_set_source_rgba (cr, &lighter); - add_path_line (cr, x, y, x, y + height); - cairo_stroke (cr); - xi++; - - gdk_cairo_set_source_rgba (cr, &darker); - add_path_line (cr, xi, y, xi, y + height); - cairo_stroke (cr); - xi += 2; - } - } - else if (sides == GTK_JUNCTION_TOP || - sides == GTK_JUNCTION_BOTTOM) - { - gint yi; - - yi = y; - - while (yi < y + height) - { - gdk_cairo_set_source_rgba (cr, &lighter); - add_path_line (cr, x, yi, x + width, yi); - cairo_stroke (cr); - yi++; - - gdk_cairo_set_source_rgba (cr, &darker); - add_path_line (cr, x, yi, x + width, yi); - cairo_stroke (cr); - yi += 2; - } - } - else if (sides == GTK_JUNCTION_CORNER_TOPLEFT) - { - gint xi, yi; - - xi = x + width; - yi = y + height; - - while (xi > x + 3) - { - gdk_cairo_set_source_rgba (cr, &darker); - add_path_line (cr, xi, y, x, yi); - cairo_stroke (cr); - - --xi; - --yi; - - add_path_line (cr, xi, y, x, yi); - cairo_stroke (cr); - - --xi; - --yi; - - gdk_cairo_set_source_rgba (cr, &lighter); - add_path_line (cr, xi, y, x, yi); - cairo_stroke (cr); - - xi -= 3; - yi -= 3; - } - } - else if (sides == GTK_JUNCTION_CORNER_TOPRIGHT) - { - gint xi, yi; - - xi = x; - yi = y + height; - - while (xi < (x + width - 3)) - { - gdk_cairo_set_source_rgba (cr, &lighter); - add_path_line (cr, xi, y, x + width, yi); - cairo_stroke (cr); - - ++xi; - --yi; + GtkBorder border; - gdk_cairo_set_source_rgba (cr, &darker); - add_path_line (cr, xi, y, x + width, yi); - cairo_stroke (cr); + border.top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100); + border.right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100); + border.bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100); + border.left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100); - ++xi; - --yi; - - add_path_line (cr, xi, y, x + width, yi); - cairo_stroke (cr); - - xi += 3; - yi -= 3; - } - } - else if (sides == GTK_JUNCTION_CORNER_BOTTOMLEFT) - { - gint xi, yi; - - xi = x + width; - yi = y; - - while (xi > x + 3) - { - gdk_cairo_set_source_rgba (cr, &darker); - add_path_line (cr, x, yi, xi, y + height); - cairo_stroke (cr); - - --xi; - ++yi; - - add_path_line (cr, x, yi, xi, y + height); - cairo_stroke (cr); - - --xi; - ++yi; - - gdk_cairo_set_source_rgba (cr, &lighter); - add_path_line (cr, x, yi, xi, y + height); - cairo_stroke (cr); - - xi -= 3; - yi += 3; - } - } - else if (sides == GTK_JUNCTION_CORNER_BOTTOMRIGHT) - { - gint xi, yi; - - xi = x; - yi = y; - - while (xi < (x + width - 3)) - { - gdk_cairo_set_source_rgba (cr, &lighter); - add_path_line (cr, xi, y + height, x + width, yi); - cairo_stroke (cr); - - ++xi; - ++yi; - - gdk_cairo_set_source_rgba (cr, &darker); - add_path_line (cr, xi, y + height, x + width, yi); - cairo_stroke (cr); - - ++xi; - ++yi; - - add_path_line (cr, xi, y + height, x + width, yi); - cairo_stroke (cr); - - xi += 3; - yi += 3; - } - } - } - else if (gtk_style_context_has_class (context, GTK_STYLE_CLASS_PANE_SEPARATOR)) - { - if (width > height) - for (xx = x + width / 2 - 15; xx <= x + width / 2 + 15; xx += 5) - render_dot (cr, &lighter, &darker, xx, y + height / 2 - 1, 3); - else - for (yy = y + height / 2 - 15; yy <= y + height / 2 + 15; yy += 5) - render_dot (cr, &lighter, &darker, x + width / 2 - 1, yy, 3); + border_width = MIN (MIN (border.top, border.bottom), + MIN (border.left, border.right)); } else { - for (yy = y; yy < y + height; yy += 3) - for (xx = x; xx < x + width; xx += 6) - { - render_dot (cr, &lighter, &darker, xx, yy, 2); - render_dot (cr, &lighter, &darker, xx + 3, yy + 1, 2); - } + border_width = 0; } - cairo_restore (cr); + cairo_translate (cr, x, y); + + if (gtk_style_context_has_class (context, GTK_STYLE_CLASS_GRIP)) + type = GTK_CSS_IMAGE_BUILTIN_GRIP; + else if (gtk_style_context_has_class (context, GTK_STYLE_CLASS_PANE_SEPARATOR)) + type = GTK_CSS_IMAGE_BUILTIN_PANE_SEPARATOR; + else + type = GTK_CSS_IMAGE_BUILTIN_HANDLE; + + gtk_css_image_builtin_draw (_gtk_css_image_value_get_image (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ICON_SOURCE)), + cr, + width, height, + type, + gtk_style_context_get_state (context), + gtk_style_context_get_junction_sides (context), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)), + border_width); } /** @@ -1672,35 +1175,6 @@ gtk_render_paint_spinner (cairo_t *cr, } static void -render_spinner (GtkStyleContext *context, - cairo_t *cr, - gdouble x, - gdouble y, - gdouble width, - gdouble height) -{ - const GdkRGBA *color; - gdouble radius; - - radius = MIN (width / 2, height / 2); - - color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)); - - cairo_save (cr); - cairo_translate (cr, x + width / 2, y + height / 2); - - _gtk_css_shadows_value_paint_spinner (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ICON_SHADOW), - cr, - radius, - -1); - - gdk_cairo_set_source_rgba (cr, color); - gtk_render_paint_spinner (cr, radius, -1); - - cairo_restore (cr); -} - -static void gtk_do_render_activity (GtkStyleContext *context, cairo_t *cr, gdouble x, @@ -1708,10 +1182,42 @@ gtk_do_render_activity (GtkStyleContext *context, gdouble width, gdouble height) { + GtkBorderStyle border_style; + gint border_width; + if (render_icon_image (context, cr, x, y, width, height)) return; - render_spinner (context, cr, x, y, width, height); + border_style = _gtk_css_border_style_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_STYLE)); + if (border_style == GTK_BORDER_STYLE_SOLID) + { + GtkBorder border; + + border.top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100); + border.right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100); + border.bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100); + border.left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100); + + border_width = MIN (MIN (border.top, border.bottom), + MIN (border.left, border.right)); + } + else + { + border_width = 0; + } + + cairo_translate (cr, x, y); + + gtk_css_image_builtin_draw (_gtk_css_image_value_get_image (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ICON_SOURCE)), + cr, + width, height, + GTK_CSS_IMAGE_BUILTIN_SPINNER, + gtk_style_context_get_state (context), + gtk_style_context_get_junction_sides (context), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR)), + _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_COLOR)), + border_width); } /** |