mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01: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
|
@ -10,8 +10,9 @@ use css::node_style::StyledNode;
|
|||
use construct::FlowConstructor;
|
||||
use context::LayoutContext;
|
||||
use floats::{ClearBoth, ClearLeft, ClearRight, ClearType};
|
||||
use flow::Flow;
|
||||
use flow::{Flow, MutableFlowUtils};
|
||||
use flow;
|
||||
use flow_ref::FlowRef;
|
||||
use inline::{InlineFragmentContext, InlineMetrics};
|
||||
use layout_debug;
|
||||
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.
|
||||
#[deriving(Clone)]
|
||||
pub enum SpecificFragmentInfo {
|
||||
InlineBlockFragment(InlineBlockFragmentInfo),
|
||||
GenericFragment,
|
||||
ImageFragment(ImageFragmentInfo),
|
||||
IframeFragment(IframeFragmentInfo),
|
||||
|
@ -137,6 +139,20 @@ pub enum SpecificFragmentInfo {
|
|||
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.
|
||||
#[deriving(Clone)]
|
||||
pub struct ImageFragmentInfo {
|
||||
|
@ -454,7 +470,7 @@ impl Fragment {
|
|||
/// replaced elements.
|
||||
fn style_specified_intrinsic_inline_size(&self) -> IntrinsicISizes {
|
||||
let (use_margins, use_padding) = match self.specific {
|
||||
GenericFragment | IframeFragment(_) | ImageFragment(_) => (true, true),
|
||||
GenericFragment | IframeFragment(_) | ImageFragment(_) | InlineBlockFragment(_) => (true, true),
|
||||
TableFragment | TableCellFragment => (false, true),
|
||||
TableWrapperFragment => (true, false),
|
||||
TableRowFragment => (false, false),
|
||||
|
@ -1082,7 +1098,7 @@ impl Fragment {
|
|||
text_fragment))
|
||||
},
|
||||
GenericFragment | IframeFragment(..) | TableFragment | TableCellFragment | TableRowFragment |
|
||||
TableWrapperFragment => {
|
||||
TableWrapperFragment | InlineBlockFragment(_) => {
|
||||
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
||||
// should have a real `SERVO_DEBUG` system.
|
||||
debug!("{:?}", self.build_debug_borders_around_fragment(display_list, flow_origin))
|
||||
|
@ -1151,6 +1167,11 @@ impl Fragment {
|
|||
match self.specific {
|
||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableColumnFragment(_) | TableRowFragment |
|
||||
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) => {
|
||||
let image_inline_size = image_fragment_info.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 {
|
||||
match self.specific {
|
||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
||||
TableWrapperFragment => Au(0),
|
||||
TableWrapperFragment | InlineBlockFragment(_) => Au(0),
|
||||
ImageFragment(ref image_fragment_info) => {
|
||||
image_fragment_info.computed_inline_size()
|
||||
}
|
||||
|
@ -1209,7 +1230,7 @@ impl Fragment {
|
|||
pub fn content_block_size(&self, layout_context: &LayoutContext) -> Au {
|
||||
match self.specific {
|
||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
||||
TableWrapperFragment => Au(0),
|
||||
TableWrapperFragment | InlineBlockFragment(_) => Au(0),
|
||||
ImageFragment(ref image_fragment_info) => {
|
||||
image_fragment_info.computed_block_size()
|
||||
}
|
||||
|
@ -1246,6 +1267,7 @@ impl Fragment {
|
|||
TableRowFragment | TableWrapperFragment => None,
|
||||
TableColumnFragment(_) => fail!("Table column fragments do not need to split"),
|
||||
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||
InlineBlockFragment(_) => fail!("Inline blocks do not get split"),
|
||||
ScannedTextFragment(ref text_fragment_info) => {
|
||||
let mut new_line_pos = self.new_line_pos.clone();
|
||||
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 */)> {
|
||||
match self.specific {
|
||||
GenericFragment | IframeFragment(_) | ImageFragment(_) | TableFragment | TableCellFragment |
|
||||
TableRowFragment | TableWrapperFragment => None,
|
||||
TableRowFragment | TableWrapperFragment | InlineBlockFragment(_) => None,
|
||||
TableColumnFragment(_) => fail!("Table column fragments do not have inline_size"),
|
||||
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||
ScannedTextFragment(ref text_fragment_info) => {
|
||||
|
@ -1390,7 +1412,7 @@ impl Fragment {
|
|||
TableWrapperFragment => return,
|
||||
TableColumnFragment(_) => fail!("Table column fragments do not have inline_size"),
|
||||
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||
ImageFragment(_) | ScannedTextFragment(_) => {}
|
||||
ImageFragment(_) | ScannedTextFragment(_) | InlineBlockFragment(_) => {}
|
||||
};
|
||||
|
||||
self.compute_border_padding_margins(container_inline_size);
|
||||
|
@ -1400,6 +1422,11 @@ impl Fragment {
|
|||
let noncontent_inline_size = self.border_padding.inline_start_end();
|
||||
|
||||
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(_) => {
|
||||
// Scanned text fragments will have already had their content inline-sizes assigned by this
|
||||
// point.
|
||||
|
@ -1441,7 +1468,7 @@ impl Fragment {
|
|||
TableWrapperFragment => return,
|
||||
TableColumnFragment(_) => fail!("Table column fragments do not have block_size"),
|
||||
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();
|
||||
|
@ -1480,6 +1507,10 @@ impl Fragment {
|
|||
// during flow construction.
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
@ -1501,6 +1532,13 @@ impl Fragment {
|
|||
let line_height = self.calculate_line_height(layout_context);
|
||||
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 {
|
||||
block_size_above_baseline: self.border_box.size.block,
|
||||
|
@ -1566,6 +1604,7 @@ impl fmt::Show for Fragment {
|
|||
TableRowFragment => "TableRowFragment",
|
||||
TableWrapperFragment => "TableWrapperFragment",
|
||||
UnscannedTextFragment(_) => "UnscannedTextFragment",
|
||||
InlineBlockFragment(_) => "InlineBlockFragment",
|
||||
}));
|
||||
try!(write!(f, "bp {}", self.border_padding));
|
||||
try!(write!(f, " "));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue