mirror of
https://github.com/servo/servo.git
synced 2025-06-13 19:04:30 +00:00
Use real clips when generating scroll roots
This is the first step toward removing inherited clips in favor of scroll roots for handling overflow and CSS clipping. This will allow us to more easily handle elements that should not be clipped. While we are still using inherited clips here, we now properly clip some types of content that wasn't clipped before.
This commit is contained in:
parent
21eafebd37
commit
0353aad4e3
6 changed files with 134 additions and 12 deletions
|
@ -508,7 +508,7 @@ pub struct ScrollRoot {
|
|||
pub parent_id: ScrollRootId,
|
||||
|
||||
/// The position of this scroll root's frame in the parent stacking context.
|
||||
pub clip: Rect<Au>,
|
||||
pub clip: ClippingRegion,
|
||||
|
||||
/// The rect of the contents that can be scrolled inside of the scroll root.
|
||||
pub content_rect: Rect<Au>,
|
||||
|
|
|
@ -520,7 +520,9 @@ fn handle_overlapping_radii(size: &Size2D<Au>, radii: &BorderRadii<Au>) -> Borde
|
|||
}
|
||||
}
|
||||
|
||||
fn build_border_radius(abs_bounds: &Rect<Au>, border_style: &style_structs::Border) -> BorderRadii<Au> {
|
||||
fn build_border_radius(abs_bounds: &Rect<Au>,
|
||||
border_style: &style_structs::Border)
|
||||
-> BorderRadii<Au> {
|
||||
// TODO(cgaebel): Support border radii even in the case of multiple border widths.
|
||||
// This is an extension of supporting elliptical radii. For now, all percentage
|
||||
// radii will be relative to the width.
|
||||
|
@ -537,6 +539,34 @@ fn build_border_radius(abs_bounds: &Rect<Au>, border_style: &style_structs::Bord
|
|||
})
|
||||
}
|
||||
|
||||
/// Get the border radius for the rectangle inside of a rounded border. This is useful
|
||||
/// for building the clip for the content inside the border.
|
||||
fn build_border_radius_for_inner_rect(outer_rect: &Rect<Au>,
|
||||
style: Arc<ServoComputedValues>)
|
||||
-> BorderRadii<Au> {
|
||||
let mut radii = build_border_radius(&outer_rect, style.get_border());
|
||||
if radii.is_square() {
|
||||
return radii;
|
||||
}
|
||||
|
||||
// Since we are going to using the inner rectangle (outer rectangle minus
|
||||
// border width), we need to adjust to border radius so that we are smaller
|
||||
// rectangle with the same border curve.
|
||||
let border_widths = style.logical_border_width().to_physical(style.writing_mode);
|
||||
radii.top_left.width = cmp::max(Au(0), radii.top_left.width - border_widths.left);
|
||||
radii.bottom_left.width = cmp::max(Au(0), radii.bottom_left.width - border_widths.left);
|
||||
|
||||
radii.top_right.width = cmp::max(Au(0), radii.top_right.width - border_widths.right);
|
||||
radii.bottom_right.width = cmp::max(Au(0), radii.bottom_right.width - border_widths.right);
|
||||
|
||||
radii.top_left.height = cmp::max(Au(0), radii.top_left.height - border_widths.top);
|
||||
radii.top_right.height = cmp::max(Au(0), radii.top_right.height - border_widths.top);
|
||||
|
||||
radii.bottom_left.height = cmp::max(Au(0), radii.bottom_left.height - border_widths.bottom);
|
||||
radii.bottom_right.height = cmp::max(Au(0), radii.bottom_right.height - border_widths.bottom);
|
||||
radii
|
||||
}
|
||||
|
||||
impl FragmentDisplayListBuilding for Fragment {
|
||||
fn build_display_list_for_background_if_applicable(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
|
@ -1978,12 +2008,21 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
let new_scroll_root_id = ScrollRootId::new_of_type(self.fragment.node.id() as usize,
|
||||
self.fragment.fragment_type());
|
||||
|
||||
let clip_rect = Rect::new(Point2D::zero(), content_box.size);
|
||||
let mut clip = ClippingRegion::from_rect(&clip_rect);
|
||||
|
||||
let border_radii = build_border_radius_for_inner_rect(&border_box,
|
||||
self.fragment.style.clone());
|
||||
if !border_radii.is_square() {
|
||||
clip.intersect_with_rounded_rect(&clip_rect, &border_radii)
|
||||
}
|
||||
|
||||
let content_size = self.base.overflow.scroll.origin + self.base.overflow.scroll.size;
|
||||
state.add_scroll_root(
|
||||
ScrollRoot {
|
||||
id: new_scroll_root_id,
|
||||
parent_id: containing_scroll_root_id,
|
||||
clip: Rect::new(Point2D::zero(), content_box.size),
|
||||
clip: clip,
|
||||
content_rect: Rect::new(content_box.origin,
|
||||
Size2D::new(content_size.x, content_size.y)),
|
||||
},
|
||||
|
|
|
@ -421,15 +421,11 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
}
|
||||
DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(),
|
||||
DisplayItem::PushScrollRoot(ref item) => {
|
||||
let clip = builder.new_clip_region(&item.scroll_root.clip.to_rectf(),
|
||||
vec![],
|
||||
None);
|
||||
|
||||
let provided_id = ScrollLayerId::new(item.scroll_root.id.0 as u64, builder.pipeline_id);
|
||||
let id = builder.define_clip(item.scroll_root.content_rect.to_rectf(),
|
||||
clip,
|
||||
Some(provided_id));
|
||||
debug_assert!(provided_id == id);
|
||||
let our_id = ScrollLayerId::new(item.scroll_root.id.0 as u64, builder.pipeline_id);
|
||||
let clip = item.scroll_root.clip.to_clip_region(builder);
|
||||
let content_rect = item.scroll_root.content_rect.to_rectf();
|
||||
let webrender_id = builder.define_clip(content_rect, clip, Some(our_id));
|
||||
debug_assert!(our_id == webrender_id);
|
||||
}
|
||||
DisplayItem::PopScrollRoot(_) => {} //builder.pop_scroll_layer(),
|
||||
}
|
||||
|
|
|
@ -4079,6 +4079,18 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/overflow_border_radius.html": [
|
||||
[
|
||||
"/_mozilla/css/overflow_border_radius.html",
|
||||
[
|
||||
[
|
||||
"/_mozilla/css/overflow_border_radius_ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/overflow_position_abs_inline_block.html": [
|
||||
[
|
||||
"/_mozilla/css/overflow_position_abs_inline_block.html",
|
||||
|
@ -8415,6 +8427,11 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/overflow_border_radius_ref.html": [
|
||||
[
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/overflow_position_abs_inline_block_ref.html": [
|
||||
[
|
||||
{}
|
||||
|
@ -22689,6 +22706,14 @@
|
|||
"195201950fd56bd139e71971d66f92ee4fef815d",
|
||||
"support"
|
||||
],
|
||||
"css/overflow_border_radius.html": [
|
||||
"2c8a650f518ccff78517556540416f7e0e798033",
|
||||
"reftest"
|
||||
],
|
||||
"css/overflow_border_radius_ref.html": [
|
||||
"3798d0efb1b9858ad47ecf6f09357c3c0dae1b80",
|
||||
"support"
|
||||
],
|
||||
"css/overflow_position_abs_inline_block.html": [
|
||||
"7550f9c9f3e91635c15554d9ae21e172944054e6",
|
||||
"reftest"
|
||||
|
|
36
tests/wpt/mozilla/tests/css/overflow_border_radius.html
Normal file
36
tests/wpt/mozilla/tests/css/overflow_border_radius.html
Normal file
|
@ -0,0 +1,36 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<title>Test to ensure that clipped overflow is clipped to border radius</title>
|
||||
<link rel="match" href="overflow_border_radius_ref.html">
|
||||
|
||||
<body>
|
||||
<style>
|
||||
.box {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 20px;
|
||||
border: 5px transparent solid;
|
||||
margin-right: 10px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.overflowingbox {
|
||||
margin-left: -25px;
|
||||
margin-top: -25px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: gray;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="box border" style="overflow: auto;">
|
||||
<div class="overflowingbox"></div>
|
||||
</div>
|
||||
|
||||
<div class="box border" style="overflow: scroll;">
|
||||
<div class="overflowingbox"></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
26
tests/wpt/mozilla/tests/css/overflow_border_radius_ref.html
Normal file
26
tests/wpt/mozilla/tests/css/overflow_border_radius_ref.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
|
||||
<body>
|
||||
<style>
|
||||
.box {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-left: 5px;
|
||||
margin-top: 5px;
|
||||
|
||||
border-radius: 15px;
|
||||
background: gray;
|
||||
float: left;
|
||||
|
||||
margin-right: 15px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="box"></div>
|
||||
<div class="box"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue