diff --git a/Cargo.lock b/Cargo.lock index 536e77a8dc..515fc90573 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,7 +21,7 @@ dependencies = [ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "servo-glutin 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.46.0", + "webrender 0.47.0", "yaml-rust 0.3.4 (git+https://github.com/vvuk/yaml-rust)", ] @@ -1022,7 +1022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "webrender" -version = "0.46.0" +version = "0.47.0" dependencies = [ "angle 0.1.2 (git+https://github.com/servo/angle?branch=servo)", "app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,12 +1048,12 @@ dependencies = [ "servo-glutin 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.46.0", + "webrender_api 0.47.0", ] [[package]] name = "webrender_api" -version = "0.46.0" +version = "0.47.0" dependencies = [ "app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index 80e32bc65e..9b0d00e0dd 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender" -version = "0.46.0" +version = "0.47.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender/examples/animation.rs b/webrender/examples/animation.rs index 0fe3ea0afc..77b0b89368 100644 --- a/webrender/examples/animation.rs +++ b/webrender/examples/animation.rs @@ -36,9 +36,7 @@ fn body(_api: &RenderApi, Vec::new()); // Fill it with a white rect - builder.push_rect(bounds, - bounds, - ColorF::new(1.0, 1.0, 1.0, 1.0)); + builder.push_rect(bounds, None, ColorF::new(1.0, 1.0, 1.0, 1.0)); builder.pop_stacking_context(); } diff --git a/webrender/examples/basic.rs b/webrender/examples/basic.rs index 8e0acdb1ef..a65f95d7f8 100644 --- a/webrender/examples/basic.rs +++ b/webrender/examples/basic.rs @@ -197,15 +197,14 @@ fn body(api: &RenderApi, repeat: false, }; let complex = ComplexClipRegion::new((50, 50).to(150, 150), BorderRadius::uniform(20.0)); - builder.push_clip_node(None, bounds, bounds, vec![complex], Some(mask)); + let id = builder.define_clip(None, bounds, vec![complex], Some(mask)); + builder.push_clip_id(id); let bounds = (100, 100).to(200, 200); - builder.push_rect(bounds, bounds, ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder.push_rect(bounds, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); let bounds = (250, 100).to(350, 200); - builder.push_rect(bounds, - bounds, - ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder.push_rect(bounds, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); let border_side = BorderSide { color: ColorF::new(0.0, 0.0, 1.0, 1.0), style: BorderStyle::Groove, @@ -225,10 +224,7 @@ fn body(api: &RenderApi, }); let bounds = (100, 100).to(200, 200); - builder.push_border(bounds, - bounds, - border_widths, - border_details); + builder.push_border(bounds, None, border_widths, border_details); if false { // draw text? @@ -289,7 +285,7 @@ fn body(api: &RenderApi, ]; builder.push_text(text_bounds, - text_bounds, + None, &glyphs, font_key, ColorF::new(1.0, 1.0, 0.0, 1.0), @@ -309,7 +305,7 @@ fn body(api: &RenderApi, let box_shadow_type = BoxShadowClipMode::Inset; builder.push_box_shadow(rect, - bounds, + Some(LocalClip::from(bounds)), simple_box_bounds, offset, color, @@ -319,7 +315,7 @@ fn body(api: &RenderApi, box_shadow_type); } - builder.pop_clip_node(); + builder.pop_clip_id(); builder.pop_stacking_context(); } diff --git a/webrender/examples/blob.rs b/webrender/examples/blob.rs index 189f73e42f..de1fde1d0a 100644 --- a/webrender/examples/blob.rs +++ b/webrender/examples/blob.rs @@ -243,7 +243,7 @@ fn body(api: &api::RenderApi, builder.push_image( (30, 30).by(500, 500), - bounds, + Some(api::LocalClip::from(bounds)), api::LayoutSize::new(500.0, 500.0), api::LayoutSize::new(0.0, 0.0), api::ImageRendering::Auto, @@ -252,7 +252,7 @@ fn body(api: &api::RenderApi, builder.push_image( (600, 600).by(200, 200), - bounds, + Some(api::LocalClip::from(bounds)), api::LayoutSize::new(200.0, 200.0), api::LayoutSize::new(0.0, 0.0), api::ImageRendering::Auto, diff --git a/webrender/examples/nested_display_list.rs b/webrender/examples/nested_display_list.rs index 53661917a5..755c3b7f40 100644 --- a/webrender/examples/nested_display_list.rs +++ b/webrender/examples/nested_display_list.rs @@ -30,22 +30,20 @@ fn body(_api: &RenderApi, Vec::new()); let outer_scroll_frame_rect = (100, 100).to(600, 400); - builder.push_rect(outer_scroll_frame_rect, - outer_scroll_frame_rect, - ColorF::new(1.0, 1.0, 1.0, 1.0)); - - let nested_clip_id = builder.define_clip(None, - (100, 100).to(1000, 1000), - outer_scroll_frame_rect, - vec![], - None); + builder.push_rect(outer_scroll_frame_rect, None, ColorF::new(1.0, 1.0, 1.0, 1.0)); + + let nested_clip_id = builder.define_scroll_frame(None, + (100, 100).to(1000, 1000), + outer_scroll_frame_rect, + vec![], + None); builder.push_clip_id(nested_clip_id); let mut builder2 = DisplayListBuilder::new(*pipeline_id, *layout_size); let mut builder3 = DisplayListBuilder::new(*pipeline_id, *layout_size); let rect = (110, 110).to(210, 210); - builder3.push_rect(rect, rect, ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder3.push_rect(rect, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); // A fixed position rectangle should be fixed to the reference frame that starts // in the outer display list. @@ -57,24 +55,22 @@ fn body(_api: &RenderApi, MixBlendMode::Normal, Vec::new()); let rect = (0, 0).to(100, 100); - builder3.push_rect(rect, rect, ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder3.push_rect(rect, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); builder3.pop_stacking_context(); // Now we push an inner scroll frame that should have the same id as the outer one, // but the WebRender nested display list replacement code should convert it into // a unique ClipId. let inner_scroll_frame_rect = (330, 110).to(530, 360); - builder3.push_rect(inner_scroll_frame_rect, - inner_scroll_frame_rect, - ColorF::new(1.0, 0.0, 1.0, 0.5)); - let inner_nested_clip_id = builder3.define_clip(None, - (330, 110).to(2000, 2000), - inner_scroll_frame_rect, - vec![], - None); + builder3.push_rect(inner_scroll_frame_rect, None, ColorF::new(1.0, 0.0, 1.0, 0.5)); + let inner_nested_clip_id = builder3.define_scroll_frame(None, + (330, 110).to(2000, 2000), + inner_scroll_frame_rect, + vec![], + None); builder3.push_clip_id(inner_nested_clip_id); let rect = (340, 120).to(440, 220); - builder3.push_rect(rect, rect, ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder3.push_rect(rect, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); builder3.pop_clip_id(); let (_, _, built_list) = builder3.finalize(); diff --git a/webrender/examples/scrolling.rs b/webrender/examples/scrolling.rs index a843a736d7..9052327c2b 100644 --- a/webrender/examples/scrolling.rs +++ b/webrender/examples/scrolling.rs @@ -41,50 +41,49 @@ fn body(_api: &RenderApi, MixBlendMode::Normal, Vec::new()); // set the scrolling clip - let clip_id = builder.define_clip(None, (0, 0).by(1000, 1000), scrollbox, vec![], None); + let clip_id = builder.define_scroll_frame(None, + (0, 0).by(1000, 1000), + scrollbox, + vec![], + None); builder.push_clip_id(clip_id); // now put some content into it. // start with a white background - builder.push_rect((0, 0).to(1000, 1000), - (0, 0).to(1000, 1000), - ColorF::new(1.0, 1.0, 1.0, 1.0)); + builder.push_rect((0, 0).to(1000, 1000), None, ColorF::new(1.0, 1.0, 1.0, 1.0)); + // let's make a 50x50 blue square as a visual reference - builder.push_rect((0, 0).to(50, 50), - (0, 0).to(50, 50), - ColorF::new(0.0, 0.0, 1.0, 1.0)); + builder.push_rect((0, 0).to(50, 50), None, ColorF::new(0.0, 0.0, 1.0, 1.0)); + // and a 50x50 green square next to it with an offset clip // to see what that looks like builder.push_rect((50, 0).to(100, 50), - (60, 10).to(110, 60), + Some(LocalClip::from((60, 10).to(110, 60))), ColorF::new(0.0, 1.0, 0.0, 1.0)); // Below the above rectangles, set up a nested scrollbox. It's still in // the same stacking context, so note that the rects passed in need to // be relative to the stacking context. - let nested_clip_id = builder.define_clip(None, - (0, 100).to(300, 400), - (0, 100).to(200, 300), - vec![], - None); + let nested_clip_id = builder.define_scroll_frame(None, + (0, 100).to(300, 400), + (0, 100).to(200, 300), + vec![], + None); builder.push_clip_id(nested_clip_id); // give it a giant gray background just to distinguish it and to easily // visually identify the nested scrollbox - builder.push_rect((-1000, -1000).to(5000, 5000), - (-1000, -1000).to(5000, 5000), - ColorF::new(0.5, 0.5, 0.5, 1.0)); + builder.push_rect((-1000, -1000).to(5000, 5000), None, ColorF::new(0.5, 0.5, 0.5, 1.0)); + // add a teal square to visualize the scrolling/clipping behaviour // as you scroll the nested scrollbox with WASD keys - builder.push_rect((0, 100).to(50, 150), - (0, 100).to(50, 150), - ColorF::new(0.0, 1.0, 1.0, 1.0)); + builder.push_rect((0, 100).to(50, 150), None, ColorF::new(0.0, 1.0, 1.0, 1.0)); + // just for good measure add another teal square in the bottom-right // corner of the nested scrollframe content, which can be scrolled into // view by the user - builder.push_rect((250, 350).to(300, 400), - (250, 350).to(300, 400), - ColorF::new(0.0, 1.0, 1.0, 1.0)); + builder.push_rect((250, 350).to(300, 400), None, ColorF::new(0.0, 1.0, 1.0, 1.0)); + builder.pop_clip_id(); // nested_clip_id builder.pop_clip_id(); // clip_id diff --git a/webrender/examples/yuv.rs b/webrender/examples/yuv.rs index 56b193c370..4f4a70d0eb 100644 --- a/webrender/examples/yuv.rs +++ b/webrender/examples/yuv.rs @@ -206,7 +206,7 @@ fn body(api: &RenderApi, builder.push_yuv_image( LayoutRect::new(LayoutPoint::new(100.0, 0.0), LayoutSize::new(100.0, 100.0)), - bounds, + Some(LocalClip::from(bounds)), YuvData::NV12(yuv_chanel1, yuv_chanel2), YuvColorSpace::Rec601, ImageRendering::Auto, @@ -214,7 +214,7 @@ fn body(api: &RenderApi, builder.push_yuv_image( LayoutRect::new(LayoutPoint::new(300.0, 0.0), LayoutSize::new(100.0, 100.0)), - bounds, + Some(LocalClip::from(bounds)), YuvData::PlanarYCbCr(yuv_chanel1, yuv_chanel2_1, yuv_chanel3), YuvColorSpace::Rec601, ImageRendering::Auto, diff --git a/webrender/src/border.rs b/webrender/src/border.rs index 0184b6e013..5603344b31 100644 --- a/webrender/src/border.rs +++ b/webrender/src/border.rs @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BorderSide, BorderStyle, BorderWidths, ClipAndScrollInfo, ColorF, LayerPoint, LayerRect}; +use api::{LayerSize, LocalClip, NormalBorder}; use ellipse::Ellipse; use gpu_cache::GpuDataRequest; use frame_builder::FrameBuilder; @@ -9,8 +11,6 @@ use mask_cache::ClipSource; use prim_store::{BorderPrimitiveCpu, PrimitiveContainer}; use tiling::PrimitiveFlags; use util::{lerp, pack_as_float}; -use api::{BorderSide, BorderStyle, BorderWidths, ClipAndScrollInfo, ColorF}; -use api::{LayerPoint, LayerRect, LayerSize, NormalBorder}; #[repr(u8)] #[derive(Debug, Copy, Clone, PartialEq)] @@ -226,7 +226,7 @@ impl FrameBuilder { border: &NormalBorder, widths: &BorderWidths, clip_and_scroll: ClipAndScrollInfo, - clip_rect: &LayerRect, + local_clip: &LocalClip, corner_instances: [BorderCornerInstance; 4], extra_clips: &[ClipSource]) { let radius = &border.radius; @@ -273,7 +273,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, extra_clips, PrimitiveContainer::Border(prim_cpu)); } @@ -287,7 +287,7 @@ impl FrameBuilder { border: &NormalBorder, widths: &BorderWidths, clip_and_scroll: ClipAndScrollInfo, - clip_rect: &LayerRect) { + local_clip: &LocalClip) { // The border shader is quite expensive. For simple borders, we can just draw // the border with a few rectangles. This generally gives better batching, and // a GPU win in fragment shader time. @@ -367,7 +367,7 @@ impl FrameBuilder { if top_edge == BorderEdgeKind::Solid { self.add_solid_rectangle(clip_and_scroll, &LayerRect::new(p0, LayerSize::new(rect_width, top_len)), - clip_rect, + local_clip, &border.top.color, PrimitiveFlags::None); } @@ -376,7 +376,7 @@ impl FrameBuilder { &LayerRect::new(LayerPoint::new(p0.x, p0.y + top_len), LayerSize::new(left_len, rect_height - top_len - bottom_len)), - clip_rect, + local_clip, &border.left.color, PrimitiveFlags::None); } @@ -386,7 +386,7 @@ impl FrameBuilder { p0.y + top_len), LayerSize::new(right_len, rect_height - top_len - bottom_len)), - clip_rect, + local_clip, &border.right.color, PrimitiveFlags::None); } @@ -394,7 +394,7 @@ impl FrameBuilder { self.add_solid_rectangle(clip_and_scroll, &LayerRect::new(LayerPoint::new(p0.x, p1.y - bottom_len), LayerSize::new(rect_width, bottom_len)), - clip_rect, + local_clip, &border.bottom.color, PrimitiveFlags::None); } @@ -423,7 +423,7 @@ impl FrameBuilder { border, widths, clip_and_scroll, - clip_rect, + local_clip, corner_instances, &extra_clips); } diff --git a/webrender/src/clip_scroll_node.rs b/webrender/src/clip_scroll_node.rs index 578b9f0a28..0b78d1532c 100644 --- a/webrender/src/clip_scroll_node.rs +++ b/webrender/src/clip_scroll_node.rs @@ -2,15 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{ClipId, DeviceIntRect, LayerPixel, LayerPoint, LayerRect, LayerSize}; +use api::{LayerToScrollTransform, LayerToWorldTransform, LayerVector2D, PipelineId}; +use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, WorldPoint}; use geometry::ray_intersects_rect; -use mask_cache::{ClipSource, MaskCacheInfo}; +use mask_cache::{ClipRegion, ClipSource, MaskCacheInfo}; use spring::{DAMPING, STIFFNESS, Spring}; -use tiling::{DisplayListMap, PackedLayerIndex}; -use util::{ComplexClipRegionHelpers, MatrixHelpers, TransformedRectKind}; -use api::{ClipId, ClipRegion, DeviceIntRect, LayerPixel, LayerPoint, LayerRect}; -use api::{LayerSize, LayerToScrollTransform, LayerToWorldTransform, PipelineId}; -use api::{ScrollClamping, ScrollEventPhase, ScrollLocation}; -use api::{WorldPoint, LayerVector2D}; +use tiling::PackedLayerIndex; +use util::{MatrixHelpers, TransformedRectKind}; #[cfg(target_os = "macos")] const CAN_OVERSCROLL: bool = true; @@ -39,19 +38,23 @@ pub struct ClipInfo { /// The biggest final transformed rectangle that is completely inside the /// clipping region for this node. pub screen_inner_rect: DeviceIntRect, + + /// A rectangle which defines the rough boundaries of this clip in reference + /// frame relative coordinates (with no scroll offsets). + pub clip_rect: LayerRect, } impl ClipInfo { - pub fn new(clip_region: &ClipRegion, - packed_layer_index: PackedLayerIndex) - -> ClipInfo { - let clip_sources = vec![ClipSource::Region(clip_region.clone())]; + pub fn new(clip_region: ClipRegion, packed_layer_index: PackedLayerIndex) -> ClipInfo { + let clip_rect = LayerRect::new(clip_region.origin, clip_region.main.size); + let clip_sources = vec![ClipSource::Region(clip_region)]; ClipInfo { mask_cache_info: MaskCacheInfo::new(&clip_sources), clip_sources, packed_layer_index, screen_bounding_rect: None, screen_inner_rect: DeviceIntRect::zero(), + clip_rect: clip_rect, } } } @@ -118,11 +121,11 @@ pub struct ClipScrollNode { impl ClipScrollNode { pub fn new_scroll_frame(pipeline_id: PipelineId, parent_id: ClipId, - content_rect: &LayerRect, - frame_rect: &LayerRect) + frame_rect: &LayerRect, + content_size: &LayerSize) -> ClipScrollNode { ClipScrollNode { - content_size: content_rect.size, + content_size: *content_size, local_viewport_rect: *frame_rect, local_clip_rect: *frame_rect, combined_local_viewport_rect: LayerRect::zero(), @@ -136,29 +139,11 @@ impl ClipScrollNode { } } - pub fn new(pipeline_id: PipelineId, - parent_id: ClipId, - content_rect: &LayerRect, - clip_rect: &LayerRect, - clip_info: ClipInfo) - -> ClipScrollNode { - // FIXME(mrobinson): We don't yet handle clipping rectangles that don't start at the origin - // of the node. - // Accumulate the local clips - //Note: `MaskCacheInfo::bounds` have that intersection as well, - // but we don't have it by hand - let local_viewport_rect = LayerRect::new(content_rect.origin, clip_rect.size); - let local_clip_rect = clip_info.clip_sources.iter().fold( - Some(*clip_rect), |intersection, source| match *source { - ClipSource::Complex(rect, _, _) => intersection.and_then(|r| r.intersection(&rect)), - ClipSource::Region(ref region) => intersection.and_then(|r| r.intersection(®ion.main)), - ClipSource::BorderCorner(_) => intersection, - } - ); + pub fn new(pipeline_id: PipelineId, parent_id: ClipId, clip_info: ClipInfo) -> ClipScrollNode { ClipScrollNode { - content_size: content_rect.size, - local_viewport_rect, - local_clip_rect: LayerRect::new(content_rect.origin, local_clip_rect.unwrap_or(LayerRect::zero()).size), + content_size: clip_info.clip_rect.size, + local_viewport_rect: clip_info.clip_rect, + local_clip_rect: clip_info.clip_rect, combined_local_viewport_rect: LayerRect::zero(), world_viewport_transform: LayerToWorldTransform::identity(), world_content_transform: LayerToWorldTransform::identity(), @@ -408,38 +393,6 @@ impl ClipScrollNode { _ => false, } } - - pub fn find_unclipped_rectangle(&self, - display_lists: &DisplayListMap, - rect: &LayerRect) - -> Option { - let clip_sources = match self.node_type { - NodeType::Clip(ref clip_info) => &clip_info.clip_sources, - _ => return None, - }; - - let clip_region = match clip_sources.last() { - Some(&ClipSource::Region(ref clip_region)) if clip_sources.len() == 1 => clip_region, - _ => return None, - }; - - if clip_region.image_mask.is_some() || clip_region.complex_clips.is_empty() { - return None; - } - - let offset = &self.local_viewport_rect.origin.to_vector(); - let display_list = display_lists.get(&self.pipeline_id).expect("No display list?"); - let complex_clips = display_list.get(clip_region.complex_clips); - - let base_rect = clip_region.main.translate(offset).intersection(rect); - complex_clips.fold(base_rect, |inner_combined, ccr| { - inner_combined.and_then(|combined| { - ccr.get_inner_rect_full().and_then(|ir| { - ir.translate(offset).intersection(&combined) - }) - }) - }) - } } #[derive(Copy, Clone, Debug)] diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index a31283a612..bd450642bd 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -2,7 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BuiltDisplayList, BuiltDisplayListIter, ClipAndScrollInfo, ClipId, ColorF}; +use api::{ComplexClipRegion, DeviceUintRect, DeviceUintSize, DisplayItemRef, Epoch, FilterOp}; +use api::{ImageDisplayItem, ItemRange, LayerPoint, LayerRect, LayerSize, LayerToScrollTransform}; +use api::{LayerVector2D, LayoutSize, LayoutTransform, LocalClip, MixBlendMode, PipelineId}; +use api::{ScrollClamping, ScrollEventPhase, ScrollLayerState, ScrollLocation, ScrollPolicy}; +use api::{SpecificDisplayItem, StackingContext, TileOffset, TransformStyle, WorldPoint}; use app_units::Au; +use clip_scroll_tree::{ClipScrollTree, ScrollStates}; use euclid::rect; use fnv::FnvHasher; use gpu_cache::GpuCache; @@ -10,7 +17,7 @@ use internal_types::{ANGLE_FLOAT_TO_FIXED, AxisDirection}; use internal_types::{LowLevelFilterOp}; use internal_types::{RendererFrame}; use frame_builder::{FrameBuilder, FrameBuilderConfig}; -use clip_scroll_tree::{ClipScrollTree, ScrollStates}; +use mask_cache::ClipRegion; use profiler::{GpuCacheProfileCounters, TextureCacheProfileCounters}; use resource_cache::ResourceCache; use scene::{Scene, SceneProperties}; @@ -18,14 +25,7 @@ use std::cmp; use std::collections::HashMap; use std::hash::BuildHasherDefault; use tiling::{CompositeOps, DisplayListMap, PrimitiveFlags}; -use util::subtract_rect; -use api::{BuiltDisplayList, BuiltDisplayListIter, ClipAndScrollInfo, ClipDisplayItem}; -use api::{ClipId, ClipRegion, ColorF, DeviceUintRect, DeviceUintSize, DisplayItemRef}; -use api::{Epoch, FilterOp, ImageDisplayItem, ItemRange, LayerPoint, LayerRect}; -use api::{LayerSize, LayerToScrollTransform, LayoutSize, LayoutTransform, LayerVector2D}; -use api::{MixBlendMode, PipelineId, ScrollClamping, ScrollEventPhase}; -use api::{ScrollLayerState, ScrollLocation, ScrollPolicy, SpecificDisplayItem}; -use api::{StackingContext, TileOffset, TransformStyle, WorldPoint}; +use util::{ComplexClipRegionHelpers, subtract_rect}; #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] pub struct FrameId(pub u32); @@ -152,6 +152,20 @@ impl<'a> FlattenContext<'a> { _ => id, } } + + fn get_complex_clips(&self, + pipeline_id: PipelineId, + complex_clips: ItemRange) + -> Vec { + if complex_clips.is_empty() { + return vec![]; + } + + self.scene.display_lists.get(&pipeline_id) + .expect("No display list?") + .get(complex_clips) + .collect() + } } // TODO: doc @@ -341,36 +355,39 @@ impl Frame { fn flatten_clip<'a>(&mut self, context: &mut FlattenContext, pipeline_id: PipelineId, - parent_id: ClipId, - item: &ClipDisplayItem, - content_rect: &LayerRect, - clip: &ClipRegion) { - let is_scroll_frame = - clip.main.origin != LayerPoint::zero() || clip.main.size != content_rect.size; - - let new_id = context.convert_new_id_to_neested(&item.id); - let new_clip_id = if is_scroll_frame { - self.clip_scroll_tree.generate_new_clip_id(pipeline_id) - } else { - new_id - }; + parent_id: &ClipId, + new_clip_id: &ClipId, + clip_region: ClipRegion) { + let new_clip_id = context.convert_new_id_to_neested(new_clip_id); + context.builder.add_clip_node(new_clip_id, + *parent_id, + pipeline_id, + clip_region, + &mut self.clip_scroll_tree); + } - let clip_viewport = LayerRect::new(content_rect.origin, clip.main.size); - context.builder.add_clip_scroll_node(new_clip_id, - parent_id, - pipeline_id, - &clip_viewport, - clip, - &mut self.clip_scroll_tree); - if is_scroll_frame { - context.builder.add_scroll_frame(new_id, - new_clip_id, - pipeline_id, - &content_rect, - &clip_viewport, - &mut self.clip_scroll_tree); - } + fn flatten_scroll_frame<'a>(&mut self, + context: &mut FlattenContext, + pipeline_id: PipelineId, + parent_id: &ClipId, + new_scroll_frame_id: &ClipId, + frame_rect: &LayerRect, + content_rect: &LayerRect, + clip_region: ClipRegion) { + let clip_id = self.clip_scroll_tree.generate_new_clip_id(pipeline_id); + context.builder.add_clip_node(clip_id, + *parent_id, + pipeline_id, + clip_region, + &mut self.clip_scroll_tree); + let new_scroll_frame_id = context.convert_new_id_to_neested(new_scroll_frame_id); + context.builder.add_scroll_frame(new_scroll_frame_id, + clip_id, + pipeline_id, + &frame_rect, + &content_rect.size, + &mut self.clip_scroll_tree); } fn flatten_stacking_context<'a>(&mut self, @@ -497,8 +514,8 @@ impl Frame { ClipId::root_scroll_node(pipeline_id), iframe_reference_frame_id, pipeline_id, - &LayerRect::new(LayerPoint::zero(), pipeline.content_size), &iframe_rect, + &pipeline.content_size, &mut self.clip_scroll_tree); self.flatten_root(&mut display_list.iter(), pipeline_id, context, &pipeline.content_size); @@ -523,7 +540,7 @@ impl Frame { SpecificDisplayItem::WebGL(ref info) => { context.builder.add_webgl_rectangle(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info.context_id); } SpecificDisplayItem::Image(ref info) => { @@ -536,14 +553,14 @@ impl Frame { self.decompose_image(clip_and_scroll, context, &item.rect(), - item.clip_rect(), + item.local_clip(), info, image_size, tile_size as u32); } else { context.builder.add_image(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), &info.stretch_size, &info.tile_spacing, None, @@ -555,7 +572,7 @@ impl Frame { SpecificDisplayItem::YuvImage(ref info) => { context.builder.add_yuv_image(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info.yuv_data, info.color_space, info.image_rendering); @@ -563,7 +580,7 @@ impl Frame { SpecificDisplayItem::Text(ref text_info) => { context.builder.add_text(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), text_info.font_key, text_info.size, text_info.blur_radius, @@ -575,14 +592,12 @@ impl Frame { SpecificDisplayItem::Rectangle(ref info) => { if !self.try_to_add_rectangle_splitting_on_clip(context, &item.rect(), - item.clip_rect(), + item.local_clip(), &info.color, - &clip_and_scroll, - &reference_frame_relative_offset, - &context.scene.display_lists) { + &clip_and_scroll) { context.builder.add_solid_rectangle(clip_and_scroll, &item.rect(), - item.clip_rect(), + item.local_clip(), &info.color, PrimitiveFlags::None); @@ -591,7 +606,7 @@ impl Frame { SpecificDisplayItem::Gradient(ref info) => { context.builder.add_gradient(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info.gradient.start_point, info.gradient.end_point, item.gradient_stops(), @@ -604,7 +619,7 @@ impl Frame { SpecificDisplayItem::RadialGradient(ref info) => { context.builder.add_radial_gradient(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info.gradient.start_center, info.gradient.start_radius, info.gradient.end_center, @@ -618,7 +633,7 @@ impl Frame { SpecificDisplayItem::BoxShadow(ref box_shadow_info) => { context.builder.add_box_shadow(clip_and_scroll, &box_shadow_info.box_bounds, - item.clip_rect(), + item.local_clip(), &box_shadow_info.offset, &box_shadow_info.color, box_shadow_info.blur_radius, @@ -629,7 +644,7 @@ impl Frame { SpecificDisplayItem::Border(ref info) => { context.builder.add_border(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info, item.gradient_stops(), item.display_list() @@ -655,13 +670,39 @@ impl Frame { reference_frame_relative_offset); } SpecificDisplayItem::Clip(ref info) => { - let content_rect = &item.rect().translate(&reference_frame_relative_offset); + let complex_clips = context.get_complex_clips(pipeline_id, item.complex_clip().0); + let mut clip_region = ClipRegion::for_clip_node(*item.local_clip().clip_rect(), + complex_clips, + info.image_mask); + clip_region.origin += reference_frame_relative_offset; + self.flatten_clip(context, pipeline_id, - clip_and_scroll.scroll_node_id, - &info, - &content_rect, - item.clip_region()); + &clip_and_scroll.scroll_node_id, + &info.id, + clip_region); + } + SpecificDisplayItem::ScrollFrame(ref info) => { + let complex_clips = context.get_complex_clips(pipeline_id, item.complex_clip().0); + let mut clip_region = ClipRegion::for_clip_node(*item.local_clip().clip_rect(), + complex_clips, + info.image_mask); + clip_region.origin += reference_frame_relative_offset; + + // Just use clip rectangle as the frame rect for this scroll frame. + // This is only interesting when calculating scroll extents for the + // ClipScrollNode::scroll(..) API + let frame_rect = item.local_clip() + .clip_rect() + .translate(&reference_frame_relative_offset); + let content_rect = item.rect().translate(&reference_frame_relative_offset); + self.flatten_scroll_frame(context, + pipeline_id, + &clip_and_scroll.scroll_node_id, + &info.id, + &frame_rect, + &content_rect, + clip_region); } SpecificDisplayItem::PushNestedDisplayList => { // Using the clip and scroll already processed for nesting here @@ -688,11 +729,9 @@ impl Frame { fn try_to_add_rectangle_splitting_on_clip(&mut self, context: &mut FlattenContext, rect: &LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, color: &ColorF, - clip_and_scroll: &ClipAndScrollInfo, - reference_frame_relative_offset: &LayerVector2D, - display_lists: &DisplayListMap) + clip_and_scroll: &ClipAndScrollInfo) -> bool { // If this rectangle is not opaque, splitting the rectangle up // into an inner opaque region just ends up hurting batching and @@ -701,71 +740,37 @@ impl Frame { return false; } - let (unclipped_rect, parent_clip_and_scroll) = - match self.find_unclipped_rectangle(clip_and_scroll, - rect, - reference_frame_relative_offset, - display_lists) { - Some((rect, clip_and_scroll)) => (rect, clip_and_scroll), + let inner_unclipped_rect = match local_clip { + &LocalClip::Rect(_) => return false, + &LocalClip::RoundedRect(_, ref region) => region.get_inner_rect_full(), + }; + let inner_unclipped_rect = match inner_unclipped_rect { + Some(rect) => rect, None => return false, }; - // The inner rectangle is not clipped by its assigned clipping node, so we can // let it be clipped by the parent of the clipping node, which may result in // less masking some cases. let mut clipped_rects = Vec::new(); - subtract_rect(rect, &unclipped_rect, &mut clipped_rects); + subtract_rect(rect, &inner_unclipped_rect, &mut clipped_rects); - context.builder.add_solid_rectangle(parent_clip_and_scroll, - &unclipped_rect, - clip_rect, + context.builder.add_solid_rectangle(*clip_and_scroll, + &inner_unclipped_rect, + &LocalClip::from(*local_clip.clip_rect()), color, PrimitiveFlags::None); for clipped_rect in &clipped_rects { context.builder.add_solid_rectangle(*clip_and_scroll, clipped_rect, - clip_rect, + local_clip, color, PrimitiveFlags::None); } true } - fn find_unclipped_rectangle(&mut self, - clip_and_scroll: &ClipAndScrollInfo, - rect: &LayerRect, - reference_frame_relative_offset: &LayerVector2D, - display_lists: &DisplayListMap) - -> Option<(LayerRect, ClipAndScrollInfo)> { - // Try to extract the opaque inner rectangle out of the clipped primitive. - if clip_and_scroll.scroll_node_id != clip_and_scroll.clip_node_id() { - return None; - } - - let clip_node = match self.clip_scroll_tree.nodes.get(&clip_and_scroll.scroll_node_id) { - Some(node) => node, - None => return None, - }; - - let parent_node_id = match clip_node.parent { - Some(id) => id, - None => return None, - }; - - let rect_in_reference_frame = rect.translate(reference_frame_relative_offset); - let unclipped_rect = match clip_node.find_unclipped_rectangle(display_lists, - &rect_in_reference_frame) { - Some(rect) => rect, - None => return None, - }; - - let mut new_clip_and_scroll = *clip_and_scroll; - new_clip_and_scroll.clip_node_id = Some(parent_node_id); - Some((unclipped_rect, new_clip_and_scroll)) - } - fn flatten_root<'a>(&mut self, traversal: &mut BuiltDisplayListIter<'a>, pipeline_id: PipelineId, @@ -791,7 +796,7 @@ impl Frame { let root_bounds = LayerRect::new(LayerPoint::zero(), *content_size); context.builder.add_solid_rectangle(ClipAndScrollInfo::simple(clip_id), &root_bounds, - &root_bounds, + &LocalClip::from(root_bounds), &bg_color, PrimitiveFlags::None); } @@ -806,7 +811,7 @@ impl Frame { context.builder.add_solid_rectangle( ClipAndScrollInfo::simple(clip_id), &scrollbar_rect, - &scrollbar_rect, + &LocalClip::from(scrollbar_rect), &DEFAULT_SCROLLBAR_COLOR, PrimitiveFlags::Scrollbar(self.clip_scroll_tree.topmost_scrolling_node_id(), 4.0)); } @@ -856,7 +861,7 @@ impl Frame { clip_and_scroll: ClipAndScrollInfo, context: &mut FlattenContext, item_rect: &LayerRect, - item_clip_rect: &LayerRect, + item_local_clip: &LocalClip, info: &ImageDisplayItem, image_size: DeviceUintSize, tile_size: u32) { @@ -866,7 +871,7 @@ impl Frame { self.decompose_image_row(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, image_size, tile_size); @@ -886,7 +891,7 @@ impl Frame { self.decompose_image_row(clip_and_scroll, context, &row_rect, - item_clip_rect, + item_local_clip, info, image_size, tile_size); @@ -898,7 +903,7 @@ impl Frame { clip_and_scroll: ClipAndScrollInfo, context: &mut FlattenContext, item_rect: &LayerRect, - item_clip_rect: &LayerRect, + item_local_clip: &LocalClip, info: &ImageDisplayItem, image_size: DeviceUintSize, tile_size: u32) { @@ -908,7 +913,7 @@ impl Frame { self.decompose_tiled_image(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, image_size, tile_size); @@ -928,7 +933,7 @@ impl Frame { self.decompose_tiled_image(clip_and_scroll, context, &decomposed_rect, - item_clip_rect, + item_local_clip, info, image_size, tile_size); @@ -940,7 +945,7 @@ impl Frame { clip_and_scroll: ClipAndScrollInfo, context: &mut FlattenContext, item_rect: &LayerRect, - item_clip_rect: &LayerRect, + item_local_clip: &LocalClip, info: &ImageDisplayItem, image_size: DeviceUintSize, tile_size: u32) { @@ -1019,7 +1024,7 @@ impl Frame { self.add_tile_primitive(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, TileOffset::new(tx, ty), stretched_tile_size, @@ -1031,7 +1036,7 @@ impl Frame { self.add_tile_primitive(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, TileOffset::new(num_tiles_x, ty), stretched_tile_size, @@ -1047,7 +1052,7 @@ impl Frame { self.add_tile_primitive(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, TileOffset::new(tx, num_tiles_y), stretched_tile_size, @@ -1062,7 +1067,7 @@ impl Frame { self.add_tile_primitive(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, TileOffset::new(num_tiles_x, num_tiles_y), stretched_tile_size, @@ -1078,7 +1083,7 @@ impl Frame { clip_and_scroll: ClipAndScrollInfo, context: &mut FlattenContext, item_rect: &LayerRect, - item_clip_rect: &LayerRect, + item_local_clip: &LocalClip, info: &ImageDisplayItem, tile_offset: TileOffset, stretched_tile_size: LayerSize, @@ -1122,7 +1127,7 @@ impl Frame { if let Some(prim_rect) = prim_rect.intersection(item_rect) { context.builder.add_image(clip_and_scroll, prim_rect, - item_clip_rect, + item_local_clip, &stretched_size, &info.tile_spacing, None, diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index db3240efd9..db5947328e 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -2,11 +2,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BorderDetails, BorderDisplayItem, BoxShadowClipMode, ClipAndScrollInfo, ClipId, ColorF}; +use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize}; +use api::{ExtendMode, FontKey, FontRenderMode, GlyphInstance, GlyphOptions, GradientStop}; +use api::{ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize}; +use api::{LayerToScrollTransform, LayerVector2D, LocalClip, PipelineId, RepeatMode, TileOffset}; +use api::{TransformStyle, WebGLContextId, WorldPixel, YuvColorSpace, YuvData}; use app_units::Au; use frame::FrameId; use gpu_cache::GpuCache; use internal_types::HardwareCompositeOp; -use mask_cache::{ClipMode, ClipSource, MaskCacheInfo}; +use mask_cache::{ClipMode, ClipRegion, ClipSource, MaskCacheInfo}; use plane_split::{BspSplitter, Polygon, Splitter}; use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu}; use prim_store::{ImagePrimitiveKind, PrimitiveContainer, PrimitiveIndex}; @@ -28,13 +34,6 @@ use tiling::{PackedLayer, PackedLayerIndex, PrimitiveFlags, PrimitiveRunCmd, Ren use tiling::{RenderTargetContext, RenderTaskCollection, ScrollbarPrimitive, StackingContext}; use util::{self, pack_as_float, subtract_rect, recycle_vec}; use util::{MatrixHelpers, RectHelpers}; -use api::{BorderDetails, BorderDisplayItem, BoxShadowClipMode, ClipAndScrollInfo}; -use api::{ClipId, ClipRegion, ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize}; -use api::{DeviceUintRect, DeviceUintSize, ExtendMode, FontKey, FontRenderMode}; -use api::{GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering}; -use api::{ItemRange, LayerPoint, LayerRect, LayerSize, LayerToScrollTransform}; -use api::{PipelineId, RepeatMode, TileOffset, TransformStyle, WebGLContextId}; -use api::{WorldPixel, YuvColorSpace, YuvData, LayerVector2D}; #[derive(Debug, Clone)] struct ImageBorderSegment { @@ -189,7 +188,7 @@ impl FrameBuilder { pub fn add_primitive(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: &LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, extra_clips: &[ClipSource], container: PrimitiveContainer) -> PrimitiveIndex { @@ -197,7 +196,11 @@ impl FrameBuilder { self.create_clip_scroll_group_if_necessary(stacking_context_index, clip_and_scroll); - let clip_sources = extra_clips.to_vec(); + let mut clip_sources = extra_clips.to_vec(); + if let &LocalClip::RoundedRect(_, _) = local_clip { + clip_sources.push(ClipSource::Region(ClipRegion::for_local_clip(local_clip))) + } + let clip_info = if !clip_sources.is_empty() { Some(MaskCacheInfo::new(&clip_sources)) } else { @@ -205,7 +208,7 @@ impl FrameBuilder { }; let prim_index = self.prim_store.add_primitive(rect, - &clip_rect, + &local_clip.clip_rect(), clip_sources, clip_info, container); @@ -351,28 +354,21 @@ impl FrameBuilder { self.add_scroll_frame(topmost_scrolling_node_id, clip_scroll_tree.root_reference_frame_id, pipeline_id, - &LayerRect::new(LayerPoint::zero(), *content_size), &viewport_rect, + content_size, clip_scroll_tree); topmost_scrolling_node_id } - pub fn add_clip_scroll_node(&mut self, - new_node_id: ClipId, - parent_id: ClipId, - pipeline_id: PipelineId, - content_rect: &LayerRect, - clip_region: &ClipRegion, - clip_scroll_tree: &mut ClipScrollTree) { - let clip_info = ClipInfo::new(clip_region, - PackedLayerIndex(self.packed_layers.len())); - let node = ClipScrollNode::new(pipeline_id, - parent_id, - content_rect, - &clip_region.main, - clip_info); - + pub fn add_clip_node(&mut self, + new_node_id: ClipId, + parent_id: ClipId, + pipeline_id: PipelineId, + clip_region: ClipRegion, + clip_scroll_tree: &mut ClipScrollTree) { + let clip_info = ClipInfo::new(clip_region, PackedLayerIndex(self.packed_layers.len())); + let node = ClipScrollNode::new(pipeline_id, parent_id, clip_info); clip_scroll_tree.add_node(node, new_node_id); self.packed_layers.push(PackedLayer::empty()); } @@ -381,13 +377,13 @@ impl FrameBuilder { new_node_id: ClipId, parent_id: ClipId, pipeline_id: PipelineId, - content_rect: &LayerRect, frame_rect: &LayerRect, + content_size: &LayerSize, clip_scroll_tree: &mut ClipScrollTree) { let node = ClipScrollNode::new_scroll_frame(pipeline_id, parent_id, - content_rect, - frame_rect); + frame_rect, + content_size); clip_scroll_tree.add_node(node, new_node_id); } @@ -399,7 +395,7 @@ impl FrameBuilder { pub fn add_solid_rectangle(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: &LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, color: &ColorF, flags: PrimitiveFlags) { if color.a == 0.0 { @@ -412,7 +408,7 @@ impl FrameBuilder { let prim_index = self.add_primitive(clip_and_scroll, rect, - clip_rect, + local_clip, &[], PrimitiveContainer::Rectangle(prim)); @@ -431,7 +427,7 @@ impl FrameBuilder { pub fn add_border(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, border_item: &BorderDisplayItem, gradient_stops: ItemRange, gradient_stops_count: usize) { @@ -578,7 +574,7 @@ impl FrameBuilder { for segment in segments { self.add_image(clip_and_scroll, segment.geom_rect, - clip_rect, + local_clip, &segment.stretch_size, &segment.tile_spacing, Some(segment.sub_rect), @@ -592,7 +588,7 @@ impl FrameBuilder { border, &border_item.widths, clip_and_scroll, - clip_rect); + local_clip); } BorderDetails::Gradient(ref border) => { for segment in create_segments(border.outset) { @@ -600,7 +596,7 @@ impl FrameBuilder { self.add_gradient(clip_and_scroll, segment, - clip_rect, + local_clip, border.gradient.start_point - segment_rel, border.gradient.end_point - segment_rel, gradient_stops, @@ -616,7 +612,7 @@ impl FrameBuilder { self.add_radial_gradient(clip_and_scroll, segment, - clip_rect, + local_clip, border.gradient.start_center - segment_rel, border.gradient.start_radius, border.gradient.end_center - segment_rel, @@ -634,7 +630,7 @@ impl FrameBuilder { pub fn add_gradient(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, start_point: LayerPoint, end_point: LayerPoint, stops: ItemRange, @@ -694,13 +690,13 @@ impl FrameBuilder { PrimitiveContainer::AngleGradient(gradient_cpu) }; - self.add_primitive(clip_and_scroll, &rect, clip_rect, &[], prim); + self.add_primitive(clip_and_scroll, &rect, local_clip, &[], prim); } pub fn add_radial_gradient(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, start_center: LayerPoint, start_radius: f32, end_center: LayerPoint, @@ -725,7 +721,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, &[], PrimitiveContainer::RadialGradient(radial_gradient_cpu)); } @@ -733,7 +729,7 @@ impl FrameBuilder { pub fn add_text(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, font_key: FontKey, size: Au, blur_radius: f32, @@ -796,7 +792,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, &[], PrimitiveContainer::TextRun(prim_cpu)); } @@ -805,7 +801,7 @@ impl FrameBuilder { clip_and_scroll: ClipAndScrollInfo, box_bounds: &LayerRect, bs_rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, color: &ColorF, border_radius: f32, clip_mode: BoxShadowClipMode) { @@ -828,7 +824,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect_to_draw, - clip_rect, + local_clip, &extra_clips, PrimitiveContainer::Rectangle(prim)); } @@ -836,7 +832,7 @@ impl FrameBuilder { pub fn add_box_shadow(&mut self, clip_and_scroll: ClipAndScrollInfo, box_bounds: &LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, box_offset: &LayerVector2D, color: &ColorF, blur_radius: f32, @@ -866,7 +862,7 @@ impl FrameBuilder { || bs_rect_empty { self.add_solid_rectangle(clip_and_scroll, box_bounds, - clip_rect, + local_clip, color, PrimitiveFlags::None); return; @@ -876,7 +872,7 @@ impl FrameBuilder { self.fill_box_shadow_rect(clip_and_scroll, box_bounds, bs_rect, - clip_rect, + local_clip, color, border_radius, clip_mode); @@ -949,7 +945,7 @@ impl FrameBuilder { for rect in &rects { self.add_solid_rectangle(clip_and_scroll, rect, - clip_rect, + local_clip, color, PrimitiveFlags::None) } @@ -960,7 +956,7 @@ impl FrameBuilder { self.fill_box_shadow_rect(clip_and_scroll, box_bounds, bs_rect, - clip_rect, + local_clip, color, border_radius, clip_mode); @@ -998,7 +994,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &outer_rect, - clip_rect, + local_clip, extra_clips.as_slice(), PrimitiveContainer::BoxShadow(prim_cpu)); } @@ -1008,7 +1004,7 @@ impl FrameBuilder { pub fn add_webgl_rectangle(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, context_id: WebGLContextId) { let prim_cpu = ImagePrimitiveCpu { kind: ImagePrimitiveKind::WebGL(context_id), @@ -1018,7 +1014,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, &[], PrimitiveContainer::Image(prim_cpu)); } @@ -1026,7 +1022,7 @@ impl FrameBuilder { pub fn add_image(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, stretch_size: &LayerSize, tile_spacing: &LayerSize, sub_rect: Option, @@ -1050,7 +1046,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, &[], PrimitiveContainer::Image(prim_cpu)); } @@ -1058,7 +1054,7 @@ impl FrameBuilder { pub fn add_yuv_image(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + clip_rect: &LocalClip, yuv_data: YuvData, color_space: YuvColorSpace, image_rendering: ImageRendering) { @@ -1574,14 +1570,10 @@ impl<'a> LayerRectCalculationAndCullingPass<'a> { }; node_clip_info.screen_inner_rect = inner_rect; - let display_list = self.display_lists.get(&node.pipeline_id) - .expect("No display list?"); - let bounds = node_clip_info.mask_cache_info.update(&node_clip_info.clip_sources, &transform, self.gpu_cache, - self.device_pixel_ratio, - display_list); + self.device_pixel_ratio); node_clip_info.screen_inner_rect = bounds.inner.as_ref() .and_then(|inner| inner.device_rect.intersection(&inner_rect)) diff --git a/webrender/src/mask_cache.rs b/webrender/src/mask_cache.rs index 5e205e6952..e77292eb13 100644 --- a/webrender/src/mask_cache.rs +++ b/webrender/src/mask_cache.rs @@ -2,17 +2,63 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BorderRadius, ComplexClipRegion, DeviceIntRect, ImageMask, LayerPoint, LayerRect}; +use api::{LayerSize, LayerToWorldTransform, LocalClip}; use border::BorderCornerClipSource; use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks}; use prim_store::{CLIP_DATA_GPU_BLOCKS, ClipData, ImageMaskData}; use util::{ComplexClipRegionHelpers, TransformedRect}; -use api::{BorderRadius, BuiltDisplayList, ClipRegion, ComplexClipRegion, ImageMask}; -use api::{DeviceIntRect, LayerToWorldTransform}; -use api::{LayerRect, LayerPoint, LayerSize}; use std::ops::Not; const MAX_CLIP: f32 = 1000000.0; +#[derive(Clone, Debug)] +pub struct ClipRegion { + pub origin: LayerPoint, + pub main: LayerRect, + pub image_mask: Option, + pub complex_clips: Vec, +} + +impl ClipRegion { + pub fn for_clip_node(rect: LayerRect, + mut complex_clips: Vec, + mut image_mask: Option) + -> ClipRegion { + // All the coordinates we receive are relative to the stacking context, but we want + // to convert them to something relative to the origin of the clip. + let negative_origin = -rect.origin.to_vector(); + if let Some(ref mut image_mask) = image_mask { + image_mask.rect = image_mask.rect.translate(&negative_origin); + } + + for complex_clip in complex_clips.iter_mut() { + complex_clip.rect = complex_clip.rect.translate(&negative_origin); + } + + ClipRegion { + origin: rect.origin, + main: LayerRect::new(LayerPoint::zero(), rect.size), + image_mask, + complex_clips, + } + } + + pub fn for_local_clip(local_clip: &LocalClip) -> ClipRegion { + let complex_clips = match local_clip { + &LocalClip::Rect(_) => Vec::new(), + &LocalClip::RoundedRect(_, ref region) => vec![region.clone()], + }; + + ClipRegion { + origin: LayerPoint::zero(), + main: *local_clip.clip_rect(), + image_mask: None, + complex_clips, + } + } +} + #[repr(C)] #[derive(Copy, Clone, Debug, PartialEq)] pub enum ClipMode { @@ -158,7 +204,7 @@ impl MaskCacheInfo { debug_assert!(image.is_none()); // TODO(gw): Support >1 image mask! image = Some((info, GpuCacheHandle::new())); } - complex_clip_count += region.complex_clip_count; + complex_clip_count += region.complex_clips.len(); layer_clip_count += 1; } ClipSource::BorderCorner(ref source) => { @@ -183,8 +229,8 @@ impl MaskCacheInfo { sources: &[ClipSource], transform: &LayerToWorldTransform, gpu_cache: &mut GpuCache, - device_pixel_ratio: f32, - display_list: &BuiltDisplayList) -> &MaskBounds { + device_pixel_ratio: f32) + -> &MaskBounds { // Step[1] - compute the local bounds //TODO: move to initialization stage? @@ -220,7 +266,7 @@ impl MaskCacheInfo { None => local_rect, }; - for clip in display_list.get(region.complex_clips) { + for clip in ®ion.complex_clips { local_rect = local_rect.and_then(|r| r.intersection(&clip.rect)); local_inner = local_inner.and_then(|r| clip.get_inner_rect_safe() .and_then(|ref inner| r.intersection(inner))); @@ -264,7 +310,7 @@ impl MaskCacheInfo { data.write(&mut request); } ClipSource::Region(ref region) => { - for clip in display_list.get(region.complex_clips) { + for clip in ®ion.complex_clips { let data = ClipData::from_clip_region(&clip); data.write(&mut request); } diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index c4b6dfa226..64e2f764a8 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -2,23 +2,21 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BuiltDisplayList, ColorF, ComplexClipRegion, DeviceIntRect, DeviceIntSize, DevicePoint}; +use api::{ExtendMode, FontKey, FontRenderMode, GlyphInstance, GlyphOptions, GradientStop}; +use api::{ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize}; +use api::{LayerToWorldTransform, TileOffset, WebGLContextId, YuvColorSpace, YuvFormat}; +use api::device_length; use app_units::Au; use border::BorderCornerInstance; use euclid::{Size2D}; use gpu_cache::{GpuCacheAddress, GpuBlockData, GpuCache, GpuCacheHandle, GpuDataRequest, ToGpuBlocks}; -use mask_cache::{ClipMode, ClipSource, MaskCacheInfo}; +use mask_cache::{ClipMode, ClipRegion, ClipSource, MaskCacheInfo}; use renderer::MAX_VERTEX_TEXTURE_WIDTH; use render_task::{RenderTask, RenderTaskLocation}; use resource_cache::{ImageProperties, ResourceCache}; use std::{mem, usize}; use util::{TransformedRect, recycle_vec}; -use api::{BuiltDisplayList, ColorF, ImageKey, ImageRendering, YuvColorSpace}; -use api::{YuvFormat, ClipRegion, ComplexClipRegion, ItemRange}; -use api::{FontKey, FontRenderMode, WebGLContextId}; -use api::{device_length, DeviceIntRect, DeviceIntSize}; -use api::{DevicePoint, LayerRect, LayerSize, LayerPoint}; -use api::{LayerToWorldTransform, GlyphInstance, GlyphOptions}; -use api::{ExtendMode, GradientStop, TileOffset}; pub const CLIP_DATA_GPU_BLOCKS: usize = 10; @@ -969,11 +967,7 @@ impl PrimitiveStore { let metadata = &mut self.cpu_metadata[prim_index.0]; if let Some(ref mut clip_info) = metadata.clip_cache_info { - clip_info.update(&metadata.clips, - layer_transform, - gpu_cache, - device_pixel_ratio, - display_list); + clip_info.update(&metadata.clips, layer_transform, gpu_cache, device_pixel_ratio); //TODO-LCCR: we could tighten up the `local_clip_rect` here // but that would require invalidating the whole GPU block diff --git a/webrender_api/Cargo.toml b/webrender_api/Cargo.toml index 23c9c1aac4..308bcd2d8b 100644 --- a/webrender_api/Cargo.toml +++ b/webrender_api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender_api" -version = "0.46.0" +version = "0.47.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index d1c8099457..dc1ded5710 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -4,9 +4,8 @@ use app_units::Au; use euclid::SideOffsets2D; -use {ColorF, FontKey, ImageKey, ItemRange, PipelineId, WebGLContextId}; -use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D}; -use {PropertyBinding}; +use {ColorF, FontKey, ImageKey, LayoutPoint, LayoutRect, LayoutSize, LayoutTransform}; +use {LayoutVector2D, PipelineId, PropertyBinding, WebGLContextId}; // NOTE: some of these structs have an "IMPLICIT" comment. // This indicates that the BuiltDisplayList will have serialized @@ -43,13 +42,14 @@ impl ClipAndScrollInfo { pub struct DisplayItem { pub item: SpecificDisplayItem, pub rect: LayoutRect, - pub clip_rect: LayoutRect, + pub local_clip: LocalClip, pub clip_and_scroll: ClipAndScrollInfo, } #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub enum SpecificDisplayItem { Clip(ClipDisplayItem), + ScrollFrame(ClipDisplayItem), Rectangle(RectangleDisplayItem), Text(TextDisplayItem), Image(ImageDisplayItem), @@ -71,7 +71,7 @@ pub enum SpecificDisplayItem { pub struct ClipDisplayItem { pub id: ClipId, pub parent_id: ClipId, - pub clip_region: ClipRegion, + pub image_mask: Option, } #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] @@ -448,16 +448,26 @@ pub struct ImageMask { } #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] -pub struct ClipRegion { - pub main: LayoutRect, - pub image_mask: Option, - #[serde(default, skip_serializing, skip_deserializing)] - pub complex_clips: ItemRange, - #[serde(default, skip_serializing, skip_deserializing)] - pub complex_clip_count: usize, +pub enum LocalClip { + Rect(LayoutRect), + RoundedRect(LayoutRect, ComplexClipRegion), +} + +impl From for LocalClip { + fn from(rect: LayoutRect) -> Self { + LocalClip::Rect(rect) + } +} + +impl LocalClip { + pub fn clip_rect(&self) -> &LayoutRect { + match *self { + LocalClip::Rect(ref rect) => rect, + LocalClip::RoundedRect(ref rect, _) => &rect, + } + } } -#[repr(C)] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct ComplexClipRegion { /// The boundaries of the rectangle. @@ -521,41 +531,6 @@ impl BorderRadius { } } -impl ClipRegion { - pub fn new(rect: &LayoutRect, - image_mask: Option) - -> ClipRegion { - ClipRegion { - main: *rect, - image_mask, - complex_clips: ItemRange::default(), - complex_clip_count: 0, - } - } - - pub fn simple(rect: &LayoutRect) -> ClipRegion { - ClipRegion { - main: *rect, - image_mask: None, - complex_clips: ItemRange::default(), - complex_clip_count: 0, - } - } - - pub fn empty() -> ClipRegion { - ClipRegion { - main: LayoutRect::zero(), - image_mask: None, - complex_clips: ItemRange::default(), - complex_clip_count: 0, - } - } - - pub fn is_complex(&self) -> bool { - self.complex_clip_count != 0 || self.image_mask.is_some() - } -} - impl ColorF { pub fn new(r: f32, g: f32, b: f32, a: f32) -> ColorF { ColorF { @@ -661,3 +636,4 @@ define_empty_heap_size_of!(RepeatMode); define_empty_heap_size_of!(ImageKey); define_empty_heap_size_of!(MixBlendMode); define_empty_heap_size_of!(TransformStyle); +define_empty_heap_size_of!(LocalClip); diff --git a/webrender_api/src/display_list.rs b/webrender_api/src/display_list.rs index e597d89658..26c4a0321c 100644 --- a/webrender_api/src/display_list.rs +++ b/webrender_api/src/display_list.rs @@ -7,11 +7,11 @@ use bincode; use serde::{Deserialize, Serialize, Serializer}; use serde::ser::{SerializeSeq, SerializeMap}; use time::precise_time_ns; -use {ImageMask, BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem}; -use {ClipAndScrollInfo, ClipDisplayItem, ClipId, ClipRegion, ColorF, ComplexClipRegion}; -use {DisplayItem, ExtendMode, FilterOp, FontKey, GlyphInstance, GlyphOptions, Gradient}; -use {GradientDisplayItem, GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey}; -use {ImageRendering, LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D}; +use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem}; +use {ClipAndScrollInfo, ClipDisplayItem, ClipId, ColorF, ComplexClipRegion, DisplayItem}; +use {ExtendMode, FilterOp, FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem}; +use {GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering}; +use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, LocalClip}; use {MixBlendMode, PipelineId, PropertyBinding, PushStackingContextDisplayItem, RadialGradient}; use {RadialGradientDisplayItem, RectangleDisplayItem, ScrollPolicy, SpecificDisplayItem}; use {StackingContext, TextDisplayItem, TransformStyle, WebGLContextId, WebGLDisplayItem}; @@ -67,7 +67,7 @@ pub struct BuiltDisplayListIter<'a> { cur_stops: ItemRange, cur_glyphs: ItemRange, cur_filters: ItemRange, - cur_clip: ClipRegion, + cur_complex_clip: (ItemRange, usize), peeking: Peek, } @@ -137,13 +137,13 @@ impl<'a> BuiltDisplayListIter<'a> { cur_item: DisplayItem { // Dummy data, will be overwritten by `next` item: SpecificDisplayItem::PopStackingContext, rect: LayoutRect::zero(), - clip_rect: LayoutRect::zero(), + local_clip: LocalClip::from(LayoutRect::zero()), clip_and_scroll: ClipAndScrollInfo::simple(ClipId::new(0, PipelineId(0, 0))), }, cur_stops: ItemRange::default(), cur_glyphs: ItemRange::default(), cur_filters: ItemRange::default(), - cur_clip: ClipRegion::empty(), + cur_complex_clip: (ItemRange::default(), 0), peeking: Peek::NotPeeking, } } @@ -168,7 +168,7 @@ impl<'a> BuiltDisplayListIter<'a> { // Don't let these bleed into another item self.cur_stops = ItemRange::default(); - self.cur_clip = ClipRegion::empty(); + self.cur_complex_clip = (ItemRange::default(), 0); loop { if self.data.len() == 0 { @@ -185,12 +185,8 @@ impl<'a> BuiltDisplayListIter<'a> { // This is a dummy item, skip over it continue; } - Clip(clip) => { - self.cur_clip = clip.clip_region; - let (clip_range, clip_count) = self.skip_slice::(); - self.cur_clip.complex_clip_count = clip_count; - self.cur_clip.complex_clips = clip_range; - } + Clip(_) | ScrollFrame(_) => + self.cur_complex_clip = self.skip_slice::(), Text(_) => self.cur_glyphs = self.skip_slice::().0, PushStackingContext(_) => self.cur_filters = self.skip_slice::().0, _ => { /* do nothing */ } @@ -276,8 +272,8 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> { self.iter.cur_item.rect } - pub fn clip_rect(&self) -> &LayoutRect { - &self.iter.cur_item.clip_rect + pub fn local_clip(&self) -> &LocalClip { + &self.iter.cur_item.local_clip } pub fn clip_and_scroll(&self) -> ClipAndScrollInfo { @@ -288,8 +284,8 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> { &self.iter.cur_item.item } - pub fn clip_region(&self) -> &ClipRegion { - &self.iter.cur_clip + pub fn complex_clip(&self) -> &(ItemRange, usize) { + &self.iter.cur_complex_clip } pub fn gradient_stops(&self) -> ItemRange { @@ -383,13 +379,12 @@ impl<'a, 'b> Serialize for DisplayItemRef<'a, 'b> { _ => { } } - let clip_region = self.clip_region(); + let &(complex_clips, number_of_complex_clips) = self.complex_clip(); let gradient_stops = self.gradient_stops(); - map.serialize_entry("clip_region", &clip_region)?; - if !clip_region.complex_clips.is_empty() { + if number_of_complex_clips > 0 { map.serialize_entry("complex_clips", - &self.iter.list.get(clip_region.complex_clips).collect::>())?; + &self.iter.list.get(complex_clips).collect::>())?; } if !gradient_stops.is_empty() { @@ -451,11 +446,15 @@ impl DisplayListBuilder { self.data = temp.data; } - fn push_item(&mut self, item: SpecificDisplayItem, rect: LayoutRect, clip_rect: LayoutRect) { + fn push_item(&mut self, + item: SpecificDisplayItem, + rect: LayoutRect, + local_clip: Option) { + let local_clip = local_clip.unwrap_or_else(|| LocalClip::from(rect)); bincode::serialize_into(&mut self.data, &DisplayItem { item, rect, - clip_rect, + local_clip: local_clip, clip_and_scroll: *self.clip_stack.last().unwrap(), }, bincode::Infinite).unwrap(); } @@ -464,7 +463,7 @@ impl DisplayListBuilder { bincode::serialize_into(&mut self.data, &DisplayItem { item, rect: LayoutRect::zero(), - clip_rect: LayoutRect::zero(), + local_clip: LocalClip::from(LayoutRect::zero()), clip_and_scroll: *self.clip_stack.last().unwrap(), }, bincode::Infinite).unwrap(); } @@ -487,17 +486,17 @@ impl DisplayListBuilder { debug_assert_eq!(len, count); } - pub fn push_rect(&mut self, rect: LayoutRect, clip_rect: LayoutRect, color: ColorF) { + pub fn push_rect(&mut self, rect: LayoutRect, local_clip: Option, color: ColorF) { let item = SpecificDisplayItem::Rectangle(RectangleDisplayItem { color, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_image(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, stretch_size: LayoutSize, tile_spacing: LayoutSize, image_rendering: ImageRendering, @@ -509,13 +508,13 @@ impl DisplayListBuilder { image_rendering, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } /// Push a yuv image. All planar data in yuv image should use the same buffer type. pub fn push_yuv_image(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, yuv_data: YuvData, color_space: YuvColorSpace, image_rendering: ImageRendering) { @@ -524,22 +523,22 @@ impl DisplayListBuilder { color_space, image_rendering, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_webgl_canvas(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, context_id: WebGLContextId) { let item = SpecificDisplayItem::WebGL(WebGLDisplayItem { context_id, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_text(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, glyphs: &[GlyphInstance], font_key: FontKey, color: ColorF, @@ -561,7 +560,7 @@ impl DisplayListBuilder { glyph_options, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); self.push_iter(glyphs); } } @@ -739,7 +738,7 @@ impl DisplayListBuilder { pub fn push_border(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, widths: BorderWidths, details: BorderDetails) { let item = SpecificDisplayItem::Border(BorderDisplayItem { @@ -747,12 +746,12 @@ impl DisplayListBuilder { widths, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_box_shadow(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, box_bounds: LayoutRect, offset: LayoutVector2D, color: ColorF, @@ -770,12 +769,12 @@ impl DisplayListBuilder { clip_mode, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_gradient(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, gradient: Gradient, tile_size: LayoutSize, tile_spacing: LayoutSize) { @@ -785,12 +784,12 @@ impl DisplayListBuilder { tile_spacing, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_radial_gradient(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, gradient: RadialGradient, tile_size: LayoutSize, tile_spacing: LayoutSize) { @@ -800,7 +799,7 @@ impl DisplayListBuilder { tile_spacing, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_stacking_context(&mut self, @@ -821,7 +820,7 @@ impl DisplayListBuilder { } }); - self.push_item(item, bounds, bounds); + self.push_item(item, bounds, None); self.push_iter(&filters); } @@ -837,46 +836,54 @@ impl DisplayListBuilder { self.push_iter(stops); } + fn generate_clip_id(&mut self, id: Option) -> ClipId { + id.unwrap_or_else(|| { + self.next_clip_id += 1; + ClipId::Clip(self.next_clip_id - 1, 0, self.pipeline_id) + }) + } + + pub fn define_scroll_frame(&mut self, + id: Option, + content_rect: LayoutRect, + clip_rect: LayoutRect, + complex_clips: I, + image_mask: Option) + -> ClipId + where I: IntoIterator, + I::IntoIter: ExactSizeIterator { + let id = self.generate_clip_id(id); + let item = SpecificDisplayItem::ScrollFrame(ClipDisplayItem { + id: id, + parent_id: self.clip_stack.last().unwrap().scroll_node_id, + image_mask: image_mask, + }); + + self.push_item(item, content_rect, Some(LocalClip::from(clip_rect))); + self.push_iter(complex_clips); + id + } + pub fn define_clip(&mut self, id: Option, - content_rect: LayoutRect, clip_rect: LayoutRect, complex_clips: I, image_mask: Option) -> ClipId where I: IntoIterator, I::IntoIter: ExactSizeIterator { - let id = match id { - Some(id) => id, - None => { - self.next_clip_id += 1; - ClipId::Clip(self.next_clip_id - 1, 0, self.pipeline_id) - } - }; - + let id = self.generate_clip_id(id); let item = SpecificDisplayItem::Clip(ClipDisplayItem { id, parent_id: self.clip_stack.last().unwrap().scroll_node_id, - clip_region: ClipRegion::new(&clip_rect, image_mask), + image_mask: image_mask, }); - self.push_item(item, content_rect, clip_rect); + self.push_item(item, clip_rect, Some(LocalClip::from(clip_rect))); self.push_iter(complex_clips); id } - pub fn push_clip_node(&mut self, - id: Option, - content_rect: LayoutRect, - clip_rect: LayoutRect, - complex_clips: I, - image_mask: Option) - where I: IntoIterator, - I::IntoIter: ExactSizeIterator { - let id = self.define_clip(id, content_rect, clip_rect, complex_clips, image_mask); - self.clip_stack.push(ClipAndScrollInfo::simple(id)); - } - pub fn push_clip_id(&mut self, id: ClipId) { self.clip_stack.push(ClipAndScrollInfo::simple(id)); } @@ -890,13 +897,9 @@ impl DisplayListBuilder { assert!(self.clip_stack.len() > 0); } - pub fn pop_clip_node(&mut self) { - self.pop_clip_id(); - } - pub fn push_iframe(&mut self, rect: LayoutRect, pipeline_id: PipelineId) { let item = SpecificDisplayItem::Iframe(IframeDisplayItem { pipeline_id: pipeline_id }); - self.push_item(item, rect, rect); + self.push_item(item, rect, None); } // Don't use this function. It will go away. diff --git a/wrench/reftests/aa/rounded-rects.yaml b/wrench/reftests/aa/rounded-rects.yaml index f103bd27a5..ab675ec8ee 100644 --- a/wrench/reftests/aa/rounded-rects.yaml +++ b/wrench/reftests/aa/rounded-rects.yaml @@ -8,7 +8,7 @@ root: - type: clip bounds: [50, 50, 200, 200] complex: - - rect: [0, 0, 200, 200] + - rect: [50, 50, 200, 200] radius: 8 items: - type: rect @@ -18,7 +18,7 @@ root: - type: clip bounds: [270, 50, 200, 200] complex: - - rect: [0, 0, 200, 200] + - rect: [270, 50, 200, 200] radius: [16, 32, 48, 64] items: - type: rect @@ -28,7 +28,7 @@ root: - type: clip bounds: [490, 50, 200, 200] complex: - - rect: [0, 0, 200, 200] + - rect: [490, 50, 200, 200] radius: { top-left: [32, 16], top-right: [40, 24], diff --git a/wrench/reftests/border/degenerate-curve.yaml b/wrench/reftests/border/degenerate-curve.yaml index a01bba4539..6e1c467488 100644 --- a/wrench/reftests/border/degenerate-curve.yaml +++ b/wrench/reftests/border/degenerate-curve.yaml @@ -9,7 +9,7 @@ root: "transform-style": flat items: - type: clip - bounds: [0, 0, 1000, 1000] + bounds: [28, 18, 144, 122] complex: - rect: [28, 18, 144, 122] radius: @@ -38,7 +38,7 @@ root: "bottom-left": [0, 0] "bottom-right": [61, 61] - type: clip - bounds: [0, 0, 1000, 1000] + bounds: [28, 160, 144, 122] complex: - rect: [28, 160, 144, 122] radius: [61, 61] @@ -60,7 +60,7 @@ root: - none radius: [61, 61] - type: clip - bounds: [0, 0, 1000, 1000] + bounds: [28, 302, 154, 122] complex: - rect: [28, 302, 154, 122] radius: @@ -93,7 +93,7 @@ root: "bottom-left": [0, 0] "bottom-right": [61, 61] - type: clip - bounds: [0, 0, 1000, 1000] + bounds: [202, 18, 145, 122] complex: - rect: [202, 18, 144.03334, 122] radius: @@ -124,7 +124,7 @@ root: - type: clip bounds: [202, 160, 144, 122] complex: - - rect: [0, 0, 144, 122] + - rect: [202, 160, 144, 122] radius: [61, 61] items: - type: rect @@ -145,7 +145,7 @@ root: - type: clip bounds: [202, 302, 154, 122] complex: - - rect: [0, 0, 154, 122] + - rect: [202, 302, 154, 122] radius: "top-left": [0, 0] "top-right": [72, 72] @@ -179,7 +179,7 @@ root: - type: clip bounds: [376, 18, 144, 122] complex: - - rect: [0, 0, 144, 122] + - rect: [376, 18, 144, 122] radius: [61, 61] items: - type: rect @@ -205,7 +205,7 @@ root: - type: clip bounds: [376, 160, 144, 122] complex: - - rect: [0, 0, 144, 122] + - rect: [376, 160, 144, 122] radius: [61, 61] items: - type: rect @@ -232,7 +232,7 @@ root: - type: clip bounds: [376, 302, 144, 122] complex: - - rect: [0, 0, 144, 122] + - rect: [376, 302, 144, 122] radius: "top-left": [0, 0] "top-right": [72, 72] diff --git a/wrench/reftests/mask/aligned-layer-rect.yaml b/wrench/reftests/mask/aligned-layer-rect.yaml index 5f52e3926c..a1c6e2f17e 100644 --- a/wrench/reftests/mask/aligned-layer-rect.yaml +++ b/wrench/reftests/mask/aligned-layer-rect.yaml @@ -1,11 +1,11 @@ --- root: items: - - type: scroll-layer + - type: scroll-frame bounds: [9, 9, 10, 10] content-size: [95, 88] items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 100, 100] items: - type: rect diff --git a/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml b/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml index 75afaabbe7..15ae96127a 100644 --- a/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml +++ b/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml @@ -7,7 +7,7 @@ root: z-index: 4 transform: [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 150, -150, 1] items: - - type: scroll-layer + - type: clip bounds: [0, 0, 300, 300] # This image mask here assures that we will be forced to try to # mask instead of skipping it due to the mask rect becoming a diff --git a/wrench/reftests/mask/nested-mask.yaml b/wrench/reftests/mask/nested-mask.yaml index e6ebea3300..cacbb63434 100644 --- a/wrench/reftests/mask/nested-mask.yaml +++ b/wrench/reftests/mask/nested-mask.yaml @@ -1,14 +1,14 @@ --- root: items: - - type: scroll-layer + - type: clip bounds: [0, 0, 95, 88] image-mask: image: "mask.png" rect: [0, 0, 35, 35] repeat: false items: - - type: scroll-layer + - type: clip bounds: [0, 0, 95, 88] image-mask: image: "mask.png" diff --git a/wrench/reftests/mask/out-of-bounds.yaml b/wrench/reftests/mask/out-of-bounds.yaml index 6b1cb07e60..8e0eed09e0 100644 --- a/wrench/reftests/mask/out-of-bounds.yaml +++ b/wrench/reftests/mask/out-of-bounds.yaml @@ -1,7 +1,7 @@ --- root: items: - - type: scroll-layer + - type: clip bounds: [0, 0, 10000, 10000] complex: - rect: [0, 0, 10000, 10000] diff --git a/wrench/reftests/mask/rounded-corners.yaml b/wrench/reftests/mask/rounded-corners.yaml index ecb36e043f..e26a656cc0 100644 --- a/wrench/reftests/mask/rounded-corners.yaml +++ b/wrench/reftests/mask/rounded-corners.yaml @@ -1,7 +1,7 @@ --- root: items: - - type: scroll-layer + - type: clip bounds: [0, 0, 100, 100] complex: - rect: [0, 0, 100, 100] diff --git a/wrench/reftests/scrolling/empty-mask.yaml b/wrench/reftests/scrolling/empty-mask.yaml index 634c125559..69378dd5ad 100644 --- a/wrench/reftests/scrolling/empty-mask.yaml +++ b/wrench/reftests/scrolling/empty-mask.yaml @@ -3,7 +3,7 @@ root: - type: rect bounds: [0, 0, 100, 100] color: green - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 100, 100] items: - type: clip diff --git a/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml b/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml index d2285d56aa..270b227157 100644 --- a/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml +++ b/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml @@ -1,6 +1,6 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [10, 10, 100, 300] content-size: [100, 700] id: 41 diff --git a/wrench/reftests/scrolling/nested-scroll-offset.yaml b/wrench/reftests/scrolling/nested-scroll-offset.yaml index c16aaba073..850468f180 100644 --- a/wrench/reftests/scrolling/nested-scroll-offset.yaml +++ b/wrench/reftests/scrolling/nested-scroll-offset.yaml @@ -1,14 +1,14 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 500, 500] content-size: [1000, 1000] scroll-offset: [0, 300] items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 300, 50, 50] items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 300, 50, 50] items: - type: rect diff --git a/wrench/reftests/scrolling/out-of-bounds-scroll.yaml b/wrench/reftests/scrolling/out-of-bounds-scroll.yaml index 61d63d6f49..8c87bd6f5c 100644 --- a/wrench/reftests/scrolling/out-of-bounds-scroll.yaml +++ b/wrench/reftests/scrolling/out-of-bounds-scroll.yaml @@ -1,6 +1,6 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [10, 10, 50, 100] content-size: [50, 200] scroll-offset: [0, 50] diff --git a/wrench/reftests/scrolling/scroll-layer-with-mask.yaml b/wrench/reftests/scrolling/scroll-layer-with-mask.yaml index 841beef510..dc4ee4410f 100644 --- a/wrench/reftests/scrolling/scroll-layer-with-mask.yaml +++ b/wrench/reftests/scrolling/scroll-layer-with-mask.yaml @@ -8,7 +8,7 @@ root: bounds: [10, 10, 100, 100] scroll-policy: scrollable items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 100, 100] image-mask: image: "mask.png" @@ -25,12 +25,12 @@ root: bounds: [100, 0, 100, 100] scroll-policy: scrollable items: - - type: scroll-layer + - type: scroll-frame bounds: [10, 10, 100, 300] scroll-offset: [0, 100] image-mask: image: "mask.png" - rect: [0, 0, 100, 100] + rect: [10, 10, 100, 100] repeat: false items: - type: rect @@ -40,13 +40,13 @@ root: # Same as the previous case, but this time we verify that a scroll layer that is # not at the origin works as well. - - type: scroll-layer + type: scroll-frame bounds: [210, 10, 100, 100] content-size: [100, 300] scroll-offset: [0, 100] image-mask: image: "mask.png" - rect: [0, 0, 100, 100] + rect: [210, 10, 100, 100] repeat: false items: - type: rect diff --git a/wrench/reftests/scrolling/scroll-layer.yaml b/wrench/reftests/scrolling/scroll-layer.yaml index fa108573e0..4956672a77 100644 --- a/wrench/reftests/scrolling/scroll-layer.yaml +++ b/wrench/reftests/scrolling/scroll-layer.yaml @@ -1,6 +1,6 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 100, 100] content-size: [1000, 1000] scroll-offset: [50, 50] diff --git a/wrench/reftests/scrolling/simple.yaml b/wrench/reftests/scrolling/simple.yaml index efbc72f2d6..b8061dfca9 100644 --- a/wrench/reftests/scrolling/simple.yaml +++ b/wrench/reftests/scrolling/simple.yaml @@ -1,13 +1,13 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [10, 10, 50, 50] content-size: [100, 100] items: - type: rect bounds: [10, 10, 500, 500] color: green - - type: scroll-layer + - type: scroll-frame bounds: [70, 10, 50, 50] content-size: [100, 100] items: diff --git a/wrench/reftests/scrolling/translate-nested.yaml b/wrench/reftests/scrolling/translate-nested.yaml index 1f2cefd1b3..1607a01171 100644 --- a/wrench/reftests/scrolling/translate-nested.yaml +++ b/wrench/reftests/scrolling/translate-nested.yaml @@ -8,7 +8,7 @@ root: items: - bounds: [0, 0, 200, 200] - type: scroll-layer + type: clip id: 1 items: - diff --git a/wrench/src/yaml_frame_reader.rs b/wrench/src/yaml_frame_reader.rs index 1ad37b4eba..8b2ff69c47 100644 --- a/wrench/src/yaml_frame_reader.rs +++ b/wrench/src/yaml_frame_reader.rs @@ -213,34 +213,34 @@ impl YamlFrameReader { } } - fn handle_rect(&mut self, item: &Yaml, clip_rect: LayoutRect) { + fn handle_rect(&mut self, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "rect" } else { "bounds" }; let rect = item[bounds_key].as_rect().expect("rect type must have bounds"); let color = item["color"].as_colorf().unwrap_or(*WHITE_COLOR); - self.builder().push_rect(rect, clip_rect, color); + self.builder().push_rect(rect, Some(local_clip), color); } - fn handle_gradient(&mut self, item: &Yaml, clip_rect: LayoutRect) { + fn handle_gradient(&mut self, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "gradient" } else { "bounds" }; let bounds = item[bounds_key].as_rect().expect("gradient must have bounds"); let gradient = self.to_gradient(item); let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size); let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero()); - self.builder().push_gradient(bounds, clip_rect, gradient, tile_size, tile_spacing); + self.builder().push_gradient(bounds, Some(local_clip), gradient, tile_size, tile_spacing); } - fn handle_radial_gradient(&mut self, item: &Yaml, clip_rect: LayoutRect) { + fn handle_radial_gradient(&mut self, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "radial-gradient" } else { "bounds" }; let bounds = item[bounds_key].as_rect().expect("radial gradient must have bounds"); let gradient = self.to_radial_gradient(item); let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size); let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero()); - self.builder().push_radial_gradient(bounds, clip_rect, gradient, tile_size, tile_spacing); + self.builder().push_radial_gradient(bounds, Some(local_clip), gradient, tile_size, tile_spacing); } - fn handle_border(&mut self, wrench: &mut Wrench, item: &Yaml, clip_rect: LayoutRect) { + fn handle_border(&mut self, wrench: &mut Wrench, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "border" } else { "bounds" }; let bounds = item[bounds_key].as_rect().expect("borders must have bounds"); let widths = item["width"].as_vec_f32().expect("borders must have width(s)"); @@ -350,11 +350,11 @@ impl YamlFrameReader { None }; if let Some(details) = border_details { - self.builder().push_border(bounds, clip_rect, widths, details); + self.builder().push_border(bounds, Some(local_clip), widths, details); } } - fn handle_box_shadow(&mut self, item: &Yaml, clip_rect: LayoutRect) { + fn handle_box_shadow(&mut self, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "box-shadow" } else { "bounds" }; let bounds = item[bounds_key].as_rect().expect("box shadow must have bounds"); let box_bounds = item["box-bounds"].as_rect().unwrap_or(bounds); @@ -375,7 +375,7 @@ impl YamlFrameReader { }; self.builder().push_box_shadow(bounds, - clip_rect, + Some(local_clip), box_bounds, offset, color, @@ -392,7 +392,7 @@ impl YamlFrameReader { file } - fn handle_image(&mut self, wrench: &mut Wrench, item: &Yaml, clip_rect: LayoutRect) { + fn handle_image(&mut self, wrench: &mut Wrench, item: &Yaml, local_clip: LocalClip) { let filename = &item[if item["type"].is_badvalue() { "image" } else { "src" }]; let tiling = item["tile-size"].as_i64(); let (image_key, image_dims) = wrench.add_or_get_image(&self.rsrc_path(filename), tiling); @@ -419,14 +419,14 @@ impl YamlFrameReader { Some(_) => panic!("ImageRendering can be auto, crisp-edges, or pixelated -- got {:?}", item), }; self.builder().push_image(bounds, - clip_rect, + Some(local_clip), stretch_size, tile_spacing, rendering, image_key); } - fn handle_text(&mut self, wrench: &mut Wrench, item: &Yaml, clip_rect: LayoutRect) { + fn handle_text(&mut self, wrench: &mut Wrench, item: &Yaml, local_clip: LocalClip) { let size = item["size"].as_pt_to_au().unwrap_or(Au::from_f32_px(16.0)); let color = item["color"].as_colorf().unwrap_or(*BLACK_COLOR); let blur_radius = item["blur-radius"].as_force_f32().unwrap_or(0.0); @@ -493,7 +493,7 @@ impl YamlFrameReader { }; self.builder().push_text(rect, - clip_rect, + Some(local_clip), &glyphs, font_key, color, @@ -508,8 +508,18 @@ impl YamlFrameReader { self.builder().push_iframe(bounds, pipeline_id); } + pub fn get_local_clip_for_item(&mut self, yaml: &Yaml, full_clip: LayoutRect) -> LocalClip { + let rect = yaml["clip-rect"].as_rect().unwrap_or(full_clip); + let complex_clip = &yaml["complex-clip"]; + if !complex_clip.is_badvalue() { + LocalClip::RoundedRect(rect, self.to_complex_clip_region(complex_clip)) + } else { + LocalClip::from(rect) + } + } + pub fn add_display_list_items_from_yaml(&mut self, wrench: &mut Wrench, yaml: &Yaml) { - let full_clip_rect = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32()); + let full_clip = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32()); for item in yaml.as_vec().unwrap() { // an explicit type can be skipped with some shorthand @@ -548,18 +558,17 @@ impl YamlFrameReader { self.builder().push_clip_and_scroll_info(clip_scroll_info); } - let clip_rect = item["clip-rect"].as_rect().unwrap_or(full_clip_rect); - + let local_clip = self.get_local_clip_for_item(item, full_clip); match item_type { - "rect" => self.handle_rect(item, clip_rect), - "image" => self.handle_image(wrench, item, clip_rect), - "text" | "glyphs" => self.handle_text(wrench, item, clip_rect), - "scroll-layer" => self.handle_scroll_layer(wrench, item), + "rect" => self.handle_rect(item, local_clip), + "image" => self.handle_image(wrench, item, local_clip), + "text" | "glyphs" => self.handle_text(wrench, item, local_clip), + "scroll-frame" => self.handle_scroll_frame(wrench, item), "clip" => self.handle_clip(wrench, item), - "border" => self.handle_border(wrench, item, clip_rect), - "gradient" => self.handle_gradient(item, clip_rect), - "radial-gradient" => self.handle_radial_gradient(item, clip_rect), - "box-shadow" => self.handle_box_shadow(item, clip_rect), + "border" => self.handle_border(wrench, item, local_clip), + "gradient" => self.handle_gradient(item, local_clip), + "radial-gradient" => self.handle_radial_gradient(item, local_clip), + "box-shadow" => self.handle_box_shadow(item, local_clip), "iframe" => self.handle_iframe(item), "stacking-context" => self.add_stacking_context_from_yaml(wrench, item, false), _ => println!("Skipping unknown item type: {:?}", item), @@ -571,21 +580,39 @@ impl YamlFrameReader { } } - pub fn handle_scroll_layer(&mut self, wrench: &mut Wrench, yaml: &Yaml) { - self.handle_clip(wrench, yaml); + pub fn handle_scroll_frame(&mut self, wrench: &mut Wrench, yaml: &Yaml) { + let clip_rect = yaml["bounds"].as_rect().expect("clip must have a bounds"); + let content_size = yaml["content-size"].as_size().unwrap_or(clip_rect.size); + let content_rect = LayerRect::new(clip_rect.origin, content_size); + + let id = yaml["id"].as_i64().map(|id| ClipId::new(id as u64, self.builder().pipeline_id)); + let complex_clips = self.to_complex_clip_regions(&yaml["complex"]); + let image_mask = self.to_image_mask(&yaml["image-mask"], wrench); + + let id = self.builder().define_scroll_frame(id, + content_rect, + clip_rect, + complex_clips, + image_mask); + + if let Some(size) = yaml["scroll-offset"].as_point() { + self.scroll_offsets.insert(id, LayerPoint::new(size.x, size.y)); + } + + self.builder().push_clip_id(id); + if !yaml["items"].is_badvalue() { + self.add_display_list_items_from_yaml(wrench, &yaml["items"]); + } + self.builder().pop_clip_id(); } pub fn handle_clip(&mut self, wrench: &mut Wrench, yaml: &Yaml) { - let bounds = yaml["bounds"].as_rect().expect("clip must have a bounds"); - let content_size = yaml["content-size"].as_size().unwrap_or(bounds.size); - let content_rect = LayerRect::new(bounds.origin, content_size); - let clip_rect = LayerRect::new(LayerPoint::zero(), bounds.size); - + let clip_rect = yaml["bounds"].as_rect().expect("clip must have a bounds"); let id = yaml["id"].as_i64().map(|id| ClipId::new(id as u64, self.builder().pipeline_id)); let complex_clips = self.to_complex_clip_regions(&yaml["complex"]); let image_mask = self.to_image_mask(&yaml["image-mask"], wrench); - let id = self.builder().define_clip(id, content_rect, clip_rect, complex_clips, image_mask); + let id = self.builder().define_clip(id, clip_rect, complex_clips, image_mask); if let Some(size) = yaml["scroll-offset"].as_point() { self.scroll_offsets.insert(id, LayerPoint::new(size.x, size.y)); diff --git a/wrench/src/yaml_frame_writer.rs b/wrench/src/yaml_frame_writer.rs index 7b226d9be9..7b2f1f9656 100644 --- a/wrench/src/yaml_frame_writer.rs +++ b/wrench/src/yaml_frame_writer.rs @@ -432,31 +432,36 @@ impl YamlFrameWriter { Some(path) } - fn make_clip_complex_node(&mut self, - clip: &ClipRegion, + fn make_complex_clip_node(&mut self, complex_clip: &ComplexClipRegion) -> Yaml { + let mut t = new_table(); + rect_node(&mut t, "rect", &complex_clip.rect); + yaml_node(&mut t, "radius", maybe_radius_yaml(&complex_clip.radii).unwrap()); + Yaml::Hash(t) + } + + fn make_complex_clips_node(&mut self, + complex_clip_count: usize, + complex_clips: ItemRange, list: &BuiltDisplayList) -> Option { - if clip.complex_clip_count == 0 { + if complex_clip_count == 0 { return None; } - let complex_items = list.get(clip.complex_clips).map(|ccx| + let complex_items = list.get(complex_clips).map(|ccx| if ccx.radii.is_zero() { rect_yaml(&ccx.rect) } else { - let mut t = new_table(); - rect_node(&mut t, "rect", &ccx.rect); - yaml_node(&mut t, "radius", maybe_radius_yaml(&ccx.radii).unwrap()); - Yaml::Hash(t) + self.make_complex_clip_node(&ccx) } ).collect(); Some(Yaml::Array(complex_items)) } - fn make_clip_mask_image_node(&mut self, clip: &ClipRegion) -> Option { - let mask = match clip.image_mask { - Some(ref mask) => mask, - None => return None, + fn make_clip_mask_image_node(&mut self, image_mask: &Option) -> Option { + let mask = match image_mask { + &Some(ref mask) => mask, + &None => return None, }; let mut mask_table = new_table(); @@ -486,7 +491,11 @@ impl YamlFrameWriter { let mut v = new_table(); rect_node(&mut v, "bounds", &base.rect()); - rect_node(&mut v, "clip-rect", &base.clip_rect()); + + rect_node(&mut v, "clip-rect", base.local_clip().clip_rect()); + if let &LocalClip::RoundedRect(_, ref region) = base.local_clip() { + yaml_node(&mut v, "complex-clip", self.make_complex_clip_node(region)); + } let clip_and_scroll_info = clip_id_mapper.fix_ids_for_nesting(&base.clip_and_scroll()); let clip_and_scroll_yaml = match clip_id_mapper.map_info(&clip_and_scroll_info) { @@ -746,22 +755,36 @@ impl YamlFrameWriter { Clip(item) => { str_node(&mut v, "type", "clip"); usize_node(&mut v, "id", clip_id_mapper.add_id(item.id)); + size_node(&mut v, "content-size", &base.rect().size); - let mut bounds = base.rect(); - let content_size = bounds.size; - let clip_region = base.clip_region(); - bounds.size = clip_region.main.size; + let &(complex_clips, complex_clip_count) = base.complex_clip(); + if let Some(complex) = self.make_complex_clips_node(complex_clip_count, + complex_clips, + display_list) { + yaml_node(&mut v, "complex", complex); + } - rect_node(&mut v, "bounds", &bounds); - size_node(&mut v, "content-size", &content_size); + if let Some(mask_yaml) = self.make_clip_mask_image_node(&item.image_mask) { + yaml_node(&mut v, "image-mask", mask_yaml); + } + } + ScrollFrame(item) => { + str_node(&mut v, "type", "scroll-frame"); + usize_node(&mut v, "id", clip_id_mapper.add_id(item.id)); + size_node(&mut v, "content-size", &base.rect().size); + rect_node(&mut v, "bounds", &base.local_clip().clip_rect()); - if let Some(complex) = self.make_clip_complex_node(clip_region, display_list) { + let &(complex_clips, complex_clip_count) = base.complex_clip(); + if let Some(complex) = self.make_complex_clips_node(complex_clip_count, + complex_clips, + display_list) { yaml_node(&mut v, "complex", complex); } - if let Some(mask_yaml) = self.make_clip_mask_image_node(clip_region) { + if let Some(mask_yaml) = self.make_clip_mask_image_node(&item.image_mask) { yaml_node(&mut v, "image-mask", mask_yaml); } + } PushNestedDisplayList => clip_id_mapper.push_nested_display_list_ids(clip_and_scroll_info),