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; } diff --git a/src/batch_builder.rs b/src/batch_builder.rs index 045a6c4a2e..3bee801486 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. @@ -604,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); @@ -840,9 +858,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 @@ -1320,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, @@ -1352,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, @@ -1367,6 +1395,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,