mirror of
https://github.com/servo/servo.git
synced 2025-06-19 22:59:03 +01:00
Auto merge of #27388 - Manishearth:clip-2020, r=SimonSapin
Layout 2020: Implement `clip: rect` This implements `clip: rect` Unfortunately, none of the tests pass yet, they are all broken due to https://github.com/servo/servo/issues/27387 Additionally, currently `clip` does not seem to clip the element itself, only its children. I'm not quite sure what to do about that, I patterned this off of the code in the layout 2013 which handled clip immediately after scroll overflow.
This commit is contained in:
commit
b41f5f97f2
140 changed files with 5140 additions and 153 deletions
|
@ -63,7 +63,7 @@ use style::properties::{style_structs, ComputedValues};
|
|||
use style::servo::restyle_damage::ServoRestyleDamage;
|
||||
use style::values::computed::effects::SimpleShadow;
|
||||
use style::values::computed::image::Image;
|
||||
use style::values::computed::{ClipRectOrAuto, Gradient, LengthOrAuto};
|
||||
use style::values::computed::{ClipRectOrAuto, Gradient};
|
||||
use style::values::generics::background::BackgroundSize;
|
||||
use style::values::generics::image::PaintWorklet;
|
||||
use style::values::specified::ui::CursorKind;
|
||||
|
@ -2701,26 +2701,7 @@ impl BlockFlow {
|
|||
_ => return,
|
||||
}
|
||||
|
||||
fn extract_clip_component(p: &LengthOrAuto) -> Option<Au> {
|
||||
match *p {
|
||||
LengthOrAuto::Auto => None,
|
||||
LengthOrAuto::LengthPercentage(ref length) => Some(Au::from(*length)),
|
||||
}
|
||||
}
|
||||
|
||||
let clip_origin = Point2D::new(
|
||||
stacking_relative_border_box.origin.x +
|
||||
extract_clip_component(&style_clip_rect.left).unwrap_or_default(),
|
||||
stacking_relative_border_box.origin.y +
|
||||
extract_clip_component(&style_clip_rect.top).unwrap_or_default(),
|
||||
);
|
||||
let right = extract_clip_component(&style_clip_rect.right)
|
||||
.unwrap_or(stacking_relative_border_box.size.width);
|
||||
let bottom = extract_clip_component(&style_clip_rect.bottom)
|
||||
.unwrap_or(stacking_relative_border_box.size.height);
|
||||
let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
|
||||
|
||||
let clip_rect = Rect::new(clip_origin, clip_size);
|
||||
let clip_rect = style_clip_rect.for_border_rect(stacking_relative_border_box);
|
||||
preserved_state.push_clip(state, clip_rect, self.positioning());
|
||||
|
||||
let new_index = state.add_clip_scroll_node(ClipScrollNode {
|
||||
|
|
|
@ -19,6 +19,7 @@ use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode;
|
|||
use style::computed_values::overflow_x::T as ComputedOverflow;
|
||||
use style::computed_values::position::T as ComputedPosition;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::ClipRectOrAuto;
|
||||
use style::values::computed::Length;
|
||||
use style::values::generics::box_::Perspective;
|
||||
use style::values::generics::transform;
|
||||
|
@ -660,6 +661,7 @@ impl BoxFragment {
|
|||
containing_block_info: &ContainingBlockInfo,
|
||||
stacking_context: &mut StackingContext,
|
||||
) {
|
||||
self.build_clip_frame_if_necessary(builder, containing_block_info);
|
||||
stacking_context.fragments.push(StackingContextFragment {
|
||||
space_and_clip: builder.current_space_and_clip,
|
||||
section: self.get_stacking_context_section(),
|
||||
|
@ -708,6 +710,32 @@ impl BoxFragment {
|
|||
builder.current_space_and_clip.spatial_id = builder.nearest_reference_frame;
|
||||
}
|
||||
|
||||
fn build_clip_frame_if_necessary(
|
||||
&self,
|
||||
builder: &mut StackingContextBuilder,
|
||||
containing_block_info: &ContainingBlockInfo,
|
||||
) {
|
||||
let position = self.style.get_box().position;
|
||||
// https://drafts.csswg.org/css2/#clipping
|
||||
// The clip property applies only to absolutely positioned elements
|
||||
if position == ComputedPosition::Absolute || position == ComputedPosition::Fixed {
|
||||
let clip = self.style.get_effects().clip;
|
||||
if let ClipRectOrAuto::Rect(r) = clip {
|
||||
let border_rect = self
|
||||
.border_rect()
|
||||
.to_physical(self.style.writing_mode, &containing_block_info.rect);
|
||||
let clip_rect = r
|
||||
.for_border_rect(border_rect)
|
||||
.translate(containing_block_info.rect.origin.to_vector())
|
||||
.to_webrender();
|
||||
|
||||
let parent = builder.current_space_and_clip;
|
||||
builder.current_space_and_clip.clip_id =
|
||||
builder.wr.define_clip_rect(&parent, clip_rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_scroll_frame_if_necessary<'a>(
|
||||
&self,
|
||||
builder: &mut StackingContextBuilder,
|
||||
|
@ -715,6 +743,7 @@ impl BoxFragment {
|
|||
) {
|
||||
let overflow_x = self.style.get_box().overflow_x;
|
||||
let overflow_y = self.style.get_box().overflow_y;
|
||||
|
||||
let original_scroll_and_clip_info = builder.current_space_and_clip;
|
||||
if overflow_x != ComputedOverflow::Visible || overflow_y != ComputedOverflow::Visible {
|
||||
let external_id = wr::ExternalScrollId(
|
||||
|
|
|
@ -38,7 +38,6 @@ ${helpers.predefined_type(
|
|||
"ClipRectOrAuto",
|
||||
"computed::ClipRectOrAuto::auto()",
|
||||
engines="gecko servo-2013 servo-2020",
|
||||
servo_2020_pref="layout.2020.unimplemented",
|
||||
animation_value_type="ComputedValue",
|
||||
boxed=True,
|
||||
allow_quirks="Yes",
|
||||
|
|
|
@ -22,11 +22,12 @@ use crate::properties;
|
|||
use crate::properties::{ComputedValues, LonghandId, StyleBuilder};
|
||||
use crate::rule_cache::RuleCacheConditions;
|
||||
use crate::{ArcSlice, Atom, One};
|
||||
use euclid::default::Size2D;
|
||||
use euclid::{default, Point2D, Rect, Size2D};
|
||||
use servo_arc::Arc;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp;
|
||||
use std::f32;
|
||||
use std::ops::{Add, Sub};
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use self::align::{
|
||||
|
@ -208,7 +209,7 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
|
||||
/// The current viewport size, used to resolve viewport units.
|
||||
pub fn viewport_size_for_viewport_unit_resolution(&self) -> Size2D<Au> {
|
||||
pub fn viewport_size_for_viewport_unit_resolution(&self) -> default::Size2D<Au> {
|
||||
self.builder
|
||||
.device
|
||||
.au_viewport_size_for_viewport_unit_resolution()
|
||||
|
@ -353,11 +354,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> ToComputedValue for Size2D<T>
|
||||
impl<T> ToComputedValue for default::Size2D<T>
|
||||
where
|
||||
T: ToComputedValue,
|
||||
{
|
||||
type ComputedValue = Size2D<<T as ToComputedValue>::ComputedValue>;
|
||||
type ComputedValue = default::Size2D<<T as ToComputedValue>::ComputedValue>;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
|
@ -814,3 +815,29 @@ pub type GridLine = GenericGridLine<Integer>;
|
|||
|
||||
/// `<grid-template-rows> | <grid-template-columns>`
|
||||
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
|
||||
|
||||
impl ClipRect {
|
||||
/// Given a border box, resolves the clip rect against the border box
|
||||
/// in the same space the border box is in
|
||||
pub fn for_border_rect<T: Copy + From<Length> + Add<Output = T> + Sub<Output = T>, U>(
|
||||
&self,
|
||||
border_box: Rect<T, U>,
|
||||
) -> Rect<T, U> {
|
||||
fn extract_clip_component<T: From<Length>>(p: &LengthOrAuto, or: T) -> T {
|
||||
match *p {
|
||||
LengthOrAuto::Auto => or,
|
||||
LengthOrAuto::LengthPercentage(ref length) => T::from(*length),
|
||||
}
|
||||
}
|
||||
|
||||
let clip_origin = Point2D::new(
|
||||
From::from(self.left.auto_is(|| Length::new(0.))),
|
||||
From::from(self.top.auto_is(|| Length::new(0.))),
|
||||
);
|
||||
let right = extract_clip_component(&self.right, border_box.size.width);
|
||||
let bottom = extract_clip_component(&self.bottom, border_box.size.height);
|
||||
let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
|
||||
|
||||
Rect::new(clip_origin, clip_size).translate(border_box.origin.to_vector())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue