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.
This commit is contained in:
Benjamin Otte 2015-01-18 20:24:27 +01:00
parent ebb64c2288
commit 1c3dd5d46b
3 changed files with 977 additions and 662 deletions

View File

@ -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;
}
}

View File

@ -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__ */

View File

@ -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;
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_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);
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);
}
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);
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_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_translate (cr, - size / 2.0, - size / 2.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);
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));
is_rtl = (gtk_style_context_get_state (context) & GTK_STATE_FLAG_DIR_RTL);
line_width = 1;
progress = (flags & GTK_STATE_FLAG_CHECKED) ? 1 : 0;
if (!gtk_style_context_has_class (context, GTK_STYLE_CLASS_HORIZONTAL))
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)
{
if (is_rtl)
angle = (G_PI) - ((G_PI / 2) * progress);
else
angle = (G_PI / 2) * progress;
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
{
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;
cairo_translate (cr, x, y);
/* 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_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);
}
/**
@ -1227,62 +1026,6 @@ gtk_render_extension (GtkStyleContext *context,
cairo_restore (cr);
}
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,
@ -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;
GtkBorder border;
if ((sides & (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMLEFT)) == (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMLEFT))
sides &= ~GTK_JUNCTION_CORNER_TOPRIGHT;
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 (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;
gdk_cairo_set_source_rgba (cr, &darker);
add_path_line (cr, xi, y, x + width, yi);
cairo_stroke (cr);
++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);
}
/**
@ -1671,35 +1174,6 @@ gtk_render_paint_spinner (cairo_t *cr,
cairo_restore (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,
@ -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);
}
/**