diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 4ddea7d62c8..3263961d46c 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -16,8 +16,7 @@ use flow_ref::FlowRef; use incremental::{self, RestyleDamage}; use inline::{InlineFragmentContext, InlineMetrics}; use layout_debug; -use model::{IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified}; -use model; +use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified}; use text; use opaque_node::OpaqueNodeMethods; use wrapper::{TLayoutNode, ThreadSafeLayoutNode}; @@ -1191,7 +1190,6 @@ impl Fragment { } SpecificFragmentInfo::ScannedText(ref text_fragment_info) => { let range = &text_fragment_info.range; - let min_line_inline_size = text_fragment_info.run.min_width_for_range(range); // See http://dev.w3.org/csswg/css-sizing/#max-content-inline-size. // TODO: Account for soft wrap opportunities. @@ -1199,6 +1197,11 @@ impl Fragment { .metrics_for_range(range) .advance_width; + let min_line_inline_size = match self.style.get_inheritedtext().white_space { + white_space::T::pre | white_space::T::nowrap => max_line_inline_size, + white_space::T::normal => text_fragment_info.run.min_width_for_range(range), + }; + result.union_block(&IntrinsicISizes { minimum_inline_size: min_line_inline_size, preferred_inline_size: max_line_inline_size, diff --git a/components/layout/inline.rs b/components/layout/inline.rs index cf42b29577d..0c48d214a5a 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -1133,12 +1133,49 @@ impl Flow for InlineFlow { flow::mut_base(kid).floats = Floats::new(writing_mode); } - let mut computation = IntrinsicISizesContribution::new(); + let mut intrinsic_sizes_for_flow = IntrinsicISizesContribution::new(); + let mut intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new(); + let mut intrinsic_sizes_for_nonbroken_run = IntrinsicISizesContribution::new(); for fragment in self.fragments.fragments.iter_mut() { - debug!("Flow: measuring {:?}", *fragment); - computation.union_inline(&fragment.compute_intrinsic_inline_sizes().finish()) + let intrinsic_sizes_for_fragment = fragment.compute_intrinsic_inline_sizes().finish(); + match fragment.style.get_inheritedtext().white_space { + white_space::T::nowrap => { + intrinsic_sizes_for_nonbroken_run.union_nonbreaking_inline( + &intrinsic_sizes_for_fragment) + } + white_space::T::pre => { + intrinsic_sizes_for_nonbroken_run.union_nonbreaking_inline( + &intrinsic_sizes_for_fragment); + + // Flush the intrinsic sizes we've been gathering up in order to handle the + // line break, if necessary. + if fragment.requires_line_break_afterward_if_wrapping_on_newlines() { + intrinsic_sizes_for_inline_run.union_inline( + &intrinsic_sizes_for_nonbroken_run.finish()); + intrinsic_sizes_for_nonbroken_run = IntrinsicISizesContribution::new(); + intrinsic_sizes_for_flow.union_block( + &intrinsic_sizes_for_inline_run.finish()); + intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new(); + } + } + white_space::T::normal => { + // Flush the intrinsic sizes we were gathering up for the nonbroken run, if + // necessary. + intrinsic_sizes_for_inline_run.union_inline( + &intrinsic_sizes_for_nonbroken_run.finish()); + intrinsic_sizes_for_nonbroken_run = IntrinsicISizesContribution::new(); + + intrinsic_sizes_for_nonbroken_run.union_inline(&intrinsic_sizes_for_fragment) + } + } } - self.base.intrinsic_inline_sizes = computation.finish() + + // Flush any remaining nonbroken-run and inline-run intrinsic sizes. + intrinsic_sizes_for_inline_run.union_inline(&intrinsic_sizes_for_nonbroken_run.finish()); + intrinsic_sizes_for_flow.union_block(&intrinsic_sizes_for_inline_run.finish()); + + // Finish up the computation. + self.base.intrinsic_inline_sizes = intrinsic_sizes_for_flow.finish() } /// Recursively (top-down) determines the actual inline-size of child contexts and fragments. diff --git a/components/layout/model.rs b/components/layout/model.rs index 670d2210681..ebd70dcae84 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -331,6 +331,17 @@ impl IntrinsicISizesContribution { self.content_intrinsic_sizes.preferred_inline_size + sizes.preferred_inline_size } + /// Updates the computation so that the minimum is the sum of the current minimum and the + /// given minimum and the preferred is the sum of the current preferred and the given + /// preferred. This is used when laying out fragments in the inline direction when + /// `white-space` is `pre` or `nowrap`. + pub fn union_nonbreaking_inline(&mut self, sizes: &IntrinsicISizes) { + self.content_intrinsic_sizes.minimum_inline_size = + self.content_intrinsic_sizes.minimum_inline_size + sizes.minimum_inline_size; + self.content_intrinsic_sizes.preferred_inline_size = + self.content_intrinsic_sizes.preferred_inline_size + sizes.preferred_inline_size + } + /// Updates the computation so that the minimum is the maximum of the current minimum and the /// given minimum and the preferred is the maximum of the current preferred and the given /// preferred. This can be useful when laying out fragments in the block direction (but note diff --git a/tests/ref/white_space_intrinsic_sizes_a.html b/tests/ref/white_space_intrinsic_sizes_a.html new file mode 100644 index 00000000000..87944c21b5c --- /dev/null +++ b/tests/ref/white_space_intrinsic_sizes_a.html @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + +
+
+
Instant Video
+
+
+
+
Digital Music Store
+
+
+
+
Cloud Drive
+
+
+
+
Fire Phone
+
+
+
+
Appstore
for Android
+
+
+ + diff --git a/tests/ref/white_space_intrinsic_sizes_ref.html b/tests/ref/white_space_intrinsic_sizes_ref.html new file mode 100644 index 00000000000..cd54f8a7e08 --- /dev/null +++ b/tests/ref/white_space_intrinsic_sizes_ref.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + +
+
+
Instant Video
+
+
+
+
Digital Music Store
+
+
+
+
Cloud Drive
+
+
+
+
Fire Phone
+
+
+
+
Appstore
for Android
+
+
+ +