summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2015-01-18 20:24:27 +0100
committerBenjamin Otte <otte@redhat.com>2015-01-20 06:30:19 +0100
commit1c3dd5d46bd2e33bc7bf43b28d9c57c69a1199dd (patch)
tree92a25cec00c67870622b0df332f2b98faf9facba
parentebb64c2288aff6bd70d349771cc564d36b2f27b0 (diff)
downloadgtk+-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.c794
-rw-r--r--gtk/gtkcssimagebuiltinprivate.h25
-rw-r--r--gtk/gtkrender.c818
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);
}
/**