зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #4394 - layout: Implement `clip` per CSS 2.1 § 11.1.2 (from pcwalton:clip); r=SimonSapin
Only the recommended, comma-separated syntax is supported. r? @SimonSapin Source-Repo: https://github.com/servo/servo Source-Revision: a80d88897d176630c79f929e8b1fd661b2e1a17c
This commit is contained in:
Родитель
370886dc52
Коммит
c36d533145
|
@ -1774,8 +1774,8 @@ impl Flow for BlockFlow {
|
|||
} else {
|
||||
self.base.stacking_relative_position
|
||||
};
|
||||
let clip_rect = self.fragment.clip_rect_for_children(self.base.clip_rect,
|
||||
origin_for_children);
|
||||
let clip_rect = self.fragment.clip_rect_for_children(&self.base.clip_rect,
|
||||
&origin_for_children);
|
||||
|
||||
// Process children.
|
||||
let writing_mode = self.base.writing_mode;
|
||||
|
|
|
@ -43,9 +43,9 @@ use std::num::FloatMath;
|
|||
use style::computed::{AngleOrCorner, LengthOrPercentage, HorizontalDirection, VerticalDirection};
|
||||
use style::computed::{Image, LinearGradient};
|
||||
use style::computed_values::{background_attachment, background_repeat, border_style, overflow};
|
||||
use style::computed_values::{visibility};
|
||||
use style::{ComputedValues, RGBA};
|
||||
use style::computed_values::{position, visibility};
|
||||
use style::style_structs::Border;
|
||||
use style::{ComputedValues, RGBA};
|
||||
use sync::Arc;
|
||||
use url::Url;
|
||||
|
||||
|
@ -167,8 +167,13 @@ pub trait FragmentDisplayListBuilding {
|
|||
offset: Point2D<Au>,
|
||||
layout_context: &LayoutContext);
|
||||
|
||||
fn clip_rect_for_children(&self, current_clip_rect: Rect<Au>, flow_origin: Point2D<Au>)
|
||||
fn clip_rect_for_children(&self, current_clip_rect: &Rect<Au>, flow_origin: &Point2D<Au>)
|
||||
-> Rect<Au>;
|
||||
|
||||
/// Calculates the clipping rectangle for a fragment, taking the `clip` property into account
|
||||
/// per CSS 2.1 § 11.1.2.
|
||||
fn calculate_style_specified_clip(&self, parent_clip_rect: &Rect<Au>, origin: &Point2D<Au>)
|
||||
-> Rect<Au>;
|
||||
}
|
||||
|
||||
fn build_border_radius(abs_bounds: &Rect<Au>, border_style: &Border) -> BorderRadii<Au> {
|
||||
|
@ -605,6 +610,24 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}));
|
||||
}
|
||||
|
||||
fn calculate_style_specified_clip(&self, parent_clip_rect: &Rect<Au>, origin: &Point2D<Au>)
|
||||
-> Rect<Au> {
|
||||
// Account for `clip` per CSS 2.1 § 11.1.2.
|
||||
let style_clip_rect = match (self.style().get_box().position,
|
||||
self.style().get_effects().clip) {
|
||||
(position::absolute, Some(style_clip_rect)) => style_clip_rect,
|
||||
_ => return *parent_clip_rect,
|
||||
};
|
||||
|
||||
// FIXME(pcwalton, #2795): Get the real container size.
|
||||
let border_box = self.border_box.to_physical(self.style.writing_mode, Size2D::zero());
|
||||
let clip_origin = Point2D(border_box.origin.x + style_clip_rect.left,
|
||||
border_box.origin.y + style_clip_rect.top);
|
||||
Rect(clip_origin + *origin,
|
||||
Size2D(style_clip_rect.right.unwrap_or(border_box.size.width) - clip_origin.x,
|
||||
style_clip_rect.bottom.unwrap_or(border_box.size.height) - clip_origin.y))
|
||||
}
|
||||
|
||||
fn build_display_list(&mut self,
|
||||
display_list: &mut DisplayList,
|
||||
layout_context: &LayoutContext,
|
||||
|
@ -646,7 +669,11 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
return
|
||||
}
|
||||
|
||||
if !absolute_fragment_bounds.intersects(clip_rect) {
|
||||
// Calculate the clip rect. If there's nothing to render at all, don't even construct
|
||||
// display list items.
|
||||
let clip_rect = self.calculate_style_specified_clip(clip_rect,
|
||||
&absolute_fragment_bounds.origin);
|
||||
if !absolute_fragment_bounds.intersects(&clip_rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -666,7 +693,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
layout_context,
|
||||
level,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
|
@ -680,7 +707,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
layout_context,
|
||||
level,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -694,7 +721,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
layout_context,
|
||||
level,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
|
@ -708,7 +735,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
layout_context,
|
||||
level,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,12 +748,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
display_list,
|
||||
&absolute_fragment_bounds,
|
||||
level,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
self.build_display_list_for_outline_if_applicable(
|
||||
&**style,
|
||||
display_list,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
|
@ -739,12 +766,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
display_list,
|
||||
&absolute_fragment_bounds,
|
||||
level,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
self.build_display_list_for_outline_if_applicable(
|
||||
&*self.style,
|
||||
display_list,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -781,7 +808,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
DisplayItemMetadata::new(self.node,
|
||||
self.style(),
|
||||
cursor),
|
||||
*clip_rect),
|
||||
clip_rect),
|
||||
text_run: text_fragment.run.clone(),
|
||||
range: text_fragment.range,
|
||||
text_color: self.style().get_color().color.to_gfx_color(),
|
||||
|
@ -805,7 +832,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
DisplayItemMetadata::new(self.node,
|
||||
style,
|
||||
DefaultCursor),
|
||||
*clip_rect),
|
||||
clip_rect),
|
||||
color: color.to_gfx_color(),
|
||||
}))
|
||||
}
|
||||
|
@ -840,7 +867,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
display_list,
|
||||
flow_origin,
|
||||
&**text_fragment,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
}
|
||||
}
|
||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(..) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
|
||||
|
@ -849,7 +876,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
if opts::get().show_debug_fragment_borders {
|
||||
self.build_debug_borders_around_fragment(display_list,
|
||||
flow_origin,
|
||||
clip_rect);
|
||||
&clip_rect);
|
||||
}
|
||||
}
|
||||
SpecificFragmentInfo::Image(ref mut image_fragment) => {
|
||||
|
@ -864,7 +891,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
DisplayItemMetadata::new(self.node,
|
||||
&*self.style,
|
||||
DefaultCursor),
|
||||
*clip_rect),
|
||||
clip_rect),
|
||||
image: image.clone(),
|
||||
stretch_size: absolute_content_box.size,
|
||||
}));
|
||||
|
@ -880,9 +907,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
|
||||
if opts::get().show_debug_fragment_borders {
|
||||
self.build_debug_borders_around_fragment(display_list,
|
||||
flow_origin,
|
||||
clip_rect)
|
||||
self.build_debug_borders_around_fragment(display_list, flow_origin, &clip_rect)
|
||||
}
|
||||
|
||||
// If this is an iframe, then send its position and size up to the constellation.
|
||||
|
@ -926,14 +951,17 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
iframe_rect));
|
||||
}
|
||||
|
||||
fn clip_rect_for_children(&self, current_clip_rect: Rect<Au>, flow_origin: Point2D<Au>)
|
||||
fn clip_rect_for_children(&self, current_clip_rect: &Rect<Au>, origin: &Point2D<Au>)
|
||||
-> Rect<Au> {
|
||||
// Don't clip if we're text.
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::ScannedText(_) => return current_clip_rect,
|
||||
SpecificFragmentInfo::ScannedText(_) => return *current_clip_rect,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Account for style-specified `clip`.
|
||||
let current_clip_rect = self.calculate_style_specified_clip(current_clip_rect, origin);
|
||||
|
||||
// Only clip if `overflow` tells us to.
|
||||
match self.style.get_box().overflow {
|
||||
overflow::hidden | overflow::auto | overflow::scroll => {}
|
||||
|
@ -944,7 +972,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
//
|
||||
// FIXME(#2795): Get the real container size.
|
||||
let physical_rect = self.border_box.to_physical(self.style.writing_mode, Size2D::zero());
|
||||
current_clip_rect.intersection(&Rect(physical_rect.origin + flow_origin,
|
||||
current_clip_rect.intersection(&Rect(Point2D(physical_rect.origin.x + origin.x,
|
||||
physical_rect.origin.y + origin.y),
|
||||
physical_rect.size)).unwrap_or(ZERO_RECT)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1215,8 +1215,8 @@ impl Flow for InlineFlow {
|
|||
_ => continue,
|
||||
};
|
||||
|
||||
let clip_rect = fragment.clip_rect_for_children(self.base.clip_rect,
|
||||
stacking_relative_position);
|
||||
let clip_rect = fragment.clip_rect_for_children(&self.base.clip_rect,
|
||||
&stacking_relative_position);
|
||||
|
||||
match fragment.specific {
|
||||
SpecificFragmentInfo::InlineBlock(ref mut info) => {
|
||||
|
|
|
@ -247,7 +247,7 @@ source = "git+https://github.com/alexcrichton/gcc-rs#903e8f8a2e3766ad3d514404d45
|
|||
[[package]]
|
||||
name = "geom"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/rust-geom#5e52790076fc238a395d1777c4280fa46a1555fa"
|
||||
source = "git+https://github.com/servo/rust-geom#da6b4a36a5549cf78bf702f0b9387b5c8cf61498"
|
||||
|
||||
[[package]]
|
||||
name = "gfx"
|
||||
|
|
|
@ -1861,6 +1861,84 @@ pub mod longhands {
|
|||
})
|
||||
}
|
||||
</%self:longhand>
|
||||
|
||||
<%self:single_component_value name="clip">
|
||||
// NB: `top` and `left` are 0 if `auto` per CSS 2.1 11.1.2.
|
||||
|
||||
pub mod computed_value {
|
||||
use super::super::Au;
|
||||
|
||||
#[deriving(Clone, PartialEq, Show)]
|
||||
pub struct ClipRect {
|
||||
pub top: Au,
|
||||
pub right: Option<Au>,
|
||||
pub bottom: Option<Au>,
|
||||
pub left: Au,
|
||||
}
|
||||
|
||||
pub type T = Option<ClipRect>;
|
||||
}
|
||||
|
||||
#[deriving(Clone, Show)]
|
||||
pub struct SpecifiedClipRect {
|
||||
pub top: specified::Length,
|
||||
pub right: Option<specified::Length>,
|
||||
pub bottom: Option<specified::Length>,
|
||||
pub left: specified::Length,
|
||||
}
|
||||
|
||||
pub type SpecifiedValue = Option<SpecifiedClipRect>;
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||
-> computed_value::T {
|
||||
value.map(|value| computed_value::ClipRect {
|
||||
top: computed::compute_Au(value.top, context),
|
||||
right: value.right.map(|right| computed::compute_Au(right, context)),
|
||||
bottom: value.bottom.map(|bottom| computed::compute_Au(bottom, context)),
|
||||
left: computed::compute_Au(value.left, context),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_component_value(input: &ComponentValue, _: &Url) -> Result<SpecifiedValue,()> {
|
||||
match *input {
|
||||
Function(ref name, ref args) if name.as_slice().eq_ignore_ascii_case("rect") => {
|
||||
let sides = try!(parse_slice_comma_separated(args.as_slice(), |parser| {
|
||||
match parser.next() {
|
||||
Some(&Ident(ref ident)) if ident.eq_ignore_ascii_case("auto") => {
|
||||
Ok(None)
|
||||
}
|
||||
Some(arg) => {
|
||||
match specified::Length::parse(arg) {
|
||||
Err(_) => {
|
||||
parser.push_back(arg);
|
||||
Err(())
|
||||
}
|
||||
Ok(value) => Ok(Some(value)),
|
||||
}
|
||||
}
|
||||
None => Err(()),
|
||||
}
|
||||
}));
|
||||
if sides.len() != 4 {
|
||||
return Err(())
|
||||
}
|
||||
Ok(Some(SpecifiedClipRect {
|
||||
top: sides[0].unwrap_or(specified::Length::Au(Au(0))),
|
||||
right: sides[1],
|
||||
bottom: sides[2],
|
||||
left: sides[3].unwrap_or(specified::Length::Au(Au(0))),
|
||||
}))
|
||||
}
|
||||
Ident(ref ident) if ident.as_slice().eq_ignore_ascii_case("auto") => Ok(None),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
</%self:single_component_value>
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -333,3 +333,4 @@ pub fn f32_rect_to_au_rect(rect: Rect<f32>) -> Rect<Au> {
|
|||
Rect(Point2D(Au::from_frac32_px(rect.origin.x), Au::from_frac32_px(rect.origin.y)),
|
||||
Size2D(Au::from_frac32_px(rect.size.width), Au::from_frac32_px(rect.size.height)))
|
||||
}
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ source = "git+https://github.com/alexcrichton/gcc-rs#903e8f8a2e3766ad3d514404d45
|
|||
[[package]]
|
||||
name = "geom"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/rust-geom#5e52790076fc238a395d1777c4280fa46a1555fa"
|
||||
source = "git+https://github.com/servo/rust-geom#da6b4a36a5549cf78bf702f0b9387b5c8cf61498"
|
||||
|
||||
[[package]]
|
||||
name = "gfx"
|
||||
|
|
|
@ -207,7 +207,7 @@ source = "git+https://github.com/alexcrichton/gcc-rs#d35c34c871dd75f97fadf04cb0e
|
|||
[[package]]
|
||||
name = "geom"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/rust-geom#5e52790076fc238a395d1777c4280fa46a1555fa"
|
||||
source = "git+https://github.com/servo/rust-geom#da6b4a36a5549cf78bf702f0b9387b5c8cf61498"
|
||||
|
||||
[[package]]
|
||||
name = "gfx"
|
||||
|
|
Загрузка…
Ссылка в новой задаче