StThemeNodeDrawing: generalize render_gradient to render_background_with_border

A lot of the border drawing logic in st_theme_node_render_gradient is
applicable to other non-solid background types than gradients.

This commit refactors that code so that support for other non-solid
background types can be more easily integrated later.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
This commit is contained in:
Ray Strode 2010-12-12 15:41:41 -05:00
parent 2b6d4ff279
commit a7fa7d748d

View File

@ -451,15 +451,54 @@ st_theme_node_has_visible_outline (StThemeNode *node)
return FALSE; return FALSE;
} }
static cairo_pattern_t *
create_cairo_pattern_of_background_gradient (StThemeNode *node)
{
cairo_pattern_t *pattern;
g_return_val_if_fail (node->background_gradient_type != ST_GRADIENT_NONE,
NULL);
if (node->background_gradient_type == ST_GRADIENT_VERTICAL)
pattern = cairo_pattern_create_linear (0, 0, 0, node->alloc_height);
else if (node->background_gradient_type == ST_GRADIENT_HORIZONTAL)
pattern = cairo_pattern_create_linear (0, 0, node->alloc_width, 0);
else
{
gdouble cx, cy;
cx = node->alloc_width / 2.;
cy = node->alloc_height / 2.;
pattern = cairo_pattern_create_radial (cx, cy, 0, cx, cy, MIN (cx, cy));
}
cairo_pattern_add_color_stop_rgba (pattern, 0,
node->background_color.red / 255.,
node->background_color.green / 255.,
node->background_color.blue / 255.,
node->background_color.alpha / 255.);
cairo_pattern_add_color_stop_rgba (pattern, 1,
node->background_gradient_end.red / 255.,
node->background_gradient_end.green / 255.,
node->background_gradient_end.blue / 255.,
node->background_gradient_end.alpha / 255.);
return pattern;
}
/* In order for borders to be smoothly blended with non-solid backgrounds,
* we need to use cairo. This function is a slow fallback path for those
* cases. It currently only supports gradients, however.
*/
static CoglHandle static CoglHandle
st_theme_node_render_gradient (StThemeNode *node) st_theme_node_render_background_with_border (StThemeNode *node)
{ {
StBorderImage *border_image; StBorderImage *border_image;
CoglHandle texture; CoglHandle texture;
int radius[4], i; int radius[4], i;
cairo_t *cr; cairo_t *cr;
cairo_surface_t *surface; cairo_surface_t *surface;
cairo_pattern_t *pattern; cairo_pattern_t *pattern = NULL;
gboolean draw_solid_background;
ClutterColor border_color; ClutterColor border_color;
int border_width[4]; int border_width[4];
guint rowstride; guint rowstride;
@ -486,30 +525,17 @@ st_theme_node_render_gradient (StThemeNode *node)
radius[i] = st_theme_node_get_border_radius (node, i); radius[i] = st_theme_node_get_border_radius (node, i);
} }
if (node->background_gradient_type == ST_GRADIENT_VERTICAL) if (node->background_gradient_type != ST_GRADIENT_NONE)
pattern = cairo_pattern_create_linear (0, 0, 0, node->alloc_height); {
else if (node->background_gradient_type == ST_GRADIENT_HORIZONTAL) pattern = create_cairo_pattern_of_background_gradient (node);
pattern = cairo_pattern_create_linear (0, 0, node->alloc_width, 0); draw_solid_background = FALSE;
}
else else
{ {
gdouble cx, cy; g_warning ("st_theme_node_render_background_with_border called with non-gradient background (which isn't yet supported). Falling back to solid background color.");
draw_solid_background = TRUE;
cx = node->alloc_width / 2.;
cy = node->alloc_height / 2.;
pattern = cairo_pattern_create_radial (cx, cy, 0, cx, cy, MIN (cx, cy));
} }
cairo_pattern_add_color_stop_rgba (pattern, 0,
node->background_color.red / 255.,
node->background_color.green / 255.,
node->background_color.blue / 255.,
node->background_color.alpha / 255.);
cairo_pattern_add_color_stop_rgba (pattern, 1,
node->background_gradient_end.red / 255.,
node->background_gradient_end.green / 255.,
node->background_gradient_end.blue / 255.,
node->background_gradient_end.alpha / 255.);
/* Create a path for the background's outline first */ /* Create a path for the background's outline first */
if (radius[ST_CORNER_TOPLEFT] > 0) if (radius[ST_CORNER_TOPLEFT] > 0)
cairo_arc (cr, cairo_arc (cr,
@ -538,11 +564,10 @@ st_theme_node_render_gradient (StThemeNode *node)
radius[ST_CORNER_BOTTOMLEFT], M_PI / 2, M_PI); radius[ST_CORNER_BOTTOMLEFT], M_PI / 2, M_PI);
cairo_close_path (cr); cairo_close_path (cr);
/* If we have a solid border, we fill the outline shape with the border
/* If we have a solid border, we fill the outline with the border * color and create the inline shape for the background;
* color and create the inline shape for the background gradient;
* otherwise the outline shape is filled with the background * otherwise the outline shape is filled with the background
* gradient directly * directly
*/ */
if (border_image == NULL && if (border_image == NULL &&
(border_width[ST_SIDE_TOP] > 0 || (border_width[ST_SIDE_TOP] > 0 ||
@ -624,10 +649,22 @@ st_theme_node_render_gradient (StThemeNode *node)
cairo_close_path (cr); cairo_close_path (cr);
} }
cairo_set_source (cr, pattern); if (draw_solid_background)
cairo_fill (cr); {
cairo_set_source_rgba (cr,
node->background_color.red / 255.,
node->background_color.green / 255.,
node->background_color.blue / 255.,
node->background_color.alpha / 255.);
cairo_fill_preserve (cr);
}
cairo_pattern_destroy (pattern); if (pattern != NULL)
{
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
}
texture = cogl_texture_new_from_data (node->alloc_width, node->alloc_height, texture = cogl_texture_new_from_data (node->alloc_width, node->alloc_height,
COGL_TEXTURE_NONE, COGL_TEXTURE_NONE,
@ -741,7 +778,7 @@ st_theme_node_render_resources (StThemeNode *node,
} }
if (node->background_gradient_type != ST_GRADIENT_NONE) if (node->background_gradient_type != ST_GRADIENT_NONE)
node->prerendered_texture = st_theme_node_render_gradient (node); node->prerendered_texture = st_theme_node_render_background_with_border (node);
if (node->border_slices_texture) if (node->border_slices_texture)
node->border_slices_material = _st_create_texture_material (node->border_slices_texture); node->border_slices_material = _st_create_texture_material (node->border_slices_texture);