mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Implement basic support for display: inline-block.
This still needs a lot of work, but it covers the basic cases and improves wikipedia while passing all existing tests. Tweak reftest to deal with linux/travis black background.
This commit is contained in:
parent
20cde10e12
commit
98624c9576
11 changed files with 350 additions and 35 deletions
|
@ -20,7 +20,7 @@ use floats::{ClearBoth, ClearLeft, ClearRight, FloatKind, Floats, PlacementInfo}
|
||||||
use flow::{BaseFlow, BlockFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
use flow::{BaseFlow, BlockFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||||
use flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal, mut_base};
|
use flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal, mut_base};
|
||||||
use flow;
|
use flow;
|
||||||
use fragment::{Fragment, ImageFragment, ScannedTextFragment};
|
use fragment::{Fragment, ImageFragment, InlineBlockFragment, ScannedTextFragment};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use model::{Auto, IntrinsicISizes, MarginCollapseInfo, MarginsCollapse};
|
use model::{Auto, IntrinsicISizes, MarginCollapseInfo, MarginsCollapse};
|
||||||
use model::{MarginsCollapseThrough, MaybeAuto, NoCollapsibleMargins, Specified, specified};
|
use model::{MarginsCollapseThrough, MaybeAuto, NoCollapsibleMargins, Specified, specified};
|
||||||
|
@ -706,7 +706,7 @@ impl BlockFlow {
|
||||||
/// and image fragments.
|
/// and image fragments.
|
||||||
fn is_replaced_content(&self) -> bool {
|
fn is_replaced_content(&self) -> bool {
|
||||||
match self.fragment.specific {
|
match self.fragment.specific {
|
||||||
ScannedTextFragment(_) | ImageFragment(_) => true,
|
ScannedTextFragment(_) | ImageFragment(_) | InlineBlockFragment(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ use flow::{Flow, ImmutableFlowUtils, MutableOwnedFlowUtils};
|
||||||
use flow::{Descendants, AbsDescendants};
|
use flow::{Descendants, AbsDescendants};
|
||||||
use flow;
|
use flow;
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
|
use fragment::{InlineBlockFragment, InlineBlockFragmentInfo};
|
||||||
use fragment::{Fragment, GenericFragment, IframeFragment, IframeFragmentInfo};
|
use fragment::{Fragment, GenericFragment, IframeFragment, IframeFragmentInfo};
|
||||||
use fragment::{ImageFragment, ImageFragmentInfo, SpecificFragmentInfo, TableFragment};
|
use fragment::{ImageFragment, ImageFragmentInfo, SpecificFragmentInfo, TableFragment};
|
||||||
use fragment::{TableCellFragment, TableColumnFragment, TableColumnFragmentInfo};
|
use fragment::{TableCellFragment, TableColumnFragment, TableColumnFragmentInfo};
|
||||||
|
@ -266,19 +267,38 @@ impl<'a, 'b> FlowConstructor<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inline_flow = box InlineFlow::from_fragments((*node).clone(), fragments);
|
// Build a list of all the inline-block fragments before fragments is moved.
|
||||||
let (ascent, descent) = inline_flow.compute_minimum_ascent_and_descent(self.layout_context.font_context(), &**node.style());
|
let mut inline_block_flows = vec!();
|
||||||
inline_flow.minimum_block_size_above_baseline = ascent;
|
for f in fragments.fragments.iter() {
|
||||||
inline_flow.minimum_depth_below_baseline = descent;
|
match f.specific {
|
||||||
let mut inline_flow = inline_flow as Box<Flow>;
|
InlineBlockFragment(ref info) => {
|
||||||
TextRunScanner::new().scan_for_runs(self.layout_context.font_context(), inline_flow);
|
inline_block_flows.push(info.flow_ref.clone());
|
||||||
let mut inline_flow = FlowRef::new(inline_flow);
|
},
|
||||||
inline_flow.finish(self.layout_context);
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if flow.get().need_anonymous_flow(inline_flow.get()) {
|
let mut inline_flow_ref = FlowRef::new(box InlineFlow::from_fragments((*node).clone(), fragments));
|
||||||
flow_list.push(inline_flow)
|
|
||||||
|
// Add all the inline-block fragments as children of the inline flow.
|
||||||
|
for inline_block_flow in inline_block_flows.iter() {
|
||||||
|
inline_flow_ref.add_new_child(inline_block_flow.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut inline_flow = inline_flow_ref.get_mut().as_inline();
|
||||||
|
let (ascent, descent) = inline_flow.compute_minimum_ascent_and_descent(self.layout_context.font_context(), &**node.style());
|
||||||
|
inline_flow.minimum_block_size_above_baseline = ascent;
|
||||||
|
inline_flow.minimum_depth_below_baseline = descent;
|
||||||
|
TextRunScanner::new().scan_for_runs(self.layout_context.font_context(), inline_flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_flow_ref.finish(self.layout_context);
|
||||||
|
|
||||||
|
if flow.get().need_anonymous_flow(inline_flow_ref.get()) {
|
||||||
|
flow_list.push(inline_flow_ref)
|
||||||
} else {
|
} else {
|
||||||
flow.add_new_child(inline_flow)
|
flow.add_new_child(inline_flow_ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,6 +602,27 @@ impl<'a, 'b> FlowConstructor<'a, 'b> {
|
||||||
ConstructionItemConstructionResult(construction_item)
|
ConstructionItemConstructionResult(construction_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_fragment_for_inline_block(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
|
let block_flow_result = self.build_flow_for_block(node);
|
||||||
|
let block_flow = match block_flow_result {
|
||||||
|
FlowConstructionResult(block_flow, _) => block_flow,
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let fragment_info = InlineBlockFragment(InlineBlockFragmentInfo::new(block_flow));
|
||||||
|
let mut fragment = Fragment::new_from_specific_info(node, fragment_info);
|
||||||
|
|
||||||
|
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
|
||||||
|
fragment_accumulator.fragments.push(&mut fragment, node.style().clone());
|
||||||
|
|
||||||
|
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
|
||||||
|
splits: Vec::new(),
|
||||||
|
fragments: fragment_accumulator.finish(),
|
||||||
|
abs_descendants: Descendants::new(),
|
||||||
|
});
|
||||||
|
ConstructionItemConstructionResult(construction_item)
|
||||||
|
}
|
||||||
|
|
||||||
/// Builds one or more fragments for a node with `display: inline`. This yields an
|
/// Builds one or more fragments for a node with `display: inline`. This yields an
|
||||||
/// `InlineFragmentsConstructionResult`.
|
/// `InlineFragmentsConstructionResult`.
|
||||||
fn build_fragments_for_inline(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_fragments_for_inline(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
|
@ -840,6 +881,12 @@ impl<'a, 'b> PostorderNodeMutTraversal for FlowConstructor<'a, 'b> {
|
||||||
node.set_flow_construction_result(construction_result)
|
node.set_flow_construction_result(construction_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inline-block items contribute inline fragment construction results.
|
||||||
|
(display::inline_block, float::none, _) => {
|
||||||
|
let construction_result = self.build_fragment_for_inline_block(node);
|
||||||
|
node.set_flow_construction_result(construction_result)
|
||||||
|
}
|
||||||
|
|
||||||
// Table items contribute table flow construction results.
|
// Table items contribute table flow construction results.
|
||||||
(display::table_caption, _, _) => {
|
(display::table_caption, _, _) => {
|
||||||
let construction_result = self.build_flow_for_table_caption(node);
|
let construction_result = self.build_flow_for_table_caption(node);
|
||||||
|
|
|
@ -10,8 +10,9 @@ use css::node_style::StyledNode;
|
||||||
use construct::FlowConstructor;
|
use construct::FlowConstructor;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use floats::{ClearBoth, ClearLeft, ClearRight, ClearType};
|
use floats::{ClearBoth, ClearLeft, ClearRight, ClearType};
|
||||||
use flow::Flow;
|
use flow::{Flow, MutableFlowUtils};
|
||||||
use flow;
|
use flow;
|
||||||
|
use flow_ref::FlowRef;
|
||||||
use inline::{InlineFragmentContext, InlineMetrics};
|
use inline::{InlineFragmentContext, InlineMetrics};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use model::{Auto, IntrinsicISizes, MaybeAuto, Specified, specified};
|
use model::{Auto, IntrinsicISizes, MaybeAuto, Specified, specified};
|
||||||
|
@ -125,6 +126,7 @@ impl<E, S: Encoder<E>> Encodable<S, E> for Fragment {
|
||||||
/// Info specific to the kind of fragment. Keep this enum small.
|
/// Info specific to the kind of fragment. Keep this enum small.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub enum SpecificFragmentInfo {
|
pub enum SpecificFragmentInfo {
|
||||||
|
InlineBlockFragment(InlineBlockFragmentInfo),
|
||||||
GenericFragment,
|
GenericFragment,
|
||||||
ImageFragment(ImageFragmentInfo),
|
ImageFragment(ImageFragmentInfo),
|
||||||
IframeFragment(IframeFragmentInfo),
|
IframeFragment(IframeFragmentInfo),
|
||||||
|
@ -137,6 +139,20 @@ pub enum SpecificFragmentInfo {
|
||||||
UnscannedTextFragment(UnscannedTextFragmentInfo),
|
UnscannedTextFragment(UnscannedTextFragmentInfo),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A fragment that represents an inline-block element.
|
||||||
|
#[deriving(Clone)]
|
||||||
|
pub struct InlineBlockFragmentInfo {
|
||||||
|
pub flow_ref: FlowRef,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlineBlockFragmentInfo {
|
||||||
|
pub fn new(flow_ref: FlowRef) -> InlineBlockFragmentInfo {
|
||||||
|
InlineBlockFragmentInfo {
|
||||||
|
flow_ref: flow_ref,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A fragment that represents a replaced content image and its accompanying borders, shadows, etc.
|
/// A fragment that represents a replaced content image and its accompanying borders, shadows, etc.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct ImageFragmentInfo {
|
pub struct ImageFragmentInfo {
|
||||||
|
@ -454,7 +470,7 @@ impl Fragment {
|
||||||
/// replaced elements.
|
/// replaced elements.
|
||||||
fn style_specified_intrinsic_inline_size(&self) -> IntrinsicISizes {
|
fn style_specified_intrinsic_inline_size(&self) -> IntrinsicISizes {
|
||||||
let (use_margins, use_padding) = match self.specific {
|
let (use_margins, use_padding) = match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | ImageFragment(_) => (true, true),
|
GenericFragment | IframeFragment(_) | ImageFragment(_) | InlineBlockFragment(_) => (true, true),
|
||||||
TableFragment | TableCellFragment => (false, true),
|
TableFragment | TableCellFragment => (false, true),
|
||||||
TableWrapperFragment => (true, false),
|
TableWrapperFragment => (true, false),
|
||||||
TableRowFragment => (false, false),
|
TableRowFragment => (false, false),
|
||||||
|
@ -1082,7 +1098,7 @@ impl Fragment {
|
||||||
text_fragment))
|
text_fragment))
|
||||||
},
|
},
|
||||||
GenericFragment | IframeFragment(..) | TableFragment | TableCellFragment | TableRowFragment |
|
GenericFragment | IframeFragment(..) | TableFragment | TableCellFragment | TableRowFragment |
|
||||||
TableWrapperFragment => {
|
TableWrapperFragment | InlineBlockFragment(_) => {
|
||||||
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
||||||
// should have a real `SERVO_DEBUG` system.
|
// should have a real `SERVO_DEBUG` system.
|
||||||
debug!("{:?}", self.build_debug_borders_around_fragment(display_list, flow_origin))
|
debug!("{:?}", self.build_debug_borders_around_fragment(display_list, flow_origin))
|
||||||
|
@ -1151,6 +1167,11 @@ impl Fragment {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableColumnFragment(_) | TableRowFragment |
|
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableColumnFragment(_) | TableRowFragment |
|
||||||
TableWrapperFragment => {}
|
TableWrapperFragment => {}
|
||||||
|
InlineBlockFragment(ref mut info) => {
|
||||||
|
let block_flow = info.flow_ref.get_mut().as_block();
|
||||||
|
result.minimum_inline_size = geometry::max(result.minimum_inline_size, block_flow.base.intrinsic_inline_sizes.minimum_inline_size);
|
||||||
|
result.preferred_inline_size = geometry::max(result.preferred_inline_size, block_flow.base.intrinsic_inline_sizes.preferred_inline_size);
|
||||||
|
},
|
||||||
ImageFragment(ref mut image_fragment_info) => {
|
ImageFragment(ref mut image_fragment_info) => {
|
||||||
let image_inline_size = image_fragment_info.image_inline_size();
|
let image_inline_size = image_fragment_info.image_inline_size();
|
||||||
result.minimum_inline_size = geometry::max(result.minimum_inline_size, image_inline_size);
|
result.minimum_inline_size = geometry::max(result.minimum_inline_size, image_inline_size);
|
||||||
|
@ -1191,7 +1212,7 @@ impl Fragment {
|
||||||
pub fn content_inline_size(&self) -> Au {
|
pub fn content_inline_size(&self) -> Au {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
||||||
TableWrapperFragment => Au(0),
|
TableWrapperFragment | InlineBlockFragment(_) => Au(0),
|
||||||
ImageFragment(ref image_fragment_info) => {
|
ImageFragment(ref image_fragment_info) => {
|
||||||
image_fragment_info.computed_inline_size()
|
image_fragment_info.computed_inline_size()
|
||||||
}
|
}
|
||||||
|
@ -1209,7 +1230,7 @@ impl Fragment {
|
||||||
pub fn content_block_size(&self, layout_context: &LayoutContext) -> Au {
|
pub fn content_block_size(&self, layout_context: &LayoutContext) -> Au {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
||||||
TableWrapperFragment => Au(0),
|
TableWrapperFragment | InlineBlockFragment(_) => Au(0),
|
||||||
ImageFragment(ref image_fragment_info) => {
|
ImageFragment(ref image_fragment_info) => {
|
||||||
image_fragment_info.computed_block_size()
|
image_fragment_info.computed_block_size()
|
||||||
}
|
}
|
||||||
|
@ -1246,6 +1267,7 @@ impl Fragment {
|
||||||
TableRowFragment | TableWrapperFragment => None,
|
TableRowFragment | TableWrapperFragment => None,
|
||||||
TableColumnFragment(_) => fail!("Table column fragments do not need to split"),
|
TableColumnFragment(_) => fail!("Table column fragments do not need to split"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
|
InlineBlockFragment(_) => fail!("Inline blocks do not get split"),
|
||||||
ScannedTextFragment(ref text_fragment_info) => {
|
ScannedTextFragment(ref text_fragment_info) => {
|
||||||
let mut new_line_pos = self.new_line_pos.clone();
|
let mut new_line_pos = self.new_line_pos.clone();
|
||||||
let cur_new_line_pos = new_line_pos.remove(0).unwrap();
|
let cur_new_line_pos = new_line_pos.remove(0).unwrap();
|
||||||
|
@ -1283,7 +1305,7 @@ impl Fragment {
|
||||||
-> Option<(Option<SplitInfo>, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
|
-> Option<(Option<SplitInfo>, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | ImageFragment(_) | TableFragment | TableCellFragment |
|
GenericFragment | IframeFragment(_) | ImageFragment(_) | TableFragment | TableCellFragment |
|
||||||
TableRowFragment | TableWrapperFragment => None,
|
TableRowFragment | TableWrapperFragment | InlineBlockFragment(_) => None,
|
||||||
TableColumnFragment(_) => fail!("Table column fragments do not have inline_size"),
|
TableColumnFragment(_) => fail!("Table column fragments do not have inline_size"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
ScannedTextFragment(ref text_fragment_info) => {
|
ScannedTextFragment(ref text_fragment_info) => {
|
||||||
|
@ -1390,7 +1412,7 @@ impl Fragment {
|
||||||
TableWrapperFragment => return,
|
TableWrapperFragment => return,
|
||||||
TableColumnFragment(_) => fail!("Table column fragments do not have inline_size"),
|
TableColumnFragment(_) => fail!("Table column fragments do not have inline_size"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
ImageFragment(_) | ScannedTextFragment(_) => {}
|
ImageFragment(_) | ScannedTextFragment(_) | InlineBlockFragment(_) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.compute_border_padding_margins(container_inline_size);
|
self.compute_border_padding_margins(container_inline_size);
|
||||||
|
@ -1400,6 +1422,11 @@ impl Fragment {
|
||||||
let noncontent_inline_size = self.border_padding.inline_start_end();
|
let noncontent_inline_size = self.border_padding.inline_start_end();
|
||||||
|
|
||||||
match self.specific {
|
match self.specific {
|
||||||
|
InlineBlockFragment(ref mut info) => {
|
||||||
|
let block_flow = info.flow_ref.get_mut().as_block();
|
||||||
|
self.border_box.size.inline = block_flow.base.intrinsic_inline_sizes.preferred_inline_size + noncontent_inline_size;
|
||||||
|
block_flow.base.position.size.inline = self.border_box.size.inline;
|
||||||
|
}
|
||||||
ScannedTextFragment(_) => {
|
ScannedTextFragment(_) => {
|
||||||
// Scanned text fragments will have already had their content inline-sizes assigned by this
|
// Scanned text fragments will have already had their content inline-sizes assigned by this
|
||||||
// point.
|
// point.
|
||||||
|
@ -1441,7 +1468,7 @@ impl Fragment {
|
||||||
TableWrapperFragment => return,
|
TableWrapperFragment => return,
|
||||||
TableColumnFragment(_) => fail!("Table column fragments do not have block_size"),
|
TableColumnFragment(_) => fail!("Table column fragments do not have block_size"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
ImageFragment(_) | ScannedTextFragment(_) => {}
|
ImageFragment(_) | ScannedTextFragment(_) | InlineBlockFragment(_) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let style_inline_size = self.style().content_inline_size();
|
let style_inline_size = self.style().content_inline_size();
|
||||||
|
@ -1480,6 +1507,10 @@ impl Fragment {
|
||||||
// during flow construction.
|
// during flow construction.
|
||||||
self.border_box.size.block = self.border_box.size.block + noncontent_block_size
|
self.border_box.size.block = self.border_box.size.block + noncontent_block_size
|
||||||
}
|
}
|
||||||
|
InlineBlockFragment(ref mut info) => {
|
||||||
|
let block_flow = info.flow_ref.get_mut().as_block();
|
||||||
|
self.border_box.size.block = block_flow.base.position.size.block + noncontent_block_size;
|
||||||
|
}
|
||||||
_ => fail!("should have been handled above"),
|
_ => fail!("should have been handled above"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1501,6 +1532,13 @@ impl Fragment {
|
||||||
let line_height = self.calculate_line_height(layout_context);
|
let line_height = self.calculate_line_height(layout_context);
|
||||||
InlineMetrics::from_font_metrics(&text_fragment.run.font_metrics, line_height)
|
InlineMetrics::from_font_metrics(&text_fragment.run.font_metrics, line_height)
|
||||||
}
|
}
|
||||||
|
InlineBlockFragment(ref info) => {
|
||||||
|
// See CSS 2.1 § 10.8.1.
|
||||||
|
let block_flow = info.flow_ref.get().as_immutable_block();
|
||||||
|
let font_style = text::computed_style_to_font_style(&*self.style);
|
||||||
|
let font_metrics = text::font_metrics_for_style(layout_context.font_context(), &font_style);
|
||||||
|
InlineMetrics::from_block_height(&font_metrics, block_flow.base.position.size.block)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
InlineMetrics {
|
InlineMetrics {
|
||||||
block_size_above_baseline: self.border_box.size.block,
|
block_size_above_baseline: self.border_box.size.block,
|
||||||
|
@ -1566,6 +1604,7 @@ impl fmt::Show for Fragment {
|
||||||
TableRowFragment => "TableRowFragment",
|
TableRowFragment => "TableRowFragment",
|
||||||
TableWrapperFragment => "TableWrapperFragment",
|
TableWrapperFragment => "TableWrapperFragment",
|
||||||
UnscannedTextFragment(_) => "UnscannedTextFragment",
|
UnscannedTextFragment(_) => "UnscannedTextFragment",
|
||||||
|
InlineBlockFragment(_) => "InlineBlockFragment",
|
||||||
}));
|
}));
|
||||||
try!(write!(f, "bp {}", self.border_padding));
|
try!(write!(f, "bp {}", self.border_padding));
|
||||||
try!(write!(f, " "));
|
try!(write!(f, " "));
|
||||||
|
|
|
@ -9,8 +9,8 @@ use context::LayoutContext;
|
||||||
use floats::{FloatLeft, Floats, PlacementInfo};
|
use floats::{FloatLeft, Floats, PlacementInfo};
|
||||||
use flow::{BaseFlow, FlowClass, Flow, InlineFlowClass};
|
use flow::{BaseFlow, FlowClass, Flow, InlineFlowClass};
|
||||||
use flow;
|
use flow;
|
||||||
use fragment::{Fragment, ScannedTextFragment, ScannedTextFragmentInfo, SplitInfo};
|
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
|
use fragment::{Fragment, InlineBlockFragment, ScannedTextFragment, ScannedTextFragmentInfo, SplitInfo};
|
||||||
use model::IntrinsicISizes;
|
use model::IntrinsicISizes;
|
||||||
use text;
|
use text;
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
@ -20,6 +20,7 @@ use geom::Rect;
|
||||||
use gfx::display_list::ContentLevel;
|
use gfx::display_list::ContentLevel;
|
||||||
use gfx::font::FontMetrics;
|
use gfx::font::FontMetrics;
|
||||||
use gfx::font_context::FontContext;
|
use gfx::font_context::FontContext;
|
||||||
|
use geom::Size2D;
|
||||||
use gfx::text::glyph::CharIndex;
|
use gfx::text::glyph::CharIndex;
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use servo_util::geometry;
|
use servo_util::geometry;
|
||||||
|
@ -760,11 +761,18 @@ impl InlineFlow {
|
||||||
let rel_offset = fragment.relative_position(&self.base
|
let rel_offset = fragment.relative_position(&self.base
|
||||||
.absolute_position_info
|
.absolute_position_info
|
||||||
.relative_containing_block_size);
|
.relative_containing_block_size);
|
||||||
drop(fragment.build_display_list(&mut self.base.display_list,
|
let mut accumulator = fragment.build_display_list(&mut self.base.display_list,
|
||||||
layout_context,
|
layout_context,
|
||||||
self.base.abs_position.add_size(
|
self.base.abs_position.add_size(
|
||||||
&rel_offset.to_physical(self.base.writing_mode)),
|
&rel_offset.to_physical(self.base.writing_mode)),
|
||||||
ContentLevel));
|
ContentLevel);
|
||||||
|
match fragment.specific {
|
||||||
|
InlineBlockFragment(ref mut block_flow) => {
|
||||||
|
let block_flow = block_flow.flow_ref.get_mut();
|
||||||
|
accumulator.push_child(&mut self.base.display_list, block_flow);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
|
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
|
||||||
|
@ -949,17 +957,6 @@ impl Flow for InlineFlow {
|
||||||
fragment.assign_replaced_inline_size_if_necessary(inline_size);
|
fragment.assign_replaced_inline_size_if_necessary(inline_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(self.base.children.len() == 0,
|
|
||||||
"InlineFlow: should not have children flows in the current layout implementation.");
|
|
||||||
|
|
||||||
// There are no child contexts, so stop here.
|
|
||||||
|
|
||||||
// TODO(Issue #225): once there are 'inline-block' elements, this won't be
|
|
||||||
// true. In that case, set the InlineBlockFragment's inline-size to the
|
|
||||||
// shrink-to-fit inline-size, perform inline flow, and set the block
|
|
||||||
// flow context's inline-size as the assigned inline-size of the
|
|
||||||
// 'inline-block' fragment that created this flow before recursing.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate and set the block-size of this flow. See CSS 2.1 § 10.6.1.
|
/// Calculate and set the block-size of this flow. See CSS 2.1 § 10.6.1.
|
||||||
|
@ -1118,6 +1115,22 @@ impl Flow for InlineFlow {
|
||||||
self.base.floats.translate(LogicalSize::new(
|
self.base.floats.translate(LogicalSize::new(
|
||||||
self.base.writing_mode, Au::new(0), -self.base.position.size.block));
|
self.base.writing_mode, Au::new(0), -self.base.position.size.block));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compute_absolute_position(&mut self) {
|
||||||
|
for f in self.fragments.fragments.mut_iter() {
|
||||||
|
match f.specific {
|
||||||
|
InlineBlockFragment(ref mut info) => {
|
||||||
|
let block_flow = info.flow_ref.get_mut().as_block();
|
||||||
|
|
||||||
|
// FIXME(#2795): Get the real container size
|
||||||
|
let container_size = Size2D::zero();
|
||||||
|
block_flow.base.abs_position = self.base.abs_position +
|
||||||
|
f.border_box.start.to_physical(self.base.writing_mode, container_size);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for InlineFlow {
|
impl fmt::Show for InlineFlow {
|
||||||
|
@ -1166,5 +1179,16 @@ impl InlineMetrics {
|
||||||
ascent: font_metrics.ascent,
|
ascent: font_metrics.ascent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculates inline metrics from font metrics and line block-size per CSS 2.1 § 10.8.1.
|
||||||
|
#[inline]
|
||||||
|
pub fn from_block_height(font_metrics: &FontMetrics, block_height: Au) -> InlineMetrics {
|
||||||
|
let leading = block_height - (font_metrics.ascent + font_metrics.descent);
|
||||||
|
InlineMetrics {
|
||||||
|
block_size_above_baseline: font_metrics.ascent + leading.scale_by(0.5),
|
||||||
|
depth_below_baseline: font_metrics.descent + leading.scale_by(0.5),
|
||||||
|
ascent: font_metrics.ascent + leading.scale_by(0.5),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,3 +119,6 @@ flaky_gpu,flaky_linux == acid2_noscroll.html acid2_ref_broken.html
|
||||||
== iframe/simple.html iframe/simple_ref.html
|
== iframe/simple.html iframe/simple_ref.html
|
||||||
== iframe/multiple_external.html iframe/multiple_external_ref.html
|
== iframe/multiple_external.html iframe/multiple_external_ref.html
|
||||||
== floated_generated_content_a.html floated_generated_content_b.html
|
== floated_generated_content_a.html floated_generated_content_b.html
|
||||||
|
== inline_block_margin_a.html inline_block_margin_ref.html
|
||||||
|
== inline_block_img_a.html inline_block_img_ref.html
|
||||||
|
== inline_block_baseline_a.html inline_block_baseline_ref.html
|
||||||
|
|
28
tests/ref/inline_block_baseline_a.html
Normal file
28
tests/ref/inline_block_baseline_a.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style type="text/css">
|
||||||
|
@font-face {
|
||||||
|
font-family: 'ahem';
|
||||||
|
src: url(fonts/ahem/ahem.ttf);
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'ahem';
|
||||||
|
font-size: 400px;
|
||||||
|
line-height: 1;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.test {
|
||||||
|
color: green;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 300px;
|
||||||
|
}
|
||||||
|
.cdef {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="cdef">X<span class="test">X</span></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
32
tests/ref/inline_block_baseline_ref.html
Normal file
32
tests/ref/inline_block_baseline_ref.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.red {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
.green {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
.d1 {
|
||||||
|
position: absolute;
|
||||||
|
width: 400px;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
.d2 {
|
||||||
|
position: absolute;
|
||||||
|
left: 400px;
|
||||||
|
top: 80px;
|
||||||
|
width: 300px;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="d1 red"></div>
|
||||||
|
<div class="d2 green"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
36
tests/ref/inline_block_img_a.html
Normal file
36
tests/ref/inline_block_img_a.html
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: 'ahem';
|
||||||
|
src: url(fonts/ahem/ahem.ttf);
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
.red {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
.green {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
.ib {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
font-family: ahem;
|
||||||
|
font-size: 100px;
|
||||||
|
}
|
||||||
|
.bg {
|
||||||
|
background-color: white;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 500px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body><div class="bg"><span class="red">X</span><img src="400x400_green.png"><span class="green ib">X</span></div></body>
|
||||||
|
</html>
|
47
tests/ref/inline_block_img_ref.html
Normal file
47
tests/ref/inline_block_img_ref.html
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.red {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
.green {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
.d1 {
|
||||||
|
position: absolute;
|
||||||
|
top: 320px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.d2 {
|
||||||
|
position: absolute;
|
||||||
|
left: 500px;
|
||||||
|
top: 320px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
left: 100px;
|
||||||
|
}
|
||||||
|
.bg {
|
||||||
|
background-color: white;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 500px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="bg">
|
||||||
|
<div class="d1 red"></div>
|
||||||
|
<img src="400x400_green.png">
|
||||||
|
<div class="d2 green"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
28
tests/ref/inline_block_margin_a.html
Normal file
28
tests/ref/inline_block_margin_a.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style type="text/css">
|
||||||
|
@font-face {
|
||||||
|
font-family: 'ahem';
|
||||||
|
src: url(fonts/ahem/ahem.ttf);
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'ahem';
|
||||||
|
font-size: 100px;
|
||||||
|
margin: 32px;
|
||||||
|
}
|
||||||
|
.ib {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.yellow {
|
||||||
|
color: #ff0;
|
||||||
|
}
|
||||||
|
.grey {
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="grey">X<span class="yellow ib">X</span></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
31
tests/ref/inline_block_margin_ref.html
Normal file
31
tests/ref/inline_block_margin_ref.html
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style type="text/css">
|
||||||
|
.yellow {
|
||||||
|
background-color: #ff0;
|
||||||
|
}
|
||||||
|
.grey {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
.d1 {
|
||||||
|
position: absolute;
|
||||||
|
left: 32px;
|
||||||
|
top: 32px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.d2 {
|
||||||
|
position: absolute;
|
||||||
|
left: 132px;
|
||||||
|
top: 32px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="d1 grey"></div>
|
||||||
|
<div class="d2 yellow"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue