diff options
-rw-r--r-- | components/layout/display_list_builder.rs | 145 | ||||
-rw-r--r-- | tests/ref/basic.list | 1 | ||||
-rw-r--r-- | tests/ref/filter_inline_a.html | 18 | ||||
-rw-r--r-- | tests/ref/filter_inline_ref.html | 18 | ||||
-rw-r--r-- | tests/ref/rust.png | bin | 0 -> 13361 bytes |
5 files changed, 112 insertions, 70 deletions
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index a1074a0a27e..153afb61ee0 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -230,6 +230,14 @@ pub trait FragmentDisplayListBuilding { display_list: &mut DisplayList, stacking_relative_border_box: &Rect<Au>, clip: &ClippingRegion); + + /// Creates a stacking context for associated fragment. + fn create_stacking_context(&self, + base_flow: &BaseFlow, + display_list: Box<DisplayList>, + layer: Option<Arc<PaintLayer>>) + -> Arc<StackingContext>; + } fn handle_overlapping_radii(size: &Size2D<Au>, radii: &BorderRadii<Au>) -> BorderRadii<Au> { @@ -1017,6 +1025,52 @@ impl FragmentDisplayListBuilding for Fragment { } } + fn create_stacking_context(&self, + base_flow: &BaseFlow, + display_list: Box<DisplayList>, + layer: Option<Arc<PaintLayer>>) + -> Arc<StackingContext> { + + let border_box = self.stacking_relative_border_box(&base_flow.stacking_relative_position, + &base_flow.absolute_position_info + .relative_containing_block_size, + base_flow.absolute_position_info + .relative_containing_block_mode, + CoordinateSystem::Parent); + + let transform_origin = self.style().get_effects().transform_origin; + let transform_origin = + Point2D(model::specified(transform_origin.horizontal, + border_box.size.width).to_frac32_px(), + model::specified(transform_origin.vertical, + border_box.size.height).to_frac32_px()); + let transform = self.style().get_effects().transform + .unwrap_or(ComputedMatrix::identity()).to_gfx_matrix(&border_box.size); + + let transform = Matrix2D::identity().translate(transform_origin.x, transform_origin.y) + .mul(&transform).translate(-transform_origin.x, -transform_origin.y); + + // FIXME(pcwalton): Is this vertical-writing-direction-safe? + let margin = self.margin.to_physical(base_flow.writing_mode); + let overflow = base_flow.overflow.translate(&-Point2D(margin.left, Au(0))); + + // Create the filter pipeline. + let effects = self.style().get_effects(); + let mut filters = effects.filter.clone(); + if effects.opacity != 1.0 { + filters.push(Filter::Opacity(effects.opacity)) + } + + Arc::new(StackingContext::new(display_list, + &border_box, + &overflow, + self.style().get_box().z_index.number_or_zero(), + &transform, + filters, + self.style().get_effects().mix_blend_mode, + layer)) + } + #[inline(never)] fn finalize_position_and_size_of_iframe(&self, iframe_fragment: &IframeFragmentInfo, @@ -1222,10 +1276,6 @@ pub trait BlockFlowDisplayListBuilding { fn build_display_list_for_block(&mut self, display_list: Box<DisplayList>, layout_context: &LayoutContext); - fn create_stacking_context(&self, - display_list: Box<DisplayList>, - layer: Option<Arc<PaintLayer>>) - -> Arc<StackingContext>; } impl BlockFlowDisplayListBuilding for BlockFlow { @@ -1268,8 +1318,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { background_border_level); self.base.display_list_building_result = if self.fragment.establishes_stacking_context() { - DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, - None)) + DisplayListBuildingResult::StackingContext(self.fragment.create_stacking_context(&self.base, display_list, None)) } else { DisplayListBuildingResult::Normal(display_list) } @@ -1286,9 +1335,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow { !self.base.flags.contains(NEEDS_LAYER) { // We didn't need a layer. self.base.display_list_building_result = - DisplayListBuildingResult::StackingContext(self.create_stacking_context( - display_list, - None)); + DisplayListBuildingResult::StackingContext(self.fragment + .create_stacking_context(&self.base, display_list, None)); return } @@ -1299,12 +1347,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow { ScrollPolicy::Scrollable }; + let transparent = color::transparent(); - let stacking_context = - self.create_stacking_context(display_list, - Some(Arc::new(PaintLayer::new(self.layer_id(0), - transparent, - scroll_policy)))); + let stacking_context = self.fragment.create_stacking_context(&self.base, display_list, + Some(Arc::new(PaintLayer::new(self.layer_id(0), + transparent, + scroll_policy)))); self.base.display_list_building_result = DisplayListBuildingResult::StackingContext(stacking_context) } @@ -1318,8 +1366,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow { display_list.form_float_pseudo_stacking_context(); self.base.display_list_building_result = if self.fragment.establishes_stacking_context() { - DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, - None)) + DisplayListBuildingResult::StackingContext(self.fragment + .create_stacking_context(&self.base, display_list, None)) } else { DisplayListBuildingResult::Normal(display_list) } @@ -1340,58 +1388,6 @@ impl BlockFlowDisplayListBuilding for BlockFlow { BackgroundAndBorderLevel::Block); } } - - fn create_stacking_context(&self, - display_list: Box<DisplayList>, - layer: Option<Arc<PaintLayer>>) - -> Arc<StackingContext> { - debug_assert!(self.fragment.establishes_stacking_context()); - let border_box = self.fragment - .stacking_relative_border_box(&self.base.stacking_relative_position, - &self.base - .absolute_position_info - .relative_containing_block_size, - self.base - .absolute_position_info - .relative_containing_block_mode, - CoordinateSystem::Parent); - - let transform_origin = self.fragment.style().get_effects().transform_origin; - let transform_origin = - Point2D(model::specified(transform_origin.horizontal, - border_box.size.width).to_frac32_px(), - model::specified(transform_origin.vertical, - border_box.size.height).to_frac32_px()); - let transform = self.fragment - .style() - .get_effects() - .transform - .unwrap_or(ComputedMatrix::identity()) - .to_gfx_matrix(&border_box.size); - let transform = Matrix2D::identity().translate(transform_origin.x, transform_origin.y) - .mul(&transform) - .translate(-transform_origin.x, -transform_origin.y); - - // FIXME(pcwalton): Is this vertical-writing-direction-safe? - let margin = self.fragment.margin.to_physical(self.base.writing_mode); - let overflow = self.base.overflow.translate(&-Point2D(margin.left, Au(0))); - - // Create the filter pipeline. - let effects = self.fragment.style().get_effects(); - let mut filters = effects.filter.clone(); - if effects.opacity != 1.0 { - filters.push(Filter::Opacity(effects.opacity)) - } - - Arc::new(StackingContext::new(display_list, - &border_box, - &overflow, - self.fragment.style().get_box().z_index.number_or_zero(), - &transform, - filters, - self.fragment.style().get_effects().mix_blend_mode, - layer)) - } } pub trait InlineFlowDisplayListBuilding { @@ -1405,7 +1401,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow { debug!("Flow: building display list for {} inline fragments", self.fragments.len()); let mut display_list = box DisplayList::new(); - + let mut has_stacking_context = false; for fragment in self.fragments.fragments.iter_mut() { fragment.build_display_list(&mut *display_list, layout_context, @@ -1418,6 +1414,8 @@ impl InlineFlowDisplayListBuilding for InlineFlow { .relative_containing_block_mode, BackgroundAndBorderLevel::Content, &self.base.clip); + + has_stacking_context = fragment.establishes_stacking_context(); match fragment.specific { SpecificFragmentInfo::InlineBlock(ref mut block_flow) => { let block_flow = &mut *block_flow.flow_ref; @@ -1438,7 +1436,14 @@ impl InlineFlowDisplayListBuilding for InlineFlow { self.fragments.fragments[0].node); } - self.base.display_list_building_result = DisplayListBuildingResult::Normal(display_list); + // FIXME(Savago): fix Fragment::establishes_stacking_context() for absolute positioned item + // and remove the check for filter presence. Further details on #5812. + if has_stacking_context && !self.fragments.fragments[0].style().get_effects().filter.is_empty() { + self.base.display_list_building_result = + DisplayListBuildingResult::StackingContext(self.fragments.fragments[0].create_stacking_context(&self.base, display_list, None)); + } else { + self.base.display_list_building_result = DisplayListBuildingResult::Normal(display_list); + } if opts::get().validate_display_list_geometry { self.base.validate_display_list_geometry(); diff --git a/tests/ref/basic.list b/tests/ref/basic.list index 2f17b1e9e59..8d8a6b21add 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -108,6 +108,7 @@ flaky_cpu == append_style_a.html append_style_b.html == empty_cells_a.html empty_cells_ref.html == external_media_query_link.html external_media_query_ref.html == external_media_query_style.html external_media_query_ref.html +== filter_inline_a.html filter_inline_ref.html == filter_opacity_a.html filter_opacity_ref.html == filter_sepia_a.html filter_sepia_ref.html == first_child_pseudo_a.html first_child_pseudo_b.html diff --git a/tests/ref/filter_inline_a.html b/tests/ref/filter_inline_a.html new file mode 100644 index 00000000000..1190c6602ad --- /dev/null +++ b/tests/ref/filter_inline_a.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<head> +<style type="text/css"> + +.ex { + <!-- display: block; --> + -webkit-filter: opacity(25%); + -moz-filter: opacity(25%); + filter: opacity(25%); +} + +</style> +</head> +<body> + <img class="ex" src="rust.png"> +</body> +</html> diff --git a/tests/ref/filter_inline_ref.html b/tests/ref/filter_inline_ref.html new file mode 100644 index 00000000000..0bc34849029 --- /dev/null +++ b/tests/ref/filter_inline_ref.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<head> +<style type="text/css"> + +.ex { + display: block; + -webkit-filter: opacity(25%); + -moz-filter: opacity(25%); + filter: opacity(25%); +} + +</style> +</head> +<body> + <img class="ex" src="rust.png"> +</body> +</html> diff --git a/tests/ref/rust.png b/tests/ref/rust.png Binary files differnew file mode 100644 index 00000000000..68b5ed31e7b --- /dev/null +++ b/tests/ref/rust.png |