[gnome-shell] st: Use scaled surfaces for creating cairo background shadows
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] st: Use scaled surfaces for creating cairo background shadows
- Date: Fri, 1 Mar 2019 18:07:14 +0000 (UTC)
commit 5617ffc79ceb3acb291332879cbbe161cea0a316
Author: Marco Trevisan (Treviño) <mail 3v1n0 net>
Date: Mon Feb 25 13:45:02 2019 +0100
st: Use scaled surfaces for creating cairo background shadows
Create the surfaces for background shadows at scaled sizes and then draw on them
using logical coordinates, by setting the surface device scale accordingly.
Use the said surface scale when generating the actual shadow cairo pattern
but in such case, to reduce the number of code changes, is better to work in
absolute coordinates, and to do so:
1) Create a temporary shadow-spec copy with scaled values to absolute sizes
2) Invert the scaling on the shadow matrix
3) Do the actual painting in absolute coordinates
4) Set the shadow matrix scaling back to the logical coordinates.
Finally scale down the created shadow pattern surface size when painting it,
applying again a reverse scale to the matrix.
https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5
src/st/st-private.c | 39 +++++++++++++++++++++++++++++++++++++--
src/st/st-theme-node-drawing.c | 19 +++++++++++++++----
2 files changed, 52 insertions(+), 6 deletions(-)
---
diff --git a/src/st/st-private.c b/src/st/st-private.c
index 688b17b78..a74368709 100644
--- a/src/st/st-private.c
+++ b/src/st/st-private.c
@@ -536,9 +536,10 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
* the offset.
*/
cairo_pattern_t *
-_st_create_shadow_cairo_pattern (StShadow *shadow_spec,
+_st_create_shadow_cairo_pattern (StShadow *shadow_spec_in,
cairo_pattern_t *src_pattern)
{
+ g_autoptr(StShadow) shadow_spec = NULL;
static cairo_user_data_key_t shadow_pattern_user_data;
cairo_t *cr;
cairo_surface_t *src_surface;
@@ -549,9 +550,10 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
gint width_in, height_in, rowstride_in;
gint width_out, height_out, rowstride_out;
cairo_matrix_t shadow_matrix;
+ double xscale_in, yscale_in;
int i, j;
- g_return_val_if_fail (shadow_spec != NULL, NULL);
+ g_return_val_if_fail (shadow_spec_in != NULL, NULL);
g_return_val_if_fail (src_pattern != NULL, NULL);
if (cairo_pattern_get_surface (src_pattern, &src_surface) != CAIRO_STATUS_SUCCESS)
@@ -564,6 +566,25 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
width_in = cairo_image_surface_get_width (src_surface);
height_in = cairo_image_surface_get_height (src_surface);
+ cairo_surface_get_device_scale (src_surface, &xscale_in, &yscale_in);
+
+ if (xscale_in != 1.0 || yscale_in != 1.0)
+ {
+ /* Scale the shadow specifications in a temporary copy so that
+ * we can work everywhere in absolute surface coordinates */
+ double scale = (xscale_in + yscale_in) / 2.0;
+ shadow_spec = st_shadow_new (&shadow_spec_in->color,
+ shadow_spec_in->xoffset * xscale_in,
+ shadow_spec_in->yoffset * yscale_in,
+ shadow_spec_in->blur * scale,
+ shadow_spec_in->spread * scale,
+ shadow_spec_in->inset);
+ }
+ else
+ {
+ shadow_spec = st_shadow_ref (shadow_spec_in);
+ }
+
/* We want the output to be a color agnostic alpha mask,
* so we need to strip the color channels from the input
*/
@@ -606,6 +627,7 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
width_out,
height_out,
rowstride_out);
+ cairo_surface_set_device_scale (surface_out, xscale_in, yscale_in);
cairo_surface_set_user_data (surface_out, &shadow_pattern_user_data,
pixels_out, (cairo_destroy_func_t) g_free);
@@ -616,6 +638,9 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
if (shadow_spec->inset)
{
+ /* Scale the matrix in surface absolute coordinates */
+ cairo_matrix_scale (&shadow_matrix, 1.0 / xscale_in, 1.0 / yscale_in);
+
/* For inset shadows, offsets and spread radius have already been
* applied to the original pattern, so all left to do is shift the
* blurred image left, so that it aligns centered under the
@@ -624,6 +649,10 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
cairo_matrix_translate (&shadow_matrix,
(width_out - width_in) / 2.0,
(height_out - height_in) / 2.0);
+
+ /* Scale back the matrix in original coordinates */
+ cairo_matrix_scale (&shadow_matrix, xscale_in, yscale_in);
+
cairo_pattern_set_matrix (dst_pattern, &shadow_matrix);
return dst_pattern;
}
@@ -636,6 +665,9 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
/* 6. Invert the matrix back */
cairo_matrix_invert (&shadow_matrix);
+ /* Scale the matrix in surface absolute coordinates */
+ cairo_matrix_scale (&shadow_matrix, 1.0 / xscale_in, 1.0 / yscale_in);
+
/* 5. Adjust based on specified offsets */
cairo_matrix_translate (&shadow_matrix,
shadow_spec->xoffset,
@@ -657,6 +689,9 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
- (width_out - width_in) / 2.0,
- (height_out - height_in) / 2.0);
+ /* Scale back the matrix in scaled coordinates */
+ cairo_matrix_scale (&shadow_matrix, xscale_in, yscale_in);
+
/* 1. Invert the matrix so we can work with it in pattern space
*/
cairo_matrix_invert (&shadow_matrix);
diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c
index a94253f4e..7db928a0d 100644
--- a/src/st/st-theme-node-drawing.c
+++ b/src/st/st-theme-node-drawing.c
@@ -759,6 +759,7 @@ paint_shadow_pattern_to_cairo_context (StShadow *shadow_spec,
{
cairo_surface_t *surface;
int width, height;
+ double xscale, yscale;
cairo_matrix_t matrix;
cairo_save (cr);
@@ -775,11 +776,13 @@ paint_shadow_pattern_to_cairo_context (StShadow *shadow_spec,
/* Something went wrong previously */
goto no_surface;
+ cairo_surface_get_device_scale (surface, &xscale, &yscale);
width = cairo_image_surface_get_width (surface);
height = cairo_image_surface_get_height (surface);
cairo_pattern_get_matrix (pattern, &matrix);
cairo_matrix_invert (&matrix);
+ cairo_matrix_scale (&matrix, 1.0 / xscale, 1.0 / yscale);
cairo_transform (cr, &matrix);
cairo_rectangle (cr, 0, height, width, - height);
@@ -803,7 +806,8 @@ paint_background_image_shadow_to_cairo_context (StThemeNode *node,
int x,
int y,
int width,
- int height)
+ int height,
+ float resource_scale)
{
cairo_pattern_t *shadow_pattern;
@@ -819,7 +823,10 @@ paint_background_image_shadow_to_cairo_context (StThemeNode *node,
/* Prerender the pattern to a temporary surface,
* so it's properly clipped before we create a shadow from it
*/
+ width = ceilf (width * resource_scale);
+ height = ceilf (height * resource_scale);
clipped_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ cairo_surface_set_device_scale (clipped_surface, resource_scale, resource_scale);
temp_cr = cairo_create (clipped_surface);
cairo_set_operator (temp_cr, CAIRO_OPERATOR_CLEAR);
@@ -883,6 +890,7 @@ path_extents (cairo_path_t *path,
static void
paint_inset_box_shadow_to_cairo_context (StThemeNode *node,
StShadow *shadow_spec,
+ float resource_scale,
cairo_t *cr,
cairo_path_t *shadow_outline)
{
@@ -923,8 +931,8 @@ paint_inset_box_shadow_to_cairo_context (StThemeNode *node,
/* Bounds of temporary surface */
int surface_x = floor (shrunk_extents_x1);
int surface_y = floor (shrunk_extents_y1);
- int surface_width = ceil (shrunk_extents_x2) - surface_x;
- int surface_height = ceil (shrunk_extents_y2) - surface_y;
+ int surface_width = ceil ((shrunk_extents_x2 - surface_x) * resource_scale);
+ int surface_height = ceil ((shrunk_extents_y2 - surface_y) * resource_scale);
/* Center of the original path */
double x_center = (extents_x1 + extents_x2) / 2;
@@ -935,6 +943,7 @@ paint_inset_box_shadow_to_cairo_context (StThemeNode *node,
cairo_matrix_t matrix;
shadow_surface = cairo_image_surface_create (CAIRO_FORMAT_A8, surface_width, surface_height);
+ cairo_surface_set_device_scale (shadow_surface, resource_scale, resource_scale);
temp_cr = cairo_create (shadow_surface);
/* Match the coordinates in the temporary context to the parent context */
@@ -1284,7 +1293,8 @@ st_theme_node_prerender_background (StThemeNode *node,
has_visible_outline? outline_path : NULL,
actor_box.x1,
actor_box.y1,
- width, height);
+ width, height,
+ resource_scale);
cairo_append_path (cr, outline_path);
}
@@ -1301,6 +1311,7 @@ st_theme_node_prerender_background (StThemeNode *node,
{
paint_inset_box_shadow_to_cairo_context (node,
box_shadow_spec,
+ resource_scale,
cr,
interior_path ? interior_path
: outline_path);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]