Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

layout: Unify size calculation of replaced elements #14490

Merged
merged 7 commits into from Dec 12, 2016
@@ -42,12 +42,11 @@ use flow::IS_ABSOLUTELY_POSITIONED;
use flow_list::FlowList;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
use fragment::{IS_INLINE_FLEX_ITEM, IS_BLOCK_FLEX_ITEM};
use fragment::SpecificFragmentInfo;
use gfx::display_list::{ClippingRegion, StackingContext};
use gfx_traits::ScrollRootId;
use gfx_traits::print_tree::PrintTree;
use layout_debug;
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo, MaybeAuto};
use model::{AdjoiningMargins, CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo, MaybeAuto};
use model::{specified, specified_or_none};
use sequential;
use serde::{Serialize, Serializer};
@@ -555,27 +554,27 @@ impl BlockFlow {
/// relevant margins for this Block.
pub fn block_type(&self) -> BlockType {
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
if self.is_replaced_content() {
if self.fragment.is_replaced() {
BlockType::AbsoluteReplaced
} else {
BlockType::AbsoluteNonReplaced
}
} else if self.is_inline_flex_item() {
BlockType::InlineFlexItem
} else if self.base.flags.is_float() {
if self.is_replaced_content() {
if self.fragment.is_replaced() {
BlockType::FloatReplaced
} else {
BlockType::FloatNonReplaced
}
} else if self.is_inline_block() {
if self.is_replaced_content() {
if self.fragment.is_replaced() {
BlockType::InlineBlockReplaced
} else {
BlockType::InlineBlockNonReplaced
}
} else {
if self.is_replaced_content() {
if self.fragment.is_replaced() {
BlockType::Replaced
} else {
BlockType::NonReplaced
@@ -668,22 +667,6 @@ impl BlockFlow {
}
}

/// Return true if this has a replaced fragment.
///
/// Text, Images, Inline Block and Canvas
/// (https://html.spec.whatwg.org/multipage/#replaced-elements) fragments are considered as
/// replaced fragments.
fn is_replaced_content(&self) -> bool {
match self.fragment.specific {
SpecificFragmentInfo::ScannedText(_) |
SpecificFragmentInfo::Svg(_) |
SpecificFragmentInfo::Image(_) |
SpecificFragmentInfo::Canvas(_) |
SpecificFragmentInfo::InlineBlock(_) => true,
_ => false,
}
}

/// Return shrink-to-fit inline-size.
///
/// This is where we use the preferred inline-sizes and minimum inline-sizes
@@ -1267,11 +1250,11 @@ impl BlockFlow {

let available_block_size = containing_block_block_size -
self.fragment.border_padding.block_start_end();
if self.is_replaced_content() {
if self.fragment.is_replaced() {
// Calculate used value of block-size just like we do for inline replaced elements.
// TODO: Pass in the containing block block-size when Fragment's
// assign-block-size can handle it correctly.
self.fragment.assign_replaced_block_size_if_necessary(Some(containing_block_block_size));
self.fragment.assign_replaced_block_size_if_necessary();
// TODO: Right now, this content block-size value includes the
// margin because of erroneous block-size calculation in fragment.
// Check this when that has been fixed.
@@ -1896,16 +1879,22 @@ impl Flow for BlockFlow {
fn fragment(&mut self, layout_context: &LayoutContext,
fragmentation_context: Option<FragmentationContext>)
-> Option<Arc<Flow>> {
if self.is_replaced_content() {
if self.fragment.is_replaced() {
let _scope = layout_debug_scope!("assign_replaced_block_size_if_necessary {:x}",
self.base.debug_id());

// Assign block-size for fragment if it is an image fragment.
let containing_block_block_size =
self.base.block_container_explicit_block_size;
self.fragment.assign_replaced_block_size_if_necessary(containing_block_block_size);
self.fragment.assign_replaced_block_size_if_necessary();
if !self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
self.base.position.size.block = self.fragment.border_box.size.block;
let mut block_start = AdjoiningMargins::from_margin(self.fragment.margin.block_start);
let block_end = AdjoiningMargins::from_margin(self.fragment.margin.block_end);
if self.fragment.border_box.size.block == Au(0) {
block_start.union(block_end);
self.base.collapsible_margins = CollapsibleMargins::CollapseThrough(block_start);
} else {
self.base.collapsible_margins = CollapsibleMargins::Collapse(block_start, block_end);
}
self.base.restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
self.fragment.restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
}
@@ -2870,7 +2859,7 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
fragment.assign_replaced_inline_size_if_necessary(containing_block_inline_size, container_block_size);
// For replaced absolute flow, the rest of the constraint solving will
// take inline-size to be specified as the value computed here.
MaybeAuto::Specified(fragment.content_inline_size())
MaybeAuto::Specified(fragment.content_box().size.inline)
}

fn containing_block_inline_size(&self,
@@ -2929,7 +2918,7 @@ impl ISizeAndMarginsComputer for BlockReplaced {
fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, container_block_size);
// For replaced block flow, the rest of the constraint solving will
// take inline-size to be specified as the value computed here.
MaybeAuto::Specified(fragment.content_inline_size())
MaybeAuto::Specified(fragment.content_box().size.inline)
}

}
@@ -2987,7 +2976,7 @@ impl ISizeAndMarginsComputer for FloatReplaced {
fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, container_block_size);
// For replaced block flow, the rest of the constraint solving will
// take inline-size to be specified as the value computed here.
MaybeAuto::Specified(fragment.content_inline_size())
MaybeAuto::Specified(fragment.content_box().size.inline)
}
}

@@ -3075,7 +3064,7 @@ impl ISizeAndMarginsComputer for InlineBlockReplaced {
fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, container_block_size);
// For replaced block flow, the rest of the constraint solving will
// take inline-size to be specified as the value computed here.
MaybeAuto::Specified(fragment.content_inline_size())
MaybeAuto::Specified(fragment.content_box().size.inline)
}
}

@@ -346,14 +346,12 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
SpecificFragmentInfo::Iframe(IframeFragmentInfo::new(node))
}
Some(LayoutNodeType::Element(LayoutElementType::HTMLImageElement)) => {
let image_info = box ImageFragmentInfo::new(node,
node.image_url(),
let image_info = box ImageFragmentInfo::new(node.image_url(),
&self.layout_context.shared);
SpecificFragmentInfo::Image(image_info)
}
Some(LayoutNodeType::Element(LayoutElementType::HTMLObjectElement)) => {
let image_info = box ImageFragmentInfo::new(node,
node.object_data(),
let image_info = box ImageFragmentInfo::new(node.object_data(),
&self.layout_context.shared);
SpecificFragmentInfo::Image(image_info)
}
@@ -372,11 +370,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
}
Some(LayoutNodeType::Element(LayoutElementType::HTMLCanvasElement)) => {
let data = node.canvas_data().unwrap();
SpecificFragmentInfo::Canvas(box CanvasFragmentInfo::new(node, data, self.style_context()))
SpecificFragmentInfo::Canvas(box CanvasFragmentInfo::new(data))
}
Some(LayoutNodeType::Element(LayoutElementType::SVGSVGElement)) => {
let data = node.svg_data().unwrap();
SpecificFragmentInfo::Svg(box SvgFragmentInfo::new(node, data, self.style_context()))
SpecificFragmentInfo::Svg(box SvgFragmentInfo::new(data))
}
_ => {
// This includes pseudo-elements.
@@ -1207,8 +1205,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let flotation = FloatKind::from_property(flotation);
let marker_fragments = match node.style(self.style_context()).get_list().list_style_image {
Either::First(ref url_value) => {
let image_info = box ImageFragmentInfo::new(node,
url_value.url().map(|u| u.clone()),
let image_info = box ImageFragmentInfo::new(url_value.url().map(|u| u.clone()),
&self.layout_context.shared);
vec![Fragment::new(node, SpecificFragmentInfo::Image(image_info), self.layout_context)]
}
@@ -1489,57 +1489,51 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
SpecificFragmentInfo::Canvas(ref canvas_fragment_info) => {
let width = canvas_fragment_info.replaced_image_fragment_info
.computed_inline_size.map_or(0, |w| w.to_px() as usize);
let height = canvas_fragment_info.replaced_image_fragment_info
.computed_block_size.map_or(0, |h| h.to_px() as usize);
if width > 0 && height > 0 {
let computed_width = canvas_fragment_info.canvas_inline_size().to_px();
let computed_height = canvas_fragment_info.canvas_block_size().to_px();

let canvas_data = match canvas_fragment_info.ipc_renderer {
Some(ref ipc_renderer) => {
let ipc_renderer = ipc_renderer.lock().unwrap();
let (sender, receiver) = ipc::channel().unwrap();
ipc_renderer.send(CanvasMsg::FromLayout(
FromLayoutMsg::SendData(sender))).unwrap();
receiver.recv().unwrap()
},
None => return,
};
let computed_width = canvas_fragment_info.dom_width.to_px();
let computed_height = canvas_fragment_info.dom_height.to_px();

let canvas_data = match canvas_fragment_info.ipc_renderer {
Some(ref ipc_renderer) => {
let ipc_renderer = ipc_renderer.lock().unwrap();
let (sender, receiver) = ipc::channel().unwrap();
ipc_renderer.send(CanvasMsg::FromLayout(
FromLayoutMsg::SendData(sender))).unwrap();
receiver.recv().unwrap()
},
None => return,
};

let base = state.create_base_display_item(
&stacking_relative_content_box,
clip,
self.node,
self.style.get_cursor(Cursor::Default),
DisplayListSection::Content);
let display_item = match canvas_data {
CanvasData::Image(canvas_data) => {
DisplayItem::Image(box ImageDisplayItem {
base: base,
webrender_image: WebRenderImageInfo {
width: computed_width as u32,
height: computed_height as u32,
format: PixelFormat::RGBA8,
key: Some(canvas_data.image_key),
},
image_data: None,
stretch_size: stacking_relative_content_box.size,
tile_spacing: Size2D::zero(),
image_rendering: image_rendering::T::auto,
})
}
CanvasData::WebGL(context_id) => {
DisplayItem::WebGL(box WebGLDisplayItem {
base: base,
context_id: context_id,
})
}
};

let base = state.create_base_display_item(
&stacking_relative_content_box,
clip,
self.node,
self.style.get_cursor(Cursor::Default),
DisplayListSection::Content);
let display_item = match canvas_data {
CanvasData::Image(canvas_data) => {
DisplayItem::Image(box ImageDisplayItem {
base: base,
webrender_image: WebRenderImageInfo {
width: computed_width as u32,
height: computed_height as u32,
format: PixelFormat::RGBA8,
key: Some(canvas_data.image_key),
},
image_data: None,
stretch_size: stacking_relative_content_box.size,
tile_spacing: Size2D::zero(),
image_rendering: image_rendering::T::auto,
})
}
CanvasData::WebGL(context_id) => {
DisplayItem::WebGL(box WebGLDisplayItem {
base: base,
context_id: context_id,
})
}
};

state.add_display_item(display_item);
}
state.add_display_item(display_item);
}
SpecificFragmentInfo::UnscannedText(_) => {
panic!("Shouldn't see unscanned fragments here.")
@@ -19,7 +19,7 @@ use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::StackingContext;
use gfx_traits::ScrollRootId;
use layout_debug;
use model::{IntrinsicISizes, MaybeAuto, MinMaxConstraint};
use model::{IntrinsicISizes, MaybeAuto, SizeConstraint};
use model::{specified, specified_or_none};
use std::cmp::{max, min};
use std::ops::Range;
@@ -38,7 +38,7 @@ use style::values::computed::{LengthOrPercentageOrAutoOrContent, LengthOrPercent
#[derive(Debug)]
enum AxisSize {
Definite(Au),
MinMax(MinMaxConstraint),
MinMax(SizeConstraint),
Infinite,
}

@@ -62,7 +62,7 @@ impl AxisSize {
}
}
LengthOrPercentageOrAuto::Auto => {
AxisSize::MinMax(MinMaxConstraint::new(content_size, min, max))
AxisSize::MinMax(SizeConstraint::new(content_size, min, max, None))
}
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.