diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index ac1db774f10a..d0ea9036a756 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -30,11 +30,11 @@ use std::cmp::{self, Ordering}; use std::collections::HashMap; use std::fmt; use std::sync::Arc; -use style::computed_values::{border_style, filter, image_rendering, mix_blend_mode}; +use style::computed_values::{border_style, filter, image_rendering}; use style_traits::cursor::Cursor; use text::TextRun; use text::glyph::ByteIndex; -use webrender_traits::{self, ClipId, ColorF, GradientStop, ScrollPolicy, WebGLContextId}; +use webrender_traits::{self, ClipId, ColorF, GradientStop, MixBlendMode, ScrollPolicy, TransformStyle, WebGLContextId}; pub use style::dom::OpaqueNode; @@ -375,11 +375,14 @@ pub struct StackingContext { pub filters: filter::T, /// The blend mode with which this stacking context blends with its backdrop. - pub blend_mode: mix_blend_mode::T, + pub mix_blend_mode: MixBlendMode, /// A transform to be applied to this stacking context. pub transform: Option>, + /// The transform style of this stacking context. + pub transform_style: TransformStyle, + /// The perspective matrix to be applied to children. pub perspective: Option>, @@ -399,8 +402,9 @@ impl StackingContext { overflow: &Rect, z_index: i32, filters: filter::T, - blend_mode: mix_blend_mode::T, + mix_blend_mode: MixBlendMode, transform: Option>, + transform_style: TransformStyle, perspective: Option>, scroll_policy: ScrollPolicy, parent_scroll_id: ClipId) @@ -412,8 +416,9 @@ impl StackingContext { overflow: *overflow, z_index: z_index, filters: filters, - blend_mode: blend_mode, + mix_blend_mode: mix_blend_mode, transform: transform, + transform_style: transform_style, perspective: perspective, scroll_policy: scroll_policy, parent_scroll_id: parent_scroll_id, @@ -428,8 +433,9 @@ impl StackingContext { &Rect::zero(), 0, filter::T::new(Vec::new()), - mix_blend_mode::T::normal, + MixBlendMode::Normal, None, + TransformStyle::Flat, None, ScrollPolicy::Scrollable, pipeline_id.root_scroll_node()) diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index c3ac7f09048c..3d2de769d4b8 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -68,7 +68,8 @@ use style::values::specified::position::{X, Y}; use style_traits::CSSPixel; use style_traits::cursor::Cursor; use table_cell::CollapsedBordersForCell; -use webrender_traits::{ColorF, ClipId, GradientStop, RepeatMode, ScrollPolicy}; +use webrender_helpers::{ToMixBlendMode, ToTransformStyle}; +use webrender_traits::{ColorF, ClipId, GradientStop, RepeatMode, ScrollPolicy, TransformStyle}; trait ResolvePercentage { fn resolve(&self, length: u32) -> u32; @@ -184,6 +185,9 @@ pub struct DisplayListBuildState<'a> { /// A stack of clips used to cull display list entries that are outside the /// rendered region, but only collected at containing block boundaries. pub containing_block_clip_stack: Vec>, + + /// The current transform style of the stacking context. + current_transform_style: TransformStyle, } impl<'a> DisplayListBuildState<'a> { @@ -201,6 +205,7 @@ impl<'a> DisplayListBuildState<'a> { iframe_sizes: Vec::new(), clip_stack: Vec::new(), containing_block_clip_stack: Vec::new(), + current_transform_style: TransformStyle::Flat, } } @@ -212,6 +217,7 @@ impl<'a> DisplayListBuildState<'a> { fn add_stacking_context(&mut self, parent_id: StackingContextId, stacking_context: StackingContext) { + self.current_transform_style = stacking_context.transform_style; let info = self.stacking_context_info .entry(parent_id) .or_insert(StackingContextInfo::new()); @@ -1947,8 +1953,9 @@ impl FragmentDisplayListBuilding for Fragment { &overflow, self.effective_z_index(), filters, - self.style().get_effects().mix_blend_mode, + self.style().get_effects().mix_blend_mode.to_mix_blend_mode(), self.transform_matrix(&border_box), + self.style().get_used_transform_style().to_transform_style(), self.perspective_matrix(&border_box), scroll_policy, parent_scroll_id) @@ -2153,6 +2160,7 @@ pub struct PreservedDisplayListState { containing_block_scroll_root_id: ClipId, clips_pushed: usize, containing_block_clips_pushed: usize, + transform_style: TransformStyle, } impl PreservedDisplayListState { @@ -2163,6 +2171,7 @@ impl PreservedDisplayListState { containing_block_scroll_root_id: state.containing_block_scroll_root_id, clips_pushed: 0, containing_block_clips_pushed: 0, + transform_style: state.current_transform_style, } } @@ -2183,6 +2192,8 @@ impl PreservedDisplayListState { let truncate_length = state.containing_block_clip_stack.len() - self.containing_block_clips_pushed; state.containing_block_clip_stack.truncate(truncate_length); + + state.current_transform_style = self.transform_style; } fn push_clip(&mut self, @@ -2614,14 +2625,14 @@ impl InlineFlowDisplayListBuilding for InlineFlow { fragment.stacking_context_id = fragment.stacking_context_id(); let current_stacking_context_id = state.current_stacking_context_id; - let current_scroll_root_id = state.current_scroll_root_id; + let stacking_context = fragment.create_stacking_context(fragment.stacking_context_id, + &self.base, + ScrollPolicy::Scrollable, + StackingContextCreationMode::Normal, + state.current_scroll_root_id); + state.add_stacking_context(current_stacking_context_id, - fragment.create_stacking_context( - fragment.stacking_context_id, - &self.base, - ScrollPolicy::Scrollable, - StackingContextCreationMode::Normal, - current_scroll_root_id)); + stacking_context); } _ => fragment.stacking_context_id = state.current_stacking_context_id, } diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index c4dfefcc696c..30ee0ad3a020 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -2470,7 +2470,10 @@ impl Fragment { if self.style().get_effects().mix_blend_mode != mix_blend_mode::T::normal { return true } - if self.style().get_box().transform.0.is_some() { + + if self.style().get_box().transform.0.is_some() || + self.style().get_box().transform_style == transform_style::T::preserve_3d || + self.style().overrides_transform_style() { return true } @@ -2485,13 +2488,6 @@ impl Fragment { return true } - match self.style().get_used_transform_style() { - transform_style::T::flat | transform_style::T::preserve_3d => { - return true - } - transform_style::T::auto => {} - } - match (self.style().get_box().position, self.style().get_position().z_index, self.style().get_box().overflow_x, diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index ca7cdb27a3f0..537d5f042676 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -12,7 +12,7 @@ use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use gfx::display_list::{BorderDetails, BorderRadii, BoxShadowClipMode, ClippingRegion}; use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal, StackingContextType}; use msg::constellation_msg::PipelineId; -use style::computed_values::{image_rendering, mix_blend_mode}; +use style::computed_values::{image_rendering, mix_blend_mode, transform_style}; use style::computed_values::filter::{self, Filter}; use style::values::computed::BorderStyle; use webrender_traits::{self, DisplayListBuilder, ExtendMode}; @@ -146,12 +146,12 @@ impl ToBorderRadius for BorderRadii { } } -trait ToBlendMode { - fn to_blend_mode(&self) -> webrender_traits::MixBlendMode; +pub trait ToMixBlendMode { + fn to_mix_blend_mode(&self) -> webrender_traits::MixBlendMode; } -impl ToBlendMode for mix_blend_mode::T { - fn to_blend_mode(&self) -> webrender_traits::MixBlendMode { +impl ToMixBlendMode for mix_blend_mode::T { + fn to_mix_blend_mode(&self) -> webrender_traits::MixBlendMode { match *self { mix_blend_mode::T::normal => webrender_traits::MixBlendMode::Normal, mix_blend_mode::T::multiply => webrender_traits::MixBlendMode::Multiply, @@ -211,6 +211,19 @@ impl ToFilterOps for filter::T { } } +pub trait ToTransformStyle { + fn to_transform_style(&self) -> webrender_traits::TransformStyle; +} + +impl ToTransformStyle for transform_style::T { + fn to_transform_style(&self) -> webrender_traits::TransformStyle { + match *self { + transform_style::T::auto | transform_style::T::flat => webrender_traits::TransformStyle::Flat, + transform_style::T::preserve_3d => webrender_traits::TransformStyle::Preserve3D, + } + } +} + impl WebRenderDisplayListConverter for DisplayList { fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder { let traversal = DisplayListTraversal::new(self); @@ -464,9 +477,9 @@ impl WebRenderDisplayItemConverter for DisplayItem { builder.push_stacking_context(stacking_context.scroll_policy, stacking_context.bounds.to_rectf(), transform, - webrender_traits::TransformStyle::Flat, + stacking_context.transform_style, perspective, - stacking_context.blend_mode.to_blend_mode(), + stacking_context.mix_blend_mode, stacking_context.filters.to_filter_ops()); } DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(), diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 79505e926572..1f5c951d1f46 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1954,33 +1954,30 @@ impl ComputedValues { )) } - /// https://drafts.csswg.org/css-transforms/#grouping-property-values - pub fn get_used_transform_style(&self) -> computed_values::transform_style::T { + /// Return true if the effects force the transform style to be Flat + pub fn overrides_transform_style(&self) -> bool { use computed_values::mix_blend_mode; - use computed_values::transform_style; let effects = self.get_effects(); - let box_ = self.get_box(); - // TODO(gw): Add clip-path, isolation, mask-image, mask-border-source when supported. - if effects.opacity < 1.0 || + effects.opacity < 1.0 || !effects.filter.is_empty() || - !effects.clip.is_auto() { - effects.mix_blend_mode != mix_blend_mode::T::normal || - return transform_style::T::flat; - } + !effects.clip.is_auto() || + effects.mix_blend_mode != mix_blend_mode::T::normal + } - if box_.transform_style == transform_style::T::auto { - if box_.transform.0.is_some() { - return transform_style::T::flat; - } - if let Either::First(ref _length) = box_.perspective { - return transform_style::T::flat; - } - } + /// https://drafts.csswg.org/css-transforms/#grouping-property-values + pub fn get_used_transform_style(&self) -> computed_values::transform_style::T { + use computed_values::transform_style; - // Return the computed value if not overridden by the above exceptions - box_.transform_style + let box_ = self.get_box(); + + if self.overrides_transform_style() { + transform_style::T::flat + } else { + // Return the computed value if not overridden by the above exceptions + box_.transform_style + } } /// Whether given this transform value, the compositor would require a diff --git a/tests/wpt/metadata-css/css-transforms-1_dev/html/css-transform-3d-transform-style.htm.ini b/tests/wpt/metadata-css/css-transforms-1_dev/html/css-transform-3d-transform-style.htm.ini deleted file mode 100644 index 5057dc804a73..000000000000 --- a/tests/wpt/metadata-css/css-transforms-1_dev/html/css-transform-3d-transform-style.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[css-transform-3d-transform-style.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-004.htm.ini b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-004.htm.ini new file mode 100644 index 000000000000..680f6a37a899 --- /dev/null +++ b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-004.htm.ini @@ -0,0 +1,4 @@ +[transform3d-sorting-004.htm] + type: reftest + expected: FAIL + bug: https://github.com/w3c/web-platform-tests/issues/5931 diff --git a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-005.htm.ini b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-005.htm.ini deleted file mode 100644 index d51b70bab1b8..000000000000 --- a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-005.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[transform3d-sorting-005.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-006.htm.ini b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-006.htm.ini index e275c5457a6c..e3fa053475b7 100644 --- a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-006.htm.ini +++ b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform3d-sorting-006.htm.ini @@ -1,3 +1,4 @@ [transform3d-sorting-006.htm] type: reftest expected: FAIL + bug: https://github.com/w3c/web-platform-tests/pull/5922