On Wed, 29 Oct 2014 14:51:23 +0100 Marek Chalupa <mchqwe...@gmail.com> wrote:
> If the client is small (< 128 pixels in any ward), > then the shadows overlap and create dark lines behind clients. > This is a problem mosly with pop-up menues. The lines become observable > when the menu has less than three items. The other case is when > the client doesn't restrict its size when resizing (try > 'weston-eventdemo --max-width=1 --max-height=1' for example) > > This fixes a part of the bug: > https://bugs.freedesktop.org/show_bug.cgi?id=78511 > > v2: > - rework computing of the size of corners > - rewrite some comments > - rename tile_mask to render_shadow (in separate patch) > > Signed-off-by: Marek Chalupa <mchqwe...@gmail.com> > --- > shared/cairo-util.c | 129 > +++++++++++++++++++++++++++++++++------------------- > 1 file changed, 83 insertions(+), 46 deletions(-) > > diff --git a/shared/cairo-util.c b/shared/cairo-util.c > index 73e3ae7..a73c08b 100644 > --- a/shared/cairo-util.c > +++ b/shared/cairo-util.c > @@ -142,7 +142,7 @@ render_shadow(cairo_t *cr, cairo_surface_t *surface, > { > cairo_pattern_t *pattern; > cairo_matrix_t matrix; > - int i, fx, fy, vmargin; > + int i, fx, fy, shadow_height, shadow_width; > > cairo_set_source_rgba(cr, 0, 0, 0, 0.45); > cairo_set_operator(cr, CAIRO_OPERATOR_OVER); > @@ -150,6 +150,14 @@ render_shadow(cairo_t *cr, cairo_surface_t *surface, > cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); > > for (i = 0; i < 4; i++) { > + /* when fy is set, then we are working with lower corners, > + * when fx is set, then we are working with right corners > + * > + * 00 ------- 01 > + * | | > + * | | > + * 10 ------- 11 > + */ > fx = i & 1; > fy = i >> 1; > > @@ -158,63 +166,92 @@ render_shadow(cairo_t *cr, cairo_surface_t *surface, > -y + fy * (128 - height)); > cairo_pattern_set_matrix(pattern, &matrix); > > - if (fy) > - vmargin = margin; > - else > - vmargin = top_margin; > + shadow_width = margin; > + shadow_height = fy ? margin : top_margin; > + > + /* if the shadows together are greater than the surface, we need > + * to fix it - set the shadow size to the half of > + * the size of surface. Also handle the case when the size is > + * not divisible by 2. In that case we need one part of the > + * shadow to be one pixel greater. !fy or !fx, respectively, > + * will do the work. > + */ > + if (height < 2 * shadow_height) > + shadow_height = (height + !fy) / 2; > + > + if (width < 2 * shadow_width) > + shadow_width = (width + !fx) / 2; > > cairo_reset_clip(cr); > cairo_rectangle(cr, > - x + fx * (width - margin), > - y + fy * (height - vmargin), > - margin, vmargin); > + x + fx * (width - shadow_width), > + y + fy * (height - shadow_height), > + shadow_width, shadow_height); > cairo_clip (cr); > cairo_mask(cr, pattern); > } > > - /* Top stretch */ > - cairo_matrix_init_translate(&matrix, 60, 0); > - cairo_matrix_scale(&matrix, 8.0 / width, 1); > - cairo_matrix_translate(&matrix, -x - width / 2, -y); > - cairo_pattern_set_matrix(pattern, &matrix); > - cairo_rectangle(cr, x + margin, y, width - 2 * margin, margin); > > - cairo_reset_clip(cr); > - cairo_rectangle(cr, > - x + margin, > - y, > - width - 2 * margin, margin); > - cairo_clip (cr); > - cairo_mask(cr, pattern); > + shadow_width = width - 2 * margin; > + shadow_height = top_margin; > + if (height < 2 * shadow_height) > + shadow_height = height / 2; > > - /* Bottom stretch */ > - cairo_matrix_translate(&matrix, 0, -height + 128); > - cairo_pattern_set_matrix(pattern, &matrix); > + if (shadow_width > 0 && shadow_height) { > + /* Top stretch */ > + cairo_matrix_init_translate(&matrix, 60, 0); > + cairo_matrix_scale(&matrix, 8.0 / width, 1); > + cairo_matrix_translate(&matrix, -x - width / 2, -y); > + cairo_pattern_set_matrix(pattern, &matrix); > + cairo_rectangle(cr, x + margin, y, shadow_width, shadow_height); > > - cairo_reset_clip(cr); > - cairo_rectangle(cr, x + margin, y + height - margin, > - width - 2 * margin, margin); > - cairo_clip (cr); > - cairo_mask(cr, pattern); > + cairo_reset_clip(cr); > + cairo_rectangle(cr, > + x + margin, y, > + shadow_width, shadow_height); > + cairo_clip (cr); > + cairo_mask(cr, pattern); > > - /* Left stretch */ > - cairo_matrix_init_translate(&matrix, 0, 60); > - cairo_matrix_scale(&matrix, 1, 8.0 / height); > - cairo_matrix_translate(&matrix, -x, -y - height / 2); > - cairo_pattern_set_matrix(pattern, &matrix); > - cairo_reset_clip(cr); > - cairo_rectangle(cr, x, y + margin, margin, height - 2 * margin); > - cairo_clip (cr); > - cairo_mask(cr, pattern); > + /* Bottom stretch */ > + cairo_matrix_translate(&matrix, 0, -height + 128); > + cairo_pattern_set_matrix(pattern, &matrix); > > - /* Right stretch */ > - cairo_matrix_translate(&matrix, -width + 128, 0); > - cairo_pattern_set_matrix(pattern, &matrix); > - cairo_rectangle(cr, x + width - margin, y + margin, > - margin, height - 2 * margin); > - cairo_reset_clip(cr); > - cairo_clip (cr); > - cairo_mask(cr, pattern); > + cairo_reset_clip(cr); > + cairo_rectangle(cr, x + margin, y + height - margin, > + shadow_width, margin); > + cairo_clip (cr); > + cairo_mask(cr, pattern); > + } > + > + shadow_width = margin; > + if (width < 2 * shadow_width) > + shadow_width = width / 2; > + > + shadow_height = height - margin - top_margin; > + > + /* if height is smaller than sum of margins, > + * then the shadow is already done by the corners */ > + if (shadow_height > 0 && shadow_width) { > + /* Left stretch */ > + cairo_matrix_init_translate(&matrix, 0, 60); > + cairo_matrix_scale(&matrix, 1, 8.0 / height); > + cairo_matrix_translate(&matrix, -x, -y - height / 2); > + cairo_pattern_set_matrix(pattern, &matrix); > + cairo_reset_clip(cr); > + cairo_rectangle(cr, x, y + top_margin, > + shadow_width, shadow_height); > + cairo_clip (cr); > + cairo_mask(cr, pattern); > + > + /* Right stretch */ > + cairo_matrix_translate(&matrix, -width + 128, 0); > + cairo_pattern_set_matrix(pattern, &matrix); > + cairo_rectangle(cr, x + width - shadow_width, y + top_margin, > + shadow_width, shadow_height); > + cairo_reset_clip(cr); > + cairo_clip (cr); > + cairo_mask(cr, pattern); > + } > > cairo_pattern_destroy(pattern); > cairo_reset_clip(cr); Excellent documentation, both in code and commit message. Pushed, both of them. Thanks, pq _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel