mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
Handle overlapping border-radius corners
Conforming to section 5.5 (Rounded Corners/Overlapping Curves) of "CSS Background and Borders Module Level 3", border radii on elements whose border curves would have overlapped are uniformly scaled down to the point that they no longer do. http://dev.w3.org/csswg/css-backgrounds/#corner-overlap
This commit is contained in:
parent
4a3e4032fe
commit
c9cbb5b071
4 changed files with 46 additions and 3 deletions
|
@ -40,7 +40,7 @@ use servo_msg::constellation_msg::Msg as ConstellationMsg;
|
|||
use servo_msg::constellation_msg::ConstellationChan;
|
||||
use servo_net::image::holder::ImageHolder;
|
||||
use servo_util::cursor::Cursor;
|
||||
use servo_util::geometry::{self, Au, to_px};
|
||||
use servo_util::geometry::{self, Au, to_px, to_frac_px};
|
||||
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
|
||||
use servo_util::opts;
|
||||
use std::default::Default;
|
||||
|
@ -218,12 +218,42 @@ pub trait FragmentDisplayListBuilding {
|
|||
clip: &ClippingRegion);
|
||||
}
|
||||
|
||||
fn handle_overlapping_radii(size: &Size2D<Au>, radii: &BorderRadii<Au>) -> BorderRadii<Au> {
|
||||
// No two corners' border radii may add up to more than the length of the edge
|
||||
// between them. To prevent that, all radii are scaled down uniformly.
|
||||
fn scale_factor(radius_a: Au, radius_b: Au, edge_length: Au) -> f64 {
|
||||
let required = radius_a + radius_b;
|
||||
|
||||
if required <= edge_length {
|
||||
1.0
|
||||
} else {
|
||||
to_frac_px(edge_length) / to_frac_px(required)
|
||||
}
|
||||
}
|
||||
|
||||
let top_factor = scale_factor(radii.top_left, radii.top_right, size.width);
|
||||
let bottom_factor = scale_factor(radii.bottom_left, radii.bottom_right, size.width);
|
||||
let left_factor = scale_factor(radii.top_left, radii.bottom_left, size.height);
|
||||
let right_factor = scale_factor(radii.top_right, radii.bottom_right, size.height);
|
||||
let min_factor = top_factor.min(bottom_factor).min(left_factor).min(right_factor);
|
||||
if min_factor < 1.0 {
|
||||
BorderRadii {
|
||||
top_left: radii.top_left .scale_by(min_factor),
|
||||
top_right: radii.top_right .scale_by(min_factor),
|
||||
bottom_left: radii.bottom_left .scale_by(min_factor),
|
||||
bottom_right: radii.bottom_right.scale_by(min_factor),
|
||||
}
|
||||
} else {
|
||||
*radii
|
||||
}
|
||||
}
|
||||
|
||||
fn build_border_radius(abs_bounds: &Rect<Au>, border_style: &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.
|
||||
|
||||
BorderRadii {
|
||||
handle_overlapping_radii(&abs_bounds.size, &BorderRadii {
|
||||
top_left: model::specified(border_style.border_top_left_radius,
|
||||
abs_bounds.size.width),
|
||||
top_right: model::specified(border_style.border_top_right_radius,
|
||||
|
@ -232,7 +262,7 @@ fn build_border_radius(abs_bounds: &Rect<Au>, border_style: &Border) -> BorderRa
|
|||
abs_bounds.size.width),
|
||||
bottom_left: model::specified(border_style.border_bottom_left_radius,
|
||||
abs_bounds.size.width),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
impl FragmentDisplayListBuilding for Fragment {
|
||||
|
|
|
@ -223,6 +223,7 @@ fragment=top != ../html/acid2.html acid2_ref.html
|
|||
!= inset_blackborder.html blackborder_ref.html
|
||||
!= outset_blackborder.html blackborder_ref.html
|
||||
== border_radius_clip_a.html border_radius_clip_ref.html
|
||||
== border_radius_overlapping_a.html border_radius_overlapping_ref.html
|
||||
== stacking_context_overflow_a.html stacking_context_overflow_ref.html
|
||||
== stacking_context_overflow_relative_outline_a.html stacking_context_overflow_relative_outline_ref.html
|
||||
== word_break_a.html word_break_ref.html
|
||||
|
|
6
tests/ref/border_radius_overlapping_a.html
Normal file
6
tests/ref/border_radius_overlapping_a.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<div style='box-sizing:border-box; width:6em; height:2em; border-radius:.5em 2em .5em 2em; background-color:red;'></div>
|
||||
</body>
|
||||
</html>
|
6
tests/ref/border_radius_overlapping_ref.html
Normal file
6
tests/ref/border_radius_overlapping_ref.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<div style='box-sizing:border-box; width:6em; height:2em; border-radius:.4em 1.6em .4em 1.6em; background-color:red;'></div>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue