diff --git a/res/box_shadow.fs.glsl b/res/box_shadow.fs.glsl
index 2d83b576f4..4574a293b4 100644
--- a/res/box_shadow.fs.glsl
+++ b/res/box_shadow.fs.glsl
@@ -16,18 +16,26 @@ void main(void)
float sigma = vBlurRadius / 2.0;
float sigmaSqrt2 = sigma * 1.41421356237;
+ float length;
+ float value;
vec2 position = vPosition - vBorderPosition.zw;
- vec2 arcCenter = vDestTextureSize;
- float arcRadius = vBorderRadii.x;
- float distance = distance(position, vec2(arcCenter));
- float value = clamp(distance, arcRadius - vBlurRadius, arcRadius + vBlurRadius);
- float minValue = min(value - range, arcRadius) - value;
- float maxValue = min(value + range, arcRadius) - value;
+ if (vBorderRadii.y == 0.0) {
+ length = range;
+ value = position.x;
+ } else {
+ length = vBorderRadii.x;
+ vec2 center = vec2(max(position.x - range, length),
+ max(position.y - range, length));
+ value = distance(position - range, 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));
} else {
- value = 0.0;
+ value = 1.0;
}
- SetFragColor(vColor - vec4(value));
+ SetFragColor(vec4(vColor.rgb, vColor.a == 0.0 ? value : 1.0 - value));
}
diff --git a/src/clipper.rs b/src/clipper.rs
index 457b6de014..ed0a6fce1f 100644
--- a/src/clipper.rs
+++ b/src/clipper.rs
@@ -1,10 +1,11 @@
use euclid::{Point2D, Rect, Size2D};
-use internal_types::{ClipRectToRegionMaskResult, ClipRectToRegionResult, PolygonPosColorUv};
-use internal_types::{RectPosUv, RectUv, WorkVertex};
+use internal_types::{ClipRectToRegionMaskResult, ClipRectToRegionResult};
+use internal_types::{CombinedClipRegion, PolygonPosColorUv, RectPosUv, RectUv, WorkVertex};
use render_backend::MAX_RECT;
use simd::f32x4;
+use std::fmt::Debug;
use std::mem;
-use types::{BoxShadowClipMode, ClipRegion, ColorF};
+use types::{ColorF, ComplexClipRegion};
use util;
/// Computes whether the point c is inside the clipping edge ab.
@@ -149,183 +150,166 @@ pub fn clip_polygon<'a>(buffers: &'a mut ShClipBuffers,
result
}
-pub fn clip_rect_with_mode
(polygon: P,
- sh_clip_buffers: &mut ShClipBuffers,
- clip_rect: &Rect,
- clip_mode: BoxShadowClipMode,
- output: &mut Vec)
- where P: Polygon {
- match clip_mode {
- BoxShadowClipMode::None => output.push(polygon),
- BoxShadowClipMode::Inset => polygon.clip_to_rect(sh_clip_buffers, clip_rect, output),
- BoxShadowClipMode::Outset => polygon.clip_out_rect(sh_clip_buffers, clip_rect, output),
- }
-}
-
-fn clip_to_region
(polygon: P,
- sh_clip_buffers: &mut ShClipBuffers,
- polygon_scratch: &mut Vec
,
- clip_rect_to_region_result_scratch: &mut Vec>,
- output: &mut Vec>,
- region: &ClipRegion)
- where P: Polygon + Clone {
- polygon_scratch.clear();
- polygon.clip_to_rect(sh_clip_buffers, ®ion.main, polygon_scratch);
- if polygon_scratch.is_empty() {
- return
- }
-
- for main_result in polygon_scratch.drain(..) {
- output.push(ClipRectToRegionResult::new(main_result, None));
- }
+fn clip_to_complex_region(
+ sh_clip_buffers: &mut ShClipBuffers,
+ polygon_scratch: &mut Vec
,
+ clip_rect_to_region_result_scratch: &mut Vec>,
+ output: &mut Vec>,
+ complex_region: &ComplexClipRegion)
+ where P: Polygon + Clone {
+ mem::swap(clip_rect_to_region_result_scratch, output);
+ for intermediate_result in clip_rect_to_region_result_scratch.drain(..) {
+ // Quick rejection:
+ let intermediate_polygon = intermediate_result.rect_result.clone();
+ if !intermediate_polygon.intersects_rect(&complex_region.rect) {
+ continue
+ }
- for complex_region in region.complex.iter() {
- mem::swap(clip_rect_to_region_result_scratch, output);
- for intermediate_result in clip_rect_to_region_result_scratch.drain(..) {
- // Quick rejection:
- let intermediate_polygon = intermediate_result.rect_result.clone();
- if !intermediate_polygon.intersects_rect(&complex_region.rect) {
- continue
- }
+ // FIXME(pcwalton): This is pretty bogus. I guess we should create a region for the
+ // inner area -- which may not be rectangular due to nonequal border radii! -- and use
+ // Sutherland-Hodgman clipping for it.
+ let border_radius =
+ f32::max(f32::max(f32::max(size_max(&complex_region.radii.top_left),
+ size_max(&complex_region.radii.top_right)),
+ size_max(&complex_region.radii.bottom_left)),
+ size_max(&complex_region.radii.bottom_right));
+
+ if border_radius == 0.0 {
+ intermediate_polygon.clip_to_rect(sh_clip_buffers,
+ &complex_region.rect,
+ polygon_scratch);
+ push_results(output, polygon_scratch, None);
+ continue
+ }
- // FIXME(pcwalton): This is pretty bogus. I guess we should create a region for the
- // inner area -- which may not be rectangular due to nonequal border radii! -- and use
- // Sutherland-Hodgman clipping for it.
- let border_radius =
- f32::max(f32::max(f32::max(size_max(&complex_region.radii.top_left),
- size_max(&complex_region.radii.top_right)),
- size_max(&complex_region.radii.bottom_left)),
- size_max(&complex_region.radii.bottom_right));
-
- // Compute the middle intersected region:
- //
- // +--+-----------------+--+
- // | /| |\ |
- // +--+-----------------+--+
- // |#######################|
- // |#######################|
- // |#######################|
- // +--+-----------------+--+
- // | \| |/ |
- // +--+-----------------+--+
- let inner_rect = Rect::new(
- Point2D::new(complex_region.rect.origin.x,
- complex_region.rect.origin.y + border_radius),
- Size2D::new(complex_region.rect.size.width,
- complex_region.rect.size.height - (border_radius + border_radius)));
- if !util::rect_is_empty(&inner_rect) {
- intermediate_polygon.clip_to_rect(sh_clip_buffers, &inner_rect, polygon_scratch);
- push_results(output, polygon_scratch, None);
- }
+ // Compute the middle intersected region:
+ //
+ // +--+-----------------+--+
+ // | /| |\ |
+ // +--+-----------------+--+
+ // |#######################|
+ // |#######################|
+ // |#######################|
+ // +--+-----------------+--+
+ // | \| |/ |
+ // +--+-----------------+--+
+ let inner_rect = Rect::new(
+ Point2D::new(complex_region.rect.origin.x,
+ complex_region.rect.origin.y + border_radius),
+ Size2D::new(complex_region.rect.size.width,
+ complex_region.rect.size.height - (border_radius + border_radius)));
+ if !util::rect_is_empty(&inner_rect) {
+ intermediate_polygon.clip_to_rect(sh_clip_buffers, &inner_rect, polygon_scratch);
+ push_results(output, polygon_scratch, None);
+ }
- // Compute the top region:
- //
- // +--+-----------------+--+
- // | /|#################|\ |
- // +--+-----------------+--+
- // | |
- // | |
- // | |
- // +--+-----------------+--+
- // | \| |/ |
- // +--+-----------------+--+
- let top_rect = Rect::new(
- Point2D::new(complex_region.rect.origin.x + border_radius,
- complex_region.rect.origin.y),
- Size2D::new(complex_region.rect.size.width - (border_radius + border_radius),
- border_radius));
- if !util::rect_is_empty(&top_rect) {
- intermediate_polygon.clip_to_rect(sh_clip_buffers, &top_rect, polygon_scratch);
- push_results(output, polygon_scratch, None);
- }
+ // Compute the top region:
+ //
+ // +--+-----------------+--+
+ // | /|#################|\ |
+ // +--+-----------------+--+
+ // | |
+ // | |
+ // | |
+ // +--+-----------------+--+
+ // | \| |/ |
+ // +--+-----------------+--+
+ let top_rect = Rect::new(
+ Point2D::new(complex_region.rect.origin.x + border_radius,
+ complex_region.rect.origin.y),
+ Size2D::new(complex_region.rect.size.width - (border_radius + border_radius),
+ border_radius));
+ if !util::rect_is_empty(&top_rect) {
+ intermediate_polygon.clip_to_rect(sh_clip_buffers, &top_rect, polygon_scratch);
+ push_results(output, polygon_scratch, None);
+ }
- // Compute the bottom region:
- //
- // +--+-----------------+--+
- // | /| |\ |
- // +--+-----------------+--+
- // | |
- // | |
- // | |
- // +--+-----------------+--+
- // | \|#################|/ |
- // +--+-----------------+--+
- let bottom_rect = Rect::new(
- Point2D::new(complex_region.rect.origin.x + border_radius,
- complex_region.rect.max_y() - border_radius),
- Size2D::new(complex_region.rect.size.width - (border_radius + border_radius),
- border_radius));
- if !util::rect_is_empty(&bottom_rect) {
- intermediate_polygon.clip_to_rect(sh_clip_buffers, &bottom_rect, polygon_scratch);
- push_results(output, polygon_scratch, None);
- }
+ // Compute the bottom region:
+ //
+ // +--+-----------------+--+
+ // | /| |\ |
+ // +--+-----------------+--+
+ // | |
+ // | |
+ // | |
+ // +--+-----------------+--+
+ // | \|#################|/ |
+ // +--+-----------------+--+
+ let bottom_rect = Rect::new(
+ Point2D::new(complex_region.rect.origin.x + border_radius,
+ complex_region.rect.max_y() - border_radius),
+ Size2D::new(complex_region.rect.size.width - (border_radius + border_radius),
+ border_radius));
+ if !util::rect_is_empty(&bottom_rect) {
+ intermediate_polygon.clip_to_rect(sh_clip_buffers, &bottom_rect, polygon_scratch);
+ push_results(output, polygon_scratch, None);
+ }
- // Now for the corners:
- //
- // +--+-----------------+--+
- // A | /| |\ | B
- // +--+-----------------+--+
- // | |
- // | |
- // | |
- // +--+-----------------+--+
- // C | \| |/ | D
- // +--+-----------------+--+
- //
- // FIXME(pcwalton): This should clip the mask u and v properly too. For now we just
- // blindly assume that the border was not clipped.
-
- // Compute A:
- let mut corner_rect = Rect::new(complex_region.rect.origin,
- Size2D::new(border_radius, border_radius));
- if !util::rect_is_empty(&corner_rect) {
- let mask_rect = Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1.0, 1.0));
- intermediate_polygon.clip_to_rect(sh_clip_buffers, &corner_rect, polygon_scratch);
- push_results(output,
- polygon_scratch,
- Some(ClipRectToRegionMaskResult::new(&mask_rect,
- &corner_rect,
- border_radius)))
- }
+ // Now for the corners:
+ //
+ // +--+-----------------+--+
+ // A | /| |\ | B
+ // +--+-----------------+--+
+ // | |
+ // | |
+ // | |
+ // +--+-----------------+--+
+ // C | \| |/ | D
+ // +--+-----------------+--+
+ //
+ // FIXME(pcwalton): This should clip the mask u and v properly too. For now we just
+ // blindly assume that the border was not clipped.
+
+ // Compute A:
+ let mut corner_rect = Rect::new(complex_region.rect.origin,
+ Size2D::new(border_radius, border_radius));
+ if !util::rect_is_empty(&corner_rect) {
+ let mask_rect = Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1.0, 1.0));
+ intermediate_polygon.clip_to_rect(sh_clip_buffers, &corner_rect, polygon_scratch);
+ push_results(output,
+ polygon_scratch,
+ Some(ClipRectToRegionMaskResult::new(&mask_rect,
+ &corner_rect,
+ border_radius)))
+ }
- // B:
- corner_rect.origin = Point2D::new(complex_region.rect.max_x() - border_radius,
- complex_region.rect.origin.y);
- if !util::rect_is_empty(&corner_rect) {
- intermediate_polygon.clip_to_rect(sh_clip_buffers, &corner_rect, polygon_scratch);
- let mask_rect = Rect::new(Point2D::new(1.0, 0.0), Size2D::new(-1.0, 1.0));
- push_results(output,
- polygon_scratch,
- Some(ClipRectToRegionMaskResult::new(&mask_rect,
- &corner_rect,
- border_radius)))
- }
+ // B:
+ corner_rect.origin = Point2D::new(complex_region.rect.max_x() - border_radius,
+ complex_region.rect.origin.y);
+ if !util::rect_is_empty(&corner_rect) {
+ intermediate_polygon.clip_to_rect(sh_clip_buffers, &corner_rect, polygon_scratch);
+ let mask_rect = Rect::new(Point2D::new(1.0, 0.0), Size2D::new(-1.0, 1.0));
+ push_results(output,
+ polygon_scratch,
+ Some(ClipRectToRegionMaskResult::new(&mask_rect,
+ &corner_rect,
+ border_radius)))
+ }
- // C:
- corner_rect.origin = Point2D::new(complex_region.rect.origin.x,
- complex_region.rect.max_y() - border_radius);
- if !util::rect_is_empty(&corner_rect) {
- intermediate_polygon.clip_to_rect(sh_clip_buffers, &corner_rect, polygon_scratch);
- let mask_rect = Rect::new(Point2D::new(0.0, 1.0), Size2D::new(1.0, -1.0));
- push_results(output,
- polygon_scratch,
- Some(ClipRectToRegionMaskResult::new(&mask_rect,
- &corner_rect,
- border_radius)))
- }
+ // C:
+ corner_rect.origin = Point2D::new(complex_region.rect.origin.x,
+ complex_region.rect.max_y() - border_radius);
+ if !util::rect_is_empty(&corner_rect) {
+ intermediate_polygon.clip_to_rect(sh_clip_buffers, &corner_rect, polygon_scratch);
+ let mask_rect = Rect::new(Point2D::new(0.0, 1.0), Size2D::new(1.0, -1.0));
+ push_results(output,
+ polygon_scratch,
+ Some(ClipRectToRegionMaskResult::new(&mask_rect,
+ &corner_rect,
+ border_radius)))
+ }
- // D:
- corner_rect.origin = Point2D::new(complex_region.rect.max_x() - border_radius,
- complex_region.rect.max_y() - border_radius);
- if !util::rect_is_empty(&corner_rect) {
- intermediate_polygon.clip_to_rect(sh_clip_buffers, &corner_rect, polygon_scratch);
- let mask_rect = Rect::new(Point2D::new(1.0, 1.0), Size2D::new(-1.0, -1.0));
- push_results(output,
- polygon_scratch,
- Some(ClipRectToRegionMaskResult::new(&mask_rect,
- &corner_rect,
- border_radius)))
- }
+ // D:
+ corner_rect.origin = Point2D::new(complex_region.rect.max_x() - border_radius,
+ complex_region.rect.max_y() - border_radius);
+ if !util::rect_is_empty(&corner_rect) {
+ intermediate_polygon.clip_to_rect(sh_clip_buffers, &corner_rect, polygon_scratch);
+ let mask_rect = Rect::new(Point2D::new(1.0, 1.0), Size2D::new(-1.0, -1.0));
+ push_results(output,
+ polygon_scratch,
+ Some(ClipRectToRegionMaskResult::new(&mask_rect,
+ &corner_rect,
+ border_radius)))
}
}
@@ -344,27 +328,44 @@ fn clip_to_region(polygon: P,
}
/// NB: Clobbers both `polygon_scratch` and `polygon_output` in the typed clip buffers.
-pub fn clip_rect_with_mode_and_to_region
(polygon: P,
- sh_clip_buffers: &mut ShClipBuffers,
- typed_clip_buffers: &mut TypedClipBuffers
,
- clip_rect: &Rect,
- clip_mode: BoxShadowClipMode,
- clip_region: &ClipRegion)
- where P: Polygon + Clone {
- typed_clip_buffers.polygon_scratch.clear();
- clip_rect_with_mode(polygon,
- sh_clip_buffers,
- clip_rect,
- clip_mode,
- &mut typed_clip_buffers.polygon_scratch);
-
- for initial_clip_result in typed_clip_buffers.polygon_scratch.drain(..) {
- clip_to_region(initial_clip_result,
- sh_clip_buffers,
- &mut typed_clip_buffers.polygon_output,
- &mut typed_clip_buffers.clip_rect_to_region_result_scratch,
- &mut typed_clip_buffers.clip_rect_to_region_result_output,
- clip_region)
+pub fn clip_rect_to_combined_region(polygon: P,
+ sh_clip_buffers: &mut ShClipBuffers,
+ typed_clip_buffers: &mut TypedClipBuffers
,
+ clip_region: &CombinedClipRegion)
+ where P: Polygon + Debug + Clone {
+ polygon.clip_to_rect(sh_clip_buffers,
+ &clip_region.clip_in_rect,
+ &mut typed_clip_buffers.polygon_scratch);
+
+ if let Some(ref clip_out_complex) = clip_region.clip_out_complex {
+ for initial_clip_result in typed_clip_buffers.polygon_scratch.drain(..) {
+ initial_clip_result.clip_out_rect(sh_clip_buffers,
+ &clip_out_complex.rect,
+ &mut typed_clip_buffers.polygon_output);
+ }
+ mem::swap(&mut typed_clip_buffers.polygon_output,
+ &mut typed_clip_buffers.polygon_scratch)
+ }
+
+ typed_clip_buffers.clip_rect_to_region_result_output
+ .extend(typed_clip_buffers.polygon_scratch.drain(..).map(|clip_rect_result| {
+ ClipRectToRegionResult::new(clip_rect_result, None)
+ }));
+
+ if let Some(ref clip_in_complex) = clip_region.clip_in_complex {
+ clip_to_complex_region(sh_clip_buffers,
+ &mut typed_clip_buffers.polygon_output,
+ &mut typed_clip_buffers.clip_rect_to_region_result_scratch,
+ &mut typed_clip_buffers.clip_rect_to_region_result_output,
+ clip_in_complex);
+ }
+
+ for clip_in_complex in clip_region.clip_in_complex_stack {
+ clip_to_complex_region(sh_clip_buffers,
+ &mut typed_clip_buffers.polygon_output,
+ &mut typed_clip_buffers.clip_rect_to_region_result_scratch,
+ &mut typed_clip_buffers.clip_rect_to_region_result_output,
+ clip_in_complex)
}
}
diff --git a/src/internal_types.rs b/src/internal_types.rs
index da6ee590d2..8b1abdf87d 100644
--- a/src/internal_types.rs
+++ b/src/internal_types.rs
@@ -11,8 +11,9 @@ use std::collections::hash_state::DefaultState;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use texture_cache::TextureCacheItem;
-use types::{FontKey, ImageKey, Epoch, ColorF, PipelineId, ImageFormat, DisplayListID};
-use types::{StackingContext, DisplayListBuilder, DisplayListMode, CompositionOp};
+use types::{DisplayListID, FontKey, ImageKey, Epoch, ColorF, PipelineId};
+use types::{ImageFormat, StackingContext, DisplayListBuilder, DisplayListMode, CompositionOp};
+use types::{ComplexClipRegion};
use util;
const UV_FLOAT_TO_FIXED: f32 = 65535.0;
@@ -21,6 +22,17 @@ const COLOR_FLOAT_TO_FIXED: f32 = 255.0;
pub const ORTHO_NEAR_PLANE: f32 = -1000000.0;
pub const ORTHO_FAR_PLANE: f32 = 1000000.0;
+static ZERO_RECT_F32: Rect = Rect {
+ origin: Point2D {
+ x: 0.0,
+ y: 0.0,
+ },
+ size: Size2D {
+ width: 0.0,
+ height: 0.0,
+ },
+};
+
#[derive(Clone, Copy, Debug)]
pub struct IdNamespace(pub u32);
@@ -826,3 +838,41 @@ pub enum BasicRotationAngle {
Clockwise270,
}
+#[derive(Debug, Clone, Copy)]
+pub struct CombinedClipRegion<'a> {
+ pub clip_in_rect: Rect,
+ pub clip_in_complex: Option,
+ pub clip_in_complex_stack: &'a [ComplexClipRegion],
+ pub clip_out_complex: Option,
+}
+
+impl<'a> CombinedClipRegion<'a> {
+ pub fn from_clip_in_rect_and_stack<'b>(clip_in_rect: &Rect,
+ clip_in_complex_stack: &'b [ComplexClipRegion])
+ -> CombinedClipRegion<'b> {
+ CombinedClipRegion {
+ clip_in_rect: *clip_in_rect,
+ clip_in_complex: None,
+ clip_in_complex_stack: clip_in_complex_stack,
+ clip_out_complex: None,
+ }
+ }
+
+ pub fn clip_in_rect(&mut self, rect: &Rect) -> &mut CombinedClipRegion<'a> {
+ self.clip_in_rect = self.clip_in_rect.intersection(rect).unwrap_or(ZERO_RECT_F32);
+ self
+ }
+
+ pub fn clip_in(&mut self, region: &ComplexClipRegion) -> &mut CombinedClipRegion<'a> {
+ debug_assert!(self.clip_in_complex.is_none());
+ self.clip_in_complex = Some(*region);
+ self
+ }
+
+ pub fn clip_out(&mut self, region: &ComplexClipRegion) -> &mut CombinedClipRegion<'a> {
+ debug_assert!(self.clip_out_complex.is_none());
+ self.clip_out_complex = Some(*region);
+ self
+ }
+}
+
diff --git a/src/render_backend.rs b/src/render_backend.rs
index c71fc444e6..63dfe7359b 100644
--- a/src/render_backend.rs
+++ b/src/render_backend.rs
@@ -13,7 +13,7 @@ use internal_types::{ClipRectToRegionResult, DrawListIndex, DrawListItemIndex, D
use internal_types::{CompositeInfo, BorderEdgeDirection, RenderTargetIndex, GlyphKey};
use internal_types::{FontTemplate, Glyph, PolygonPosColorUv, RectPosUv, TextureTarget};
use internal_types::{ResourceId, IdNamespace, TiledImageKey, BasicRotationAngle};
-use internal_types::{RectUv};
+use internal_types::{RectUv, CombinedClipRegion};
use layer::Layer;
use optimizer;
use render_api::RenderApi;
@@ -39,6 +39,7 @@ use types::{GlyphInstance, DrawList, ImageFormat, BoxShadowClipMode, DisplayItem
use types::{PipelineId, RenderNotifier, StackingContext, SpecificDisplayItem, ColorF};
use types::{RenderTargetID, MixBlendMode, CompositeDisplayItem, BorderSide, BorderStyle};
use types::{NodeIndex, CompositionOp, FilterOp, LowLevelFilterOp, BlurDirection};
+use types::{ComplexClipRegion, BorderRadius};
use util;
use util::MatrixHelpers;
use scoped_threadpool;
@@ -1473,9 +1474,7 @@ impl DrawCommandBuilder {
fn add_textured_rectangle(&mut self,
sort_key: &DisplayItemKey,
rect: &Rect,
- clip: &Rect,
- clip_mode: BoxShadowClipMode,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
image_info: &TextureCacheItem,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers,
@@ -1483,8 +1482,6 @@ impl DrawCommandBuilder {
self.add_axis_aligned_gradient_with_texture(sort_key,
rect,
clip,
- clip_mode,
- clip_region,
image_info,
resource_cache,
clip_buffers,
@@ -1495,17 +1492,13 @@ impl DrawCommandBuilder {
fn add_color_rectangle(&mut self,
sort_key: &DisplayItemKey,
rect: &Rect,
- clip: &Rect,
- clip_mode: BoxShadowClipMode,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers,
color: &ColorF) {
self.add_axis_aligned_gradient(sort_key,
rect,
clip,
- clip_mode,
- clip_region,
resource_cache,
clip_buffers,
&[*color, *color, *color, *color])
@@ -1532,8 +1525,7 @@ impl DrawCommandBuilder {
fn add_image(&mut self,
sort_key: &DisplayItemKey,
rect: &Rect,
- clip_rect: &Rect,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
stretch_size: &Size2D,
image_key: ImageKey,
resource_cache: &ResourceCache,
@@ -1554,8 +1546,7 @@ impl DrawCommandBuilder {
self.push_image_rect(color,
image_info,
- clip_rect,
- clip_region,
+ clip,
&sort_key,
resource_cache,
clip_buffers,
@@ -1591,8 +1582,7 @@ impl DrawCommandBuilder {
self.push_image_rect(color,
image_info,
- clip_rect,
- clip_region,
+ clip,
&sort_key,
resource_cache,
clip_buffers,
@@ -1609,28 +1599,21 @@ impl DrawCommandBuilder {
fn push_image_rect(&mut self,
color: &ColorF,
image_info: &TextureCacheItem,
- clip_rect: &Rect,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
sort_key: &DisplayItemKey,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers,
rect: &Rect,
uv: &RectUv) {
- clipper::clip_rect_with_mode_and_to_region(
- RectPosUv {
- pos: *rect,
- uv: *uv
- },
- &mut clip_buffers.sh_clip_buffers,
- &mut clip_buffers.rect_pos_uv,
- clip_rect,
- BoxShadowClipMode::Inset,
- clip_region);
+ clipper::clip_rect_to_combined_region(RectPosUv {
+ pos: *rect,
+ uv: *uv
+ },
+ &mut clip_buffers.sh_clip_buffers,
+ &mut clip_buffers.rect_pos_uv,
+ clip);
for clip_region in clip_buffers.rect_pos_uv.clip_rect_to_region_result_output.drain(..) {
- let mask = mask_for_clip_region(resource_cache,
- &clip_region,
- false);
-
+ let mask = mask_for_clip_region(resource_cache, &clip_region, false);
let colors = [*color, *color, *color, *color];
let mut vertices = clip_region.make_packed_vertices_for_rect(&colors,
mask,
@@ -1732,9 +1715,7 @@ impl DrawCommandBuilder {
fn add_axis_aligned_gradient(&mut self,
sort_key: &DisplayItemKey,
rect: &Rect,
- clip: &Rect,
- clip_mode: BoxShadowClipMode,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers,
colors: &[ColorF; 4]) {
@@ -1742,8 +1723,6 @@ impl DrawCommandBuilder {
self.add_axis_aligned_gradient_with_texture(sort_key,
rect,
clip,
- clip_mode,
- clip_region,
white_image,
resource_cache,
clip_buffers,
@@ -1754,9 +1733,7 @@ impl DrawCommandBuilder {
fn add_axis_aligned_gradient_with_texture(&mut self,
sort_key: &DisplayItemKey,
rect: &Rect,
- clip: &Rect,
- clip_mode: BoxShadowClipMode,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
image_info: &TextureCacheItem,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers,
@@ -1772,20 +1749,16 @@ impl DrawCommandBuilder {
bottom_right: Point2D::new(image_info.u1, image_info.v1),
};
- clipper::clip_rect_with_mode_and_to_region(
+ clipper::clip_rect_to_combined_region(
RectPosUv {
pos: *rect,
uv: uv,
},
&mut clip_buffers.sh_clip_buffers,
&mut clip_buffers.rect_pos_uv,
- clip,
- clip_mode,
- clip_region);
+ clip);
for clip_region in clip_buffers.rect_pos_uv.clip_rect_to_region_result_output.drain(..) {
- let mask = mask_for_clip_region(resource_cache,
- &clip_region,
- false);
+ let mask = mask_for_clip_region(resource_cache, &clip_region, false);
let mut vertices = clip_region.make_packed_vertices_for_rect(colors,
mask,
@@ -1801,8 +1774,7 @@ impl DrawCommandBuilder {
fn add_gradient(&mut self,
sort_key: &DisplayItemKey,
- rect: &Rect,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
start_point: &Point2D,
end_point: &Point2D,
stops: &[GradientStop],
@@ -1861,19 +1833,14 @@ impl DrawCommandBuilder {
};
{ // scope for buffers
- clipper::clip_rect_with_mode_and_to_region(
- gradient_polygon,
- &mut clip_buffers.sh_clip_buffers,
- &mut clip_buffers.polygon_pos_color_uv,
- &rect,
- BoxShadowClipMode::Inset,
- &clip_region);
+ clipper::clip_rect_to_combined_region(gradient_polygon,
+ &mut clip_buffers.sh_clip_buffers,
+ &mut clip_buffers.polygon_pos_color_uv,
+ clip);
for clip_result in clip_buffers.polygon_pos_color_uv
.clip_rect_to_region_result_output
.drain(..) {
- let mask = mask_for_clip_region(resource_cache,
- &clip_result,
- false);
+ let mask = mask_for_clip_region(resource_cache, &clip_result, false);
let mut packed_vertices = Vec::new();
if clip_result.rect_result.vertices.len() >= 3 {
@@ -1902,8 +1869,7 @@ impl DrawCommandBuilder {
fn add_box_shadow(&mut self,
sort_key: &DisplayItemKey,
box_bounds: &Rect,
- clip: &Rect,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
box_offset: &Point2D,
color: &ColorF,
blur_radius: f32,
@@ -1916,14 +1882,7 @@ impl DrawCommandBuilder {
// Fast path.
if blur_radius == 0.0 && spread_radius == 0.0 && clip_mode == BoxShadowClipMode::None {
- self.add_color_rectangle(sort_key,
- &rect,
- clip,
- BoxShadowClipMode::Inset,
- clip_region,
- resource_cache,
- clip_buffers,
- color);
+ self.add_color_rectangle(sort_key, &rect, clip, resource_cache, clip_buffers, color);
return;
}
@@ -1936,13 +1895,14 @@ impl DrawCommandBuilder {
spread_radius,
border_radius,
clip_mode,
+ clip,
resource_cache,
clip_buffers);
// Draw the sides.
self.add_box_shadow_sides(sort_key,
box_bounds,
- clip_region,
+ clip,
box_offset,
color,
blur_radius,
@@ -1953,17 +1913,26 @@ impl DrawCommandBuilder {
clip_buffers);
match clip_mode {
- BoxShadowClipMode::None | BoxShadowClipMode::Outset => {
+ BoxShadowClipMode::None => {
+ // Fill the center area.
+ self.add_color_rectangle(sort_key,
+ box_bounds,
+ clip,
+ resource_cache,
+ clip_buffers,
+ color);
+ }
+ 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(sort_key,
¢er_rect,
- box_bounds,
- clip_mode,
- clip_region,
+ &clip,
resource_cache,
clip_buffers,
color);
@@ -1972,13 +1941,12 @@ impl DrawCommandBuilder {
// Fill in the outsides.
self.fill_outside_area_of_inset_box_shadow(sort_key,
box_bounds,
- clip_region,
+ clip,
box_offset,
color,
blur_radius,
spread_radius,
border_radius,
- clip_mode,
resource_cache,
clip_buffers);
}
@@ -1994,6 +1962,7 @@ impl DrawCommandBuilder {
spread_radius: f32,
border_radius: f32,
clip_mode: BoxShadowClipMode,
+ clip: &CombinedClipRegion,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers) {
// Draw the corners.
@@ -2010,47 +1979,53 @@ impl DrawCommandBuilder {
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);
+
self.add_box_shadow_corner(sort_key,
&metrics.tl_outer,
&metrics.tl_inner,
- box_bounds,
&color,
blur_radius,
border_radius,
clip_mode,
+ &clip,
resource_cache,
clip_buffers,
BasicRotationAngle::Upright);
self.add_box_shadow_corner(sort_key,
&Point2D::new(metrics.tr_inner.x, metrics.tr_outer.y),
&Point2D::new(metrics.tr_outer.x, metrics.tr_inner.y),
- box_bounds,
&color,
blur_radius,
border_radius,
clip_mode,
+ &clip,
resource_cache,
clip_buffers,
BasicRotationAngle::Clockwise90);
self.add_box_shadow_corner(sort_key,
&metrics.br_inner,
&metrics.br_outer,
- box_bounds,
&color,
blur_radius,
border_radius,
clip_mode,
+ &clip,
resource_cache,
clip_buffers,
BasicRotationAngle::Clockwise180);
self.add_box_shadow_corner(sort_key,
&Point2D::new(metrics.bl_outer.x, metrics.bl_inner.y),
&Point2D::new(metrics.bl_inner.x, metrics.bl_outer.y),
- box_bounds,
&color,
blur_radius,
border_radius,
clip_mode,
+ &clip,
resource_cache,
clip_buffers,
BasicRotationAngle::Clockwise270);
@@ -2059,7 +2034,7 @@ impl DrawCommandBuilder {
fn add_box_shadow_sides(&mut self,
sort_key: &DisplayItemKey,
box_bounds: &Rect,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
box_offset: &Point2D,
color: &ColorF,
blur_radius: f32,
@@ -2071,6 +2046,11 @@ impl DrawCommandBuilder {
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);
+
// Draw the sides.
//
// +--+------------------+--+
@@ -2101,48 +2081,44 @@ impl DrawCommandBuilder {
self.add_box_shadow_edge(sort_key,
&top_rect.origin,
&top_rect.bottom_right(),
- box_bounds,
color,
blur_radius,
border_radius,
clip_mode,
- clip_region,
+ &clip,
resource_cache,
clip_buffers,
BasicRotationAngle::Clockwise270);
self.add_box_shadow_edge(sort_key,
&right_rect.origin,
&right_rect.bottom_right(),
- box_bounds,
color,
blur_radius,
border_radius,
clip_mode,
- clip_region,
+ &clip,
resource_cache,
clip_buffers,
BasicRotationAngle::Upright);
self.add_box_shadow_edge(sort_key,
&bottom_rect.origin,
&bottom_rect.bottom_right(),
- box_bounds,
color,
blur_radius,
border_radius,
clip_mode,
- clip_region,
+ &clip,
resource_cache,
clip_buffers,
BasicRotationAngle::Clockwise90);
self.add_box_shadow_edge(sort_key,
&left_rect.origin,
&left_rect.bottom_right(),
- box_bounds,
color,
blur_radius,
border_radius,
clip_mode,
- clip_region,
+ &clip,
resource_cache,
clip_buffers,
BasicRotationAngle::Clockwise180);
@@ -2151,18 +2127,22 @@ impl DrawCommandBuilder {
fn fill_outside_area_of_inset_box_shadow(&mut self,
sort_key: &DisplayItemKey,
box_bounds: &Rect,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
box_offset: &Point2D,
color: &ColorF,
blur_radius: f32,
spread_radius: f32,
border_radius: f32,
- clip_mode: BoxShadowClipMode,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers) {
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,
+ BoxShadowClipMode::Inset);
+
// Fill in the outside area of the box.
//
// +------------------------------+
@@ -2184,9 +2164,7 @@ impl DrawCommandBuilder {
&Rect::new(box_bounds.origin,
Size2D::new(box_bounds.size.width,
metrics.tl_outer.y - box_bounds.origin.y)),
- box_bounds,
- clip_mode,
- clip_region,
+ &clip,
resource_cache,
clip_buffers,
color);
@@ -2196,9 +2174,7 @@ impl DrawCommandBuilder {
&Rect::new(metrics.tr_outer,
Size2D::new(box_bounds.max_x() - metrics.tr_outer.x,
metrics.br_outer.y - metrics.tr_outer.y)),
- box_bounds,
- clip_mode,
- clip_region,
+ &clip,
resource_cache,
clip_buffers,
color);
@@ -2208,9 +2184,7 @@ impl DrawCommandBuilder {
&Rect::new(Point2D::new(box_bounds.origin.x, metrics.bl_outer.y),
Size2D::new(box_bounds.size.width,
box_bounds.max_y() - metrics.br_outer.y)),
- box_bounds,
- clip_mode,
- clip_region,
+ &clip,
resource_cache,
clip_buffers,
color);
@@ -2220,20 +2194,41 @@ impl DrawCommandBuilder {
&Rect::new(Point2D::new(box_bounds.origin.x, metrics.tl_outer.y),
Size2D::new(metrics.tl_outer.x - box_bounds.origin.x,
metrics.bl_outer.y - metrics.tl_outer.y)),
- box_bounds,
- clip_mode,
- clip_region,
+ &clip,
resource_cache,
clip_buffers,
color);
}
+ fn adjust_clip_for_box_shadow_clip_mode<'a>(&mut self,
+ clip: &CombinedClipRegion<'a>,
+ box_bounds: &Rect,
+ border_radius: f32,
+ clip_mode: BoxShadowClipMode)
+ -> CombinedClipRegion<'a> {
+ let mut clip = *clip;
+ match clip_mode {
+ BoxShadowClipMode::None => {}
+ BoxShadowClipMode::Inset => {
+ clip.clip_in(&ComplexClipRegion {
+ rect: *box_bounds,
+ radii: BorderRadius::uniform(border_radius),
+ });
+ }
+ 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
+ }
+
#[inline]
fn add_border_edge(&mut self,
sort_key: &DisplayItemKey,
rect: &Rect,
- clip: &Rect,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
direction: BorderEdgeDirection,
color: &ColorF,
border_style: BorderStyle,
@@ -2272,8 +2267,6 @@ impl DrawCommandBuilder {
self.add_color_rectangle(sort_key,
&dash_rect,
clip,
- BoxShadowClipMode::Inset,
- clip_region,
resource_cache,
clip_buffers,
color);
@@ -2318,8 +2311,6 @@ impl DrawCommandBuilder {
Size2D::new(dot_rect.size.width / 2.0,
dot_rect.size.height / 2.0)),
clip,
- BoxShadowClipMode::Inset,
- clip_region,
color_image,
resource_cache,
clip_buffers,
@@ -2331,8 +2322,6 @@ impl DrawCommandBuilder {
Size2D::new(-dot_rect.size.width / 2.0,
dot_rect.size.height / 2.0)),
clip,
- BoxShadowClipMode::Inset,
- clip_region,
color_image,
resource_cache,
clip_buffers,
@@ -2344,8 +2333,6 @@ impl DrawCommandBuilder {
Size2D::new(-dot_rect.size.width / 2.0,
-dot_rect.size.height / 2.0)),
clip,
- BoxShadowClipMode::Inset,
- clip_region,
color_image,
resource_cache,
clip_buffers,
@@ -2357,8 +2344,6 @@ impl DrawCommandBuilder {
Size2D::new(dot_rect.size.width / 2.0,
-dot_rect.size.height / 2.0)),
clip,
- BoxShadowClipMode::Inset,
- clip_region,
color_image,
resource_cache,
clip_buffers,
@@ -2387,16 +2372,12 @@ impl DrawCommandBuilder {
self.add_color_rectangle(sort_key,
&outer_rect,
clip,
- BoxShadowClipMode::Inset,
- clip_region,
resource_cache,
clip_buffers,
color);
self.add_color_rectangle(sort_key,
&inner_rect,
clip,
- BoxShadowClipMode::Inset,
- clip_region,
resource_cache,
clip_buffers,
color);
@@ -2405,8 +2386,6 @@ impl DrawCommandBuilder {
self.add_color_rectangle(sort_key,
rect,
clip,
- BoxShadowClipMode::Inset,
- clip_region,
resource_cache,
clip_buffers,
color);
@@ -2417,13 +2396,14 @@ impl DrawCommandBuilder {
#[inline]
fn add_border_corner(&mut self,
sort_key: &DisplayItemKey,
- clip: &Rect,
+ clip: &CombinedClipRegion,
vertices_rect: &Rect,
color0: &ColorF,
color1: &ColorF,
outer_radius: &Size2D,
inner_radius: &Size2D,
resource_cache: &ResourceCache,
+ clip_buffers: &mut clipper::ClipBuffers,
rotation_angle: BasicRotationAngle) {
if color0.a <= 0.0 && color1.a <= 0.0 {
return
@@ -2444,36 +2424,46 @@ impl DrawCommandBuilder {
}
};
+ // FIXME(pcwalton): Either use RGBA8 textures instead of alpha masks here, or implement
+ // a mask combiner.
let mask_uv = RectUv::from_image_and_rotation_angle(mask_image, rotation_angle);
- if vertices_rect.intersects(clip) {
+ clipper::clip_rect_to_combined_region(
+ RectPosUv {
+ pos: *vertices_rect,
+ uv: mask_uv,
+ },
+ &mut clip_buffers.sh_clip_buffers,
+ &mut clip_buffers.rect_pos_uv,
+ clip);
+ for clip_region in clip_buffers.rect_pos_uv.clip_rect_to_region_result_output.drain(..) {
let v0;
let v1;
let muv0;
let muv1;
match rotation_angle {
BasicRotationAngle::Upright => {
- v0 = vertices_rect.origin;
- muv0 = mask_uv.top_left;
- v1 = vertices_rect.bottom_right();
- muv1 = mask_uv.bottom_right;
+ v0 = clip_region.rect_result.pos.origin;
+ muv0 = clip_region.rect_result.uv.top_left;
+ v1 = clip_region.rect_result.pos.bottom_right();
+ muv1 = clip_region.rect_result.uv.bottom_right;
}
BasicRotationAngle::Clockwise90 => {
- v0 = vertices_rect.top_right();
- muv0 = mask_uv.top_right;
- v1 = vertices_rect.bottom_left();
- muv1 = mask_uv.bottom_left;
+ v0 = clip_region.rect_result.pos.top_right();
+ muv0 = clip_region.rect_result.uv.top_right;
+ v1 = clip_region.rect_result.pos.bottom_left();
+ muv1 = clip_region.rect_result.uv.bottom_left;
}
BasicRotationAngle::Clockwise180 => {
- v0 = vertices_rect.bottom_right();
- muv0 = mask_uv.bottom_right;
- v1 = vertices_rect.origin;
- muv1 = mask_uv.top_left;
+ v0 = clip_region.rect_result.pos.bottom_right();
+ muv0 = clip_region.rect_result.uv.bottom_right;
+ v1 = clip_region.rect_result.pos.origin;
+ muv1 = clip_region.rect_result.uv.top_left;
}
BasicRotationAngle::Clockwise270 => {
- v0 = vertices_rect.bottom_left();
- muv0 = mask_uv.bottom_left;
- v1 = vertices_rect.top_right();
- muv1 = mask_uv.top_right;
+ v0 = clip_region.rect_result.pos.bottom_left();
+ muv0 = clip_region.rect_result.uv.bottom_left;
+ v1 = clip_region.rect_result.pos.top_right();
+ muv1 = clip_region.rect_result.uv.top_right;
}
}
@@ -2519,68 +2509,43 @@ impl DrawCommandBuilder {
}
}
- fn add_masked_rectangle(&mut self,
- sort_key: &DisplayItemKey,
- v0: &Point2D,
- v1: &Point2D,
- clip: &Rect,
- clip_mode: BoxShadowClipMode,
- color0: &ColorF,
- color1: &ColorF,
- mask_image: &TextureCacheItem,
- resource_cache: &ResourceCache,
- clip_buffers: &mut ClipBuffers,
- rotation_angle: BasicRotationAngle) {
+ fn add_color_image_rectangle(&mut self,
+ sort_key: &DisplayItemKey,
+ v0: &Point2D,
+ v1: &Point2D,
+ clip: &CombinedClipRegion,
+ color0: &ColorF,
+ color1: &ColorF,
+ color_image: &TextureCacheItem,
+ resource_cache: &ResourceCache,
+ clip_buffers: &mut ClipBuffers,
+ rotation_angle: BasicRotationAngle) {
if color0.a <= 0.0 || color1.a <= 0.0 {
return
}
- let white_image = resource_cache.get_dummy_color_image();
let vertices_rect = Rect::new(*v0, Size2D::new(v1.x - v0.x, v1.y - v0.y));
- let mask_uv = RectUv::from_image_and_rotation_angle(mask_image, rotation_angle);
-
- clipper::clip_rect_with_mode(RectPosUv {
- pos: vertices_rect,
- uv: mask_uv,
- },
- &mut clip_buffers.sh_clip_buffers,
- clip,
- clip_mode,
- &mut clip_buffers.rect_pos_uv.polygon_output);
- for clip_result in clip_buffers.rect_pos_uv.polygon_output.drain(..) {
- let mut vertices = [
- PackedVertex::from_components(clip_result.pos.origin.x, clip_result.pos.origin.y,
- color0,
- 0.0, 0.0,
- clip_result.uv.top_left.x, clip_result.uv.top_left.y,
- white_image.texture_index,
- mask_image.texture_index),
- PackedVertex::from_components(clip_result.pos.max_x(), clip_result.pos.origin.y,
- color0,
- 0.0, 0.0,
- clip_result.uv.top_right.x,
- clip_result.uv.top_right.y,
- white_image.texture_index,
- mask_image.texture_index),
- PackedVertex::from_components(clip_result.pos.origin.x, clip_result.pos.max_y(),
- color1,
- 0.0, 0.0,
- clip_result.uv.bottom_left.x,
- clip_result.uv.bottom_left.y,
- white_image.texture_index,
- mask_image.texture_index),
- PackedVertex::from_components(clip_result.pos.max_x(), clip_result.pos.max_y(),
- color1,
- 0.0, 0.0,
- clip_result.uv.bottom_right.x,
- clip_result.uv.bottom_right.y,
- white_image.texture_index,
- mask_image.texture_index),
- ];
+ let color_uv = RectUv::from_image_and_rotation_angle(color_image, rotation_angle);
+
+ clipper::clip_rect_to_combined_region(RectPosUv {
+ pos: vertices_rect,
+ uv: color_uv,
+ },
+ &mut clip_buffers.sh_clip_buffers,
+ &mut clip_buffers.rect_pos_uv,
+ clip);
+ for clip_region in clip_buffers.rect_pos_uv.clip_rect_to_region_result_output.drain(..) {
+ let mask = mask_for_clip_region(resource_cache,
+ &clip_region,
+ false);
+ let colors = [*color0, *color0, *color1, *color1];
+ let mut vertices = clip_region.make_packed_vertices_for_rect(&colors,
+ mask,
+ color_image.texture_index);
self.add_draw_item(sort_key,
- white_image.texture_id,
- mask_image.texture_id,
+ color_image.texture_id,
+ mask.texture_id,
Primitive::Rectangles,
&mut vertices);
}
@@ -2589,8 +2554,7 @@ impl DrawCommandBuilder {
fn add_border(&mut self,
sort_key: &DisplayItemKey,
rect: &Rect,
- clip: &Rect,
- clip_region: &ClipRegion,
+ clip: &CombinedClipRegion,
info: &BorderDisplayItem,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers) {
@@ -2629,7 +2593,6 @@ impl DrawCommandBuilder {
&Rect::new(Point2D::new(tl_outer.x, tl_inner.y),
Size2D::new(left.width, bl_inner.y - tl_inner.y)),
clip,
- clip_region,
BorderEdgeDirection::Vertical,
&left_color,
info.left.style,
@@ -2641,7 +2604,6 @@ impl DrawCommandBuilder {
Size2D::new(tr_inner.x - tl_inner.x,
tr_outer.y + top.width - tl_outer.y)),
clip,
- clip_region,
BorderEdgeDirection::Horizontal,
&top_color,
info.top.style,
@@ -2652,7 +2614,6 @@ impl DrawCommandBuilder {
&Rect::new(Point2D::new(br_outer.x - right.width, tr_inner.y),
Size2D::new(right.width, br_inner.y - tr_inner.y)),
clip,
- clip_region,
BorderEdgeDirection::Vertical,
&right_color,
info.right.style,
@@ -2664,7 +2625,6 @@ impl DrawCommandBuilder {
Size2D::new(br_inner.x - bl_inner.x,
br_outer.y - bl_outer.y + bottom.width)),
clip,
- clip_region,
BorderEdgeDirection::Horizontal,
&bottom_color,
info.bottom.style,
@@ -2682,6 +2642,7 @@ impl DrawCommandBuilder {
&radius.top_left,
&info.top_left_inner_radius(),
resource_cache,
+ clip_buffers,
BasicRotationAngle::Upright);
self.add_border_corner(sort_key,
@@ -2694,6 +2655,7 @@ impl DrawCommandBuilder {
&radius.top_right,
&info.top_right_inner_radius(),
resource_cache,
+ clip_buffers,
BasicRotationAngle::Clockwise90);
self.add_border_corner(sort_key,
@@ -2706,6 +2668,7 @@ impl DrawCommandBuilder {
&radius.bottom_right,
&info.bottom_right_inner_radius(),
resource_cache,
+ clip_buffers,
BasicRotationAngle::Clockwise180);
self.add_border_corner(sort_key,
@@ -2718,6 +2681,7 @@ impl DrawCommandBuilder {
&radius.bottom_left,
&info.bottom_left_inner_radius(),
resource_cache,
+ clip_buffers,
BasicRotationAngle::Clockwise270);
}
@@ -2726,83 +2690,78 @@ impl DrawCommandBuilder {
sort_key: &DisplayItemKey,
top_left: &Point2D,
bottom_right: &Point2D,
- box_bounds: &Rect,
color: &ColorF,
blur_radius: f32,
border_radius: f32,
clip_mode: BoxShadowClipMode,
+ clip: &CombinedClipRegion,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers,
rotation_angle: BasicRotationAngle) {
- let (inverted, clip_rect) = match clip_mode {
- BoxShadowClipMode::Outset => (false, *box_bounds),
- BoxShadowClipMode::Inset => (true, *box_bounds),
- BoxShadowClipMode::None => (false, MAX_RECT),
+ let inverted = match clip_mode {
+ BoxShadowClipMode::Outset | BoxShadowClipMode::None => false,
+ BoxShadowClipMode::Inset => true,
};
- let mask_image = match BoxShadowRasterOp::create_corner(blur_radius,
- border_radius,
- inverted) {
+ let color_image = match BoxShadowRasterOp::create_corner(blur_radius,
+ border_radius,
+ inverted) {
Some(raster_item) => {
let raster_item = RasterItem::BoxShadow(raster_item);
resource_cache.get_raster(&raster_item)
}
- None => resource_cache.get_dummy_mask_image(),
+ None => resource_cache.get_dummy_color_image(),
};
- self.add_masked_rectangle(sort_key,
- top_left,
- bottom_right,
- &clip_rect,
- clip_mode,
- color,
- color,
- &mask_image,
- resource_cache,
- clip_buffers,
- rotation_angle)
+ self.add_color_image_rectangle(sort_key,
+ top_left,
+ bottom_right,
+ clip,
+ color,
+ color,
+ &color_image,
+ resource_cache,
+ clip_buffers,
+ rotation_angle)
}
fn add_box_shadow_edge(&mut self,
sort_key: &DisplayItemKey,
top_left: &Point2D,
bottom_right: &Point2D,
- box_bounds: &Rect,
color: &ColorF,
blur_radius: f32,
border_radius: f32,
clip_mode: BoxShadowClipMode,
- _: &ClipRegion,
+ clip: &CombinedClipRegion,
resource_cache: &ResourceCache,
clip_buffers: &mut ClipBuffers,
rotation_angle: BasicRotationAngle) {
- let (inverted, clip_rect) = match clip_mode {
- BoxShadowClipMode::Outset => (false, *box_bounds),
- BoxShadowClipMode::Inset => (true, *box_bounds),
- BoxShadowClipMode::None => (false, MAX_RECT),
+ let inverted = match clip_mode {
+ BoxShadowClipMode::Outset | BoxShadowClipMode::None => false,
+ BoxShadowClipMode::Inset => true,
};
- let mask_image = match BoxShadowRasterOp::create_edge(blur_radius,
- border_radius,
- inverted) {
+ let color_image = match BoxShadowRasterOp::create_edge(blur_radius,
+ border_radius,
+ inverted) {
Some(raster_item) => {
let raster_item = RasterItem::BoxShadow(raster_item);
resource_cache.get_raster(&raster_item)
}
- None => resource_cache.get_dummy_mask_image(),
+ None => resource_cache.get_dummy_color_image(),
};
- self.add_masked_rectangle(sort_key,
- top_left,
- bottom_right,
- &clip_rect,
- clip_mode,
- color,
- color,
- &mask_image,
- resource_cache,
- clip_buffers,
- rotation_angle)
+ self.add_color_image_rectangle(sort_key,
+ top_left,
+ bottom_right,
+ clip,
+ color,
+ color,
+ &color_image,
+ resource_cache,
+ clip_buffers,
+ rotation_angle)
}
}
@@ -2820,22 +2779,7 @@ impl BuildRequiredResources for AABBTreeNode {
// Handle border radius for complex clipping regions.
for complex_clip_region in display_item.clip.complex.iter() {
- resource_list.add_radius_raster(&complex_clip_region.radii.top_left,
- &Size2D::new(0.0, 0.0),
- false,
- ImageFormat::A8);
- resource_list.add_radius_raster(&complex_clip_region.radii.top_right,
- &Size2D::new(0.0, 0.0),
- false,
- ImageFormat::A8);
- resource_list.add_radius_raster(&complex_clip_region.radii.bottom_left,
- &Size2D::new(0.0, 0.0),
- false,
- ImageFormat::A8);
- resource_list.add_radius_raster(&complex_clip_region.radii.bottom_right,
- &Size2D::new(0.0, 0.0),
- false,
- ImageFormat::A8);
+ resource_list.add_radius_raster_for_border_radii(&complex_clip_region.radii);
}
match display_item.item {
@@ -2856,6 +2800,8 @@ impl BuildRequiredResources for AABBTreeNode {
SpecificDisplayItem::Composite(..) => {}
SpecificDisplayItem::Clear(..) => {}
SpecificDisplayItem::BoxShadow(ref info) => {
+ resource_list.add_radius_raster_for_border_radii(
+ &BorderRadius::uniform(info.border_radius));
resource_list.add_box_shadow_corner(info.blur_radius,
info.border_radius,
false);
@@ -3027,7 +2973,10 @@ impl NodeCompiler for AABBTreeNode {
node_scroll_layer_id == draw_context.scroll_layer_id {
let clip_rect = display_item.clip.main.intersection(&draw_context.overflow);
- if let Some(clip_rect) = clip_rect {
+ if let Some(ref clip_rect) = clip_rect {
+ let mut clip = CombinedClipRegion::from_clip_in_rect_and_stack(
+ clip_rect,
+ &display_item.clip.complex[..]);
let builder = match draw_cmd_builders.entry(draw_context.render_target_index) {
Vacant(entry) => {
@@ -3042,8 +2991,7 @@ impl NodeCompiler for AABBTreeNode {
SpecificDisplayItem::Image(ref info) => {
builder.add_image(&key,
&display_item.rect,
- &clip_rect,
- &display_item.clip,
+ &clip,
&info.stretch_size,
info.image_key,
resource_cache,
@@ -3063,18 +3011,16 @@ impl NodeCompiler for AABBTreeNode {
SpecificDisplayItem::Rectangle(ref info) => {
builder.add_color_rectangle(&key,
&display_item.rect,
- &clip_rect,
- BoxShadowClipMode::Inset,
- &display_item.clip,
+ &clip,
resource_cache,
&mut clip_buffers,
&info.color);
}
SpecificDisplayItem::Iframe(..) => {}
SpecificDisplayItem::Gradient(ref info) => {
+ clip.clip_in_rect(&display_item.rect);
builder.add_gradient(&key,
- &display_item.rect,
- &display_item.clip,
+ &clip,
&info.start_point,
&info.end_point,
&info.stops,
@@ -3084,8 +3030,7 @@ impl NodeCompiler for AABBTreeNode {
SpecificDisplayItem::BoxShadow(ref info) => {
builder.add_box_shadow(&key,
&info.box_bounds,
- &clip_rect,
- &display_item.clip,
+ &clip,
&info.offset,
&info.color,
info.blur_radius,
@@ -3098,8 +3043,7 @@ impl NodeCompiler for AABBTreeNode {
SpecificDisplayItem::Border(ref info) => {
builder.add_border(&key,
&display_item.rect,
- &clip_rect,
- &display_item.clip,
+ &clip,
info,
resource_cache,
&mut clip_buffers);
diff --git a/src/renderer.rs b/src/renderer.rs
index d5d3644614..7e37706a21 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -67,7 +67,7 @@ pub struct Renderer {
u_filter_params: UniformLocation,
u_filter_texture_size: UniformLocation,
- shadow_corner_program_id: ProgramId,
+ box_shadow_program_id: ProgramId,
blur_program_id: ProgramId,
u_direction: UniformLocation,
@@ -94,8 +94,8 @@ impl Renderer {
let border_program_id = device.create_program("border.vs.glsl", "border.fs.glsl");
let blend_program_id = device.create_program("blend.vs.glsl", "blend.fs.glsl");
let filter_program_id = device.create_program("filter.vs.glsl", "filter.fs.glsl");
- let shadow_corner_program_id = device.create_program("shadow_corner.vs.glsl",
- "shadow_corner.fs.glsl");
+ let box_shadow_program_id = device.create_program("box_shadow.vs.glsl",
+ "box_shadow.fs.glsl");
let blur_program_id = device.create_program("blur.vs.glsl", "blur.fs.glsl");
let tile_program_id = device.create_program("tile.vs.glsl", "tile.fs.glsl");
@@ -170,7 +170,7 @@ impl Renderer {
filter_program_id: filter_program_id,
quad_program_id: quad_program_id,
blit_program_id: blit_program_id,
- shadow_corner_program_id: shadow_corner_program_id,
+ box_shadow_program_id: box_shadow_program_id,
blur_program_id: blur_program_id,
tile_program_id: tile_program_id,
u_blend_params: u_blend_params,
@@ -486,7 +486,7 @@ impl Renderer {
let border_program_id = self.border_program_id;
let color = if inverted {
- ColorF::new(0.0, 0.0, 0.0, 0.0)
+ ColorF::new(0.0, 0.0, 0.0, 1.0)
} else {
ColorF::new(1.0, 1.0, 1.0, 1.0)
};
@@ -660,12 +660,12 @@ impl Renderer {
blur_radius: Au,
box_shadow_part: BoxShadowPart,
inverted: bool) {
- let shadow_corner_program_id = self.shadow_corner_program_id;
+ let box_shadow_program_id = self.box_shadow_program_id;
let blur_radius = blur_radius.to_f32_px();
let color = if inverted {
- ColorF::new(0.0, 0.0, 0.0, 0.0)
+ ColorF::new(1.0, 1.0, 1.0, 0.0)
} else {
ColorF::new(1.0, 1.0, 1.0, 1.0)
};
@@ -730,7 +730,7 @@ impl Renderer {
let mut batch = self.get_or_create_raster_batch(update_id,
update_index,
TextureId(0),
- shadow_corner_program_id,
+ box_shadow_program_id,
None);
batch.add_draw_item(update_id, TextureId(0), &vertices);
}
diff --git a/src/resource_list.rs b/src/resource_list.rs
index 30f31e2db7..306c27b7f7 100644
--- a/src/resource_list.rs
+++ b/src/resource_list.rs
@@ -6,7 +6,7 @@ use internal_types::{Glyph, GlyphKey, RasterItem, TiledImageKey};
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::hash_state::DefaultState;
-use types::{FontKey, ImageFormat, ImageKey};
+use types::{BorderRadius, FontKey, ImageFormat, ImageKey};
type RequiredImageSet = HashSet>;
type RequiredGlyphMap = HashMap, DefaultState>;
@@ -75,6 +75,14 @@ impl ResourceList {
}
}
+ pub fn add_radius_raster_for_border_radii(&mut self, radii: &BorderRadius) {
+ let zero_size = Size2D::new(0.0, 0.0);
+ self.add_radius_raster(&radii.top_left, &zero_size, false, ImageFormat::A8);
+ self.add_radius_raster(&radii.top_right, &zero_size, false, ImageFormat::A8);
+ self.add_radius_raster(&radii.bottom_left, &zero_size, false, ImageFormat::A8);
+ self.add_radius_raster(&radii.bottom_right, &zero_size, false, ImageFormat::A8);
+ }
+
pub fn add_box_shadow_corner(&mut self, blur_radius: f32, border_radius: f32, inverted: bool) {
if let Some(raster_item) = BoxShadowRasterOp::create_corner(blur_radius,
border_radius,
diff --git a/src/texture_cache.rs b/src/texture_cache.rs
index 72c97f17ff..f304c317d2 100644
--- a/src/texture_cache.rs
+++ b/src/texture_cache.rs
@@ -501,7 +501,7 @@ impl TextureCache {
0,
op.raster_size.to_nearest_px() as u32,
op.raster_size.to_nearest_px() as u32,
- ImageFormat::A8,
+ ImageFormat::RGBA8,
false);
// TODO(pcwalton): Handle large box shadows not fitting in texture cache page.
diff --git a/src/types.rs b/src/types.rs
index 3415276647..2c08ca7fb1 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -131,6 +131,26 @@ pub struct BorderRadius {
pub bottom_right: Size2D,
}
+impl BorderRadius {
+ pub fn zero() -> BorderRadius {
+ BorderRadius {
+ top_left: Size2D::new(0.0, 0.0),
+ top_right: Size2D::new(0.0, 0.0),
+ bottom_left: Size2D::new(0.0, 0.0),
+ bottom_right: Size2D::new(0.0, 0.0),
+ }
+ }
+
+ pub fn uniform(radius: f32) -> BorderRadius {
+ BorderRadius {
+ top_left: Size2D::new(radius, radius),
+ top_right: Size2D::new(radius, radius),
+ bottom_left: Size2D::new(radius, radius),
+ bottom_right: Size2D::new(radius, radius),
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BorderStyle {
None,
@@ -615,7 +635,7 @@ impl ClipRegion {
}
}
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ComplexClipRegion {
/// The boundaries of the rectangle.
pub rect: Rect,
@@ -630,6 +650,13 @@ impl ComplexClipRegion {
radii: radii,
}
}
+
+ pub fn from_rect(rect: &Rect) -> ComplexClipRegion {
+ ComplexClipRegion {
+ rect: *rect,
+ radii: BorderRadius::zero(),
+ }
+ }
}
#[derive(Clone, PartialEq, Eq, Copy, Deserialize, Serialize, Debug)]