aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/construct.rs85
-rw-r--r--components/layout/display_list_builder.rs13
-rw-r--r--components/layout/fragment.rs244
-rw-r--r--components/layout/inline.rs18
-rw-r--r--components/layout/text.rs14
-rw-r--r--components/style/properties.mako.rs44
-rw-r--r--tests/ref/basic.list1
-rw-r--r--tests/ref/input_button_margins_a.html2
-rw-r--r--tests/ref/input_button_margins_ref.html1
-rw-r--r--tests/ref/margin_padding_inline_block_a.html10
-rw-r--r--tests/ref/margin_padding_inline_block_ref.html17
11 files changed, 319 insertions, 130 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index d701edfc435..eb43c81b93e 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -27,7 +27,8 @@ use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo};
use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
use fragment::{WhitespaceStrippingResult};
use incremental::{RECONSTRUCT_FLOW, RestyleDamage};
-use inline::{InlineFlow, InlineFragmentNodeInfo};
+use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, InlineFragmentNodeFlags};
+use inline::{InlineFragmentNodeInfo, LAST_FRAGMENT_OF_ELEMENT};
use list_item::{ListItemFlow, ListStyleTypeContent};
use multicol::MulticolFlow;
use parallel;
@@ -217,20 +218,7 @@ impl InlineFragmentsAccumulator {
address: node.opaque(),
pseudo: node.get_pseudo_element_type().strip(),
style: node.style().clone(),
- }),
- bidi_control_chars: None,
- restyle_damage: node.restyle_damage(),
- }
- }
-
- fn from_inline_node_and_style(node: &ThreadSafeLayoutNode, style: Arc<ComputedValues>)
- -> InlineFragmentsAccumulator {
- InlineFragmentsAccumulator {
- fragments: IntermediateInlineFragments::new(),
- enclosing_node: Some(InlineFragmentNodeInfo {
- address: node.opaque(),
- pseudo: node.get_pseudo_element_type().strip(),
- style: style,
+ flags: InlineFragmentNodeFlags::empty(),
}),
bidi_control_chars: None,
restyle_damage: node.restyle_damage(),
@@ -254,15 +242,16 @@ impl InlineFragmentsAccumulator {
restyle_damage,
} = self;
if let Some(enclosing_node) = enclosing_node {
- let frag_len = fragments.fragments.len();
- for (idx, frag) in fragments.fragments.iter_mut().enumerate() {
-
- // frag is first inline fragment in the inline node
- let is_first = idx == 0;
- // frag is the last inline fragment in the inline node
- let is_last = idx == frag_len - 1;
-
- frag.add_inline_context_style(enclosing_node.clone(), is_first, is_last);
+ let fragment_count = fragments.fragments.len();
+ for (index, fragment) in fragments.fragments.iter_mut().enumerate() {
+ let mut enclosing_node = enclosing_node.clone();
+ if index == 0 {
+ enclosing_node.flags.insert(FIRST_FRAGMENT_OF_ELEMENT)
+ }
+ if index == fragment_count - 1 {
+ enclosing_node.flags.insert(LAST_FRAGMENT_OF_ELEMENT)
+ }
+ fragment.add_inline_context_style(enclosing_node);
}
// Control characters are later discarded in transform_text, so they don't affect the
@@ -596,6 +585,7 @@ impl<'a> FlowConstructor<'a> {
let fragment_info = SpecificFragmentInfo::UnscannedText(
UnscannedTextFragmentInfo::from_text(" ".to_owned()));
properties::modify_style_for_replaced_content(&mut whitespace_style);
+ properties::modify_style_for_text(&mut whitespace_style);
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
whitespace_style,
@@ -863,6 +853,7 @@ impl<'a> FlowConstructor<'a> {
let fragment_info = SpecificFragmentInfo::UnscannedText(
UnscannedTextFragmentInfo::from_text(" ".to_owned()));
properties::modify_style_for_replaced_content(&mut whitespace_style);
+ properties::modify_style_for_text(&mut whitespace_style);
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
whitespace_style,
@@ -966,8 +957,7 @@ impl<'a> FlowConstructor<'a> {
node.restyle_damage(),
fragment_info);
- let mut fragment_accumulator =
- InlineFragmentsAccumulator::from_inline_node_and_style(node, modified_style);
+ let mut fragment_accumulator = InlineFragmentsAccumulator::new();
fragment_accumulator.fragments.fragments.push_back(fragment);
fragment_accumulator.fragments.absolute_descendants.push_descendants(abs_descendants);
@@ -1718,12 +1708,36 @@ pub fn strip_ignorable_whitespace_from_start(this: &mut LinkedList<Fragment>) {
this.pop_front().unwrap())
}
WhitespaceStrippingResult::FragmentContainedOnlyWhitespace => {
- this.pop_front();
+ let removed_fragment = this.pop_front().unwrap();
+ if let Some(ref mut remaining_fragment) = this.front_mut() {
+ if let Some(ref mut inline_context_of_remaining_fragment) =
+ remaining_fragment.inline_context {
+ if let Some(ref inline_context_of_removed_fragment) =
+ removed_fragment.inline_context {
+ for (i, inline_context_node_from_removed_fragment) in
+ inline_context_of_removed_fragment.nodes.iter().enumerate() {
+ if i >= inline_context_of_remaining_fragment.nodes.len() {
+ break
+ }
+ if !inline_context_node_from_removed_fragment.flags.contains(
+ FIRST_FRAGMENT_OF_ELEMENT) {
+ continue
+ }
+ if inline_context_node_from_removed_fragment.address !=
+ inline_context_of_remaining_fragment.nodes[i].address {
+ continue
+ }
+ inline_context_of_remaining_fragment.nodes[i].flags.insert(
+ FIRST_FRAGMENT_OF_ELEMENT);
+ }
+ }
+ }
+ }
}
}
}
linked_list::prepend_from(this,
- &mut leading_fragments_consisting_of_solely_bidi_control_characters)
+ &mut leading_fragments_consisting_of_solely_bidi_control_characters);
}
/// Strips ignorable whitespace from the end of a list of fragments.
@@ -1741,7 +1755,10 @@ pub fn strip_ignorable_whitespace_from_end(this: &mut LinkedList<Fragment>) {
this.pop_back().unwrap())
}
WhitespaceStrippingResult::FragmentContainedOnlyWhitespace => {
- this.pop_back();
+ let removed_fragment = this.pop_back().unwrap();
+ if let Some(ref mut remaining_fragment) = this.back_mut() {
+ remaining_fragment.meld_with_next_inline_fragment(&removed_fragment);
+ }
}
}
}
@@ -1772,13 +1789,17 @@ fn bidi_control_chars(style: &Arc<ComputedValues>) -> Option<(&'static str, &'st
}
}
-fn control_chars_to_fragment(node: &InlineFragmentNodeInfo, text: &str,
- restyle_damage: RestyleDamage) -> Fragment {
+fn control_chars_to_fragment(node: &InlineFragmentNodeInfo,
+ text: &str,
+ restyle_damage: RestyleDamage)
+ -> Fragment {
let info = SpecificFragmentInfo::UnscannedText(
UnscannedTextFragmentInfo::from_text(String::from(text)));
+ let mut style = node.style.clone();
+ properties::modify_style_for_text(&mut style);
Fragment::from_opaque_node_and_style(node.address,
node.pseudo,
- node.style.clone(),
+ style,
restyle_damage,
info)
}
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index d2dd57f0e21..9e82add3a12 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -18,7 +18,7 @@ use flow::{self, BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref;
use fragment::{CoordinateSystem, Fragment, HAS_LAYER, IframeFragmentInfo, ImageFragmentInfo};
use fragment::{ScannedTextFragmentInfo, SpecificFragmentInfo};
-use inline::InlineFlow;
+use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
use list_item::ListItemFlow;
use model::{self, MaybeAuto, ToGfxMatrix};
use table_cell::CollapsedBordersForCell;
@@ -51,8 +51,8 @@ use style::computed_values::{background_attachment, background_clip, background_
use style::computed_values::{background_repeat, background_size};
use style::computed_values::{border_style, image_rendering, overflow_x, position};
use style::computed_values::{visibility, transform, transform_style};
-use style::properties::ComputedValues;
use style::properties::style_structs::Border;
+use style::properties::{self, ComputedValues};
use style::values::RGBA;
use style::values::computed;
use style::values::computed::LinearGradient;
@@ -951,13 +951,20 @@ impl FragmentDisplayListBuilding for Fragment {
level,
&stacking_relative_border_box,
&clip);
+
+ let mut style = node.style.clone();
+ properties::modify_border_style_for_inline_sides(
+ &mut style,
+ node.flags.contains(FIRST_FRAGMENT_OF_ELEMENT),
+ node.flags.contains(LAST_FRAGMENT_OF_ELEMENT));
self.build_display_list_for_borders_if_applicable(
- &*node.style,
+ &*style,
border_painting_mode,
display_list,
&stacking_relative_border_box,
level,
&clip);
+
self.build_display_list_for_outline_if_applicable(
&*node.style,
display_list,
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index f03e0cc7f7a..c11d9170679 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -13,7 +13,8 @@ use flow;
use flow::Flow;
use flow_ref::{self, FlowRef};
use incremental::{self, RestyleDamage};
-use inline::{InlineFragmentContext, InlineFragmentNodeInfo, InlineMetrics};
+use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo};
+use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT};
use layout_debug;
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified};
use text;
@@ -39,7 +40,7 @@ use style::computed_values::content::ContentItem;
use style::computed_values::{border_collapse, clear, mix_blend_mode, overflow_wrap, overflow_x};
use style::computed_values::{position, text_align, text_decoration, transform_style, white_space};
use style::computed_values::{word_break, z_index};
-use style::properties::{self, ComputedValues};
+use style::properties::ComputedValues;
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use style::values::computed::{LengthOrPercentageOrNone};
use text::TextRunScanner;
@@ -194,7 +195,9 @@ impl SpecificFragmentInfo {
SpecificFragmentInfo::Iframe(_) => "SpecificFragmentInfo::Iframe",
SpecificFragmentInfo::Image(_) => "SpecificFragmentInfo::Image",
SpecificFragmentInfo::InlineAbsolute(_) => "SpecificFragmentInfo::InlineAbsolute",
- SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => "SpecificFragmentInfo::InlineAbsoluteHypothetical",
+ SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {
+ "SpecificFragmentInfo::InlineAbsoluteHypothetical"
+ }
SpecificFragmentInfo::InlineBlock(_) => "SpecificFragmentInfo::InlineBlock",
SpecificFragmentInfo::ScannedText(_) => "SpecificFragmentInfo::ScannedText",
SpecificFragmentInfo::Table => "SpecificFragmentInfo::Table",
@@ -876,16 +879,10 @@ impl Fragment {
/// Adds a style to the inline context for this fragment. If the inline context doesn't exist
/// yet, it will be created.
- pub fn add_inline_context_style(&mut self,
- mut node_info: InlineFragmentNodeInfo,
- first_frag: bool,
- last_frag: bool) {
+ pub fn add_inline_context_style(&mut self, node_info: InlineFragmentNodeInfo) {
if self.inline_context.is_none() {
self.inline_context = Some(InlineFragmentContext::new());
}
- if !first_frag || !last_frag {
- properties::modify_style_for_inline_sides(&mut node_info.style, first_frag, last_frag)
- };
self.inline_context.as_mut().unwrap().nodes.push(node_info);
}
@@ -1015,17 +1012,24 @@ impl Fragment {
#[inline]
fn border_width(&self) -> LogicalMargin<Au> {
let style_border_width = match self.specific {
- SpecificFragmentInfo::ScannedText(_) => LogicalMargin::zero(self.style.writing_mode),
+ SpecificFragmentInfo::ScannedText(_) |
+ SpecificFragmentInfo::InlineBlock(_) => LogicalMargin::zero(self.style.writing_mode),
_ => self.style().logical_border_width(),
};
match self.inline_context {
None => style_border_width,
Some(ref inline_fragment_context) => {
- inline_fragment_context.nodes
- .iter()
- .fold(style_border_width,
- |acc, node| acc + node.style.logical_border_width())
+ inline_fragment_context.nodes.iter().fold(style_border_width, |accumulator, node| {
+ let mut this_border_width = node.style.logical_border_width();
+ if !node.flags.contains(FIRST_FRAGMENT_OF_ELEMENT) {
+ this_border_width.inline_start = Au(0)
+ }
+ if !node.flags.contains(LAST_FRAGMENT_OF_ELEMENT) {
+ this_border_width.inline_end = Au(0)
+ }
+ accumulator + this_border_width
+ })
}
}
}
@@ -1037,7 +1041,6 @@ impl Fragment {
/// (for example, via constraint solving for blocks).
pub fn compute_inline_direction_margins(&mut self, containing_block_inline_size: Au) {
match self.specific {
- SpecificFragmentInfo::InlineBlock(_) |
SpecificFragmentInfo::Table |
SpecificFragmentInfo::TableCell |
SpecificFragmentInfo::TableRow |
@@ -1046,27 +1049,41 @@ impl Fragment {
self.margin.inline_end = Au(0);
return
}
- _ => {}
+ SpecificFragmentInfo::InlineBlock(_) => {
+ // Inline-blocks do not take self margins into account but do account for margins
+ // from outer inline contexts.
+ self.margin.inline_start = Au(0);
+ self.margin.inline_end = Au(0);
+ }
+ _ => {
+ let margin = self.style().logical_margin();
+ self.margin.inline_start =
+ MaybeAuto::from_style(margin.inline_start,
+ containing_block_inline_size).specified_or_zero();
+ self.margin.inline_end =
+ MaybeAuto::from_style(margin.inline_end,
+ containing_block_inline_size).specified_or_zero();
+ }
}
-
- let margin = self.style().logical_margin();
- self.margin.inline_start =
- MaybeAuto::from_style(margin.inline_start,
- containing_block_inline_size).specified_or_zero();
- self.margin.inline_end =
- MaybeAuto::from_style(margin.inline_end,
- containing_block_inline_size).specified_or_zero();
-
if let Some(ref inline_context) = self.inline_context {
for node in &inline_context.nodes {
let margin = node.style.logical_margin();
- self.margin.inline_start = self.margin.inline_start +
+ let this_inline_start_margin = if !node.flags.contains(FIRST_FRAGMENT_OF_ELEMENT) {
+ Au(0)
+ } else {
MaybeAuto::from_style(margin.inline_start,
- containing_block_inline_size).specified_or_zero();
- self.margin.inline_end = self.margin.inline_end +
+ containing_block_inline_size).specified_or_zero()
+ };
+ let this_inline_end_margin = if !node.flags.contains(LAST_FRAGMENT_OF_ELEMENT) {
+ Au(0)
+ } else {
MaybeAuto::from_style(margin.inline_end,
- containing_block_inline_size).specified_or_zero();
+ containing_block_inline_size).specified_or_zero()
+ };
+
+ self.margin.inline_start = self.margin.inline_start + this_inline_start_margin;
+ self.margin.inline_end = self.margin.inline_end + this_inline_end_margin;
}
}
}
@@ -1114,33 +1131,42 @@ impl Fragment {
border_collapse::T::collapse => LogicalMargin::zero(self.style.writing_mode),
};
- // Compute padding.
- let padding = match self.specific {
- SpecificFragmentInfo::TableColumn(_) | SpecificFragmentInfo::TableRow |
- SpecificFragmentInfo::TableWrapper => LogicalMargin::zero(self.style.writing_mode),
- _ => {
- let style_padding = match self.specific {
- SpecificFragmentInfo::ScannedText(_) => {
- LogicalMargin::zero(self.style.writing_mode)
- }
- _ => model::padding_from_style(self.style(), containing_block_inline_size),
- };
+ // Compute padding from the fragment's style.
+ //
+ // This is zero in the case of `inline-block` because that padding is applied to the
+ // wrapped block, not the fragment.
+ let padding_from_style = match self.specific {
+ SpecificFragmentInfo::TableColumn(_) |
+ SpecificFragmentInfo::TableRow |
+ SpecificFragmentInfo::TableWrapper |
+ SpecificFragmentInfo::InlineBlock(_) => LogicalMargin::zero(self.style.writing_mode),
+ _ => model::padding_from_style(self.style(), containing_block_inline_size),
+ };
- match self.inline_context {
- None => style_padding,
- Some(ref inline_fragment_context) => {
- inline_fragment_context.nodes
- .iter()
- .fold(style_padding, |acc, node| {
- acc + model::padding_from_style(&*node.style,
- Au(0))
- })
+ // Compute padding from the inline fragment context.
+ let padding_from_inline_fragment_context = match (&self.specific, &self.inline_context) {
+ (_, &None) |
+ (&SpecificFragmentInfo::TableColumn(_), _) |
+ (&SpecificFragmentInfo::TableRow, _) |
+ (&SpecificFragmentInfo::TableWrapper, _) => {
+ LogicalMargin::zero(self.style.writing_mode)
+ }
+ (_, &Some(ref inline_fragment_context)) => {
+ let zero_padding = LogicalMargin::zero(self.style.writing_mode);
+ inline_fragment_context.nodes.iter().fold(zero_padding, |accumulator, node| {
+ let mut padding = model::padding_from_style(&*node.style, Au(0));
+ if !node.flags.contains(FIRST_FRAGMENT_OF_ELEMENT) {
+ padding.inline_start = Au(0)
}
- }
+ if !node.flags.contains(LAST_FRAGMENT_OF_ELEMENT) {
+ padding.inline_end = Au(0)
+ }
+ accumulator + padding
+ })
}
};
- self.border_padding = border + padding
+ self.border_padding = border + padding_from_style + padding_from_inline_fragment_context
}
// Return offset from original position because of `position: relative`.
@@ -1335,13 +1361,25 @@ impl Fragment {
if self.is_primary_fragment() {
if let Some(ref context) = self.inline_context {
for node in &context.nodes {
- let border_width = node.style.logical_border_width().inline_start_end();
- let padding_inline_size =
- model::padding_from_style(&*node.style, Au(0)).inline_start_end();
- let margin_inline_size =
- model::specified_margin_from_style(&*node.style).inline_start_end();
- result.surrounding_size = result.surrounding_size + border_width +
- padding_inline_size + margin_inline_size;
+ let mut border_width = node.style.logical_border_width();
+ let mut padding = model::padding_from_style(&*node.style, Au(0));
+ let mut margin = model::specified_margin_from_style(&*node.style);
+ if !node.flags.contains(FIRST_FRAGMENT_OF_ELEMENT) {
+ border_width.inline_start = Au(0);
+ padding.inline_start = Au(0);
+ margin.inline_start = Au(0);
+ }
+ if !node.flags.contains(LAST_FRAGMENT_OF_ELEMENT) {
+ border_width.inline_end = Au(0);
+ padding.inline_end = Au(0);
+ margin.inline_end = Au(0);
+ }
+
+ result.surrounding_size =
+ result.surrounding_size +
+ border_width.inline_start_end() +
+ padding.inline_start_end() +
+ margin.inline_start_end();
}
}
}
@@ -1610,11 +1648,14 @@ impl Fragment {
this_info.requires_line_break_afterward_if_wrapping_on_newlines =
this_info.requires_line_break_afterward_if_wrapping_on_newlines ||
other_info.requires_line_break_afterward_if_wrapping_on_newlines;
+ self.border_padding.inline_end = next_fragment.border_padding.inline_end;
self.border_box.size.inline = this_info.content_size.inline +
self.border_padding.inline_start_end();
}
_ => panic!("Can only merge two scanned-text fragments!"),
}
+
+ self.meld_with_next_inline_fragment(&next_fragment);
}
/// Returns true if this fragment is an unscanned text fragment that consists entirely of
@@ -1871,17 +1912,67 @@ impl Fragment {
}
}
- /// Returns true if this fragment can merge with another adjacent fragment or false otherwise.
+ /// Returns true if this fragment can merge with another immediately-following fragment or
+ /// false otherwise.
pub fn can_merge_with_fragment(&self, other: &Fragment) -> bool {
match (&self.specific, &other.specific) {
(&SpecificFragmentInfo::UnscannedText(ref first_unscanned_text),
&SpecificFragmentInfo::UnscannedText(_)) => {
// FIXME: Should probably use a whitelist of styles that can safely differ (#3165)
+ if self.style().get_font() != other.style().get_font() ||
+ self.text_decoration() != other.text_decoration() ||
+ self.white_space() != other.white_space() {
+ return false
+ }
+
let length = first_unscanned_text.text.len();
- self.style().get_font() == other.style().get_font() &&
- self.text_decoration() == other.text_decoration() &&
- self.white_space() == other.white_space() &&
- (length == 0 || first_unscanned_text.text.char_at_reverse(length) != '\n')
+ if length != 0 && first_unscanned_text.text.char_at_reverse(length) == '\n' {
+ return false
+ }
+
+ // If this node has any styles that have border/padding/margins on the following
+ // side, then we can't merge with the next fragment.
+ if let Some(ref inline_context) = self.inline_context {
+ for inline_context_node in inline_context.nodes.iter() {
+ if !inline_context_node.flags.contains(LAST_FRAGMENT_OF_ELEMENT) {
+ continue
+ }
+ if inline_context_node.style.logical_margin().inline_end !=
+ LengthOrPercentageOrAuto::Length(Au(0)) {
+ return false
+ }
+ if inline_context_node.style.logical_padding().inline_end !=
+ LengthOrPercentage::Length(Au(0)) {
+ return false
+ }
+ if inline_context_node.style.logical_border_width().inline_end != Au(0) {
+ return false
+ }
+ }
+ }
+
+ // If the next fragment has any styles that have border/padding/margins on the
+ // preceding side, then it can't merge with us.
+ if let Some(ref inline_context) = other.inline_context {
+ for inline_context_node in inline_context.nodes.iter() {
+ if !inline_context_node.flags.contains(FIRST_FRAGMENT_OF_ELEMENT) {
+ continue
+ }
+ if inline_context_node.style.logical_margin().inline_start !=
+ LengthOrPercentageOrAuto::Length(Au(0)) {
+ return false
+ }
+ if inline_context_node.style.logical_padding().inline_start !=
+ LengthOrPercentage::Length(Au(0)) {
+ return false
+ }
+ if inline_context_node.style.logical_border_width().inline_start != Au(0) {
+ return false
+ }
+ }
+ }
+
+ true
}
_ => false,
}
@@ -2286,6 +2377,29 @@ impl Fragment {
pub fn is_absolutely_positioned(&self) -> bool {
self.style.get_box().position == position::T::absolute
}
+
+ pub fn meld_with_next_inline_fragment(&mut self, next_fragment: &Fragment) {
+ if let Some(ref mut inline_context_of_this_fragment) = self.inline_context {
+ if let Some(ref inline_context_of_next_fragment) = next_fragment.inline_context {
+ for (i, inline_context_node_from_next_fragment) in
+ inline_context_of_next_fragment.nodes.iter().enumerate() {
+ if i >= inline_context_of_this_fragment.nodes.len() {
+ continue
+ }
+ if !inline_context_node_from_next_fragment.flags.contains(
+ LAST_FRAGMENT_OF_ELEMENT) {
+ continue
+ }
+ if inline_context_node_from_next_fragment.address !=
+ inline_context_of_this_fragment.nodes[i].address {
+ continue
+ }
+ inline_context_of_this_fragment.nodes[i].flags.insert(
+ LAST_FRAGMENT_OF_ELEMENT);
+ }
+ }
+ }
+ }
}
impl fmt::Debug for Fragment {
@@ -2378,7 +2492,7 @@ impl<'a> InlineStyleIterator<'a> {
}
}
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq)]
pub enum WhitespaceStrippingResult {
RetainFragment,
FragmentContainedOnlyBidiControlCharacters,
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index 51739ede4c8..6066b4a8473 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -1666,6 +1666,8 @@ impl Flow for InlineFlow {
.early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Parent);
+ let stacking_relative_content_box =
+ fragment.stacking_relative_content_box(&stacking_relative_border_box);
let clip = fragment.clipping_region_for_children(&self.base.clip,
&stacking_relative_border_box,
false);
@@ -1689,7 +1691,7 @@ impl Flow for InlineFlow {
}
block_flow.base.stacking_relative_position =
- stacking_relative_border_box.origin;
+ stacking_relative_content_box.origin;
block_flow.base.stacking_relative_position_of_display_port =
self.base.stacking_relative_position_of_display_port;
}
@@ -1817,6 +1819,20 @@ pub struct InlineFragmentNodeInfo {
pub address: OpaqueNode,
pub style: Arc<ComputedValues>,
pub pseudo: PseudoElementType<()>,
+ pub flags: InlineFragmentNodeFlags,
+}
+
+bitflags! {
+ flags InlineFragmentNodeFlags: u8 {
+ const FIRST_FRAGMENT_OF_ELEMENT = 0x01,
+ const LAST_FRAGMENT_OF_ELEMENT = 0x02,
+ }
+}
+
+impl fmt::Debug for InlineFragmentNodeInfo {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?}", self.flags.bits())
+ }
}
#[derive(Clone)]
diff --git a/components/layout/text.rs b/components/layout/text.rs
index a61393b5d20..f0b64903b59 100644
--- a/components/layout/text.rs
+++ b/components/layout/text.rs
@@ -184,7 +184,6 @@ impl TextRunScanner {
};
let (mut start_position, mut end_position) = (0, 0);
-
for character in text.chars() {
// Search for the first font in this font group that contains a glyph for this
// character.
@@ -286,10 +285,15 @@ impl TextRunScanner {
for (logical_offset, old_fragment) in
mem::replace(&mut self.clump, LinkedList::new()).into_iter().enumerate() {
loop {
- match mappings.peek() {
- Some(mapping) if mapping.old_fragment_index == logical_offset => {}
- Some(_) | None => break,
- };
+ match mappings.peek() {
+ Some(mapping) if mapping.old_fragment_index == logical_offset => {}
+ Some(_) | None => {
+ if let Some(ref mut last_fragment) = out_fragments.last_mut() {
+ last_fragment.meld_with_next_inline_fragment(&old_fragment);
+ }
+ break;
+ }
+ };
let mut mapping = mappings.next().unwrap();
let run = runs[mapping.text_run_index].clone();
diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs
index 857718e7a44..5b305f490ec 100644
--- a/components/style/properties.mako.rs
+++ b/components/style/properties.mako.rs
@@ -6456,15 +6456,15 @@ pub fn modify_style_for_replaced_content(style: &mut Arc<ComputedValues>) {
}
}
-/// Adjusts borders, padding, and margins as appropriate to account for a fragment's status as the
-/// first or last fragment within the range of an element.
+/// Adjusts borders as appropriate to account for a fragment's status as the first or last fragment
+/// within the range of an element.
///
-/// Specifically, this function sets border/padding/margin widths to zero on the sides for which
-/// the fragment is not outermost.
+/// Specifically, this function sets border widths to zero on the sides for which the fragment is
+/// not outermost.
#[inline]
-pub fn modify_style_for_inline_sides(style: &mut Arc<ComputedValues>,
- is_first_fragment_of_element: bool,
- is_last_fragment_of_element: bool) {
+pub fn modify_border_style_for_inline_sides(style: &mut Arc<ComputedValues>,
+ is_first_fragment_of_element: bool,
+ is_last_fragment_of_element: bool) {
fn modify_side(style: &mut Arc<ComputedValues>, side: PhysicalSide) {
let mut style = Arc::make_mut(style);
let border = Arc::make_mut(&mut style.border);
@@ -6472,34 +6472,18 @@ pub fn modify_style_for_inline_sides(style: &mut Arc<ComputedValues>,
PhysicalSide::Left => {
border.border_left_width = Au(0);
border.border_left_style = BorderStyle::none;
- Arc::make_mut(&mut style.padding).padding_left =
- computed::LengthOrPercentage::Length(Au(0));
- Arc::make_mut(&mut style.margin).margin_left =
- computed::LengthOrPercentageOrAuto::Length(Au(0))
}
PhysicalSide::Right => {
border.border_right_width = Au(0);
border.border_right_style = BorderStyle::none;
- Arc::make_mut(&mut style.padding).padding_right =
- computed::LengthOrPercentage::Length(Au(0));
- Arc::make_mut(&mut style.margin).margin_right =
- computed::LengthOrPercentageOrAuto::Length(Au(0))
}
PhysicalSide::Bottom => {
border.border_bottom_width = Au(0);
border.border_bottom_style = BorderStyle::none;
- Arc::make_mut(&mut style.padding).padding_bottom =
- computed::LengthOrPercentage::Length(Au(0));
- Arc::make_mut(&mut style.margin).margin_bottom =
- computed::LengthOrPercentageOrAuto::Length(Au(0))
}
PhysicalSide::Top => {
border.border_top_width = Au(0);
border.border_top_style = BorderStyle::none;
- Arc::make_mut(&mut style.padding).padding_top =
- computed::LengthOrPercentage::Length(Au(0));
- Arc::make_mut(&mut style.margin).margin_top =
- computed::LengthOrPercentageOrAuto::Length(Au(0))
}
}
}
@@ -6534,7 +6518,7 @@ pub fn modify_style_for_outer_inline_block_fragment(style: &mut Arc<ComputedValu
box_style.position = longhands::position::computed_value::T::static_
}
-/// Adjusts the `position` property as necessary to account for text.
+/// Adjusts the `position` and `padding` properties as necessary to account for text.
///
/// Text is never directly relatively positioned; it's always contained within an element that is
/// itself relatively positioned.
@@ -6550,6 +6534,18 @@ pub fn modify_style_for_text(style: &mut Arc<ComputedValues>) {
position_offsets.bottom = computed::LengthOrPercentageOrAuto::Auto;
position_offsets.left = computed::LengthOrPercentageOrAuto::Auto;
}
+
+ if style.padding.padding_top != computed::LengthOrPercentage::Length(Au(0)) ||
+ style.padding.padding_right != computed::LengthOrPercentage::Length(Au(0)) ||
+ style.padding.padding_bottom != computed::LengthOrPercentage::Length(Au(0)) ||
+ style.padding.padding_left != computed::LengthOrPercentage::Length(Au(0)) {
+ let mut style = Arc::make_unique(style);
+ let mut padding = Arc::make_unique(&mut style.padding);
+ padding.padding_top = computed::LengthOrPercentage::Length(Au(0));
+ padding.padding_right = computed::LengthOrPercentage::Length(Au(0));
+ padding.padding_bottom = computed::LengthOrPercentage::Length(Au(0));
+ padding.padding_left = computed::LengthOrPercentage::Length(Au(0));
+ }
}
/// Adjusts the `margin` property as necessary to account for the text of an `input` element.
diff --git a/tests/ref/basic.list b/tests/ref/basic.list
index c7aeb3a1de8..e68864215a6 100644
--- a/tests/ref/basic.list
+++ b/tests/ref/basic.list
@@ -224,6 +224,7 @@ flaky_cpu == linebreak_simple_a.html linebreak_simple_b.html
!= list_style_type_a.html list_style_type_ref.html
== many_brs_a.html many_brs_ref.html
== margin_a.html margin_b.html
+== margin_padding_inline_block_a.html margin_padding_inline_block_ref.html
== margins_inside_floats_a.html margins_inside_floats_ref.html
== marker_block_direction_placement_a.html marker_block_direction_placement_ref.html
== max_width_float_simple_a.html max_width_float_simple_b.html
diff --git a/tests/ref/input_button_margins_a.html b/tests/ref/input_button_margins_a.html
index b35a3b5ccb6..a207daac455 100644
--- a/tests/ref/input_button_margins_a.html
+++ b/tests/ref/input_button_margins_a.html
@@ -5,6 +5,8 @@ body, html {
}
input {
margin-left: 64px;
+ border: none;
+ vertical-align: top;
}
</style>
<input type=button value=Hello>
diff --git a/tests/ref/input_button_margins_ref.html b/tests/ref/input_button_margins_ref.html
index 07ecda7c227..63b80497bf4 100644
--- a/tests/ref/input_button_margins_ref.html
+++ b/tests/ref/input_button_margins_ref.html
@@ -6,6 +6,7 @@ body, html {
input {
position: absolute;
left: 64px;
+ border: none;
}
</style>
<input type=button value=Hello>
diff --git a/tests/ref/margin_padding_inline_block_a.html b/tests/ref/margin_padding_inline_block_a.html
new file mode 100644
index 00000000000..d2a8f5d4b82
--- /dev/null
+++ b/tests/ref/margin_padding_inline_block_a.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<style>
+html, body {
+ margin: 0;
+}
+</style>
+<div><span style="padding-left: 100px; display: inline-block">Boo</span></div>
+<div><span style="padding-left: 100px">Foo</span></div>
+<div><span style="margin-left: 100px">Foo</span></div>
+
diff --git a/tests/ref/margin_padding_inline_block_ref.html b/tests/ref/margin_padding_inline_block_ref.html
new file mode 100644
index 00000000000..58f5ba65980
--- /dev/null
+++ b/tests/ref/margin_padding_inline_block_ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<style>
+html, body {
+ margin: 0;
+}
+div {
+ position: relative;
+}
+span {
+ position: relative;
+ left: 100px;
+}
+</style>
+<div><span>Boo</span></div>
+<div><span>Foo</span></div>
+<div><span>Foo</span></div>
+