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:
Patrick Walton 2014-12-18 14:12:51 -07:00
Родитель 370886dc52
Коммит c36d533145
8 изменённых файлов: 138 добавлений и 30 удалений

Просмотреть файл

@ -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) => {

2
servo/components/servo/Cargo.lock сгенерированный
Просмотреть файл

@ -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)))
}

2
servo/ports/cef/Cargo.lock сгенерированный
Просмотреть файл

@ -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"

2
servo/ports/gonk/Cargo.lock сгенерированный
Просмотреть файл

@ -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"