From 09be868243f6633ed6c8c36e75b1bffb636c8cb5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Dec 2015 14:54:58 -0800 Subject: [PATCH 1/5] Fix an alpha scaling issue in the box shadow shader. --- res/box_shadow.fs.glsl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/res/box_shadow.fs.glsl b/res/box_shadow.fs.glsl index 9d016e0945..33895249bc 100644 --- a/res/box_shadow.fs.glsl +++ b/res/box_shadow.fs.glsl @@ -23,16 +23,17 @@ void main(void) length = range; value = position.x; } else { - length = vBorderRadii.x; + length = range; vec2 center = vec2(max(position.x - range, length), max(position.y - range, length)); - value = distance(position - range, center); + vec2 referencePoint = position - range; + value = distance(referencePoint, center); } float minValue = min(value - range, length) - value; float maxValue = min(value + range, length) - value; if (minValue < maxValue) { - value = 1.0 - 0.5 * (erf(maxValue / sigmaSqrt2) - erf(minValue / sigmaSqrt2)); + value = 1.0 - (erf(maxValue / sigmaSqrt2) - erf(minValue / sigmaSqrt2)); } else { value = 1.0; } From 61d6ad4ec51c4852721a09f4f0634bea39accfe7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Dec 2015 15:08:52 -0800 Subject: [PATCH 2/5] Don't try to fill the center area of a box shadow if the shadow isn't big enough. --- src/batch_builder.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/batch_builder.rs b/src/batch_builder.rs index 045a6c4a2e..8108bef757 100644 --- a/src/batch_builder.rs +++ b/src/batch_builder.rs @@ -549,17 +549,22 @@ impl<'a> BatchBuilder<'a> { BoxShadowClipMode::Outset => { // Fill the center area. let metrics = BoxShadowMetrics::new(&rect, border_radius, blur_radius); - let center_rect = Rect::new(metrics.tl_inner, - Size2D::new(metrics.br_inner.x - metrics.tl_inner.x, - metrics.br_inner.y - metrics.tl_inner.y)); - let mut clip = *clip; - clip.clip_out(&ComplexClipRegion::from_rect(&box_bounds)); - self.add_color_rectangle(matrix_index, - ¢er_rect, - &clip, - resource_cache, - clip_buffers, - color); + if metrics.br_inner.x > metrics.tl_inner.x && + metrics.br_inner.y > metrics.tl_inner.y { + let center_rect = + Rect::new(metrics.tl_inner, + Size2D::new(metrics.br_inner.x - metrics.tl_inner.x, + metrics.br_inner.y - metrics.tl_inner.y)); + let mut clip = *clip; + clip.clip_out(&ComplexClipRegion::new(*box_bounds, + BorderRadius::uniform(border_radius))); + self.add_color_rectangle(matrix_index, + ¢er_rect, + &clip, + resource_cache, + clip_buffers, + color); + } } BoxShadowClipMode::Inset => { // Fill in the outsides. From 67194a53aecb49acd30949da5a52c7dc214806df Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Dec 2015 15:16:29 -0800 Subject: [PATCH 3/5] Stop trying to render box shadow edges if they have zero size. --- src/batch_builder.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/batch_builder.rs b/src/batch_builder.rs index 8108bef757..4b6d684a45 100644 --- a/src/batch_builder.rs +++ b/src/batch_builder.rs @@ -1372,6 +1372,10 @@ impl<'a> BatchBuilder<'a> { resource_cache: &ResourceCache, clip_buffers: &mut ClipBuffers, rotation_angle: BasicRotationAngle) { + if top_left.x >= bottom_right.x || top_left.y >= bottom_right.y { + return + } + let inverted = match clip_mode { BoxShadowClipMode::Outset | BoxShadowClipMode::None => false, BoxShadowClipMode::Inset => true, From 8bd300b5f7a8cca6de9aca29743d6c38e0ac1efd Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Dec 2015 15:13:03 -0800 Subject: [PATCH 4/5] Take the border-radius into account when computing the clip region for outset box shadow corners. Border radii are currently ignored for clip-out operations, so this isn't sufficient to actually render them, but it'll help once the clipper is upgraded to support those. --- src/batch_builder.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/batch_builder.rs b/src/batch_builder.rs index 4b6d684a45..06eee2740e 100644 --- a/src/batch_builder.rs +++ b/src/batch_builder.rs @@ -845,9 +845,8 @@ impl<'a> BatchBuilder<'a> { }); } BoxShadowClipMode::Outset => { - // TODO(pcwalton): Support border radii here too, once we have inverted rounded - // rect clip masks. - clip.clip_out(&ComplexClipRegion::from_rect(box_bounds)); + clip.clip_out(&ComplexClipRegion::new(*box_bounds, + BorderRadius::uniform(border_radius))); } } clip From 53c94411f11e00eef847abbbf19c4a83c63f925c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Dec 2015 15:11:30 -0800 Subject: [PATCH 5/5] Prevent overlap of box shadow corners when the size of the blur is larger than the size of the box. This isn't sufficient to render them correctly, because proper rendering in this case needs a separate shader (or at least modifications to the one we currently use). But it improves the look a lot. --- src/batch_builder.rs | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/batch_builder.rs b/src/batch_builder.rs index 06eee2740e..3bee801486 100644 --- a/src/batch_builder.rs +++ b/src/batch_builder.rs @@ -609,52 +609,65 @@ impl<'a> BatchBuilder<'a> { let rect = compute_box_shadow_rect(box_bounds, box_offset, spread_radius); let metrics = BoxShadowMetrics::new(&rect, border_radius, blur_radius); - let clip = self.adjust_clip_for_box_shadow_clip_mode(clip, - box_bounds, - border_radius, - clip_mode); + let mut clip = self.adjust_clip_for_box_shadow_clip_mode(clip, + box_bounds, + border_radius, + clip_mode); + + // Prevent overlap of the box shadow corners when the size of the blur is larger than the + // size of the box. + let center = Point2D::new(box_bounds.origin.x + box_bounds.size.width / 2.0, + box_bounds.origin.y + box_bounds.size.height / 2.0); self.add_box_shadow_corner(matrix_index, &metrics.tl_outer, &metrics.tl_inner, + &metrics.tl_outer, + ¢er, &color, blur_radius, border_radius, clip_mode, - &clip, + &mut clip, resource_cache, clip_buffers, BasicRotationAngle::Upright); self.add_box_shadow_corner(matrix_index, &Point2D::new(metrics.tr_inner.x, metrics.tr_outer.y), &Point2D::new(metrics.tr_outer.x, metrics.tr_inner.y), + &Point2D::new(center.x, metrics.tr_outer.y), + &Point2D::new(metrics.tr_outer.x, center.y), &color, blur_radius, border_radius, clip_mode, - &clip, + &mut clip, resource_cache, clip_buffers, BasicRotationAngle::Clockwise90); self.add_box_shadow_corner(matrix_index, &metrics.br_inner, &metrics.br_outer, + ¢er, + &metrics.br_outer, &color, blur_radius, border_radius, clip_mode, - &clip, + &mut clip, resource_cache, clip_buffers, BasicRotationAngle::Clockwise180); self.add_box_shadow_corner(matrix_index, &Point2D::new(metrics.bl_outer.x, metrics.bl_inner.y), &Point2D::new(metrics.bl_inner.x, metrics.bl_outer.y), + &Point2D::new(metrics.bl_outer.x, center.y), + &Point2D::new(center.x, metrics.bl_outer.y), &color, blur_radius, border_radius, clip_mode, - &clip, + &mut clip, resource_cache, clip_buffers, BasicRotationAngle::Clockwise270); @@ -1324,14 +1337,23 @@ impl<'a> BatchBuilder<'a> { matrix_index: MatrixIndex, top_left: &Point2D, bottom_right: &Point2D, + corner_area_top_left: &Point2D, + corner_area_bottom_right: &Point2D, color: &ColorF, blur_radius: f32, border_radius: f32, clip_mode: BoxShadowClipMode, - clip: &CombinedClipRegion, + clip: &mut CombinedClipRegion, resource_cache: &ResourceCache, clip_buffers: &mut ClipBuffers, rotation_angle: BasicRotationAngle) { + let corner_area_rect = + Rect::new(*corner_area_top_left, + Size2D::new(corner_area_bottom_right.x - corner_area_top_left.x, + corner_area_bottom_right.y - corner_area_top_left.y)); + let old_clip_in_rect = clip.clip_in_rect; + clip.clip_in_rect(&corner_area_rect); + let inverted = match clip_mode { BoxShadowClipMode::Outset | BoxShadowClipMode::None => false, BoxShadowClipMode::Inset => true, @@ -1356,7 +1378,9 @@ impl<'a> BatchBuilder<'a> { &color_image, resource_cache, clip_buffers, - rotation_angle) + rotation_angle); + + clip.clip_in_rect = old_clip_in_rect } fn add_box_shadow_edge(&mut self,