st/theme-node-drawing: Trace the correct path for inset box shadows
Previously we just copied the outer path and scaled it down, but that resulted in an inconsistent thickness at the corners because the pivot points for the arcs also moved inward. So now we trace the inset path explicitly to maintain the correct thickness (spread) around all the corners. The spec actually mentions you need to do it in section 6.1 [1]: > Note that for inner shadows, expanding the shadow (creating more > shadow area) means contracting the shadow’s perimeter shape. Despite the fact the example diagram gets it wrong in section 6.1.1 [2], it does then follow with more confirmation that the shadow radius should be reduced: > To preserve the box’s shape when spread is applied, the corner radii > of the shadow are also increased (decreased, for inner shadows) from > the border-box (padding-box) radii by adding (subtracting) the spread > distance (and flooring at zero). [1] https://www.w3.org/TR/css-backgrounds-3/#box-shadow [2] https://www.w3.org/TR/css-backgrounds-3/#shadow-shape Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7913 Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3488>
This commit is contained in:
parent
934dbe5495
commit
dde13b30c7
@ -909,6 +909,7 @@ static void
|
||||
paint_inset_box_shadow_to_cairo_context (StThemeNode *node,
|
||||
StShadow *shadow_spec,
|
||||
float resource_scale,
|
||||
const guint outer_radius[4],
|
||||
cairo_t *cr,
|
||||
cairo_path_t *shadow_outline)
|
||||
{
|
||||
@ -952,10 +953,6 @@ paint_inset_box_shadow_to_cairo_context (StThemeNode *node,
|
||||
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;
|
||||
double y_center = (extents_y1 + extents_y2) / 2;
|
||||
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_t *temp_cr;
|
||||
cairo_matrix_t matrix;
|
||||
@ -970,14 +967,67 @@ paint_inset_box_shadow_to_cairo_context (StThemeNode *node,
|
||||
/* Shadow offset */
|
||||
cairo_translate (temp_cr, shadow_spec->xoffset, shadow_spec->yoffset);
|
||||
|
||||
/* Scale the path around the center to match the shrunk bounds */
|
||||
cairo_translate (temp_cr, x_center, y_center);
|
||||
cairo_scale (temp_cr,
|
||||
(shrunk_extents_x2 - shrunk_extents_x1) / (extents_x2 - extents_x1),
|
||||
(shrunk_extents_y2 - shrunk_extents_y1) / (extents_y2 - extents_y1));
|
||||
cairo_translate (temp_cr, - x_center, - y_center);
|
||||
cairo_new_path (temp_cr);
|
||||
|
||||
int inner_radius;
|
||||
|
||||
inner_radius = MAX (0, outer_radius[ST_CORNER_TOPLEFT] - shadow_spec->spread);
|
||||
if (inner_radius > 0)
|
||||
{
|
||||
cairo_arc (temp_cr,
|
||||
shrunk_extents_x1 + inner_radius,
|
||||
shrunk_extents_y1 + inner_radius,
|
||||
inner_radius,
|
||||
M_PI, 3 * M_PI / 2);
|
||||
}
|
||||
|
||||
inner_radius = MAX (0, outer_radius[ST_CORNER_TOPRIGHT] - shadow_spec->spread);
|
||||
|
||||
cairo_line_to (temp_cr,
|
||||
shrunk_extents_x2 - inner_radius,
|
||||
shrunk_extents_y1);
|
||||
|
||||
if (inner_radius > 0)
|
||||
{
|
||||
cairo_arc (temp_cr,
|
||||
shrunk_extents_x2 - inner_radius,
|
||||
shrunk_extents_y1 + inner_radius,
|
||||
inner_radius,
|
||||
3 * M_PI / 2, 0);
|
||||
}
|
||||
|
||||
inner_radius = MAX (0, outer_radius[ST_CORNER_BOTTOMRIGHT] - shadow_spec->spread);
|
||||
|
||||
cairo_line_to (temp_cr,
|
||||
shrunk_extents_x2,
|
||||
shrunk_extents_y2 - inner_radius);
|
||||
|
||||
if (inner_radius > 0)
|
||||
{
|
||||
cairo_arc (temp_cr,
|
||||
shrunk_extents_x2 - inner_radius,
|
||||
shrunk_extents_y2 - inner_radius,
|
||||
inner_radius,
|
||||
0, M_PI / 2);
|
||||
}
|
||||
|
||||
inner_radius = MAX (0, outer_radius[ST_CORNER_BOTTOMLEFT] - shadow_spec->spread);
|
||||
|
||||
cairo_line_to (temp_cr,
|
||||
shrunk_extents_x1 + inner_radius,
|
||||
shrunk_extents_y2);
|
||||
|
||||
if (inner_radius > 0)
|
||||
{
|
||||
cairo_arc (temp_cr,
|
||||
shrunk_extents_x1 + inner_radius,
|
||||
shrunk_extents_y2 - inner_radius,
|
||||
inner_radius,
|
||||
M_PI / 2, M_PI);
|
||||
}
|
||||
|
||||
cairo_close_path (temp_cr);
|
||||
|
||||
cairo_append_path (temp_cr, shadow_outline);
|
||||
cairo_fill (temp_cr);
|
||||
cairo_destroy (temp_cr);
|
||||
|
||||
@ -1330,6 +1380,7 @@ st_theme_node_prerender_background (StThemeNode *node,
|
||||
paint_inset_box_shadow_to_cairo_context (node,
|
||||
box_shadow_spec,
|
||||
resource_scale,
|
||||
radius,
|
||||
cr,
|
||||
interior_path ? interior_path
|
||||
: outline_path);
|
||||
|
Loading…
x
Reference in New Issue
Block a user