diff options
author | Pyfisch <pyfisch@gmail.com> | 2018-08-24 15:44:25 +0200 |
---|---|---|
committer | Pyfisch <pyfisch@gmail.com> | 2018-09-01 13:24:57 +0200 |
commit | 349047b096fc8d121bc1a5be1ab74eabe648285b (patch) | |
tree | a18c07097a9935a54c8c2f5c5a317a8479bc1dcf /components/layout | |
parent | 577830de909dd692f2d178d139984f45bbf929c3 (diff) | |
download | servo-349047b096fc8d121bc1a5be1ab74eabe648285b.tar.gz servo-349047b096fc8d121bc1a5be1ab74eabe648285b.zip |
Rustfmt layout crate
Diffstat (limited to 'components/layout')
37 files changed, 7207 insertions, 4862 deletions
diff --git a/components/layout/animation.rs b/components/layout/animation.rs index 3a09094b2a9..d8b305644c0 100644 --- a/components/layout/animation.rs +++ b/components/layout/animation.rs @@ -32,8 +32,7 @@ pub fn update_animation_state<E>( new_animations_receiver: &Receiver<Animation>, pipeline_id: PipelineId, timer: &Timer, -) -where +) where E: TElement, { let mut new_running_animations = vec![]; @@ -66,7 +65,7 @@ where if running_animations.is_empty() && new_running_animations.is_empty() { // Nothing to do. Return early so we don't flood the compositor with // `ChangeRunningAnimationsState` messages. - return + return; } let now = timer.seconds(); @@ -82,30 +81,32 @@ where let still_running = !running_animation.is_expired() && match running_animation { Animation::Transition(_, started_at, ref frame, _expired) => { now < started_at + frame.duration - } + }, Animation::Keyframes(_, _, _, ref mut state) => { // This animation is still running, or we need to keep // iterating. now < state.started_at + state.duration || state.tick() - } + }, }; if still_running { animations_still_running.push(running_animation); - continue + continue; } if let Animation::Transition(node, _, ref frame, _) = running_animation { - script_chan.send(ConstellationControlMsg::TransitionEnd(node.to_untrusted_node_address(), - frame.property_animation - .property_name().into(), - frame.duration)) - .unwrap(); + script_chan + .send(ConstellationControlMsg::TransitionEnd( + node.to_untrusted_node_address(), + frame.property_animation.property_name().into(), + frame.duration, + )).unwrap(); } - expired_animations.entry(*key) - .or_insert_with(Vec::new) - .push(running_animation); + expired_animations + .entry(*key) + .or_insert_with(Vec::new) + .push(running_animation); } if animations_still_running.is_empty() { @@ -125,16 +126,17 @@ where match newly_transitioning_nodes { Some(ref mut nodes) => { nodes.push(new_running_animation.node().to_untrusted_node_address()); - } + }, None => { warn!("New transition encountered from compositor-initiated layout."); - } + }, } } - running_animations.entry(*new_running_animation.node()) - .or_insert_with(Vec::new) - .push(new_running_animation) + running_animations + .entry(*new_running_animation.node()) + .or_insert_with(Vec::new) + .push(new_running_animation) } let animation_state = if running_animations.is_empty() { @@ -143,9 +145,11 @@ where AnimationState::AnimationsPresent }; - constellation_chan.send(ConstellationMsg::ChangeRunningAnimationsState(pipeline_id, - animation_state)) - .unwrap(); + constellation_chan + .send(ConstellationMsg::ChangeRunningAnimationsState( + pipeline_id, + animation_state, + )).unwrap(); } /// Recalculates style for a set of animations. This does *not* run with the DOM @@ -154,8 +158,7 @@ pub fn recalc_style_for_animations<E>( context: &LayoutContext, flow: &mut Flow, animations: &FxHashMap<OpaqueNode, Vec<Animation>>, -) -where +) where E: TElement, { let mut damage = RestyleDamage::empty(); @@ -170,10 +173,7 @@ where &ServoMetricsProvider, ); let difference = - RestyleDamage::compute_style_difference( - &old_style, - &fragment.style, - ); + RestyleDamage::compute_style_difference(&old_style, &fragment.style); damage |= difference.damage; } } diff --git a/components/layout/block.rs b/components/layout/block.rs index 00759909063..ae1bc242e32 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -93,15 +93,16 @@ struct BSizeConstraintSolution { block_start: Au, block_size: Au, margin_block_start: Au, - margin_block_end: Au + margin_block_end: Au, } impl BSizeConstraintSolution { - fn new(block_start: Au, - block_size: Au, - margin_block_start: Au, - margin_block_end: Au) - -> BSizeConstraintSolution { + fn new( + block_start: Au, + block_size: Au, + margin_block_start: Au, + margin_block_end: Au, + ) -> BSizeConstraintSolution { BSizeConstraintSolution { block_start: block_start, block_size: block_size, @@ -119,14 +120,15 @@ impl BSizeConstraintSolution { /// [aka available_block-size] /// /// Return the solution for the equation. - fn solve_vertical_constraints_abs_nonreplaced(block_size: MaybeAuto, - block_start_margin: MaybeAuto, - block_end_margin: MaybeAuto, - block_start: MaybeAuto, - block_end: MaybeAuto, - content_block_size: Au, - available_block_size: Au) - -> BSizeConstraintSolution { + fn solve_vertical_constraints_abs_nonreplaced( + block_size: MaybeAuto, + block_start_margin: MaybeAuto, + block_end_margin: MaybeAuto, + block_start: MaybeAuto, + block_end: MaybeAuto, + content_block_size: Au, + available_block_size: Au, + ) -> BSizeConstraintSolution { let (block_start, block_size, margin_block_start, margin_block_end) = match (block_start, block_end, block_size) { (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { @@ -137,64 +139,103 @@ impl BSizeConstraintSolution { let block_size = content_block_size; // Use a dummy value for `block_start`, since it has the static position. (Au(0), block_size, margin_block_start, margin_block_end) - } - (MaybeAuto::Specified(block_start), - MaybeAuto::Specified(block_end), - MaybeAuto::Specified(block_size)) => { + }, + ( + MaybeAuto::Specified(block_start), + MaybeAuto::Specified(block_end), + MaybeAuto::Specified(block_size), + ) => { match (block_start_margin, block_end_margin) { (MaybeAuto::Auto, MaybeAuto::Auto) => { let total_margin_val = available_block_size - block_start - block_end - block_size; - (block_start, - block_size, - total_margin_val.scale_by(0.5), - total_margin_val.scale_by(0.5)) - } + ( + block_start, + block_size, + total_margin_val.scale_by(0.5), + total_margin_val.scale_by(0.5), + ) + }, (MaybeAuto::Specified(margin_block_start), MaybeAuto::Auto) => { let sum = block_start + block_end + block_size + margin_block_start; - (block_start, - block_size, - margin_block_start, - available_block_size - sum) - } + ( + block_start, + block_size, + margin_block_start, + available_block_size - sum, + ) + }, (MaybeAuto::Auto, MaybeAuto::Specified(margin_block_end)) => { let sum = block_start + block_end + block_size + margin_block_end; - (block_start, block_size, available_block_size - sum, margin_block_end) - } - (MaybeAuto::Specified(margin_block_start), - MaybeAuto::Specified(margin_block_end)) => { + ( + block_start, + block_size, + available_block_size - sum, + margin_block_end, + ) + }, + ( + MaybeAuto::Specified(margin_block_start), + MaybeAuto::Specified(margin_block_end), + ) => { // Values are over-constrained. Ignore value for 'block-end'. - (block_start, block_size, margin_block_start, margin_block_end) - } + ( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) + }, } - } + }, // For the rest of the cases, auto values for margin are set to 0 // If only one is Auto, solve for it - (MaybeAuto::Auto, - MaybeAuto::Specified(block_end), - MaybeAuto::Specified(block_size)) => { + ( + MaybeAuto::Auto, + MaybeAuto::Specified(block_end), + MaybeAuto::Specified(block_size), + ) => { let margin_block_start = block_start_margin.specified_or_zero(); let margin_block_end = block_end_margin.specified_or_zero(); let sum = block_end + block_size + margin_block_start + margin_block_end; - (available_block_size - sum, block_size, margin_block_start, margin_block_end) - } - (MaybeAuto::Specified(block_start), - MaybeAuto::Auto, - MaybeAuto::Specified(block_size)) => { + ( + available_block_size - sum, + block_size, + margin_block_start, + margin_block_end, + ) + }, + ( + MaybeAuto::Specified(block_start), + MaybeAuto::Auto, + MaybeAuto::Specified(block_size), + ) => { let margin_block_start = block_start_margin.specified_or_zero(); let margin_block_end = block_end_margin.specified_or_zero(); - (block_start, block_size, margin_block_start, margin_block_end) - } - (MaybeAuto::Specified(block_start), - MaybeAuto::Specified(block_end), - MaybeAuto::Auto) => { + ( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) + }, + ( + MaybeAuto::Specified(block_start), + MaybeAuto::Specified(block_end), + MaybeAuto::Auto, + ) => { let margin_block_start = block_start_margin.specified_or_zero(); let margin_block_end = block_end_margin.specified_or_zero(); let sum = block_start + block_end + margin_block_start + margin_block_end; - (block_start, available_block_size - sum, margin_block_start, margin_block_end) - } + ( + block_start, + available_block_size - sum, + margin_block_start, + margin_block_end, + ) + }, // If block-size is auto, then block-size is content block-size. Solve for the // non-auto value. @@ -202,25 +243,40 @@ impl BSizeConstraintSolution { let margin_block_start = block_start_margin.specified_or_zero(); let margin_block_end = block_end_margin.specified_or_zero(); let block_size = content_block_size; - (block_start, block_size, margin_block_start, margin_block_end) - } + ( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) + }, (MaybeAuto::Auto, MaybeAuto::Specified(block_end), MaybeAuto::Auto) => { let margin_block_start = block_start_margin.specified_or_zero(); let margin_block_end = block_end_margin.specified_or_zero(); let block_size = content_block_size; let sum = block_end + block_size + margin_block_start + margin_block_end; - (available_block_size - sum, block_size, margin_block_start, margin_block_end) - } + ( + available_block_size - sum, + block_size, + margin_block_start, + margin_block_end, + ) + }, (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(block_size)) => { let margin_block_start = block_start_margin.specified_or_zero(); let margin_block_end = block_end_margin.specified_or_zero(); // Use a dummy value for `block_start`, since it has the static position. (Au(0), block_size, margin_block_start, margin_block_end) - } + }, }; - BSizeConstraintSolution::new(block_start, block_size, margin_block_start, margin_block_end) + BSizeConstraintSolution::new( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) } /// Solve the vertical constraint equation for absolute replaced elements. @@ -234,14 +290,15 @@ impl BSizeConstraintSolution { /// [aka available block-size] /// /// Return the solution for the equation. - fn solve_vertical_constraints_abs_replaced(block_size: Au, - block_start_margin: MaybeAuto, - block_end_margin: MaybeAuto, - block_start: MaybeAuto, - block_end: MaybeAuto, - _: Au, - available_block_size: Au) - -> BSizeConstraintSolution { + fn solve_vertical_constraints_abs_replaced( + block_size: Au, + block_start_margin: MaybeAuto, + block_end_margin: MaybeAuto, + block_start: MaybeAuto, + block_end: MaybeAuto, + _: Au, + available_block_size: Au, + ) -> BSizeConstraintSolution { let (block_start, block_size, margin_block_start, margin_block_end) = match (block_start, block_end) { (MaybeAuto::Auto, MaybeAuto::Auto) => { @@ -249,50 +306,81 @@ impl BSizeConstraintSolution { let margin_block_end = block_end_margin.specified_or_zero(); // Use a dummy value for `block_start`, since it has the static position. (Au(0), block_size, margin_block_start, margin_block_end) - } + }, (MaybeAuto::Specified(block_start), MaybeAuto::Specified(block_end)) => { match (block_start_margin, block_end_margin) { (MaybeAuto::Auto, MaybeAuto::Auto) => { - let total_margin_val = available_block_size - block_start - block_end - - block_size; - (block_start, - block_size, - total_margin_val.scale_by(0.5), - total_margin_val.scale_by(0.5)) - } + let total_margin_val = + available_block_size - block_start - block_end - block_size; + ( + block_start, + block_size, + total_margin_val.scale_by(0.5), + total_margin_val.scale_by(0.5), + ) + }, (MaybeAuto::Specified(margin_block_start), MaybeAuto::Auto) => { let sum = block_start + block_end + block_size + margin_block_start; - (block_start, - block_size, - margin_block_start, - available_block_size - sum) - } + ( + block_start, + block_size, + margin_block_start, + available_block_size - sum, + ) + }, (MaybeAuto::Auto, MaybeAuto::Specified(margin_block_end)) => { let sum = block_start + block_end + block_size + margin_block_end; - (block_start, block_size, available_block_size - sum, margin_block_end) - } - (MaybeAuto::Specified(margin_block_start), - MaybeAuto::Specified(margin_block_end)) => { + ( + block_start, + block_size, + available_block_size - sum, + margin_block_end, + ) + }, + ( + MaybeAuto::Specified(margin_block_start), + MaybeAuto::Specified(margin_block_end), + ) => { // Values are over-constrained. Ignore value for 'block-end'. - (block_start, block_size, margin_block_start, margin_block_end) - } + ( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) + }, } - } + }, // If only one is Auto, solve for it (MaybeAuto::Auto, MaybeAuto::Specified(block_end)) => { let margin_block_start = block_start_margin.specified_or_zero(); let margin_block_end = block_end_margin.specified_or_zero(); let sum = block_end + block_size + margin_block_start + margin_block_end; - (available_block_size - sum, block_size, margin_block_start, margin_block_end) - } + ( + available_block_size - sum, + block_size, + margin_block_start, + margin_block_end, + ) + }, (MaybeAuto::Specified(block_start), MaybeAuto::Auto) => { let margin_block_start = block_start_margin.specified_or_zero(); let margin_block_end = block_end_margin.specified_or_zero(); - (block_start, block_size, margin_block_start, margin_block_end) - } + ( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) + }, }; - BSizeConstraintSolution::new(block_start, block_size, margin_block_start, margin_block_end) + BSizeConstraintSolution::new( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) } } @@ -314,21 +402,26 @@ impl CandidateBSizeIterator { /// Creates a new candidate block-size iterator. `block_container_block-size` is `None` if the block-size /// of the block container has not been determined yet. It will always be `Some` in the case of /// absolutely-positioned containing blocks. - pub fn new(fragment: &Fragment, block_container_block_size: Option<Au>) - -> CandidateBSizeIterator { + pub fn new( + fragment: &Fragment, + block_container_block_size: Option<Au>, + ) -> CandidateBSizeIterator { // Per CSS 2.1 § 10.7, (assuming an horizontal writing mode,) // percentages in `min-height` and `max-height` refer to the height of // the containing block. // If that is not determined yet by the time we need to resolve // `min-height` and `max-height`, percentage values are ignored. - let block_size = match (fragment.style.content_block_size(), block_container_block_size) { + let block_size = match ( + fragment.style.content_block_size(), + block_container_block_size, + ) { (LengthOrPercentageOrAuto::Percentage(percent), Some(block_container_block_size)) => { MaybeAuto::Specified(block_container_block_size.scale_by(percent.0)) - } + }, (LengthOrPercentageOrAuto::Calc(calc), _) => { MaybeAuto::from_option(calc.to_used_value(block_container_block_size)) - } + }, (LengthOrPercentageOrAuto::Percentage(_), None) | (LengthOrPercentageOrAuto::Auto, _) => MaybeAuto::Auto, (LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(Au::from(length)), @@ -336,10 +429,10 @@ impl CandidateBSizeIterator { let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) { (LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => { Some(block_container_block_size.scale_by(percent.0)) - } + }, (LengthOrPercentageOrNone::Calc(calc), _) => { calc.to_used_value(block_container_block_size) - } + }, (LengthOrPercentageOrNone::Percentage(_), None) | (LengthOrPercentageOrNone::None, _) => None, (LengthOrPercentageOrNone::Length(length), _) => Some(Au::from(length)), @@ -347,10 +440,10 @@ impl CandidateBSizeIterator { let min_block_size = match (fragment.style.min_block_size(), block_container_block_size) { (LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => { block_container_block_size.scale_by(percent.0) - } - (LengthOrPercentage::Calc(calc), _) => { - calc.to_used_value(block_container_block_size).unwrap_or(Au(0)) - } + }, + (LengthOrPercentage::Calc(calc), _) => calc + .to_used_value(block_container_block_size) + .unwrap_or(Au(0)), (LengthOrPercentage::Percentage(_), None) => Au(0), (LengthOrPercentage::Length(length), _) => Au::from(length), }; @@ -380,37 +473,35 @@ impl Iterator for CandidateBSizeIterator { fn next(&mut self) -> Option<MaybeAuto> { self.status = match self.status { CandidateBSizeIteratorStatus::Initial => CandidateBSizeIteratorStatus::Trying, - CandidateBSizeIteratorStatus::Trying => { - match self.max_block_size { - Some(max_block_size) if self.candidate_value > max_block_size => { - CandidateBSizeIteratorStatus::TryingMax - } - _ if self.candidate_value < self.min_block_size => { - CandidateBSizeIteratorStatus::TryingMin - } - _ => CandidateBSizeIteratorStatus::Found, - } - } + CandidateBSizeIteratorStatus::Trying => match self.max_block_size { + Some(max_block_size) if self.candidate_value > max_block_size => { + CandidateBSizeIteratorStatus::TryingMax + }, + _ if self.candidate_value < self.min_block_size => { + CandidateBSizeIteratorStatus::TryingMin + }, + _ => CandidateBSizeIteratorStatus::Found, + }, CandidateBSizeIteratorStatus::TryingMax => { if self.candidate_value < self.min_block_size { CandidateBSizeIteratorStatus::TryingMin } else { CandidateBSizeIteratorStatus::Found } - } + }, CandidateBSizeIteratorStatus::TryingMin | CandidateBSizeIteratorStatus::Found => { CandidateBSizeIteratorStatus::Found - } + }, }; match self.status { CandidateBSizeIteratorStatus::Trying => Some(self.block_size), CandidateBSizeIteratorStatus::TryingMax => { Some(MaybeAuto::Specified(self.max_block_size.unwrap())) - } + }, CandidateBSizeIteratorStatus::TryingMin => { Some(MaybeAuto::Specified(self.min_block_size)) - } + }, CandidateBSizeIteratorStatus::Found => None, CandidateBSizeIteratorStatus::Initial => panic!(), } @@ -451,17 +542,25 @@ impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> { #[inline] fn process(&self, flow: &mut Flow) { if !flow.is_block_like() { - return + return; } // This flow might not be an absolutely positioned flow if it is the root of the tree. let block = flow.as_mut_block(); - if !block.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if !block + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { return; } - if !block.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) { - return + if !block + .base + .restyle_damage + .intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) + { + return; } block.calculate_absolute_block_size_and_margins(self.0); @@ -533,14 +632,20 @@ impl BlockFlow { BlockFlow::from_fragment_and_float_kind(fragment, None) } - pub fn from_fragment_and_float_kind(fragment: Fragment, float_kind: Option<FloatKind>) - -> BlockFlow { + pub fn from_fragment_and_float_kind( + fragment: Fragment, + float_kind: Option<FloatKind>, + ) -> BlockFlow { let writing_mode = fragment.style().writing_mode; BlockFlow { - base: BaseFlow::new(Some(fragment.style()), writing_mode, match float_kind { - Some(_) => ForceNonfloatedFlag::FloatIfNecessary, - None => ForceNonfloatedFlag::ForceNonfloated, - }), + base: BaseFlow::new( + Some(fragment.style()), + writing_mode, + match float_kind { + Some(_) => ForceNonfloatedFlag::FloatIfNecessary, + None => ForceNonfloatedFlag::ForceNonfloated, + }, + ), fragment: fragment, float: float_kind.map(|kind| Box::new(FloatedBlockInfo::new(kind))), flags: BlockFlowFlags::empty(), @@ -552,7 +657,11 @@ impl BlockFlow { /// This determines the algorithm used to calculate inline-size, block-size, and the /// relevant margins for this Block. pub fn block_type(&self) -> BlockType { - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { if self.fragment.is_replaced() { BlockType::AbsoluteReplaced } else { @@ -582,65 +691,85 @@ impl BlockFlow { } /// Compute the actual inline size and position for this block. - pub fn compute_used_inline_size(&mut self, - shared_context: &SharedStyleContext, - containing_block_inline_size: Au) { + pub fn compute_used_inline_size( + &mut self, + shared_context: &SharedStyleContext, + containing_block_inline_size: Au, + ) { let block_type = self.block_type(); match block_type { BlockType::AbsoluteReplaced => { let inline_size_computer = AbsoluteReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } + inline_size_computer.compute_used_inline_size( + self, + shared_context, + containing_block_inline_size, + ); + }, BlockType::AbsoluteNonReplaced => { let inline_size_computer = AbsoluteNonReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } + inline_size_computer.compute_used_inline_size( + self, + shared_context, + containing_block_inline_size, + ); + }, BlockType::FloatReplaced => { let inline_size_computer = FloatReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } + inline_size_computer.compute_used_inline_size( + self, + shared_context, + containing_block_inline_size, + ); + }, BlockType::FloatNonReplaced => { let inline_size_computer = FloatNonReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } + inline_size_computer.compute_used_inline_size( + self, + shared_context, + containing_block_inline_size, + ); + }, BlockType::InlineBlockReplaced => { let inline_size_computer = InlineBlockReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } + inline_size_computer.compute_used_inline_size( + self, + shared_context, + containing_block_inline_size, + ); + }, BlockType::InlineBlockNonReplaced => { let inline_size_computer = InlineBlockNonReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } + inline_size_computer.compute_used_inline_size( + self, + shared_context, + containing_block_inline_size, + ); + }, BlockType::Replaced => { let inline_size_computer = BlockReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } + inline_size_computer.compute_used_inline_size( + self, + shared_context, + containing_block_inline_size, + ); + }, BlockType::NonReplaced => { let inline_size_computer = BlockNonReplaced; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } + inline_size_computer.compute_used_inline_size( + self, + shared_context, + containing_block_inline_size, + ); + }, BlockType::InlineFlexItem => { let inline_size_computer = InlineFlexItem; - inline_size_computer.compute_used_inline_size(self, - shared_context, - containing_block_inline_size); - } + inline_size_computer.compute_used_inline_size( + self, + shared_context, + containing_block_inline_size, + ); + }, } } @@ -652,9 +781,15 @@ impl BlockFlow { pub fn stacking_relative_border_box(&self, coor: CoordinateSystem) -> Rect<Au> { return self.fragment.stacking_relative_border_box( &self.base.stacking_relative_position, - &self.base.early_absolute_position_info.relative_containing_block_size, - self.base.early_absolute_position_info.relative_containing_block_mode, - coor); + &self + .base + .early_absolute_position_info + .relative_containing_block_size, + self.base + .early_absolute_position_info + .relative_containing_block_mode, + coor, + ); } /// Return the size of the containing block for the given immediate absolute descendant of this @@ -663,14 +798,23 @@ impl BlockFlow { /// Right now, this only gets the containing block size for absolutely positioned elements. /// Note: We assume this is called in a top-down traversal, so it is ok to reference the CB. #[inline] - pub fn containing_block_size(&self, viewport_size: &Size2D<Au>, descendant: OpaqueFlow) - -> LogicalSize<Au> { - debug_assert!(self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED)); + pub fn containing_block_size( + &self, + viewport_size: &Size2D<Au>, + descendant: OpaqueFlow, + ) -> LogicalSize<Au> { + debug_assert!( + self.base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + ); if self.is_fixed() || self.is_root() { // Initial containing block is the CB for the root LogicalSize::from_physical(self.base.writing_mode, *viewport_size) } else { - self.base.absolute_cb.generated_containing_block_size(descendant) + self.base + .absolute_cb + .generated_containing_block_size(descendant) } } @@ -680,8 +824,13 @@ impl BlockFlow { /// calculated in the bubble-inline-sizes traversal. pub fn get_shrink_to_fit_inline_size(&self, available_inline_size: Au) -> Au { let content_intrinsic_inline_sizes = self.content_intrinsic_inline_sizes(); - min(content_intrinsic_inline_sizes.preferred_inline_size, - max(content_intrinsic_inline_sizes.minimum_inline_size, available_inline_size)) + min( + content_intrinsic_inline_sizes.preferred_inline_size, + max( + content_intrinsic_inline_sizes.minimum_inline_size, + available_inline_size, + ), + ) } /// If this is the root flow, shifts all kids down and adjusts our size to account for @@ -689,22 +838,24 @@ impl BlockFlow { /// /// TODO(#2017, pcwalton): This is somewhat inefficient (traverses kids twice); can we do /// better? - fn adjust_fragments_for_collapsed_margins_if_root(&mut self, - shared_context: &SharedStyleContext) { + fn adjust_fragments_for_collapsed_margins_if_root( + &mut self, + shared_context: &SharedStyleContext, + ) { if !self.is_root() { - return + return; } - let (block_start_margin_value, block_end_margin_value) = - match self.base.collapsible_margins { - CollapsibleMargins::CollapseThrough(_) => { - panic!("Margins unexpectedly collapsed through root flow.") - } - CollapsibleMargins::Collapse(block_start_margin, block_end_margin) => { - (block_start_margin.collapse(), block_end_margin.collapse()) - } - CollapsibleMargins::None(block_start, block_end) => (block_start, block_end), - }; + let (block_start_margin_value, block_end_margin_value) = match self.base.collapsible_margins + { + CollapsibleMargins::CollapseThrough(_) => { + panic!("Margins unexpectedly collapsed through root flow.") + }, + CollapsibleMargins::Collapse(block_start_margin, block_end_margin) => { + (block_start_margin.collapse(), block_end_margin.collapse()) + }, + CollapsibleMargins::None(block_start, block_end) => (block_start, block_end), + }; // Shift all kids down (or up, if margins are negative) if necessary. if block_start_margin_value != Au(0) { @@ -718,12 +869,14 @@ impl BlockFlow { // is not correct behavior according to CSS 2.1 § 10.5. Instead I think we should treat the // root element as having `overflow: scroll` and use the layers-based scrolling // infrastructure to make it scrollable. - let viewport_size = - LogicalSize::from_physical(self.fragment.style.writing_mode, - shared_context.viewport_size()); - let block_size = max(viewport_size.block, - self.fragment.border_box.size.block + block_start_margin_value + - block_end_margin_value); + let viewport_size = LogicalSize::from_physical( + self.fragment.style.writing_mode, + shared_context.viewport_size(), + ); + let block_size = max( + viewport_size.block, + self.fragment.border_box.size.block + block_start_margin_value + block_end_margin_value, + ); self.base.position.size.block = block_size; self.fragment.border_box.size.block = block_size; @@ -774,69 +927,95 @@ impl BlockFlow { /// `inline(always)` because this is only ever called by in-order or non-in-order top-level /// methods. #[inline(always)] - pub fn assign_block_size_block_base(&mut self, - layout_context: &LayoutContext, - mut fragmentation_context: Option<FragmentationContext>, - margins_may_collapse: MarginsMayCollapseFlag) - -> Option<Arc<Flow>> { - let _scope = layout_debug_scope!("assign_block_size_block_base {:x}", - self.base.debug_id()); + pub fn assign_block_size_block_base( + &mut self, + layout_context: &LayoutContext, + mut fragmentation_context: Option<FragmentationContext>, + margins_may_collapse: MarginsMayCollapseFlag, + ) -> Option<Arc<Flow>> { + let _scope = layout_debug_scope!("assign_block_size_block_base {:x}", self.base.debug_id()); let mut break_at = None; let content_box = self.fragment.content_box(); - if self.base.restyle_damage.contains(ServoRestyleDamage::REFLOW) { + if self + .base + .restyle_damage + .contains(ServoRestyleDamage::REFLOW) + { // Our current border-box position. let mut cur_b = Au(0); // Absolute positioning establishes a block formatting context. Don't propagate floats // in or out. (But do propagate them between kids.) - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) || - margins_may_collapse != MarginsMayCollapseFlag::MarginsMayCollapse { + if self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) || + margins_may_collapse != MarginsMayCollapseFlag::MarginsMayCollapse + { self.base.floats = Floats::new(self.fragment.style.writing_mode); } let writing_mode = self.base.floats.writing_mode; self.base.floats.translate(LogicalSize::new( - writing_mode, -self.fragment.inline_start_offset(), Au(0))); + writing_mode, + -self.fragment.inline_start_offset(), + Au(0), + )); // The sum of our block-start border and block-start padding. let block_start_offset = self.fragment.border_padding.block_start; translate_including_floats(&mut cur_b, block_start_offset, &mut self.base.floats); - let can_collapse_block_start_margin_with_kids = - margins_may_collapse == MarginsMayCollapseFlag::MarginsMayCollapse && - !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && + let can_collapse_block_start_margin_with_kids = margins_may_collapse == + MarginsMayCollapseFlag::MarginsMayCollapse && + !self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && self.fragment.border_padding.block_start == Au(0); let mut margin_collapse_info = MarginCollapseInfo::initialize_block_start_margin( &self.fragment, - can_collapse_block_start_margin_with_kids); + can_collapse_block_start_margin_with_kids, + ); // At this point, `cur_b` is at the content edge of our box. Now iterate over children. let mut floats = self.base.floats.clone(); let thread_id = self.base.thread_id; let (mut had_floated_children, mut had_children_with_clearance) = (false, false); for (child_index, kid) in self.base.child_iter_mut().enumerate() { - if kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if kid + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { // Assume that the *hypothetical box* for an absolute flow starts immediately // after the margin-end border edge of the previous flow. - if kid.base().flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { + if kid + .base() + .flags + .contains(FlowFlags::BLOCK_POSITION_IS_STATIC) + { let previous_bottom_margin = margin_collapse_info.current_float_ceiling(); kid.mut_base().position.start.b = cur_b + - kid.base().collapsible_margins - .block_start_margin_for_noncollapsible_context() + + kid.base() + .collapsible_margins + .block_start_margin_for_noncollapsible_context() + previous_bottom_margin } kid.place_float_if_applicable(); if !kid.base().flags.is_float() { - kid.assign_block_size_for_inorder_child_if_necessary(layout_context, - thread_id, - content_box); + kid.assign_block_size_for_inorder_child_if_necessary( + layout_context, + thread_id, + content_box, + ); } // Skip the collapsing and float processing for absolute flow kids and continue // with the next flow. - continue + continue; } let previous_b = cur_b; @@ -865,7 +1044,7 @@ impl BlockFlow { let kid_base = kid.mut_base(); floats = kid_base.floats.clone(); - continue + continue; } // If we have clearance, assume there are no floats in. @@ -880,22 +1059,26 @@ impl BlockFlow { } // Lay the child out if this was an in-order traversal. - let need_to_process_child_floats = - kid.assign_block_size_for_inorder_child_if_necessary(layout_context, - thread_id, - content_box); + let need_to_process_child_floats = kid + .assign_block_size_for_inorder_child_if_necessary( + layout_context, + thread_id, + content_box, + ); if !had_children_with_clearance && - floats.is_present() && - (kid.base().flags.contains(FlowFlags::CLEARS_LEFT) || - kid.base().flags.contains(FlowFlags::CLEARS_RIGHT)) { + floats.is_present() && + (kid.base().flags.contains(FlowFlags::CLEARS_LEFT) || + kid.base().flags.contains(FlowFlags::CLEARS_RIGHT)) + { had_children_with_clearance = true } // Handle any (possibly collapsed) top margin. let delta = margin_collapse_info.advance_block_start_margin( &kid.base().collapsible_margins, - !had_children_with_clearance); + !had_children_with_clearance, + ); translate_including_floats(&mut cur_b, delta, &mut floats); // Collapse-through margins should be placed at the top edge, @@ -905,8 +1088,10 @@ impl BlockFlow { } // Clear past the floats that came in, if necessary. - let clearance = match (kid.base().flags.contains(FlowFlags::CLEARS_LEFT), - kid.base().flags.contains(FlowFlags::CLEARS_RIGHT)) { + let clearance = match ( + kid.base().flags.contains(FlowFlags::CLEARS_LEFT), + kid.base().flags.contains(FlowFlags::CLEARS_RIGHT), + ) { (false, false) => Au(0), (true, false) => floats.clearance(ClearType::Left), (false, true) => floats.clearance(ClearType::Right), @@ -942,19 +1127,19 @@ impl BlockFlow { cur_b = cur_b + delta; kid_base.position.start.b = kid_base.position.start.b + delta; delta - } - _ => Au(0) + }, + _ => Au(0), }; if break_at.is_some() { - break + break; } if let Some(ref mut ctx) = fragmentation_context { if cur_b > ctx.available_block_size && !ctx.this_fragment_is_empty { break_at = Some((child_index, None)); cur_b = previous_b; - break + break; } ctx.this_fragment_is_empty = false } @@ -965,38 +1150,50 @@ impl BlockFlow { } // Add in our block-end margin and compute our collapsible margins. - let can_collapse_block_end_margin_with_kids = - margins_may_collapse == MarginsMayCollapseFlag::MarginsMayCollapse && - !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && + let can_collapse_block_end_margin_with_kids = margins_may_collapse == + MarginsMayCollapseFlag::MarginsMayCollapse && + !self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && self.fragment.border_padding.block_end == Au(0); - let (collapsible_margins, delta) = - margin_collapse_info.finish_and_compute_collapsible_margins( - &self.fragment, - self.base.block_container_explicit_block_size, - can_collapse_block_end_margin_with_kids, - !had_floated_children); + let (collapsible_margins, delta) = margin_collapse_info + .finish_and_compute_collapsible_margins( + &self.fragment, + self.base.block_container_explicit_block_size, + can_collapse_block_end_margin_with_kids, + !had_floated_children, + ); self.base.collapsible_margins = collapsible_margins; translate_including_floats(&mut cur_b, delta, &mut floats); let mut block_size = cur_b - block_start_offset; let is_root = self.is_root(); - if is_root || self.formatting_context_type() != FormattingContextType::None || - self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if is_root || self.formatting_context_type() != FormattingContextType::None || self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { // The content block-size includes all the floats per CSS 2.1 § 10.6.7. The easiest // way to handle this is to just treat it as clearance. block_size = block_size + floats.clearance(ClearType::Both); } - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { // FIXME(#2003, pcwalton): The max is taken here so that you can scroll the page, // but this is not correct behavior according to CSS 2.1 § 10.5. Instead I think we // should treat the root element as having `overflow: scroll` and use the layers- // based scrolling infrastructure to make it scrollable. if is_root { - let viewport_size = - LogicalSize::from_physical(self.fragment.style.writing_mode, - layout_context.shared_context().viewport_size()); + let viewport_size = LogicalSize::from_physical( + self.fragment.style.writing_mode, + layout_context.shared_context().viewport_size(), + ); block_size = max(viewport_size.block, block_size) } @@ -1007,23 +1204,26 @@ impl BlockFlow { self.fragment.border_box.size.block = block_size; } - - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { self.propagate_early_absolute_position_info_to_children(); - return None + return None; } // Compute any explicitly-specified block size. // Can't use `for` because we assign to `candidate_block_size_iterator.candidate_value`. let mut candidate_block_size_iterator = CandidateBSizeIterator::new( &self.fragment, - self.base.block_container_explicit_block_size); + self.base.block_container_explicit_block_size, + ); while let Some(candidate_block_size) = candidate_block_size_iterator.next() { - candidate_block_size_iterator.candidate_value = - match candidate_block_size { - MaybeAuto::Auto => block_size, - MaybeAuto::Specified(value) => value - } + candidate_block_size_iterator.candidate_value = match candidate_block_size { + MaybeAuto::Auto => block_size, + MaybeAuto::Specified(value) => value, + } } // Adjust `cur_b` as necessary to account for the explicitly-specified block-size. @@ -1046,9 +1246,11 @@ impl BlockFlow { // Translate the current set of floats back into the parent coordinate system in the // inline direction, and store them in the flow so that flows that come later in the // document can access them. - floats.translate(LogicalSize::new(writing_mode, - self.fragment.inline_start_offset(), - Au(0))); + floats.translate(LogicalSize::new( + writing_mode, + self.fragment.inline_start_offset(), + Au(0), + )); self.base.floats = floats.clone(); self.adjust_fragments_for_collapsed_margins_if_root(layout_context.shared_context()); } else { @@ -1056,9 +1258,11 @@ impl BlockFlow { // necessary. let thread_id = self.base.thread_id; for kid in self.base.child_iter_mut() { - kid.assign_block_size_for_inorder_child_if_necessary(layout_context, - thread_id, - content_box); + kid.assign_block_size_for_inorder_child_if_necessary( + layout_context, + thread_id, + content_box, + ); } } @@ -1075,10 +1279,18 @@ impl BlockFlow { // Also don't remove the dirty bits if we're a block formatting context since our inline // size has not yet been computed. (See `assign_inline_position_for_formatting_context()`.) if (self.base.flags.is_float() || - self.formatting_context_type() == FormattingContextType::None) && - !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - self.fragment.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.formatting_context_type() == FormattingContextType::None) && + !self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { + self.base + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.fragment + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); } break_at.and_then(|(i, child_remaining)| { @@ -1116,15 +1328,18 @@ impl BlockFlow { // Our `position` field accounts for positive margins, but not negative margins. (See // calculation of `extra_inline_size_from_margin` below.) Negative margins must be taken // into account for float placement, however. So we add them in here. - let inline_size_for_float_placement = self.base.position.size.inline + - min(Au(0), self.fragment.margin.inline_start_end()); + let inline_size_for_float_placement = + self.base.position.size.inline + min(Au(0), self.fragment.margin.inline_start_end()); let info = PlacementInfo { size: LogicalSize::new( self.fragment.style.writing_mode, inline_size_for_float_placement, - block_size + self.fragment.margin.block_start_end()) - .convert(self.fragment.style.writing_mode, self.base.floats.writing_mode), + block_size + self.fragment.margin.block_start_end(), + ).convert( + self.fragment.style.writing_mode, + self.base.floats.writing_mode, + ), ceiling: clearance + float_info.float_ceiling, max_inline_size: float_info.containing_inline_size, kind: float_info.float_kind, @@ -1139,32 +1354,51 @@ impl BlockFlow { // Move in from the margin edge, as per CSS 2.1 § 9.5, floats may not overlap anything on // their margin edges. - let float_offset = self.base.floats.last_float_pos().unwrap() - .convert(self.base.floats.writing_mode, - self.base.writing_mode, - container_size) - .start; - let margin_offset = LogicalPoint::new(self.base.writing_mode, - Au(0), - self.fragment.margin.block_start); - - let mut origin = LogicalPoint::new(self.base.writing_mode, - self.base.position.start.i, - self.base.position.start.b); + let float_offset = self + .base + .floats + .last_float_pos() + .unwrap() + .convert( + self.base.floats.writing_mode, + self.base.writing_mode, + container_size, + ).start; + let margin_offset = LogicalPoint::new( + self.base.writing_mode, + Au(0), + self.fragment.margin.block_start, + ); + + let mut origin = LogicalPoint::new( + self.base.writing_mode, + self.base.position.start.i, + self.base.position.start.b, + ); origin = origin.add_point(&float_offset).add_point(&margin_offset); - self.base.position = LogicalRect::from_point_size(self.base.writing_mode, - origin, - self.base.position.size); + self.base.position = + LogicalRect::from_point_size(self.base.writing_mode, origin, self.base.position.size); } - pub fn explicit_block_containing_size(&self, shared_context: &SharedStyleContext) -> Option<Au> { + pub fn explicit_block_containing_size( + &self, + shared_context: &SharedStyleContext, + ) -> Option<Au> { if self.is_root() || self.is_fixed() { - let viewport_size = LogicalSize::from_physical(self.fragment.style.writing_mode, - shared_context.viewport_size()); + let viewport_size = LogicalSize::from_physical( + self.fragment.style.writing_mode, + shared_context.viewport_size(), + ); Some(viewport_size.block) - } else if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.base.block_container_explicit_block_size.is_none() { - self.base.absolute_cb.explicit_block_containing_size(shared_context) + } else if self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && + self.base.block_container_explicit_block_size.is_none() + { + self.base + .absolute_cb + .explicit_block_containing_size(shared_context) } else { self.base.block_container_explicit_block_size } @@ -1174,58 +1408,56 @@ impl BlockFlow { let content_block_size = self.fragment.style().content_block_size(); match (content_block_size, containing_block_size) { - (LengthOrPercentageOrAuto::Calc(calc), _) => { - calc.to_used_value(containing_block_size) - } + (LengthOrPercentageOrAuto::Calc(calc), _) => calc.to_used_value(containing_block_size), (LengthOrPercentageOrAuto::Length(length), _) => Some(Au::from(length)), (LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => { Some(container_size.scale_by(percent.0)) - } + }, (LengthOrPercentageOrAuto::Percentage(_), None) | - (LengthOrPercentageOrAuto::Auto, None) => { - None - } + (LengthOrPercentageOrAuto::Auto, None) => None, (LengthOrPercentageOrAuto::Auto, Some(container_size)) => { let (block_start, block_end) = { let position = self.fragment.style().logical_position(); - (MaybeAuto::from_style(position.block_start, container_size), - MaybeAuto::from_style(position.block_end, container_size)) + ( + MaybeAuto::from_style(position.block_start, container_size), + MaybeAuto::from_style(position.block_end, container_size), + ) }; match (block_start, block_end) { (MaybeAuto::Specified(block_start), MaybeAuto::Specified(block_end)) => { - let available_block_size = container_size - self.fragment.border_padding.block_start_end(); + let available_block_size = + container_size - self.fragment.border_padding.block_start_end(); // Non-auto margin-block-start and margin-block-end values have already been // calculated during assign-inline-size. let margin = self.fragment.style().logical_margin(); let margin_block_start = match margin.block_start { LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto, - _ => MaybeAuto::Specified(self.fragment.margin.block_start) + _ => MaybeAuto::Specified(self.fragment.margin.block_start), }; let margin_block_end = match margin.block_end { LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto, - _ => MaybeAuto::Specified(self.fragment.margin.block_end) + _ => MaybeAuto::Specified(self.fragment.margin.block_end), }; let margin_block_start = margin_block_start.specified_or_zero(); let margin_block_end = margin_block_end.specified_or_zero(); let sum = block_start + block_end + margin_block_start + margin_block_end; Some(available_block_size - sum) - } + }, - (_, _) => { - None - } + (_, _) => None, } - } + }, } } fn calculate_absolute_block_size_and_margins(&mut self, shared_context: &SharedStyleContext) { let opaque_self = OpaqueFlow::from_flow(self); - let containing_block_block_size = - self.containing_block_size(&shared_context.viewport_size(), opaque_self).block; + let containing_block_block_size = self + .containing_block_size(&shared_context.viewport_size(), opaque_self) + .block; // This is the stored content block-size value from assign-block-size let content_block_size = self.fragment.border_box.size.block; @@ -1237,24 +1469,24 @@ impl BlockFlow { let margin = self.fragment.style().logical_margin(); let margin_block_start = match margin.block_start { LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto, - _ => MaybeAuto::Specified(self.fragment.margin.block_start) + _ => MaybeAuto::Specified(self.fragment.margin.block_start), }; let margin_block_end = match margin.block_end { LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto, - _ => MaybeAuto::Specified(self.fragment.margin.block_end) + _ => MaybeAuto::Specified(self.fragment.margin.block_end), }; let block_start; let block_end; { let position = self.fragment.style().logical_position(); - block_start = MaybeAuto::from_style(position.block_start, - containing_block_block_size); + block_start = + MaybeAuto::from_style(position.block_start, containing_block_block_size); block_end = MaybeAuto::from_style(position.block_end, containing_block_block_size); } - let available_block_size = containing_block_block_size - - self.fragment.border_padding.block_start_end(); + let available_block_size = + containing_block_block_size - self.fragment.border_padding.block_start_end(); 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 @@ -1265,21 +1497,24 @@ impl BlockFlow { // Check this when that has been fixed. let block_size_used_val = self.fragment.border_box.size.block - self.fragment.border_padding.block_start_end(); - solution = Some(BSizeConstraintSolution::solve_vertical_constraints_abs_replaced( + solution = Some( + BSizeConstraintSolution::solve_vertical_constraints_abs_replaced( block_size_used_val, margin_block_start, margin_block_end, block_start, block_end, content_block_size, - available_block_size)) + available_block_size, + ), + ) } else { let mut candidate_block_size_iterator = CandidateBSizeIterator::new(&self.fragment, Some(containing_block_block_size)); // Can't use `for` because we assign to // `candidate_block_size_iterator.candidate_value`. - while let Some(block_size_used_val) = candidate_block_size_iterator.next() { + while let Some(block_size_used_val) = candidate_block_size_iterator.next() { solution = Some( BSizeConstraintSolution::solve_vertical_constraints_abs_nonreplaced( block_size_used_val, @@ -1288,10 +1523,11 @@ impl BlockFlow { block_start, block_end, content_block_size, - available_block_size)); + available_block_size, + ), + ); - candidate_block_size_iterator.candidate_value = - solution.unwrap().block_size; + candidate_block_size_iterator.candidate_value = solution.unwrap().block_size; } } } @@ -1301,7 +1537,11 @@ impl BlockFlow { self.fragment.margin.block_end = solution.margin_block_end; self.fragment.border_box.start.b = Au(0); - if !self.base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { + if !self + .base + .flags + .contains(FlowFlags::BLOCK_POSITION_IS_STATIC) + { self.base.position.start.b = solution.block_start + self.fragment.margin.block_start } @@ -1310,8 +1550,12 @@ impl BlockFlow { self.fragment.border_box.size.block = block_size; self.base.position.size.block = block_size; - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - self.fragment.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.base + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.fragment + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); } /// Compute inline size based using the `block_container_inline_size` set by the parent flow. @@ -1332,18 +1576,16 @@ impl BlockFlow { /// `#[inline(always)]` because this is called only from block or table inline-size assignment /// and the code for block layout is significantly simpler. #[inline(always)] - pub fn propagate_assigned_inline_size_to_children<F>(&mut self, - shared_context: &SharedStyleContext, - inline_start_content_edge: Au, - inline_end_content_edge: Au, - content_inline_size: Au, - mut callback: F) - where F: FnMut(&mut Flow, - usize, - Au, - WritingMode, - &mut Au, - &mut Au) { + pub fn propagate_assigned_inline_size_to_children<F>( + &mut self, + shared_context: &SharedStyleContext, + inline_start_content_edge: Au, + inline_end_content_edge: Au, + content_inline_size: Au, + mut callback: F, + ) where + F: FnMut(&mut Flow, usize, Au, WritingMode, &mut Au, &mut Au), + { let flags = self.base.flags.clone(); let opaque_self = OpaqueFlow::from_flow(self); @@ -1355,13 +1597,20 @@ impl BlockFlow { }; let parent_container_size = self.explicit_block_containing_size(shared_context); // https://drafts.csswg.org/css-ui-3/#box-sizing - let mut explicit_content_size = self - .explicit_block_size(parent_container_size) - .map(|x| if x < box_border { Au(0) } else { x - box_border }); - if self.is_root() { explicit_content_size = max(parent_container_size, explicit_content_size); } + let mut explicit_content_size = self.explicit_block_size(parent_container_size).map(|x| { + if x < box_border { + Au(0) + } else { + x - box_border + } + }); + if self.is_root() { + explicit_content_size = max(parent_container_size, explicit_content_size); + } // Calculate containing block inline size. let containing_block_size = if flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - self.containing_block_size(&shared_context.viewport_size(), opaque_self).inline + self.containing_block_size(&shared_context.viewport_size(), opaque_self) + .inline } else { content_inline_size }; @@ -1388,13 +1637,17 @@ impl BlockFlow { // float child does not have `REFLOW` set, we must be careful to avoid touching its // inline position, as no logic will run afterward to set its true value. let kid_base = kid.mut_base(); - let reflow_damage = if kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + let reflow_damage = if kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { ServoRestyleDamage::REFLOW_OUT_OF_FLOW } else { ServoRestyleDamage::REFLOW }; - if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) && - kid_base.restyle_damage.contains(reflow_damage) { + if kid_base + .flags + .contains(FlowFlags::INLINE_POSITION_IS_STATIC) && + kid_base.restyle_damage.contains(reflow_damage) + { kid_base.position.start.i = if kid_mode.is_bidi_ltr() == containing_block_mode.is_bidi_ltr() { inline_start_content_edge @@ -1409,26 +1662,33 @@ impl BlockFlow { // Call the callback to propagate extra inline size information down to the child. This // is currently used for tables. - callback(kid, - i, - content_inline_size, - containing_block_mode, - &mut inline_start_margin_edge, - &mut inline_end_margin_edge); + callback( + kid, + i, + content_inline_size, + containing_block_mode, + &mut inline_start_margin_edge, + &mut inline_end_margin_edge, + ); // Per CSS 2.1 § 16.3.1, text alignment propagates to all children in flow. // // TODO(#2265, pcwalton): Do this in the cascade instead. let containing_block_text_align = self.fragment.style().get_inherited_text().text_align; - kid.mut_base().flags.set_text_align(containing_block_text_align); + kid.mut_base() + .flags + .set_text_align(containing_block_text_align); // Handle `text-indent` on behalf of any inline children that we have. This is // necessary because any percentages are relative to the containing block, which only // we know. if kid.is_inline_flow() { - kid.as_mut_inline().first_line_indentation = - self.fragment.style().get_inherited_text().text_indent - .to_used_value(containing_block_size); + kid.as_mut_inline().first_line_indentation = self + .fragment + .style() + .get_inherited_text() + .text_indent + .to_used_value(containing_block_size); } } } @@ -1437,11 +1697,11 @@ impl BlockFlow { /// `FormattingContextType`. pub fn formatting_context_type(&self) -> FormattingContextType { if self.is_inline_flex_item() || self.is_block_flex_item() { - return FormattingContextType::Other + return FormattingContextType::Other; } let style = self.fragment.style(); if style.get_box().float != Float::None { - return FormattingContextType::Other + return FormattingContextType::Other; } match style.get_box().display { Display::TableCell | @@ -1449,14 +1709,13 @@ impl BlockFlow { Display::TableRowGroup | Display::Table | Display::InlineBlock | - Display::Flex => { - FormattingContextType::Other - } + Display::Flex => FormattingContextType::Other, _ if style.get_box().overflow_x != StyleOverflow::Visible || - style.get_box().overflow_y != StyleOverflow::Visible || - style.is_multicol() => { + style.get_box().overflow_y != StyleOverflow::Visible || + style.is_multicol() => + { FormattingContextType::Block - } + }, _ => FormattingContextType::None, } } @@ -1472,18 +1731,28 @@ impl BlockFlow { /// on the floats we could see at the time of inline-size assignment. The job of this function, /// therefore, is not only to assign the final size but also to perform the layout again for /// this block formatting context if our speculation was wrong. - fn assign_inline_position_for_formatting_context(&mut self, - layout_context: &LayoutContext, - content_box: LogicalRect<Au>) { + fn assign_inline_position_for_formatting_context( + &mut self, + layout_context: &LayoutContext, + content_box: LogicalRect<Au>, + ) { debug_assert_ne!(self.formatting_context_type(), FormattingContextType::None); - if !self.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) { - return + if !self + .base + .restyle_damage + .intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) + { + return; } // We do this first to avoid recomputing our inline size when we propagate it. - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - self.fragment.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.base + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.fragment + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); // The code below would completely wreck the layout if run on a flex item, however: // * Flex items are always the children of flex containers. @@ -1494,16 +1763,18 @@ impl BlockFlow { // Therefore, a flex item cannot be impacted by a float. // See also: https://www.w3.org/TR/css-flexbox-1/#flex-containers if !self.base.might_have_floats_in() { - return + return; } // If you remove the might_have_floats_in conditional, this will go off. debug_assert!(!self.is_inline_flex_item()); // Compute the available space for us, based on the actual floats. - let rect = self.base.floats.available_rect(Au(0), - self.fragment.border_box.size.block, - content_box.size.inline); + let rect = self.base.floats.available_rect( + Au(0), + self.fragment.border_box.size.block, + content_box.size.inline, + ); let available_inline_size = if let Some(rect) = rect { // Offset our position by whatever displacement is needed to not impact the floats. // Also, account for margins sliding behind floats. @@ -1525,25 +1796,29 @@ impl BlockFlow { } else { content_box.size.inline } - self.fragment.margin.inline_start_end(); - let max_inline_size = - self.fragment.style().max_inline_size() - .to_used_value(self.base.block_container_inline_size) - .unwrap_or(MAX_AU); - let min_inline_size = - self.fragment.style().min_inline_size().to_used_value(self.base.block_container_inline_size); + let max_inline_size = self + .fragment + .style() + .max_inline_size() + .to_used_value(self.base.block_container_inline_size) + .unwrap_or(MAX_AU); + let min_inline_size = self + .fragment + .style() + .min_inline_size() + .to_used_value(self.base.block_container_inline_size); let specified_inline_size = self.fragment.style().content_inline_size(); let container_size = self.base.block_container_inline_size; - let inline_size = - if let MaybeAuto::Specified(size) = MaybeAuto::from_style(specified_inline_size, - container_size) { - match self.fragment.style().get_position().box_sizing { - BoxSizing::BorderBox => size, - BoxSizing::ContentBox => - size + self.fragment.border_padding.inline_start_end(), - } - } else { - max(min_inline_size, min(available_inline_size, max_inline_size)) - }; + let inline_size = if let MaybeAuto::Specified(size) = + MaybeAuto::from_style(specified_inline_size, container_size) + { + match self.fragment.style().get_position().box_sizing { + BoxSizing::BorderBox => size, + BoxSizing::ContentBox => size + self.fragment.border_padding.inline_start_end(), + } + } else { + max(min_inline_size, min(available_inline_size, max_inline_size)) + }; self.base.position.size.inline = inline_size + self.fragment.margin.inline_start_end(); // If float speculation failed, fixup our layout, and re-layout all the children. @@ -1563,12 +1838,15 @@ impl BlockFlow { self.assign_block_size(layout_context); } - debug_assert_eq!(self.fragment.margin_box_inline_size(), self.base.position.size.inline); + debug_assert_eq!( + self.fragment.margin_box_inline_size(), + self.base.position.size.inline + ); } fn is_inline_block_or_inline_flex(&self) -> bool { self.fragment.style().get_box().display == Display::InlineBlock || - self.fragment.style().get_box().display == Display::InlineFlex + self.fragment.style().get_box().display == Display::InlineFlex } /// Computes the content portion (only) of the intrinsic inline sizes of this flow. This is @@ -1578,9 +1856,11 @@ impl BlockFlow { let (border_padding, margin) = self.fragment.surrounding_intrinsic_inline_size(); IntrinsicISizes { minimum_inline_size: self.base.intrinsic_inline_sizes.minimum_inline_size - - border_padding - margin, + border_padding - + margin, preferred_inline_size: self.base.intrinsic_inline_sizes.preferred_inline_size - - border_padding - margin, + border_padding - + margin, } } @@ -1599,9 +1879,13 @@ impl BlockFlow { } else { flags.remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); for kid in self.base.children.iter() { - if kid.base().flags.contains(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS) { + if kid + .base() + .flags + .contains(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS) + { flags.insert(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); - break + break; } } } @@ -1617,15 +1901,21 @@ impl BlockFlow { let (mut left_float_width_accumulator, mut right_float_width_accumulator) = (Au(0), Au(0)); let mut preferred_inline_size_of_children_without_text_or_replaced_fragments = Au(0); for kid in self.base.child_iter_mut() { - if kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) || !consult_children { - continue + if kid + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) || + !consult_children + { + continue; } let child_base = kid.mut_base(); let float_kind = child_base.flags.float_kind(); - computation.content_intrinsic_sizes.minimum_inline_size = - max(computation.content_intrinsic_sizes.minimum_inline_size, - child_base.intrinsic_inline_sizes.minimum_inline_size); + computation.content_intrinsic_sizes.minimum_inline_size = max( + computation.content_intrinsic_sizes.minimum_inline_size, + child_base.intrinsic_inline_sizes.minimum_inline_size, + ); if child_base.flags.contains(FlowFlags::CLEARS_LEFT) { left_float_width = max(left_float_width, left_float_width_accumulator); @@ -1636,25 +1926,34 @@ impl BlockFlow { right_float_width_accumulator = Au(0) } - match (float_kind, child_base.flags.contains(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS)) { + match ( + float_kind, + child_base + .flags + .contains(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS), + ) { (Float::None, true) => { - computation.content_intrinsic_sizes.preferred_inline_size = - max(computation.content_intrinsic_sizes.preferred_inline_size, - child_base.intrinsic_inline_sizes.preferred_inline_size); - } + computation.content_intrinsic_sizes.preferred_inline_size = max( + computation.content_intrinsic_sizes.preferred_inline_size, + child_base.intrinsic_inline_sizes.preferred_inline_size, + ); + }, (Float::None, false) => { preferred_inline_size_of_children_without_text_or_replaced_fragments = max( preferred_inline_size_of_children_without_text_or_replaced_fragments, - child_base.intrinsic_inline_sizes.preferred_inline_size) - } + child_base.intrinsic_inline_sizes.preferred_inline_size, + ) + }, (Float::Left, _) => { - left_float_width_accumulator = left_float_width_accumulator + - child_base.intrinsic_inline_sizes.preferred_inline_size; - } + left_float_width_accumulator = left_float_width_accumulator + child_base + .intrinsic_inline_sizes + .preferred_inline_size; + }, (Float::Right, _) => { - right_float_width_accumulator = right_float_width_accumulator + - child_base.intrinsic_inline_sizes.preferred_inline_size; - } + right_float_width_accumulator = right_float_width_accumulator + child_base + .intrinsic_inline_sizes + .preferred_inline_size; + }, } } @@ -1662,37 +1961,50 @@ impl BlockFlow { right_float_width = max(right_float_width, right_float_width_accumulator); computation.content_intrinsic_sizes.preferred_inline_size = - computation.content_intrinsic_sizes.preferred_inline_size + left_float_width + - right_float_width; - computation.content_intrinsic_sizes.preferred_inline_size = - max(computation.content_intrinsic_sizes.preferred_inline_size, - preferred_inline_size_of_children_without_text_or_replaced_fragments); + computation.content_intrinsic_sizes.preferred_inline_size + + left_float_width + + right_float_width; + computation.content_intrinsic_sizes.preferred_inline_size = max( + computation.content_intrinsic_sizes.preferred_inline_size, + preferred_inline_size_of_children_without_text_or_replaced_fragments, + ); self.base.intrinsic_inline_sizes = computation.finish(); self.base.flags = flags } pub fn overflow_style_may_require_clip_scroll_node(&self) -> bool { - match (self.fragment.style().get_box().overflow_x, - self.fragment.style().get_box().overflow_y) { - (StyleOverflow::Auto, _) | (StyleOverflow::Scroll, _) | (StyleOverflow::Hidden, _) | - (_, StyleOverflow::Auto) | (_, StyleOverflow::Scroll) | (_, StyleOverflow::Hidden) => - true, + match ( + self.fragment.style().get_box().overflow_x, + self.fragment.style().get_box().overflow_y, + ) { + (StyleOverflow::Auto, _) | + (StyleOverflow::Scroll, _) | + (StyleOverflow::Hidden, _) | + (_, StyleOverflow::Auto) | + (_, StyleOverflow::Scroll) | + (_, StyleOverflow::Hidden) => true, (_, _) => false, } } pub fn compute_inline_sizes(&mut self, shared_context: &SharedStyleContext) { - if !self.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) { - return + if !self + .base + .restyle_damage + .intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) + { + return; } - debug!("assign_inline_sizes({}): assigning inline_size for flow", - if self.base.flags.is_float() { - "float" - } else { - "block" - }); + debug!( + "assign_inline_sizes({}): assigning inline_size for flow", + if self.base.flags.is_float() { + "float" + } else { + "block" + } + ); self.base.floats = Floats::new(self.base.writing_mode); @@ -1712,8 +2024,9 @@ impl BlockFlow { if self.is_root() { debug!("Setting root position"); self.base.position.start = LogicalPoint::zero(self.base.writing_mode); - self.base.block_container_inline_size = LogicalSize::from_physical( - self.base.writing_mode, shared_context.viewport_size()).inline; + self.base.block_container_inline_size = + LogicalSize::from_physical(self.base.writing_mode, shared_context.viewport_size()) + .inline; self.base.block_container_writing_mode = self.base.writing_mode; } } @@ -1721,14 +2034,14 @@ impl BlockFlow { fn guess_inline_size_for_block_formatting_context_if_necessary(&mut self) { // We don't need to guess anything unless this is a block formatting context. if self.formatting_context_type() != FormattingContextType::Block { - return + return; } // If `max-width` is set, then don't perform this speculation. We guess that the // page set `max-width` in order to avoid hitting floats. The search box on Google // SERPs falls into this category. if self.fragment.style.max_inline_size() != LengthOrPercentageOrNone::None { - return + return; } // At this point, we know we can't precisely compute the inline-size of this block now, @@ -1736,39 +2049,51 @@ impl BlockFlow { // inline-size computed above minus the inline-size of the previous left and/or right // floats. let speculated_left_float_size = if self.fragment.margin.inline_start >= Au(0) && - self.base.speculated_float_placement_in.left > self.fragment.margin.inline_start { + self.base.speculated_float_placement_in.left > self.fragment.margin.inline_start + { self.base.speculated_float_placement_in.left - self.fragment.margin.inline_start } else { Au(0) }; let speculated_right_float_size = if self.fragment.margin.inline_end >= Au(0) && - self.base.speculated_float_placement_in.right > self.fragment.margin.inline_end { + self.base.speculated_float_placement_in.right > self.fragment.margin.inline_end + { self.base.speculated_float_placement_in.right - self.fragment.margin.inline_end } else { Au(0) }; self.fragment.border_box.size.inline = self.fragment.border_box.size.inline - - speculated_left_float_size - speculated_right_float_size + speculated_left_float_size - + speculated_right_float_size } fn definitely_has_zero_block_size(&self) -> bool { - if !self.fragment.style.content_block_size().is_definitely_zero() { - return false + if !self + .fragment + .style + .content_block_size() + .is_definitely_zero() + { + return false; } let border_width = self.fragment.border_width(); if border_width.block_start != Au(0) || border_width.block_end != Au(0) { - return false + return false; } let padding = self.fragment.style.logical_padding(); padding.block_start.is_definitely_zero() && padding.block_end.is_definitely_zero() } pub fn is_inline_flex_item(&self) -> bool { - self.fragment.flags.contains(FragmentFlags::IS_INLINE_FLEX_ITEM) + self.fragment + .flags + .contains(FragmentFlags::IS_INLINE_FLEX_ITEM) } pub fn is_block_flex_item(&self) -> bool { - self.fragment.flags.contains(FragmentFlags::IS_BLOCK_FLEX_ITEM) + self.fragment + .flags + .contains(FragmentFlags::IS_BLOCK_FLEX_ITEM) } pub fn mark_scrolling_overflow(&mut self, has_scrolling_overflow: bool) { @@ -1785,22 +2110,30 @@ impl BlockFlow { // Return offset from original position because of `position: sticky`. pub fn sticky_position(&self) -> SideOffsets2D<MaybeAuto> { - let containing_block_size = &self.base.early_absolute_position_info - .relative_containing_block_size; - let writing_mode = self.base.early_absolute_position_info.relative_containing_block_mode; + let containing_block_size = &self + .base + .early_absolute_position_info + .relative_containing_block_size; + let writing_mode = self + .base + .early_absolute_position_info + .relative_containing_block_mode; let offsets = self.fragment.style().logical_position(); - let as_margins = LogicalMargin::new(writing_mode, + let as_margins = LogicalMargin::new( + writing_mode, MaybeAuto::from_style(offsets.block_start, containing_block_size.inline), MaybeAuto::from_style(offsets.inline_end, containing_block_size.inline), MaybeAuto::from_style(offsets.block_end, containing_block_size.inline), - MaybeAuto::from_style(offsets.inline_start, containing_block_size.inline)); + MaybeAuto::from_style(offsets.inline_start, containing_block_size.inline), + ); as_margins.to_physical(writing_mode) } pub fn background_border_section(&self) -> DisplayListSection { if self.base.flags.is_float() { DisplayListSection::BackgroundAndBorders - } else if self.base + } else if self + .base .flags .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { @@ -1842,7 +2175,9 @@ impl Flow for BlockFlow { _ => true, }; self.bubble_inline_sizes_for_block(consult_children); - self.fragment.restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES); + self.fragment + .restyle_damage + .remove(ServoRestyleDamage::BUBBLE_ISIZES); } /// Recursively (top-down) determines the actual inline-size of child contexts and fragments. @@ -1857,23 +2192,24 @@ impl Flow for BlockFlow { self.compute_inline_sizes(shared_context); // Move in from the inline-start border edge. - let inline_start_content_edge = self.fragment.border_box.start.i + - self.fragment.border_padding.inline_start; + let inline_start_content_edge = + self.fragment.border_box.start.i + self.fragment.border_padding.inline_start; let padding_and_borders = self.fragment.border_padding.inline_start_end(); // Distance from the inline-end margin edge to the inline-end content edge. let inline_end_content_edge = - self.fragment.margin.inline_end + - self.fragment.border_padding.inline_end; + self.fragment.margin.inline_end + self.fragment.border_padding.inline_end; let content_inline_size = self.fragment.border_box.size.inline - padding_and_borders; - self.propagate_assigned_inline_size_to_children(shared_context, - inline_start_content_edge, - inline_end_content_edge, - content_inline_size, - |_, _, _, _, _, _| {}); + self.propagate_assigned_inline_size_to_children( + shared_context, + inline_start_content_edge, + inline_end_content_edge, + content_inline_size, + |_, _, _, _, _, _| {}, + ); } fn place_float_if_applicable<'a>(&mut self) { @@ -1882,29 +2218,38 @@ impl Flow for BlockFlow { } } - fn assign_block_size_for_inorder_child_if_necessary(&mut self, - layout_context: &LayoutContext, - parent_thread_id: u8, - content_box: LogicalRect<Au>) - -> bool { + fn assign_block_size_for_inorder_child_if_necessary( + &mut self, + layout_context: &LayoutContext, + parent_thread_id: u8, + content_box: LogicalRect<Au>, + ) -> bool { if self.base.flags.is_float() { - return false + return false; } let is_formatting_context = self.formatting_context_type() != FormattingContextType::None; - if !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && is_formatting_context { + if !self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && + is_formatting_context + { self.assign_inline_position_for_formatting_context(layout_context, content_box); } if (self as &Flow).floats_might_flow_through() { self.base.thread_id = parent_thread_id; - if self.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | - ServoRestyleDamage::REFLOW) { + if self + .base + .restyle_damage + .intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) + { self.assign_block_size(layout_context); // Don't remove the restyle damage; `assign_block_size` decides whether that is // appropriate (which in the case of e.g. absolutely-positioned flows, it is not). } - return true + return true; } if is_formatting_context { @@ -1912,8 +2257,10 @@ impl Flow for BlockFlow { // translate the floats past us. let writing_mode = self.base.floats.writing_mode; let delta = self.base.position.size.block; - self.base.floats.translate(LogicalSize::new(writing_mode, Au(0), -delta)); - return true + self.base + .floats + .translate(LogicalSize::new(writing_mode, Au(0), -delta)); + return true; } false @@ -1924,47 +2271,68 @@ impl Flow for BlockFlow { debug_assert!(remaining.is_none()); } - fn fragment(&mut self, layout_context: &LayoutContext, - fragmentation_context: Option<FragmentationContext>) - -> Option<Arc<Flow>> { + fn fragment( + &mut self, + layout_context: &LayoutContext, + fragmentation_context: Option<FragmentationContext>, + ) -> Option<Arc<Flow>> { if self.fragment.is_replaced() { - let _scope = layout_debug_scope!("assign_replaced_block_size_if_necessary {:x}", - self.base.debug_id()); + 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. self.fragment.assign_replaced_block_size_if_necessary(); - if !self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if !self + .base + .flags + .contains(FlowFlags::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 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); + self.base.collapsible_margins = + CollapsibleMargins::CollapseThrough(block_start); } else { - self.base.collapsible_margins = CollapsibleMargins::Collapse(block_start, block_end); + self.base.collapsible_margins = + CollapsibleMargins::Collapse(block_start, block_end); } - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); - self.fragment.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | - ServoRestyleDamage::REFLOW); + self.base + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.fragment + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); } None } else if self.is_root() || - self.formatting_context_type() != FormattingContextType::None || - self.base.flags.contains(FlowFlags::MARGINS_CANNOT_COLLAPSE) { + self.formatting_context_type() != FormattingContextType::None || + self.base.flags.contains(FlowFlags::MARGINS_CANNOT_COLLAPSE) + { // Root element margins should never be collapsed according to CSS § 8.3.1. - debug!("assign_block_size: assigning block_size for root flow {:?}", - self.base().debug_id()); + debug!( + "assign_block_size: assigning block_size for root flow {:?}", + self.base().debug_id() + ); self.assign_block_size_block_base( layout_context, fragmentation_context, - MarginsMayCollapseFlag::MarginsMayNotCollapse) + MarginsMayCollapseFlag::MarginsMayNotCollapse, + ) } else { - debug!("assign_block_size: assigning block_size for block {:?}", - self.base().debug_id()); + debug!( + "assign_block_size: assigning block_size for block {:?}", + self.base().debug_id() + ); self.assign_block_size_block_base( layout_context, fragmentation_context, - MarginsMayCollapseFlag::MarginsMayCollapse) + MarginsMayCollapseFlag::MarginsMayCollapse, + ) } } @@ -1977,9 +2345,16 @@ impl Flow for BlockFlow { self.base.clip = Rect::max_rect(); } - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - let position_start = self.base.position.start.to_physical(self.base.writing_mode, - container_size); + if self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { + let position_start = self + .base + .position + .start + .to_physical(self.base.writing_mode, container_size); // Compute our position relative to the nearest ancestor stacking context. This will be // passed down later as part of containing block details for absolute descendants. @@ -1991,21 +2366,38 @@ impl Flow for BlockFlow { // flow w.r.t. the containing block. self.base .late_absolute_position_info - .stacking_relative_position_of_absolute_containing_block + position_start.to_vector() + .stacking_relative_position_of_absolute_containing_block + + position_start.to_vector() }; if !self.base.writing_mode.is_vertical() { - if !self.base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { + if !self + .base + .flags + .contains(FlowFlags::INLINE_POSITION_IS_STATIC) + { self.base.stacking_relative_position.x = absolute_stacking_relative_position.x } - if !self.base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { + if !self + .base + .flags + .contains(FlowFlags::BLOCK_POSITION_IS_STATIC) + { self.base.stacking_relative_position.y = absolute_stacking_relative_position.y } } else { - if !self.base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { + if !self + .base + .flags + .contains(FlowFlags::INLINE_POSITION_IS_STATIC) + { self.base.stacking_relative_position.y = absolute_stacking_relative_position.y } - if !self.base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { + if !self + .base + .flags + .contains(FlowFlags::BLOCK_POSITION_IS_STATIC) + { self.base.stacking_relative_position.x = absolute_stacking_relative_position.x } } @@ -2014,28 +2406,33 @@ impl Flow for BlockFlow { // For relatively-positioned descendants, the containing block formed by a block is just // the content box. The containing block for absolutely-positioned descendants, on the // other hand, is established in other circumstances (see `is_absolute_containing_block'). - let relative_offset = - self.fragment.relative_position(&self.base - .early_absolute_position_info - .relative_containing_block_size); + let relative_offset = self.fragment.relative_position( + &self + .base + .early_absolute_position_info + .relative_containing_block_size, + ); if self.is_absolute_containing_block() { - let border_box_origin = (self.fragment.border_box - - self.fragment.style.logical_border_width()).start; + let border_box_origin = + (self.fragment.border_box - self.fragment.style.logical_border_width()).start; self.base .late_absolute_position_info .stacking_relative_position_of_absolute_containing_block = - self.base.stacking_relative_position.to_point() + - (border_box_origin + relative_offset).to_physical(self.base.writing_mode, - container_size).to_vector() + self.base.stacking_relative_position.to_point() + + (border_box_origin + relative_offset) + .to_physical(self.base.writing_mode, container_size) + .to_vector() } // Compute absolute position info for children. let stacking_relative_position_of_absolute_containing_block_for_children = if self.fragment.establishes_stacking_context() { let logical_border_width = self.fragment.style().logical_border_width(); - let position = LogicalPoint::new(self.base.writing_mode, - logical_border_width.inline_start, - logical_border_width.block_start); + let position = LogicalPoint::new( + self.base.writing_mode, + logical_border_width.inline_start, + logical_border_width.block_start, + ); let position = position.to_physical(self.base.writing_mode, container_size); // Some blocks establish a stacking context, but not a containing block for @@ -2061,7 +2458,9 @@ impl Flow for BlockFlow { self.base.position.size.to_physical(self.base.writing_mode); // Compute the origin and clipping rectangle for children. - let relative_offset = relative_offset.to_physical(self.base.writing_mode).to_vector(); + let relative_offset = relative_offset + .to_physical(self.base.writing_mode) + .to_vector(); let is_stacking_context = self.fragment.establishes_stacking_context(); let origin_for_children = if is_stacking_context { // We establish a stacking context, so the position of our children is vertically @@ -2078,36 +2477,48 @@ impl Flow for BlockFlow { // Process children. for kid in self.base.child_iter_mut() { - if kid.base().flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) || - kid.base().flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { + if kid + .base() + .flags + .contains(FlowFlags::INLINE_POSITION_IS_STATIC) || + kid.base() + .flags + .contains(FlowFlags::BLOCK_POSITION_IS_STATIC) + { let kid_base = kid.mut_base(); - let physical_position = kid_base.position.to_physical(kid_base.writing_mode, - container_size_for_children); + let physical_position = kid_base + .position + .to_physical(kid_base.writing_mode, container_size_for_children); // Set the inline and block positions as necessary. if !kid_base.writing_mode.is_vertical() { - if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { - kid_base.stacking_relative_position.x = origin_for_children.x + - physical_position.origin.x + if kid_base + .flags + .contains(FlowFlags::INLINE_POSITION_IS_STATIC) + { + kid_base.stacking_relative_position.x = + origin_for_children.x + physical_position.origin.x } if kid_base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - kid_base.stacking_relative_position.y = origin_for_children.y + - physical_position.origin.y + kid_base.stacking_relative_position.y = + origin_for_children.y + physical_position.origin.y } } else { - if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { - kid_base.stacking_relative_position.y = origin_for_children.y + - physical_position.origin.y + if kid_base + .flags + .contains(FlowFlags::INLINE_POSITION_IS_STATIC) + { + kid_base.stacking_relative_position.y = + origin_for_children.y + physical_position.origin.y } if kid_base.flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - kid_base.stacking_relative_position.x = origin_for_children.x + - physical_position.origin.x + kid_base.stacking_relative_position.x = + origin_for_children.x + physical_position.origin.x } } } - kid.mut_base().late_absolute_position_info = - late_absolute_position_info_for_children; + kid.mut_base().late_absolute_position_info = late_absolute_position_info_for_children; } } @@ -2132,8 +2543,9 @@ impl Flow for BlockFlow { /// Returns true if this flow contains fragments that are roots of an absolute flow tree. fn contains_roots_of_absolute_flow_tree(&self) -> bool { - self.contains_relatively_positioned_fragments() || self.is_root() || - self.fragment.has_filter_transform_or_perspective() + self.contains_relatively_positioned_fragments() || + self.is_root() || + self.fragment.has_filter_transform_or_perspective() } /// Returns true if this is an absolute containing block. @@ -2142,21 +2554,27 @@ impl Flow for BlockFlow { } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.fragment.style().logical_position().inline_start == - LengthOrPercentageOrAuto::Auto && - self.fragment.style().logical_position().inline_end == - LengthOrPercentageOrAuto::Auto { + if self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && + self.fragment.style().logical_position().inline_start == + LengthOrPercentageOrAuto::Auto && + self.fragment.style().logical_position().inline_end == LengthOrPercentageOrAuto::Auto + { self.base.position.start.i = inline_position } } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - if self.base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.fragment.style().logical_position().block_start == - LengthOrPercentageOrAuto::Auto && - self.fragment.style().logical_position().block_end == - LengthOrPercentageOrAuto::Auto { + if self + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && + self.fragment.style().logical_position().block_start == + LengthOrPercentageOrAuto::Auto && + self.fragment.style().logical_position().block_end == LengthOrPercentageOrAuto::Auto + { self.base.position.start.b = block_position } } @@ -2175,33 +2593,43 @@ impl Flow for BlockFlow { fn compute_overflow(&self) -> Overflow { let flow_size = self.base.position.size.to_physical(self.base.writing_mode); - let overflow = self.fragment.compute_overflow(&flow_size, - &self.base - .early_absolute_position_info - .relative_containing_block_size); + let overflow = self.fragment.compute_overflow( + &flow_size, + &self + .base + .early_absolute_position_info + .relative_containing_block_size, + ); overflow } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { if !iterator.should_process(&self.fragment) { - return + return; } - iterator.process(&self.fragment, - level, - &self.fragment - .stacking_relative_border_box(&self.base.stacking_relative_position, - &self.base - .early_absolute_position_info - .relative_containing_block_size, - self.base - .early_absolute_position_info - .relative_containing_block_mode, - CoordinateSystem::Own) - .translate(&stacking_context_position.to_vector())); + iterator.process( + &self.fragment, + level, + &self + .fragment + .stacking_relative_border_box( + &self.base.stacking_relative_position, + &self + .base + .early_absolute_position_info + .relative_containing_block_size, + self.base + .early_absolute_position_info + .relative_containing_block_mode, + CoordinateSystem::Own, + ).translate(&stacking_context_position.to_vector()), + ); } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { @@ -2215,11 +2643,13 @@ impl Flow for BlockFlow { impl fmt::Debug for BlockFlow { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "{:?}({:x}) {:?}", - self.class(), - self.base.debug_id(), - self.base) + write!( + f, + "{:?}({:x}) {:?}", + self.class(), + self.base.debug_id(), + self.base + ) } } @@ -2236,14 +2666,15 @@ pub struct ISizeConstraintInput { } impl ISizeConstraintInput { - pub fn new(computed_inline_size: MaybeAuto, - inline_start_margin: MaybeAuto, - inline_end_margin: MaybeAuto, - inline_start: MaybeAuto, - inline_end: MaybeAuto, - text_align: TextAlign, - available_inline_size: Au) - -> ISizeConstraintInput { + pub fn new( + computed_inline_size: MaybeAuto, + inline_start_margin: MaybeAuto, + inline_end_margin: MaybeAuto, + inline_start: MaybeAuto, + inline_end: MaybeAuto, + text_align: TextAlign, + available_inline_size: Au, + ) -> ISizeConstraintInput { ISizeConstraintInput { computed_inline_size: computed_inline_size, inline_start_margin: inline_start_margin, @@ -2262,12 +2693,15 @@ pub struct ISizeConstraintSolution { pub inline_start: Au, pub inline_size: Au, pub margin_inline_start: Au, - pub margin_inline_end: Au + pub margin_inline_end: Au, } impl ISizeConstraintSolution { - pub fn new(inline_size: Au, margin_inline_start: Au, margin_inline_end: Au) - -> ISizeConstraintSolution { + pub fn new( + inline_size: Au, + margin_inline_start: Au, + margin_inline_end: Au, + ) -> ISizeConstraintSolution { ISizeConstraintSolution { inline_start: Au(0), inline_size: inline_size, @@ -2276,11 +2710,12 @@ impl ISizeConstraintSolution { } } - fn for_absolute_flow(inline_start: Au, - inline_size: Au, - margin_inline_start: Au, - margin_inline_end: Au) - -> ISizeConstraintSolution { + fn for_absolute_flow( + inline_start: Au, + inline_size: Au, + margin_inline_start: Au, + margin_inline_end: Au, + ) -> ISizeConstraintSolution { ISizeConstraintSolution { inline_start: inline_start, inline_size: inline_size, @@ -2296,54 +2731,57 @@ impl ISizeConstraintSolution { pub trait ISizeAndMarginsComputer { /// Instructs the fragment to compute its border and padding. fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) { - block.fragment.compute_border_and_padding(containing_block_inline_size); + block + .fragment + .compute_border_and_padding(containing_block_inline_size); } /// Compute the inputs for the ISize constraint equation. /// /// This is called only once to compute the initial inputs. For calculations involving /// minimum and maximum inline-size, we don't need to recompute these. - fn compute_inline_size_constraint_inputs(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> ISizeConstraintInput { + fn compute_inline_size_constraint_inputs( + &self, + block: &mut BlockFlow, + parent_flow_inline_size: Au, + shared_context: &SharedStyleContext, + ) -> ISizeConstraintInput { let containing_block_inline_size = self.containing_block_inline_size(block, parent_flow_inline_size, shared_context); - block.fragment.compute_block_direction_margins(containing_block_inline_size); - block.fragment.compute_inline_direction_margins(containing_block_inline_size); + block + .fragment + .compute_block_direction_margins(containing_block_inline_size); + block + .fragment + .compute_inline_direction_margins(containing_block_inline_size); self.compute_border_and_padding(block, containing_block_inline_size); - let mut computed_inline_size = self.initial_computed_inline_size(block, - parent_flow_inline_size, - shared_context); + let mut computed_inline_size = + self.initial_computed_inline_size(block, parent_flow_inline_size, shared_context); let style = block.fragment.style(); match (computed_inline_size, style.get_position().box_sizing) { (MaybeAuto::Specified(size), BoxSizing::BorderBox) => { computed_inline_size = MaybeAuto::Specified(size - block.fragment.border_padding.inline_start_end()) - } - (MaybeAuto::Auto, BoxSizing::BorderBox) | - (_, BoxSizing::ContentBox) => {} + }, + (MaybeAuto::Auto, BoxSizing::BorderBox) | (_, BoxSizing::ContentBox) => {}, } let margin = style.logical_margin(); let position = style.logical_position(); - let available_inline_size = containing_block_inline_size - - block.fragment.border_padding.inline_start_end(); - ISizeConstraintInput::new(computed_inline_size, - MaybeAuto::from_style(margin.inline_start, - containing_block_inline_size), - MaybeAuto::from_style(margin.inline_end, - containing_block_inline_size), - MaybeAuto::from_style(position.inline_start, - containing_block_inline_size), - MaybeAuto::from_style(position.inline_end, - containing_block_inline_size), - style.get_inherited_text().text_align, - available_inline_size) + let available_inline_size = + containing_block_inline_size - block.fragment.border_padding.inline_start_end(); + ISizeConstraintInput::new( + computed_inline_size, + MaybeAuto::from_style(margin.inline_start, containing_block_inline_size), + MaybeAuto::from_style(margin.inline_end, containing_block_inline_size), + MaybeAuto::from_style(position.inline_start, containing_block_inline_size), + MaybeAuto::from_style(position.inline_end, containing_block_inline_size), + style.get_inherited_text().text_align, + available_inline_size, + ) } /// Set the used values for inline-size and margins from the relevant constraint equation. @@ -2355,9 +2793,11 @@ pub trait ISizeAndMarginsComputer { /// * Inline-start coordinate of this flow's box; /// * Inline-start coordinate of the flow with respect to its containing block (if this is an /// absolute flow). - fn set_inline_size_constraint_solutions(&self, - block: &mut BlockFlow, - solution: ISizeConstraintSolution) { + fn set_inline_size_constraint_solutions( + &self, + block: &mut BlockFlow, + solution: ISizeConstraintSolution, + ) { let inline_size; let extra_inline_size_from_margin; { @@ -2388,8 +2828,8 @@ pub trait ISizeAndMarginsComputer { // To calculate the total size of this block, we also need to account for any // additional size contribution from positive margins. Negative margins means the block // isn't made larger at all by the margin. - extra_inline_size_from_margin = max(Au(0), fragment.margin.inline_start) + - max(Au(0), fragment.margin.inline_end); + extra_inline_size_from_margin = + max(Au(0), fragment.margin.inline_start) + max(Au(0), fragment.margin.inline_end); } // We also resize the block itself, to ensure that overflow is not calculated @@ -2399,45 +2839,55 @@ pub trait ISizeAndMarginsComputer { } /// Set the inline coordinate of the given flow if it is absolutely positioned. - fn set_inline_position_of_flow_if_necessary(&self, - _: &mut BlockFlow, - _: ISizeConstraintSolution) {} + fn set_inline_position_of_flow_if_necessary( + &self, + _: &mut BlockFlow, + _: ISizeConstraintSolution, + ) { + } /// Solve the inline-size and margins constraints for this block flow. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution; - - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { - MaybeAuto::from_style(block.fragment().style().content_inline_size(), - self.containing_block_inline_size(block, - parent_flow_inline_size, - shared_context)) - } - - fn containing_block_inline_size(&self, - _: &mut BlockFlow, - parent_flow_inline_size: Au, - _: &SharedStyleContext) - -> Au { + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution; + + fn initial_computed_inline_size( + &self, + block: &mut BlockFlow, + parent_flow_inline_size: Au, + shared_context: &SharedStyleContext, + ) -> MaybeAuto { + MaybeAuto::from_style( + block.fragment().style().content_inline_size(), + self.containing_block_inline_size(block, parent_flow_inline_size, shared_context), + ) + } + + fn containing_block_inline_size( + &self, + _: &mut BlockFlow, + parent_flow_inline_size: Au, + _: &SharedStyleContext, + ) -> Au { parent_flow_inline_size } /// Compute the used value of inline-size, taking care of min-inline-size and max-inline-size. /// /// CSS Section 10.4: Minimum and Maximum inline-sizes - fn compute_used_inline_size(&self, - block: &mut BlockFlow, - shared_context: &SharedStyleContext, - parent_flow_inline_size: Au) { - let mut input = self.compute_inline_size_constraint_inputs(block, - parent_flow_inline_size, - shared_context); + fn compute_used_inline_size( + &self, + block: &mut BlockFlow, + shared_context: &SharedStyleContext, + parent_flow_inline_size: Au, + ) { + let mut input = self.compute_inline_size_constraint_inputs( + block, + parent_flow_inline_size, + shared_context, + ); let containing_block_inline_size = self.containing_block_inline_size(block, parent_flow_inline_size, shared_context); @@ -2447,19 +2897,27 @@ pub trait ISizeAndMarginsComputer { // If the tentative used inline-size is greater than 'max-inline-size', inline-size should // be recalculated, but this time using the computed value of 'max-inline-size' as the // computed value for 'inline-size'. - match block.fragment().style().max_inline_size().to_used_value(containing_block_inline_size) { + match block + .fragment() + .style() + .max_inline_size() + .to_used_value(containing_block_inline_size) + { Some(max_inline_size) if max_inline_size < solution.inline_size => { input.computed_inline_size = MaybeAuto::Specified(max_inline_size); solution = self.solve_inline_size_constraints(block, &input); - } - _ => {} + }, + _ => {}, } // If the resulting inline-size is smaller than 'min-inline-size', inline-size should be // recalculated, but this time using the value of 'min-inline-size' as the computed value // for 'inline-size'. - let computed_min_inline_size = - block.fragment().style().min_inline_size().to_used_value(containing_block_inline_size); + let computed_min_inline_size = block + .fragment() + .style() + .min_inline_size() + .to_used_value(containing_block_inline_size); if computed_min_inline_size > solution.inline_size { input.computed_inline_size = MaybeAuto::Specified(computed_min_inline_size); solution = self.solve_inline_size_constraints(block, &input); @@ -2477,15 +2935,17 @@ pub trait ISizeAndMarginsComputer { /// Constraint Equation: margin-inline-start + margin-inline-end + inline-size = /// available_inline-size /// where available_inline-size = CB inline-size - (horizontal border + padding) - fn solve_block_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) = - (input.computed_inline_size, - input.inline_start_margin, - input.inline_end_margin, - input.available_inline_size); + fn solve_block_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { + let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) = ( + input.computed_inline_size, + input.inline_start_margin, + input.inline_end_margin, + input.available_inline_size, + ); // Check for direction of parent flow (NOT Containing Block) let block_mode = block.base.writing_mode; @@ -2504,11 +2964,14 @@ pub trait ISizeAndMarginsComputer { let inline_end = inline_end_margin.specified_or_zero(); if (inline_start + inline_end + inline_size) > available_inline_size { - (MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end)) + ( + MaybeAuto::Specified(inline_start), + MaybeAuto::Specified(inline_end), + ) } else { (inline_start_margin, inline_end_margin) } - } + }, }; // Invariant: inline-start_margin + inline-size + inline-end_margin == @@ -2516,9 +2979,11 @@ pub trait ISizeAndMarginsComputer { let (inline_start_margin, inline_size, inline_end_margin) = match (inline_start_margin, computed_inline_size, inline_end_margin) { // If all have a computed value other than 'auto', the system is over-constrained. - (MaybeAuto::Specified(margin_start), - MaybeAuto::Specified(inline_size), - MaybeAuto::Specified(margin_end)) => { + ( + MaybeAuto::Specified(margin_start), + MaybeAuto::Specified(inline_size), + MaybeAuto::Specified(margin_end), + ) => { // servo_left, servo_right, and servo_center are used to implement // the "align descendants" rule in HTML5 § 14.2. if block_align == TextAlign::ServoCenter { @@ -2533,52 +2998,66 @@ pub trait ISizeAndMarginsComputer { _ => parent_has_same_direction, }; if ignore_end_margin { - (margin_start, inline_size, available_inline_size - - (margin_start + inline_size)) + ( + margin_start, + inline_size, + available_inline_size - (margin_start + inline_size), + ) } else { - (available_inline_size - (margin_end + inline_size), - inline_size, - margin_end) + ( + available_inline_size - (margin_end + inline_size), + inline_size, + margin_end, + ) } } - } + }, // If exactly one value is 'auto', solve for it - (MaybeAuto::Auto, - MaybeAuto::Specified(inline_size), - MaybeAuto::Specified(margin_end)) => - (available_inline_size - (inline_size + margin_end), inline_size, margin_end), - (MaybeAuto::Specified(margin_start), - MaybeAuto::Auto, - MaybeAuto::Specified(margin_end)) => { - (margin_start, - available_inline_size - (margin_start + margin_end), - margin_end) - } - (MaybeAuto::Specified(margin_start), - MaybeAuto::Specified(inline_size), - MaybeAuto::Auto) => { - (margin_start, - inline_size, - available_inline_size - (margin_start + inline_size)) - } + ( + MaybeAuto::Auto, + MaybeAuto::Specified(inline_size), + MaybeAuto::Specified(margin_end), + ) => ( + available_inline_size - (inline_size + margin_end), + inline_size, + margin_end, + ), + ( + MaybeAuto::Specified(margin_start), + MaybeAuto::Auto, + MaybeAuto::Specified(margin_end), + ) => ( + margin_start, + available_inline_size - (margin_start + margin_end), + margin_end, + ), + ( + MaybeAuto::Specified(margin_start), + MaybeAuto::Specified(inline_size), + MaybeAuto::Auto, + ) => ( + margin_start, + inline_size, + available_inline_size - (margin_start + inline_size), + ), // If inline-size is set to 'auto', any other 'auto' value becomes '0', // and inline-size is solved for (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => { (Au(0), available_inline_size - margin_end, margin_end) - } + }, (MaybeAuto::Specified(margin_start), MaybeAuto::Auto, MaybeAuto::Auto) => { (margin_start, available_inline_size - margin_start, Au(0)) - } + }, (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { (Au(0), available_inline_size, Au(0)) - } + }, // If inline-start and inline-end margins are auto, they become equal (MaybeAuto::Auto, MaybeAuto::Specified(inline_size), MaybeAuto::Auto) => { let margin = (available_inline_size - inline_size).scale_by(0.5); (margin, inline_size, margin) - } + }, }; ISizeConstraintSolution::new(inline_size, inline_start_margin, inline_end_margin) @@ -2609,10 +3088,11 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { /// [aka available inline-size] /// /// Return the solution for the equation. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { let &ISizeConstraintInput { computed_inline_size, inline_start_margin, @@ -2639,14 +3119,16 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { // and inline-size Auto. // Set inline-end to zero to calculate inline-size. - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); (Au(0), inline_size, margin_start, margin_end) - } - (MaybeAuto::Specified(inline_start), - MaybeAuto::Specified(inline_end), - MaybeAuto::Specified(inline_size)) => { + }, + ( + MaybeAuto::Specified(inline_start), + MaybeAuto::Specified(inline_end), + MaybeAuto::Specified(inline_size), + ) => { match (inline_start_margin, inline_end_margin) { (MaybeAuto::Auto, MaybeAuto::Auto) => { let total_margin_val = @@ -2662,20 +3144,32 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { } } else { // Equal margins - (inline_start, - inline_size, - total_margin_val.scale_by(0.5), - total_margin_val.scale_by(0.5)) + ( + inline_start, + inline_size, + total_margin_val.scale_by(0.5), + total_margin_val.scale_by(0.5), + ) } - } + }, (MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => { let sum = inline_start + inline_end + inline_size + margin_start; - (inline_start, inline_size, margin_start, available_inline_size - sum) - } + ( + inline_start, + inline_size, + margin_start, + available_inline_size - sum, + ) + }, (MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => { let sum = inline_start + inline_end + inline_size + margin_end; - (inline_start, inline_size, available_inline_size - sum, margin_end) - } + ( + inline_start, + inline_size, + available_inline_size - sum, + margin_end, + ) + }, (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => { // Values are over-constrained. let sum = inline_start + inline_size + margin_start + margin_end; @@ -2684,40 +3178,58 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { (inline_start, inline_size, margin_start, margin_end) } else { // Ignore value for 'inline-start' - (available_inline_size - sum, - inline_size, - margin_start, - margin_end) + ( + available_inline_size - sum, + inline_size, + margin_start, + margin_end, + ) } - } + }, } - } + }, // For the rest of the cases, auto values for margin are set to 0 // If only one is Auto, solve for it - (MaybeAuto::Auto, - MaybeAuto::Specified(inline_end), - MaybeAuto::Specified(inline_size)) => { + ( + MaybeAuto::Auto, + MaybeAuto::Specified(inline_end), + MaybeAuto::Specified(inline_size), + ) => { let margin_start = inline_start_margin.specified_or_zero(); let margin_end = inline_end_margin.specified_or_zero(); let sum = inline_end + inline_size + margin_start + margin_end; - (available_inline_size - sum, inline_size, margin_start, margin_end) - } - (MaybeAuto::Specified(inline_start), - MaybeAuto::Auto, - MaybeAuto::Specified(inline_size)) => { + ( + available_inline_size - sum, + inline_size, + margin_start, + margin_end, + ) + }, + ( + MaybeAuto::Specified(inline_start), + MaybeAuto::Auto, + MaybeAuto::Specified(inline_size), + ) => { let margin_start = inline_start_margin.specified_or_zero(); let margin_end = inline_end_margin.specified_or_zero(); (inline_start, inline_size, margin_start, margin_end) - } - (MaybeAuto::Specified(inline_start), - MaybeAuto::Specified(inline_end), - MaybeAuto::Auto) => { + }, + ( + MaybeAuto::Specified(inline_start), + MaybeAuto::Specified(inline_end), + MaybeAuto::Auto, + ) => { let margin_start = inline_start_margin.specified_or_zero(); let margin_end = inline_end_margin.specified_or_zero(); let sum = inline_start + inline_end + margin_start + margin_end; - (inline_start, available_inline_size - sum, margin_start, margin_end) - } + ( + inline_start, + available_inline_size - sum, + margin_start, + margin_end, + ) + }, // If inline-size is auto, then inline-size is shrink-to-fit. Solve for the // non-auto value. @@ -2725,21 +3237,26 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { let margin_start = inline_start_margin.specified_or_zero(); let margin_end = inline_end_margin.specified_or_zero(); // Set inline-end to zero to calculate inline-size - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); (inline_start, inline_size, margin_start, margin_end) - } + }, (MaybeAuto::Auto, MaybeAuto::Specified(inline_end), MaybeAuto::Auto) => { let margin_start = inline_start_margin.specified_or_zero(); let margin_end = inline_end_margin.specified_or_zero(); // Set inline-start to zero to calculate inline-size - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); let sum = inline_end + inline_size + margin_start + margin_end; - (available_inline_size - sum, inline_size, margin_start, margin_end) - } + ( + available_inline_size - sum, + inline_size, + margin_start, + margin_end, + ) + }, (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(inline_size)) => { let margin_start = inline_start_margin.specified_or_zero(); @@ -2747,28 +3264,39 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { // Setting 'inline-start' to static position because direction is 'ltr'. // TODO: Handle 'rtl' when it is implemented. (Au(0), inline_size, margin_start, margin_end) - } + }, }; - ISizeConstraintSolution::for_absolute_flow(inline_start, - inline_size, - margin_inline_start, - margin_inline_end) - } - - fn containing_block_inline_size(&self, - block: &mut BlockFlow, - _: Au, - shared_context: &SharedStyleContext) - -> Au { + ISizeConstraintSolution::for_absolute_flow( + inline_start, + inline_size, + margin_inline_start, + margin_inline_end, + ) + } + + fn containing_block_inline_size( + &self, + block: &mut BlockFlow, + _: Au, + shared_context: &SharedStyleContext, + ) -> Au { let opaque_block = OpaqueFlow::from_flow(block); - block.containing_block_size(&shared_context.viewport_size(), opaque_block).inline + block + .containing_block_size(&shared_context.viewport_size(), opaque_block) + .inline } - fn set_inline_position_of_flow_if_necessary(&self, - block: &mut BlockFlow, - solution: ISizeConstraintSolution) { + fn set_inline_position_of_flow_if_necessary( + &self, + block: &mut BlockFlow, + solution: ISizeConstraintSolution, + ) { // Set the inline position of the absolute flow wrt to its containing block. - if !block.base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { + if !block + .base + .flags + .contains(FlowFlags::INLINE_POSITION_IS_STATIC) + { block.base.position.start.i = solution.inline_start; } } @@ -2784,8 +3312,11 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced { /// [aka available_inline-size] /// /// Return the solution for the equation. - fn solve_inline_size_constraints(&self, _: &mut BlockFlow, input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + fn solve_inline_size_constraints( + &self, + _: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { let &ISizeConstraintInput { computed_inline_size, inline_start_margin, @@ -2803,9 +3334,11 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced { let inline_size = match computed_inline_size { MaybeAuto::Specified(w) => w, - _ => panic!("{} {}", - "The used value for inline_size for absolute replaced flow", - "should have already been calculated by now.") + _ => panic!( + "{} {}", + "The used value for inline_size for absolute replaced flow", + "should have already been calculated by now." + ), }; let (inline_start, inline_size, margin_inline_start, margin_inline_end) = @@ -2814,86 +3347,115 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced { let margin_start = inline_start_margin.specified_or_zero(); let margin_end = inline_end_margin.specified_or_zero(); (Au(0), inline_size, margin_start, margin_end) - } + }, // If only one is Auto, solve for it (MaybeAuto::Auto, MaybeAuto::Specified(inline_end)) => { let margin_start = inline_start_margin.specified_or_zero(); let margin_end = inline_end_margin.specified_or_zero(); let sum = inline_end + inline_size + margin_start + margin_end; - (available_inline_size - sum, inline_size, margin_start, margin_end) - } + ( + available_inline_size - sum, + inline_size, + margin_start, + margin_end, + ) + }, (MaybeAuto::Specified(inline_start), MaybeAuto::Auto) => { let margin_start = inline_start_margin.specified_or_zero(); let margin_end = inline_end_margin.specified_or_zero(); (inline_start, inline_size, margin_start, margin_end) - } + }, (MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end)) => { match (inline_start_margin, inline_end_margin) { (MaybeAuto::Auto, MaybeAuto::Auto) => { - let total_margin_val = available_inline_size - inline_start - - inline_end - inline_size; + let total_margin_val = + available_inline_size - inline_start - inline_end - inline_size; if total_margin_val < Au(0) { // margin-inline-start becomes 0 because direction is 'ltr'. (inline_start, inline_size, Au(0), total_margin_val) } else { // Equal margins - (inline_start, - inline_size, - total_margin_val.scale_by(0.5), - total_margin_val.scale_by(0.5)) + ( + inline_start, + inline_size, + total_margin_val.scale_by(0.5), + total_margin_val.scale_by(0.5), + ) } - } + }, (MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => { let sum = inline_start + inline_end + inline_size + margin_start; - (inline_start, inline_size, margin_start, available_inline_size - sum) - } + ( + inline_start, + inline_size, + margin_start, + available_inline_size - sum, + ) + }, (MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => { let sum = inline_start + inline_end + inline_size + margin_end; - (inline_start, inline_size, available_inline_size - sum, margin_end) - } + ( + inline_start, + inline_size, + available_inline_size - sum, + margin_end, + ) + }, (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => { // Values are over-constrained. // Ignore value for 'inline-end' cos direction is 'ltr'. (inline_start, inline_size, margin_start, margin_end) - } + }, } - } + }, }; - ISizeConstraintSolution::for_absolute_flow(inline_start, - inline_size, - margin_inline_start, - margin_inline_end) + ISizeConstraintSolution::for_absolute_flow( + inline_start, + inline_size, + margin_inline_start, + margin_inline_end, + ) } /// Calculate used value of inline-size just like we do for inline replaced elements. - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - _: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { + fn initial_computed_inline_size( + &self, + block: &mut BlockFlow, + _: Au, + shared_context: &SharedStyleContext, + ) -> MaybeAuto { let opaque_block = OpaqueFlow::from_flow(block); - let containing_block_inline_size = - block.containing_block_size(&shared_context.viewport_size(), opaque_block).inline; + let containing_block_inline_size = block + .containing_block_size(&shared_context.viewport_size(), opaque_block) + .inline; let container_block_size = block.explicit_block_containing_size(shared_context); let fragment = block.fragment(); - fragment.assign_replaced_inline_size_if_necessary(containing_block_inline_size, container_block_size); + 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_box().size.inline) } - fn containing_block_inline_size(&self, - block: &mut BlockFlow, - _: Au, - shared_context: &SharedStyleContext) - -> Au { + fn containing_block_inline_size( + &self, + block: &mut BlockFlow, + _: Au, + shared_context: &SharedStyleContext, + ) -> Au { let opaque_block = OpaqueFlow::from_flow(block); - block.containing_block_size(&shared_context.viewport_size(), opaque_block).inline + block + .containing_block_size(&shared_context.viewport_size(), opaque_block) + .inline } - fn set_inline_position_of_flow_if_necessary(&self, - block: &mut BlockFlow, - solution: ISizeConstraintSolution) { + fn set_inline_position_of_flow_if_necessary( + &self, + block: &mut BlockFlow, + solution: ISizeConstraintSolution, + ) { // Set the x-coordinate of the absolute flow wrt to its containing block. block.base.position.start.i = solution.inline_start; } @@ -2901,10 +3463,11 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced { impl ISizeAndMarginsComputer for BlockNonReplaced { /// Compute inline-start and inline-end margins and inline-size. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { self.solve_block_inline_size_constraints(block, input) } } @@ -2914,55 +3477,64 @@ impl ISizeAndMarginsComputer for BlockReplaced { /// /// ISize has already been calculated. We now calculate the margins just /// like for non-replaced blocks. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { match input.computed_inline_size { MaybeAuto::Specified(_) => {}, MaybeAuto::Auto => { panic!("BlockReplaced: inline_size should have been computed by now") - } + }, }; self.solve_block_inline_size_constraints(block, input) } /// Calculate used value of inline-size just like we do for inline replaced elements. - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { + fn initial_computed_inline_size( + &self, + block: &mut BlockFlow, + parent_flow_inline_size: Au, + shared_context: &SharedStyleContext, + ) -> MaybeAuto { let container_block_size = block.explicit_block_containing_size(shared_context); let fragment = block.fragment(); - fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, container_block_size); + 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_box().size.inline) } - } impl ISizeAndMarginsComputer for FloatNonReplaced { /// CSS Section 10.3.5 /// /// If inline-size is computed as 'auto', the used value is the 'shrink-to-fit' inline-size. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) = - (input.computed_inline_size, - input.inline_start_margin, - input.inline_end_margin, - input.available_inline_size); + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { + let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) = ( + input.computed_inline_size, + input.inline_start_margin, + input.inline_end_margin, + input.available_inline_size, + ); let margin_inline_start = inline_start_margin.specified_or_zero(); let margin_inline_end = inline_end_margin.specified_or_zero(); - let available_inline_size_float = available_inline_size - margin_inline_start - - margin_inline_end; + let available_inline_size_float = + available_inline_size - margin_inline_start - margin_inline_end; let shrink_to_fit = block.get_shrink_to_fit_inline_size(available_inline_size_float); let inline_size = computed_inline_size.specified_or_default(shrink_to_fit); - debug!("assign_inline_sizes_float -- inline_size: {:?}", inline_size); + debug!( + "assign_inline_sizes_float -- inline_size: {:?}", + inline_size + ); ISizeConstraintSolution::new(inline_size, margin_inline_start, margin_inline_end) } } @@ -2971,29 +3543,44 @@ impl ISizeAndMarginsComputer for FloatReplaced { /// CSS Section 10.3.5 /// /// If inline-size is computed as 'auto', the used value is the 'shrink-to-fit' inline-size. - fn solve_inline_size_constraints(&self, _: &mut BlockFlow, input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let (computed_inline_size, inline_start_margin, inline_end_margin) = - (input.computed_inline_size, input.inline_start_margin, input.inline_end_margin); + fn solve_inline_size_constraints( + &self, + _: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { + let (computed_inline_size, inline_start_margin, inline_end_margin) = ( + input.computed_inline_size, + input.inline_start_margin, + input.inline_end_margin, + ); let margin_inline_start = inline_start_margin.specified_or_zero(); let margin_inline_end = inline_end_margin.specified_or_zero(); let inline_size = match computed_inline_size { MaybeAuto::Specified(w) => w, - MaybeAuto::Auto => panic!("FloatReplaced: inline_size should have been computed by now") + MaybeAuto::Auto => { + panic!("FloatReplaced: inline_size should have been computed by now") + }, }; - debug!("assign_inline_sizes_float -- inline_size: {:?}", inline_size); + debug!( + "assign_inline_sizes_float -- inline_size: {:?}", + inline_size + ); ISizeConstraintSolution::new(inline_size, margin_inline_start, margin_inline_end) } /// Calculate used value of inline-size just like we do for inline replaced elements. - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { + fn initial_computed_inline_size( + &self, + block: &mut BlockFlow, + parent_flow_inline_size: Au, + shared_context: &SharedStyleContext, + ) -> MaybeAuto { let container_block_size = block.explicit_block_containing_size(shared_context); let fragment = block.fragment(); - fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, container_block_size); + 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_box().size.inline) @@ -3002,18 +3589,17 @@ impl ISizeAndMarginsComputer for FloatReplaced { impl ISizeAndMarginsComputer for InlineBlockNonReplaced { /// Compute inline-start and inline-end margins and inline-size. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { - let (computed_inline_size, - inline_start_margin, - inline_end_margin, - available_inline_size) = - (input.computed_inline_size, - input.inline_start_margin, - input.inline_end_margin, - input.available_inline_size); + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { + let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) = ( + input.computed_inline_size, + input.inline_start_margin, + input.inline_end_margin, + input.available_inline_size, + ); // For inline-blocks, `auto` margins compute to 0. let inline_start_margin = inline_start_margin.specified_or_zero(); @@ -3022,10 +3608,9 @@ impl ISizeAndMarginsComputer for InlineBlockNonReplaced { // If inline-size is set to 'auto', and this is an inline block, use the // shrink to fit algorithm (see CSS 2.1 § 10.3.9) let inline_size = match computed_inline_size { - MaybeAuto::Auto => { - block.get_shrink_to_fit_inline_size(available_inline_size - (inline_start_margin + - inline_end_margin)) - } + MaybeAuto::Auto => block.get_shrink_to_fit_inline_size( + available_inline_size - (inline_start_margin + inline_end_margin), + ), MaybeAuto::Specified(inline_size) => inline_size, }; @@ -3038,23 +3623,22 @@ impl ISizeAndMarginsComputer for InlineBlockReplaced { /// /// ISize has already been calculated. We now calculate the margins just /// like for non-replaced blocks. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { debug_assert!(match input.computed_inline_size { MaybeAuto::Specified(_) => true, MaybeAuto::Auto => false, }); - let (computed_inline_size, - inline_start_margin, - inline_end_margin, - available_inline_size) = - (input.computed_inline_size, - input.inline_start_margin, - input.inline_end_margin, - input.available_inline_size); + let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) = ( + input.computed_inline_size, + input.inline_start_margin, + input.inline_end_margin, + input.available_inline_size, + ); // For inline-blocks, `auto` margins compute to 0. let inline_start_margin = inline_start_margin.specified_or_zero(); @@ -3063,10 +3647,9 @@ impl ISizeAndMarginsComputer for InlineBlockReplaced { // If inline-size is set to 'auto', and this is an inline block, use the // shrink to fit algorithm (see CSS 2.1 § 10.3.9) let inline_size = match computed_inline_size { - MaybeAuto::Auto => { - block.get_shrink_to_fit_inline_size(available_inline_size - (inline_start_margin + - inline_end_margin)) - } + MaybeAuto::Auto => block.get_shrink_to_fit_inline_size( + available_inline_size - (inline_start_margin + inline_end_margin), + ), MaybeAuto::Specified(inline_size) => inline_size, }; @@ -3074,14 +3657,18 @@ impl ISizeAndMarginsComputer for InlineBlockReplaced { } /// Calculate used value of inline-size just like we do for inline replaced elements. - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { + fn initial_computed_inline_size( + &self, + block: &mut BlockFlow, + parent_flow_inline_size: Au, + shared_context: &SharedStyleContext, + ) -> MaybeAuto { let container_block_size = block.explicit_block_containing_size(shared_context); let fragment = block.fragment(); - fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, container_block_size); + 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_box().size.inline) @@ -3091,23 +3678,30 @@ impl ISizeAndMarginsComputer for InlineBlockReplaced { impl ISizeAndMarginsComputer for InlineFlexItem { // Replace the default method directly to prevent recalculating and setting margins again // which has already been set by its parent. - fn compute_used_inline_size(&self, - block: &mut BlockFlow, - shared_context: &SharedStyleContext, - parent_flow_inline_size: Au) { + fn compute_used_inline_size( + &self, + block: &mut BlockFlow, + shared_context: &SharedStyleContext, + parent_flow_inline_size: Au, + ) { let container_block_size = block.explicit_block_containing_size(shared_context); - block.fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, - container_block_size); + block.fragment.assign_replaced_inline_size_if_necessary( + parent_flow_inline_size, + container_block_size, + ); } // The used inline size and margins are set by parent flex flow, do nothing here. - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - _: &ISizeConstraintInput) - -> ISizeConstraintSolution { + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + _: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { let fragment = block.fragment(); - ISizeConstraintSolution::new(fragment.border_box.size.inline, - fragment.margin.inline_start, - fragment.margin.inline_end) + ISizeConstraintSolution::new( + fragment.border_box.size.inline, + fragment.margin.inline_start, + fragment.margin.inline_end, + ) } } diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 063b1ee710f..dd4ef419bbd 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -111,7 +111,12 @@ pub enum ConstructionItem { /// /// FIXME(emilio): How could whitespace have any PseudoElementType other /// than Normal? - Whitespace(OpaqueNode, PseudoElementType, ServoArc<ComputedValues>, RestyleDamage), + Whitespace( + OpaqueNode, + PseudoElementType, + ServoArc<ComputedValues>, + RestyleDamage, + ), /// TableColumn Fragment TableColumnFragment(Fragment), } @@ -182,15 +187,17 @@ impl InlineBlockSplit { let split = InlineBlockSplit { predecessors: mem::replace( fragment_accumulator, - InlineFragmentsAccumulator::from_inline_node( - node, - style_context, - )).to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(style_context), + InlineFragmentsAccumulator::from_inline_node(node, style_context), + ).to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(style_context), flow: flow, }; - fragment_accumulator.enclosing_node.as_mut().unwrap().flags.remove( - InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT); + fragment_accumulator + .enclosing_node + .as_mut() + .unwrap() + .flags + .remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT); split } @@ -220,7 +227,8 @@ impl IntermediateInlineFragments { fn push_all(&mut self, mut other: IntermediateInlineFragments) { self.fragments.append(&mut other.fragments); - self.absolute_descendants.push_descendants(other.absolute_descendants); + self.absolute_descendants + .push_descendants(other.absolute_descendants); } } @@ -256,8 +264,13 @@ impl InlineFragmentsAccumulator { } } - fn from_inline_node<N>(node: &N, style_context: &SharedStyleContext) -> InlineFragmentsAccumulator - where N: ThreadSafeLayoutNode { + fn from_inline_node<N>( + node: &N, + style_context: &SharedStyleContext, + ) -> InlineFragmentsAccumulator + where + N: ThreadSafeLayoutNode, + { InlineFragmentsAccumulator { fragments: IntermediateInlineFragments::new(), enclosing_node: Some(InlineFragmentNodeInfo { @@ -266,7 +279,7 @@ impl InlineFragmentsAccumulator { style: node.style(style_context), selected_style: node.selected_style(), flags: InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT | - InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT, + InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT, }), bidi_control_chars: None, restyle_damage: node.restyle_damage(), @@ -279,7 +292,9 @@ impl InlineFragmentsAccumulator { fn push_all(&mut self, mut fragments: IntermediateInlineFragments) { self.fragments.fragments.append(&mut fragments.fragments); - self.fragments.absolute_descendants.push_descendants(fragments.absolute_descendants); + self.fragments + .absolute_descendants + .push_descendants(fragments.absolute_descendants); } fn to_intermediate_inline_fragments<N>( @@ -300,36 +315,42 @@ impl InlineFragmentsAccumulator { for (index, fragment) in fragments.fragments.iter_mut().enumerate() { let mut enclosing_node = enclosing_node.clone(); if index != 0 { - enclosing_node.flags.remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) + enclosing_node + .flags + .remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) } if index != fragment_count - 1 { - enclosing_node.flags.remove(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) + enclosing_node + .flags + .remove(InlineFragmentNodeFlags::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 // is_first/is_last styles above. - enclosing_node.flags.remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT | - InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); + enclosing_node.flags.remove( + InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT | + InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT, + ); if let Some((start, end)) = bidi_control_chars { - fragments.fragments.push_front( - control_chars_to_fragment::<N::ConcreteElement>( + fragments + .fragments + .push_front(control_chars_to_fragment::<N::ConcreteElement>( &enclosing_node, context, start, restyle_damage, - ) - ); - fragments.fragments.push_back( - control_chars_to_fragment::<N::ConcreteElement>( + )); + fragments + .fragments + .push_back(control_chars_to_fragment::<N::ConcreteElement>( &enclosing_node, context, end, restyle_damage, - ) - ); + )); } } fragments @@ -346,7 +367,8 @@ pub struct FlowConstructor<'a, N: ThreadSafeLayoutNode> { } impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> - FlowConstructor<'a, ConcreteThreadSafeLayoutNode> { + FlowConstructor<'a, ConcreteThreadSafeLayoutNode> +{ /// Creates a new flow constructor. pub fn new(layout_context: &'a LayoutContext<'a>) -> Self { FlowConstructor { @@ -361,9 +383,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> } #[inline] - fn set_flow_construction_result(&self, - node: &ConcreteThreadSafeLayoutNode, - result: ConstructionResult) { + fn set_flow_construction_result( + &self, + node: &ConcreteThreadSafeLayoutNode, + result: ConstructionResult, + ) { node.set_flow_construction_result(result); } @@ -372,44 +396,48 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let specific_fragment_info = match node.type_id() { Some(LayoutNodeType::Element(LayoutElementType::HTMLIFrameElement)) => { SpecificFragmentInfo::Iframe(IframeFragmentInfo::new(node)) - } + }, Some(LayoutNodeType::Element(LayoutElementType::HTMLImageElement)) => { let image_info = Box::new(ImageFragmentInfo::new( - node.image_url(), node, &self.layout_context + node.image_url(), + node, + &self.layout_context, )); SpecificFragmentInfo::Image(image_info) - } + }, Some(LayoutNodeType::Element(LayoutElementType::HTMLObjectElement)) => { let image_info = Box::new(ImageFragmentInfo::new( - node.object_data(), node, &self.layout_context - )); + node.object_data(), + node, + &self.layout_context, + )); SpecificFragmentInfo::Image(image_info) - } + }, Some(LayoutNodeType::Element(LayoutElementType::HTMLTableElement)) => { SpecificFragmentInfo::TableWrapper - } + }, Some(LayoutNodeType::Element(LayoutElementType::HTMLTableColElement)) => { SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node)) - } + }, Some(LayoutNodeType::Element(LayoutElementType::HTMLTableCellElement)) => { SpecificFragmentInfo::TableCell - } + }, Some(LayoutNodeType::Element(LayoutElementType::HTMLTableRowElement)) | Some(LayoutNodeType::Element(LayoutElementType::HTMLTableSectionElement)) => { SpecificFragmentInfo::TableRow - } + }, Some(LayoutNodeType::Element(LayoutElementType::HTMLCanvasElement)) => { let data = node.canvas_data().unwrap(); SpecificFragmentInfo::Canvas(Box::new(CanvasFragmentInfo::new(data))) - } + }, Some(LayoutNodeType::Element(LayoutElementType::SVGSVGElement)) => { let data = node.svg_data().unwrap(); SpecificFragmentInfo::Svg(Box::new(SvgFragmentInfo::new(data))) - } + }, _ => { // This includes pseudo-elements. SpecificFragmentInfo::Generic - } + }, }; Fragment::new(node, specific_fragment_info, self.layout_context) @@ -429,35 +457,33 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> legalizer: &mut Legalizer, node: &ConcreteThreadSafeLayoutNode, ) { - let mut fragments = - fragment_accumulator.to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>( - self.style_context(), - ); + let mut fragments = fragment_accumulator + .to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(self.style_context()); if fragments.is_empty() { - return + return; }; strip_ignorable_whitespace_from_start(&mut fragments.fragments); strip_ignorable_whitespace_from_end(&mut fragments.fragments); if fragments.fragments.is_empty() { absolute_descendants.push_descendants(fragments.absolute_descendants); - return + return; } // Build a list of all the inline-block fragments before fragments is moved. - let mut inline_block_flows = vec!(); + let mut inline_block_flows = vec![]; for fragment in &fragments.fragments { match fragment.specific { SpecificFragmentInfo::InlineBlock(ref info) => { inline_block_flows.push(info.flow_ref.clone()) - } + }, SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => { inline_block_flows.push(info.flow_ref.clone()) - } + }, SpecificFragmentInfo::InlineAbsolute(ref info) => { inline_block_flows.push(info.flow_ref.clone()) - } - _ => {} + }, + _ => {}, } } @@ -466,12 +492,15 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> // remain. In that case the inline flow will compute its ascent and descent to be zero. let scanned_fragments = with_thread_local_font_context(self.layout_context, |font_context| { - TextRunScanner::new().scan_for_runs(font_context, - mem::replace(&mut fragments.fragments, LinkedList::new())) + TextRunScanner::new().scan_for_runs( + font_context, + mem::replace(&mut fragments.fragments, LinkedList::new()), + ) }); - let mut inline_flow_ref = - FlowRef::new(Arc::new(InlineFlow::from_fragments(scanned_fragments, - node.style(self.style_context()).writing_mode))); + let mut inline_flow_ref = FlowRef::new(Arc::new(InlineFlow::from_fragments( + scanned_fragments, + node.style(self.style_context()).writing_mode, + ))); // Add all the inline-block fragments as children of the inline flow. for inline_block_flow in &inline_block_flows { @@ -498,7 +527,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let inline_flow = FlowRef::deref_mut(&mut inline_flow_ref).as_mut_inline(); inline_flow.minimum_line_metrics = with_thread_local_font_context(self.layout_context, |font_context| { - inline_flow.minimum_line_metrics(font_context, &node.style(self.style_context())) + inline_flow + .minimum_line_metrics(font_context, &node.style(self.style_context())) }); } @@ -511,15 +541,16 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> } fn build_block_flow_using_construction_result_of_child( - &mut self, - flow: &mut FlowRef, - node: &ConcreteThreadSafeLayoutNode, - kid: ConcreteThreadSafeLayoutNode, - inline_fragment_accumulator: &mut InlineFragmentsAccumulator, - abs_descendants: &mut AbsoluteDescendants, - legalizer: &mut Legalizer) { + &mut self, + flow: &mut FlowRef, + node: &ConcreteThreadSafeLayoutNode, + kid: ConcreteThreadSafeLayoutNode, + inline_fragment_accumulator: &mut InlineFragmentsAccumulator, + abs_descendants: &mut AbsoluteDescendants, + legalizer: &mut Legalizer, + ) { match kid.get_construction_result() { - ConstructionResult::None => {} + ConstructionResult::None => {}, ConstructionResult::Flow(kid_flow, kid_abs_descendants) => { // If kid_flow is TableCaptionFlow, kid_flow should be added under // TableWrapperFlow. @@ -528,17 +559,24 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> ConstructionResult::Flow(kid_flow, AbsoluteDescendants::new()); self.set_flow_construction_result(&kid, construction_result) } else { - if !kid_flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if !kid_flow + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { // Flush any inline fragments that we were gathering up. This allows us to // handle {ib} splits. - let old_inline_fragment_accumulator = - mem::replace(inline_fragment_accumulator, - InlineFragmentsAccumulator::new()); - self.flush_inline_fragments_to_flow(old_inline_fragment_accumulator, - flow, - abs_descendants, - legalizer, - node); + let old_inline_fragment_accumulator = mem::replace( + inline_fragment_accumulator, + InlineFragmentsAccumulator::new(), + ); + self.flush_inline_fragments_to_flow( + old_inline_fragment_accumulator, + flow, + abs_descendants, + legalizer, + node, + ); } legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>( self.style_context(), @@ -547,35 +585,41 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> ) } abs_descendants.push_descendants(kid_abs_descendants); - } + }, ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments( - InlineFragmentsConstructionResult { - splits, - fragments: successor_fragments, - })) => { + InlineFragmentsConstructionResult { + splits, + fragments: successor_fragments, + }, + )) => { // Add any {ib} splits. for split in splits { // Pull apart the {ib} split object and push its predecessor fragments // onto the list. let InlineBlockSplit { predecessors, - flow: kid_flow + flow: kid_flow, } = split; inline_fragment_accumulator.push_all(predecessors); // Flush any inline fragments that we were gathering up. - debug!("flushing {} inline box(es) to flow A", - inline_fragment_accumulator.fragments.fragments.len()); - let old_inline_fragment_accumulator = - mem::replace(inline_fragment_accumulator, - InlineFragmentsAccumulator::new()); + debug!( + "flushing {} inline box(es) to flow A", + inline_fragment_accumulator.fragments.fragments.len() + ); + let old_inline_fragment_accumulator = mem::replace( + inline_fragment_accumulator, + InlineFragmentsAccumulator::new(), + ); let absolute_descendants = &mut inline_fragment_accumulator.fragments.absolute_descendants; - self.flush_inline_fragments_to_flow(old_inline_fragment_accumulator, - flow, - absolute_descendants, - legalizer, - node); + self.flush_inline_fragments_to_flow( + old_inline_fragment_accumulator, + flow, + absolute_descendants, + legalizer, + node, + ); // Push the flow generated by the {ib} split onto our list of flows. legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>( @@ -587,29 +631,35 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> // Add the fragments to the list we're maintaining. inline_fragment_accumulator.push_all(successor_fragments); - } + }, ConstructionResult::ConstructionItem(ConstructionItem::Whitespace( + whitespace_node, + whitespace_pseudo, + whitespace_style, + whitespace_damage, + )) => { + // Add whitespace results. They will be stripped out later on when + // between block elements, and retained when between inline elements. + let fragment_info = SpecificFragmentInfo::UnscannedText(Box::new( + UnscannedTextFragmentInfo::new(Box::<str>::from(" "), None), + )); + let fragment = Fragment::from_opaque_node_and_style( whitespace_node, whitespace_pseudo, whitespace_style, - whitespace_damage)) => { - // Add whitespace results. They will be stripped out later on when - // between block elements, and retained when between inline elements. - let fragment_info = SpecificFragmentInfo::UnscannedText( - Box::new(UnscannedTextFragmentInfo::new(Box::<str>::from(" "), None)) + node.selected_style(), + whitespace_damage, + fragment_info, ); - let fragment = Fragment::from_opaque_node_and_style(whitespace_node, - whitespace_pseudo, - whitespace_style, - node.selected_style(), - whitespace_damage, - fragment_info); - inline_fragment_accumulator.fragments.fragments.push_back(fragment); - } + inline_fragment_accumulator + .fragments + .fragments + .push_back(fragment); + }, ConstructionResult::ConstructionItem(ConstructionItem::TableColumnFragment(_)) => { // TODO: Implement anonymous table objects for missing parents // CSS 2.1 § 17.2.1, step 3-2 - } + }, } } @@ -617,15 +667,17 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// appending the construction results of children to the child list of the block flow. {ib} /// splits and absolutely-positioned descendants are handled correctly. fn build_flow_for_block_starting_with_fragments( - &mut self, - mut flow: FlowRef, - node: &ConcreteThreadSafeLayoutNode, - initial_fragments: IntermediateInlineFragments) - -> ConstructionResult { + &mut self, + mut flow: FlowRef, + node: &ConcreteThreadSafeLayoutNode, + initial_fragments: IntermediateInlineFragments, + ) -> ConstructionResult { // Gather up fragments for the inline flows we might need to create. let mut inline_fragment_accumulator = InlineFragmentsAccumulator::new(); - inline_fragment_accumulator.fragments.push_all(initial_fragments); + inline_fragment_accumulator + .fragments + .push_all(initial_fragments); // List of absolute descendants, in tree order. let mut abs_descendants = AbsoluteDescendants::new(); @@ -642,17 +694,20 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> kid, &mut inline_fragment_accumulator, &mut abs_descendants, - &mut legalizer); + &mut legalizer, + ); } } // Perform a final flush of any inline fragments that we were gathering up to handle {ib} // splits, after stripping ignorable whitespace. - self.flush_inline_fragments_to_flow(inline_fragment_accumulator, - &mut flow, - &mut abs_descendants, - &mut legalizer, - node); + self.flush_inline_fragments_to_flow( + inline_fragment_accumulator, + &mut flow, + &mut abs_descendants, + &mut legalizer, + node, + ); // The flow is done. legalizer.finish(&mut flow); @@ -664,7 +719,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> flow.set_absolute_descendants(abs_descendants); abs_descendants = AbsoluteDescendants::new(); - if flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if flow + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { // This is now the only absolute flow in the subtree which hasn't yet // reached its CB. abs_descendants.push(flow.clone()); @@ -684,17 +743,23 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// /// FIXME(pcwalton): It is not clear to me that there isn't a cleaner way to handle /// `<textarea>`. - fn build_flow_for_block_like(&mut self, flow: FlowRef, node: &ConcreteThreadSafeLayoutNode) - -> ConstructionResult { + fn build_flow_for_block_like( + &mut self, + flow: FlowRef, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { let mut fragments = IntermediateInlineFragments::new(); let node_is_input_or_text_area = - node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLInputElement)) || - node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLTextAreaElement)); - if node.get_pseudo_element_type().is_replaced_content() || - node_is_input_or_text_area { + node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLInputElement)) || + node.type_id() == Some(LayoutNodeType::Element( + LayoutElementType::HTMLTextAreaElement, + )); + if node.get_pseudo_element_type().is_replaced_content() || node_is_input_or_text_area { // A TextArea's text contents are displayed through the input text // box, so don't construct them. - if node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLTextAreaElement)) { + if node.type_id() == Some(LayoutNodeType::Element( + LayoutElementType::HTMLTextAreaElement, + )) { for kid in node.children() { self.set_flow_construction_result(&kid, ConstructionResult::None) } @@ -702,17 +767,21 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let context = self.style_context(); let mut style = node.style(context); - style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( - &context.guards, - &PseudoElement::ServoText, - &style, - ); - if node_is_input_or_text_area { - style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + style = context + .stylist + .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( &context.guards, - &PseudoElement::ServoInputText, + &PseudoElement::ServoText, &style, - ) + ); + if node_is_input_or_text_area { + style = context + .stylist + .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoInputText, + &style, + ) } self.create_fragments_for_node_text_content(&mut fragments, node, &style) @@ -721,14 +790,16 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> } /// Pushes fragments appropriate for the content of the given node onto the given list. - fn create_fragments_for_node_text_content(&self, - fragments: &mut IntermediateInlineFragments, - node: &ConcreteThreadSafeLayoutNode, - style: &ServoArc<ComputedValues>) { + fn create_fragments_for_node_text_content( + &self, + fragments: &mut IntermediateInlineFragments, + node: &ConcreteThreadSafeLayoutNode, + style: &ServoArc<ComputedValues>, + ) { // Fast path: If there is no text content, return immediately. let text_content = node.text_content(); if text_content.is_empty() { - return + return; } let style = (*style).clone(); @@ -738,14 +809,17 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> TextContent::Text(string) => { let info = Box::new(UnscannedTextFragmentInfo::new(string, node.selection())); let specific_fragment_info = SpecificFragmentInfo::UnscannedText(info); - fragments.fragments.push_back(Fragment::from_opaque_node_and_style( + fragments + .fragments + .push_back(Fragment::from_opaque_node_and_style( node.opaque(), node.get_pseudo_element_type(), style, selected_style, node.restyle_damage(), - specific_fragment_info)) - } + specific_fragment_info, + )) + }, TextContent::GeneratedContent(content_items) => { for content_item in content_items.into_iter() { let specific_fragment_info = match content_item { @@ -754,52 +828,66 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> SpecificFragmentInfo::UnscannedText(info) }, content_item => { - let content_item = Box::new(GeneratedContentInfo::ContentItem(content_item)); + let content_item = + Box::new(GeneratedContentInfo::ContentItem(content_item)); SpecificFragmentInfo::GeneratedContent(content_item) - } + }, }; - fragments.fragments.push_back(Fragment::from_opaque_node_and_style( + fragments + .fragments + .push_back(Fragment::from_opaque_node_and_style( node.opaque(), node.get_pseudo_element_type(), style.clone(), selected_style.clone(), node.restyle_damage(), - specific_fragment_info)) + specific_fragment_info, + )) } - } + }, } } /// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly /// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed /// to happen. - fn build_flow_for_block(&mut self, node: &ConcreteThreadSafeLayoutNode, float_kind: Option<FloatKind>) - -> ConstructionResult { + fn build_flow_for_block( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + float_kind: Option<FloatKind>, + ) -> ConstructionResult { if node.style(self.style_context()).is_multicol() { - return self.build_flow_for_multicol(node, float_kind) + return self.build_flow_for_multicol(node, float_kind); } let fragment = self.build_fragment_for_block(node); - let flow = - FlowRef::new(Arc::new(BlockFlow::from_fragment_and_float_kind(fragment, float_kind))); + let flow = FlowRef::new(Arc::new(BlockFlow::from_fragment_and_float_kind( + fragment, float_kind, + ))); self.build_flow_for_block_like(flow, node) } /// Bubbles up {ib} splits. - fn accumulate_inline_block_splits(&mut self, - splits: LinkedList<InlineBlockSplit>, - node: &ConcreteThreadSafeLayoutNode, - fragment_accumulator: &mut InlineFragmentsAccumulator, - opt_inline_block_splits: &mut LinkedList<InlineBlockSplit>) { + fn accumulate_inline_block_splits( + &mut self, + splits: LinkedList<InlineBlockSplit>, + node: &ConcreteThreadSafeLayoutNode, + fragment_accumulator: &mut InlineFragmentsAccumulator, + opt_inline_block_splits: &mut LinkedList<InlineBlockSplit>, + ) { for split in splits { let InlineBlockSplit { predecessors, - flow: kid_flow + flow: kid_flow, } = split; fragment_accumulator.push_all(predecessors); - opt_inline_block_splits.push_back( - InlineBlockSplit::new(fragment_accumulator, node, self.style_context(), kid_flow)); + opt_inline_block_splits.push_back(InlineBlockSplit::new( + fragment_accumulator, + node, + self.style_context(), + kid_flow, + )); } } @@ -807,11 +895,15 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// Returns the `InlineFragmentsConstructionResult`, if any. There will be no /// `InlineFragmentsConstructionResult` if this node consisted entirely of ignorable /// whitespace. - fn build_fragments_for_nonreplaced_inline_content(&mut self, node: &ConcreteThreadSafeLayoutNode) - -> ConstructionResult { + fn build_fragments_for_nonreplaced_inline_content( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { let mut opt_inline_block_splits: LinkedList<InlineBlockSplit> = LinkedList::new(); - let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node, self.style_context()); - fragment_accumulator.bidi_control_chars = bidi_control_chars(&node.style(self.style_context())); + let mut fragment_accumulator = + InlineFragmentsAccumulator::from_inline_node(node, self.style_context()); + fragment_accumulator.bidi_control_chars = + bidi_control_chars(&node.style(self.style_context())); let mut abs_descendants = AbsoluteDescendants::new(); @@ -823,11 +915,19 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> self.process(&kid); } match kid.get_construction_result() { - ConstructionResult::None => {} + ConstructionResult::None => {}, ConstructionResult::Flow(flow, kid_abs_descendants) => { - if !flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if !flow + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { opt_inline_block_splits.push_back(InlineBlockSplit::new( - &mut fragment_accumulator, node, self.style_context(), flow)); + &mut fragment_accumulator, + node, + self.style_context(), + flow, + )); abs_descendants.push_descendants(kid_abs_descendants); } else { // Push the absolutely-positioned kid as an inline containing block. @@ -837,93 +937,110 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let kid_selected_style = flow.as_block().fragment.selected_style.clone(); let kid_restyle_damage = flow.as_block().fragment.restyle_damage; let fragment_info = SpecificFragmentInfo::InlineAbsolute( - InlineAbsoluteFragmentInfo::new(flow)); + InlineAbsoluteFragmentInfo::new(flow), + ); fragment_accumulator.push(Fragment::from_opaque_node_and_style( - kid_node, - kid_pseudo, - kid_style, - kid_selected_style, - kid_restyle_damage, - fragment_info)); - fragment_accumulator.fragments - .absolute_descendants - .push_descendants(kid_abs_descendants); + kid_node, + kid_pseudo, + kid_style, + kid_selected_style, + kid_restyle_damage, + fragment_info, + )); + fragment_accumulator + .fragments + .absolute_descendants + .push_descendants(kid_abs_descendants); } - } + }, ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments( - InlineFragmentsConstructionResult { - splits, - fragments: successors, - })) => { + InlineFragmentsConstructionResult { + splits, + fragments: successors, + }, + )) => { // Bubble up {ib} splits. - self.accumulate_inline_block_splits(splits, - node, - &mut fragment_accumulator, - &mut opt_inline_block_splits); + self.accumulate_inline_block_splits( + splits, + node, + &mut fragment_accumulator, + &mut opt_inline_block_splits, + ); // Push residual fragments. fragment_accumulator.push_all(successors); - } + }, ConstructionResult::ConstructionItem(ConstructionItem::Whitespace( + whitespace_node, + whitespace_pseudo, + whitespace_style, + whitespace_damage, + )) => { + // Instantiate the whitespace fragment. + let fragment_info = SpecificFragmentInfo::UnscannedText(Box::new( + UnscannedTextFragmentInfo::new(Box::<str>::from(" "), None), + )); + let fragment = Fragment::from_opaque_node_and_style( whitespace_node, whitespace_pseudo, whitespace_style, - whitespace_damage)) => { - // Instantiate the whitespace fragment. - let fragment_info = SpecificFragmentInfo::UnscannedText( - Box::new(UnscannedTextFragmentInfo::new(Box::<str>::from(" "), None)) + node.selected_style(), + whitespace_damage, + fragment_info, ); - let fragment = - Fragment::from_opaque_node_and_style(whitespace_node, - whitespace_pseudo, - whitespace_style, - node.selected_style(), - whitespace_damage, - fragment_info); fragment_accumulator.fragments.fragments.push_back(fragment) - } + }, ConstructionResult::ConstructionItem(ConstructionItem::TableColumnFragment(_)) => { // TODO: Implement anonymous table objects for missing parents // CSS 2.1 § 17.2.1, step 3-2 - } + }, } } let node_style = node.style(self.style_context()); if is_empty && node_style.has_padding_or_border() { // An empty inline box needs at least one fragment to draw its background and borders. - let info = SpecificFragmentInfo::UnscannedText( - Box::new(UnscannedTextFragmentInfo::new(Box::<str>::from(""), None)) + let info = SpecificFragmentInfo::UnscannedText(Box::new( + UnscannedTextFragmentInfo::new(Box::<str>::from(""), None), + )); + let fragment = Fragment::from_opaque_node_and_style( + node.opaque(), + node.get_pseudo_element_type(), + node_style.clone(), + node.selected_style(), + node.restyle_damage(), + info, ); - let fragment = Fragment::from_opaque_node_and_style(node.opaque(), - node.get_pseudo_element_type(), - node_style.clone(), - node.selected_style(), - node.restyle_damage(), - info); fragment_accumulator.fragments.fragments.push_back(fragment) } // Finally, make a new construction result. - if opt_inline_block_splits.len() > 0 || !fragment_accumulator.fragments.is_empty() - || abs_descendants.len() > 0 { - fragment_accumulator.fragments.absolute_descendants.push_descendants(abs_descendants); + if opt_inline_block_splits.len() > 0 || + !fragment_accumulator.fragments.is_empty() || + abs_descendants.len() > 0 + { + fragment_accumulator + .fragments + .absolute_descendants + .push_descendants(abs_descendants); // If the node is positioned, then it's the containing block for all absolutely- // positioned descendants. if node_style.get_box().position != Position::Static { - fragment_accumulator.fragments - .absolute_descendants - .mark_as_having_reached_containing_block(); - } - - let construction_item = ConstructionItem::InlineFragments( - InlineFragmentsConstructionResult { - splits: opt_inline_block_splits, - fragments: fragment_accumulator.to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>( - self.style_context(), - ), - }); + fragment_accumulator + .fragments + .absolute_descendants + .mark_as_having_reached_containing_block(); + } + + let construction_item = + ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { + splits: opt_inline_block_splits, + fragments: fragment_accumulator + .to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>( + self.style_context(), + ), + }); ConstructionResult::ConstructionItem(construction_item) } else { ConstructionResult::None @@ -933,8 +1050,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// Creates an `InlineFragmentsConstructionResult` for replaced content. Replaced content /// doesn't render its children, so this just nukes a child's fragments and creates a /// `Fragment`. - fn build_fragments_for_replaced_inline_content(&mut self, node: &ConcreteThreadSafeLayoutNode) - -> ConstructionResult { + fn build_fragments_for_replaced_inline_content( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { for kid in node.children() { self.set_flow_construction_result(&kid, ConstructionResult::None) } @@ -946,13 +1065,15 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> return ConstructionResult::ConstructionItem(ConstructionItem::Whitespace( node.opaque(), node.get_pseudo_element_type(), - context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( - &context.guards, - &PseudoElement::ServoText, - &style, - ), + context + .stylist + .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoText, + &style, + ), node.restyle_damage(), - )) + )); } // If this is generated content, then we need to initialize the accumulator with the @@ -961,16 +1082,20 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let mut fragments = IntermediateInlineFragments::new(); match (node.get_pseudo_element_type(), node.type_id()) { (_, Some(LayoutNodeType::Text)) => { - let text_style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( - &context.guards, - &PseudoElement::ServoText, - &style, - ); + let text_style = context + .stylist + .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoText, + &style, + ); self.create_fragments_for_node_text_content(&mut fragments, node, &text_style) - } + }, (PseudoElementType::Normal, _) => { - fragments.fragments.push_back(self.build_fragment_for_block(node)); - } + fragments + .fragments + .push_back(self.build_fragment_for_block(node)); + }, (_, _) => self.create_fragments_for_node_text_content(&mut fragments, node, &style), } @@ -991,32 +1116,39 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let block_flow_result = match display { Display::InlineBlock => self.build_flow_for_block(node, None), Display::InlineFlex => self.build_flow_for_flex(node, None), - _ => panic!("The flag should be inline-block or inline-flex") + _ => panic!("The flag should be inline-block or inline-flex"), }; let (block_flow, abs_descendants) = match block_flow_result { ConstructionResult::Flow(block_flow, abs_descendants) => (block_flow, abs_descendants), - _ => unreachable!() + _ => unreachable!(), }; let context = self.style_context(); let style = node.style(context); - let style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( - &context.guards, - &PseudoElement::ServoInlineBlockWrapper, - &style, + let style = context + .stylist + .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoInlineBlockWrapper, + &style, + ); + let fragment_info = + SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(block_flow)); + let fragment = Fragment::from_opaque_node_and_style( + node.opaque(), + node.get_pseudo_element_type(), + style, + node.selected_style(), + node.restyle_damage(), + fragment_info, ); - let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new( - block_flow)); - let fragment = Fragment::from_opaque_node_and_style(node.opaque(), - node.get_pseudo_element_type(), - style, - node.selected_style(), - node.restyle_damage(), - fragment_info); let mut fragment_accumulator = InlineFragmentsAccumulator::new(); fragment_accumulator.fragments.fragments.push_back(fragment); - fragment_accumulator.fragments.absolute_descendants.push_descendants(abs_descendants); + fragment_accumulator + .fragments + .absolute_descendants + .push_descendants(abs_descendants); let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { @@ -1029,47 +1161,62 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// This is an annoying case, because the computed `display` value is `block`, but the /// hypothetical box is inline. - fn build_fragment_for_absolutely_positioned_inline(&mut self, - node: &ConcreteThreadSafeLayoutNode) - -> ConstructionResult { + fn build_fragment_for_absolutely_positioned_inline( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { let block_flow_result = self.build_flow_for_block(node, None); let (block_flow, abs_descendants) = match block_flow_result { ConstructionResult::Flow(block_flow, abs_descendants) => (block_flow, abs_descendants), - _ => unreachable!() + _ => unreachable!(), }; let fragment_info = SpecificFragmentInfo::InlineAbsoluteHypothetical( - InlineAbsoluteHypotheticalFragmentInfo::new(block_flow)); + InlineAbsoluteHypotheticalFragmentInfo::new(block_flow), + ); let style_context = self.style_context(); let style = node.style(style_context); - let style = style_context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( - &style_context.guards, - &PseudoElement::ServoInlineAbsolute, - &style, + let style = style_context + .stylist + .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &style_context.guards, + &PseudoElement::ServoInlineAbsolute, + &style, + ); + let fragment = Fragment::from_opaque_node_and_style( + node.opaque(), + PseudoElementType::Normal, + style, + node.selected_style(), + node.restyle_damage(), + fragment_info, ); - let fragment = Fragment::from_opaque_node_and_style(node.opaque(), - PseudoElementType::Normal, - style, - node.selected_style(), - node.restyle_damage(), - fragment_info); - - let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node, self.style_context()); + + let mut fragment_accumulator = + InlineFragmentsAccumulator::from_inline_node(node, self.style_context()); fragment_accumulator.fragments.fragments.push_back(fragment); - fragment_accumulator.fragments.absolute_descendants.push_descendants(abs_descendants); + fragment_accumulator + .fragments + .absolute_descendants + .push_descendants(abs_descendants); let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { splits: LinkedList::new(), fragments: fragment_accumulator - .to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(style_context), + .to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>( + style_context, + ), }); ConstructionResult::ConstructionItem(construction_item) } /// Builds one or more fragments for a node with `display: inline`. This yields an /// `InlineFragmentsConstructionResult`. - fn build_fragments_for_inline(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { + fn build_fragments_for_inline( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { // Is this node replaced content? if !node.is_replaced_content() { // Go to a path that concatenates our kids' fragments. @@ -1083,39 +1230,50 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// Places any table captions found under the given table wrapper, if the value of their /// `caption-side` property is equal to the given `side`. - fn place_table_caption_under_table_wrapper_on_side(&mut self, - table_wrapper_flow: &mut FlowRef, - node: &ConcreteThreadSafeLayoutNode, - side: CaptionSide) { + fn place_table_caption_under_table_wrapper_on_side( + &mut self, + table_wrapper_flow: &mut FlowRef, + node: &ConcreteThreadSafeLayoutNode, + side: CaptionSide, + ) { // Only flows that are table captions are matched here. for kid in node.children() { match kid.get_construction_result() { ConstructionResult::Flow(kid_flow, _) => { if kid_flow.is_table_caption() && - kid_flow.as_block() - .fragment - .style() - .get_inherited_table() - .caption_side == side { + kid_flow + .as_block() + .fragment + .style() + .get_inherited_table() + .caption_side == + side + { table_wrapper_flow.add_new_child(kid_flow); } - } - ConstructionResult::None | ConstructionResult::ConstructionItem(_) => {} + }, + ConstructionResult::None | ConstructionResult::ConstructionItem(_) => {}, } } } /// Builds a flow for a node with `column-count` or `column-width` non-`auto`. /// This yields a `MulticolFlow` with a single `MulticolColumnFlow` underneath it. - fn build_flow_for_multicol(&mut self, - node: &ConcreteThreadSafeLayoutNode, - float_kind: Option<FloatKind>) - -> ConstructionResult { + fn build_flow_for_multicol( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + float_kind: Option<FloatKind>, + ) -> ConstructionResult { let fragment = Fragment::new(node, SpecificFragmentInfo::Multicol, self.layout_context); let mut flow = FlowRef::new(Arc::new(MulticolFlow::from_fragment(fragment, float_kind))); - let column_fragment = Fragment::new(node, SpecificFragmentInfo::MulticolColumn, self.layout_context); - let column_flow = FlowRef::new(Arc::new(MulticolColumnFlow::from_fragment(column_fragment))); + let column_fragment = Fragment::new( + node, + SpecificFragmentInfo::MulticolColumn, + self.layout_context, + ); + let column_flow = + FlowRef::new(Arc::new(MulticolColumnFlow::from_fragment(column_fragment))); // First populate the column flow with its children. let construction_result = self.build_flow_for_block_like(column_flow, node); @@ -1135,7 +1293,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> abs_descendants = AbsoluteDescendants::new(); - if flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if flow + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { // This is now the only absolute flow in the subtree which hasn't yet // reached its containing block. abs_descendants.push(flow.clone()); @@ -1147,8 +1309,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// Builds a flow for a node with `display: table`. This yields a `TableWrapperFlow` with /// possibly other `TableCaptionFlow`s or `TableFlow`s underneath it. - fn build_flow_for_table(&mut self, node: &ConcreteThreadSafeLayoutNode, float_value: Float) - -> ConstructionResult { + fn build_flow_for_table( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + float_value: Float, + ) -> ConstructionResult { let mut legalizer = Legalizer::new(); let table_style; @@ -1156,23 +1321,26 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> { let context = self.style_context(); table_style = node.style(context); - wrapper_style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( - &context.guards, - &PseudoElement::ServoTableWrapper, - &table_style, - ); + wrapper_style = context + .stylist + .style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoTableWrapper, + &table_style, + ); } - let wrapper_fragment = - Fragment::from_opaque_node_and_style(node.opaque(), - PseudoElementType::Normal, - wrapper_style, - node.selected_style(), - node.restyle_damage(), - SpecificFragmentInfo::TableWrapper); + let wrapper_fragment = Fragment::from_opaque_node_and_style( + node.opaque(), + PseudoElementType::Normal, + wrapper_style, + node.selected_style(), + node.restyle_damage(), + SpecificFragmentInfo::TableWrapper, + ); let wrapper_float_kind = FloatKind::from_property(float_value); - let mut wrapper_flow = - FlowRef::new(Arc::new(TableWrapperFlow::from_fragment_and_float_kind(wrapper_fragment, - wrapper_float_kind))); + let mut wrapper_flow = FlowRef::new(Arc::new( + TableWrapperFlow::from_fragment_and_float_kind(wrapper_fragment, wrapper_float_kind), + )); let table_fragment = Fragment::new(node, SpecificFragmentInfo::Table, self.layout_context); let table_flow = FlowRef::new(Arc::new(TableFlow::from_fragment(table_fragment))); @@ -1185,9 +1353,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> // The order of the caption and the table are not necessarily the same order as in the DOM // tree. All caption blocks are placed before or after the table flow, depending on the // value of `caption-side`. - self.place_table_caption_under_table_wrapper_on_side(&mut wrapper_flow, - node, - CaptionSide::Top); + self.place_table_caption_under_table_wrapper_on_side( + &mut wrapper_flow, + node, + CaptionSide::Top, + ); if let ConstructionResult::Flow(table_flow, table_abs_descendants) = construction_result { legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>( @@ -1199,9 +1369,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> } // If the value of `caption-side` is `bottom`, place it now. - self.place_table_caption_under_table_wrapper_on_side(&mut wrapper_flow, - node, - CaptionSide::Bottom); + self.place_table_caption_under_table_wrapper_on_side( + &mut wrapper_flow, + node, + CaptionSide::Bottom, + ); // The flow is done. legalizer.finish(&mut wrapper_flow); @@ -1213,7 +1385,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> abs_descendants = AbsoluteDescendants::new(); - if wrapper_flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if wrapper_flow + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { // This is now the only absolute flow in the subtree which hasn't yet // reached its containing block. abs_descendants.push(wrapper_flow.clone()); @@ -1225,7 +1401,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// Builds a flow for a node with `display: table-caption`. This yields a `TableCaptionFlow` /// with possibly other `BlockFlow`s or `InlineFlow`s underneath it. - fn build_flow_for_table_caption(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { + fn build_flow_for_table_caption( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { let fragment = self.build_fragment_for_block(node); let flow = FlowRef::new(Arc::new(TableCaptionFlow::from_fragment(fragment))); self.build_flow_for_block_like(flow, node) @@ -1233,8 +1412,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// Builds a flow for a node with `display: table-row-group`. This yields a `TableRowGroupFlow` /// with possibly other `TableRowFlow`s underneath it. - fn build_flow_for_table_rowgroup(&mut self, node: &ConcreteThreadSafeLayoutNode) - -> ConstructionResult { + fn build_flow_for_table_rowgroup( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow, self.layout_context); let flow = FlowRef::new(Arc::new(TableRowGroupFlow::from_fragment(fragment))); self.build_flow_for_block_like(flow, node) @@ -1242,7 +1423,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// Builds a flow for a node with `display: table-row`. This yields a `TableRowFlow` with /// possibly other `TableCellFlow`s underneath it. - fn build_flow_for_table_row(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { + fn build_flow_for_table_row( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow, self.layout_context); let flow = FlowRef::new(Arc::new(TableRowFlow::from_fragment(fragment))); self.build_flow_for_block_like(flow, node) @@ -1250,65 +1434,79 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// Builds a flow for a node with `display: table-cell`. This yields a `TableCellFlow` with /// possibly other `BlockFlow`s or `InlineFlow`s underneath it. - fn build_flow_for_table_cell(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { + fn build_flow_for_table_cell( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { let fragment = Fragment::new(node, SpecificFragmentInfo::TableCell, self.layout_context); // Determine if the table cell should be hidden. Per CSS 2.1 § 17.6.1.1, this will be true // if the cell has any in-flow elements (even empty ones!) and has `empty-cells` set to // `hide`. - let hide = node.style(self.style_context()).get_inherited_table().empty_cells == EmptyCells::Hide && + let hide = node + .style(self.style_context()) + .get_inherited_table() + .empty_cells == + EmptyCells::Hide && node.children().all(|kid| { let position = kid.style(self.style_context()).get_box().position; - !kid.is_content() || - position == Position::Absolute || - position == Position::Fixed + !kid.is_content() || position == Position::Absolute || position == Position::Fixed }); let flow = FlowRef::new(Arc::new( - TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide))); + TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide), + )); self.build_flow_for_block_like(flow, node) } /// Builds a flow for a node with `display: list-item`. This yields a `ListItemFlow` with /// possibly other `BlockFlow`s or `InlineFlow`s underneath it. - fn build_flow_for_list_item(&mut self, - node: &ConcreteThreadSafeLayoutNode, - flotation: Float) - -> ConstructionResult { + fn build_flow_for_list_item( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + flotation: Float, + ) -> ConstructionResult { let flotation = FloatKind::from_property(flotation); let marker_fragments = match node.style(self.style_context()).get_list().list_style_image { ImageUrlOrNone::Url(ref url_value) => { let image_info = Box::new(ImageFragmentInfo::new( - url_value.url().map(|u| u.clone()), node, &self.layout_context + url_value.url().map(|u| u.clone()), + node, + &self.layout_context, )); - vec![Fragment::new(node, SpecificFragmentInfo::Image(image_info), self.layout_context)] - } - ImageUrlOrNone::None => { - match ListStyleTypeContent::from_list_style_type(node.style(self.style_context()) - .get_list() - .list_style_type) { - ListStyleTypeContent::None => Vec::new(), - ListStyleTypeContent::StaticText(ch) => { - let text = format!("{}\u{a0}", ch); - let mut unscanned_marker_fragments = LinkedList::new(); - unscanned_marker_fragments.push_back(Fragment::new( - node, - SpecificFragmentInfo::UnscannedText( - Box::new(UnscannedTextFragmentInfo::new(Box::<str>::from(text), None)) - ), - self.layout_context)); - let marker_fragments = - with_thread_local_font_context(self.layout_context, |mut font_context| { - TextRunScanner::new().scan_for_runs(&mut font_context, - unscanned_marker_fragments) - }); - marker_fragments.fragments - } - ListStyleTypeContent::GeneratedContent(info) => { - vec![Fragment::new(node, SpecificFragmentInfo::GeneratedContent(info), self.layout_context)] - } - } - } + vec![Fragment::new( + node, + SpecificFragmentInfo::Image(image_info), + self.layout_context, + )] + }, + ImageUrlOrNone::None => match ListStyleTypeContent::from_list_style_type( + node.style(self.style_context()).get_list().list_style_type, + ) { + ListStyleTypeContent::None => Vec::new(), + ListStyleTypeContent::StaticText(ch) => { + let text = format!("{}\u{a0}", ch); + let mut unscanned_marker_fragments = LinkedList::new(); + unscanned_marker_fragments.push_back(Fragment::new( + node, + SpecificFragmentInfo::UnscannedText(Box::new( + UnscannedTextFragmentInfo::new(Box::<str>::from(text), None), + )), + self.layout_context, + )); + let marker_fragments = + with_thread_local_font_context(self.layout_context, |mut font_context| { + TextRunScanner::new() + .scan_for_runs(&mut font_context, unscanned_marker_fragments) + }); + marker_fragments.fragments + }, + ListStyleTypeContent::GeneratedContent(info) => vec![Fragment::new( + node, + SpecificFragmentInfo::GeneratedContent(info), + self.layout_context, + )], + }, }; // If the list marker is outside, it becomes the special "outside fragment" that list item @@ -1318,52 +1516,73 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> // there. let mut initial_fragments = IntermediateInlineFragments::new(); let main_fragment = self.build_fragment_for_block(node); - let flow = match node.style(self.style_context()).get_list().list_style_position { - ListStylePosition::Outside => { - Arc::new(ListItemFlow::from_fragments_and_flotation( - main_fragment, marker_fragments, flotation)) - } + let flow = match node + .style(self.style_context()) + .get_list() + .list_style_position + { + ListStylePosition::Outside => Arc::new(ListItemFlow::from_fragments_and_flotation( + main_fragment, + marker_fragments, + flotation, + )), ListStylePosition::Inside => { for marker_fragment in marker_fragments { initial_fragments.fragments.push_back(marker_fragment) } Arc::new(ListItemFlow::from_fragments_and_flotation( - main_fragment, vec![], flotation)) - } + main_fragment, + vec![], + flotation, + )) + }, }; - self.build_flow_for_block_starting_with_fragments(FlowRef::new(flow), node, initial_fragments) + self.build_flow_for_block_starting_with_fragments( + FlowRef::new(flow), + node, + initial_fragments, + ) } /// Creates a fragment for a node with `display: table-column`. - fn build_fragments_for_table_column(&mut self, node: &ConcreteThreadSafeLayoutNode) - -> ConstructionResult { + fn build_fragments_for_table_column( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { // CSS 2.1 § 17.2.1. Treat all child fragments of a `table-column` as `display: none`. for kid in node.children() { self.set_flow_construction_result(&kid, ConstructionResult::None) } let specific = SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node)); - let construction_item = ConstructionItem::TableColumnFragment(Fragment::new(node, - specific, - self.layout_context)); + let construction_item = ConstructionItem::TableColumnFragment(Fragment::new( + node, + specific, + self.layout_context, + )); ConstructionResult::ConstructionItem(construction_item) } /// Builds a flow for a node with `display: table-column-group`. /// This yields a `TableColGroupFlow`. - fn build_flow_for_table_colgroup(&mut self, node: &ConcreteThreadSafeLayoutNode) - -> ConstructionResult { - let fragment = - Fragment::new(node, - SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node)), - self.layout_context); - let mut col_fragments = vec!(); + fn build_flow_for_table_colgroup( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + ) -> ConstructionResult { + let fragment = Fragment::new( + node, + SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node)), + self.layout_context, + ); + let mut col_fragments = vec![]; for kid in node.children() { // CSS 2.1 § 17.2.1. Treat all non-column child fragments of `table-column-group` // as `display: none`. - if let ConstructionResult::ConstructionItem(ConstructionItem::TableColumnFragment(fragment)) = - kid.get_construction_result() { + if let ConstructionResult::ConstructionItem(ConstructionItem::TableColumnFragment( + fragment, + )) = kid.get_construction_result() + { col_fragments.push(fragment) } } @@ -1372,17 +1591,21 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let specific = SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node)); col_fragments.push(Fragment::new(node, specific, self.layout_context)); } - let mut flow = FlowRef::new(Arc::new(TableColGroupFlow::from_fragments(fragment, col_fragments))); + let mut flow = FlowRef::new(Arc::new(TableColGroupFlow::from_fragments( + fragment, + col_fragments, + ))); flow.finish(); ConstructionResult::Flow(flow, AbsoluteDescendants::new()) } /// Builds a flow for a node with 'display: flex'. - fn build_flow_for_flex(&mut self, - node: &ConcreteThreadSafeLayoutNode, - float_kind: Option<FloatKind>) - -> ConstructionResult { + fn build_flow_for_flex( + &mut self, + node: &ConcreteThreadSafeLayoutNode, + float_kind: Option<FloatKind>, + ) -> ConstructionResult { let fragment = self.build_fragment_for_block(node); let flow = FlowRef::new(Arc::new(FlexFlow::from_fragment(fragment, float_kind))); self.build_flow_for_block_like(flow, node) @@ -1408,18 +1631,24 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> } for kid in node.children() { - if kid.flags().contains(LayoutDataFlags::HAS_NEWLY_CONSTRUCTED_FLOW) { + if kid + .flags() + .contains(LayoutDataFlags::HAS_NEWLY_CONSTRUCTED_FLOW) + { kid.remove_flags(LayoutDataFlags::HAS_NEWLY_CONSTRUCTED_FLOW); need_to_reconstruct = true } } if need_to_reconstruct { - return false + return false; } - if node.restyle_damage().contains(ServoRestyleDamage::RECONSTRUCT_FLOW) { - return false + if node + .restyle_damage() + .contains(ServoRestyleDamage::RECONSTRUCT_FLOW) + { + return false; } let mut set_has_newly_constructed_flow_flag = false; @@ -1427,7 +1656,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let style = node.style(self.style_context()); if style.can_be_fragmented() || style.is_multicol() { - return false + return false; } let damage = node.restyle_damage(); @@ -1439,77 +1668,83 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> // The node's flow is of the same type and has the same set of children and can // therefore be repaired by simply propagating damage and style to the flow. if !flow.is_block_flow() { - return false + return false; } let flow = FlowRef::deref_mut(flow); flow.mut_base().restyle_damage.insert(damage); flow.repair_style_and_bubble_inline_sizes(&style); true - } + }, ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments( - ref mut inline_fragments_construction_result)) => { + ref mut inline_fragments_construction_result, + )) => { if !inline_fragments_construction_result.splits.is_empty() { - return false + return false; } - for fragment in inline_fragments_construction_result.fragments - .fragments - .iter_mut() { + for fragment in inline_fragments_construction_result + .fragments + .fragments + .iter_mut() + { // Only mutate the styles of fragments that represent the dirty node (including // pseudo-element). if fragment.node != node.opaque() { - continue + continue; } if fragment.pseudo != node.get_pseudo_element_type() { - continue + continue; } match fragment.specific { SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => { - let flow_ref = FlowRef::deref_mut(&mut inline_block_fragment.flow_ref); + let flow_ref = + FlowRef::deref_mut(&mut inline_block_fragment.flow_ref); flow_ref.mut_base().restyle_damage.insert(damage); // FIXME(pcwalton): Fragment restyle damage too? flow_ref.repair_style_and_bubble_inline_sizes(&style); - } + }, SpecificFragmentInfo::InlineAbsoluteHypothetical( - ref mut inline_absolute_hypothetical_fragment) => { + ref mut inline_absolute_hypothetical_fragment, + ) => { let flow_ref = FlowRef::deref_mut( - &mut inline_absolute_hypothetical_fragment.flow_ref); + &mut inline_absolute_hypothetical_fragment.flow_ref, + ); flow_ref.mut_base().restyle_damage.insert(damage); // FIXME(pcwalton): Fragment restyle damage too? flow_ref.repair_style_and_bubble_inline_sizes(&style); - } - SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => { - let flow_ref = FlowRef::deref_mut( - &mut inline_absolute_fragment.flow_ref); + }, + SpecificFragmentInfo::InlineAbsolute( + ref mut inline_absolute_fragment, + ) => { + let flow_ref = + FlowRef::deref_mut(&mut inline_absolute_fragment.flow_ref); flow_ref.mut_base().restyle_damage.insert(damage); // FIXME(pcwalton): Fragment restyle damage too? flow_ref.repair_style_and_bubble_inline_sizes(&style); - } + }, SpecificFragmentInfo::ScannedText(_) => { // Text fragments in ConstructionResult haven't been scanned yet unreachable!() - } + }, SpecificFragmentInfo::GeneratedContent(_) | SpecificFragmentInfo::UnscannedText(_) => { // We can't repair this unscanned text; we need to update the // scanned text fragments. // // TODO: Add code to find and repair the ScannedText fragments? - return false - } + return false; + }, _ => { fragment.repair_style(&style); set_has_newly_constructed_flow_flag = true; - } + }, } } true - } - ConstructionResult::ConstructionItem(_) => { - false - } + }, + ConstructionResult::ConstructionItem(_) => false, } }; if set_has_newly_constructed_flow_flag { @@ -1520,8 +1755,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> } impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadSafeLayoutNode> - for FlowConstructor<'a, ConcreteThreadSafeLayoutNode> - where ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode { + for FlowConstructor<'a, ConcreteThreadSafeLayoutNode> +where + ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode, +{ // Construct Flow based on 'display', 'position', and 'float' values. // // CSS 2.1 Section 9.7 @@ -1544,8 +1781,12 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS let (display, float, positioning) = match node.type_id() { None => { // Pseudo-element. - (style.get_box().display, style.get_box().float, style.get_box().position) - } + ( + style.get_box().display, + style.get_box().float, + style.get_box().position, + ) + }, Some(LayoutNodeType::Element(_)) => { let original_display = style.get_box().original_display; // FIXME(emilio, #19771): This munged_display business is pretty @@ -1555,26 +1796,35 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS Display::Inline | Display::InlineBlock => original_display, _ => style.get_box().display, }; - (munged_display, style.get_box().float, style.get_box().position) - } - Some(LayoutNodeType::Text) => - (Display::Inline, Float::None, Position::Static), + ( + munged_display, + style.get_box().float, + style.get_box().position, + ) + }, + Some(LayoutNodeType::Text) => (Display::Inline, Float::None, Position::Static), }; - debug!("building flow for node: {:?} {:?} {:?} {:?}", display, float, positioning, node.type_id()); + debug!( + "building flow for node: {:?} {:?} {:?} {:?}", + display, + float, + positioning, + node.type_id() + ); // Switch on display and floatedness. match (display, float, positioning) { // `display: none` contributes no flow construction result. (Display::None, _, _) => { self.set_flow_construction_result(node, ConstructionResult::None); - } + }, // Table items contribute table flow construction results. (Display::Table, float_value, _) => { let construction_result = self.build_flow_for_table(node, float_value); self.set_flow_construction_result(node, construction_result) - } + }, // Absolutely positioned elements will have computed value of // `float` as 'none' and `display` as per the table. @@ -1582,17 +1832,16 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS // positioned, but inline we shouldn't try to construct a block // flow here - instead, let it match the inline case // below. - (Display::Block, _, Position::Absolute) | - (Display::Block, _, Position::Fixed) => { + (Display::Block, _, Position::Absolute) | (Display::Block, _, Position::Fixed) => { let construction_result = self.build_flow_for_block(node, None); self.set_flow_construction_result(node, construction_result) - } + }, // List items contribute their own special flows. (Display::ListItem, float_value, _) => { let construction_result = self.build_flow_for_list_item(node, float_value); self.set_flow_construction_result(node, construction_result) - } + }, // Inline items that are absolutely-positioned contribute inline fragment construction // results with a hypothetical fragment. @@ -1601,7 +1850,7 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS let construction_result = self.build_fragment_for_absolutely_positioned_inline(node); self.set_flow_construction_result(node, construction_result) - } + }, // Inline items contribute inline fragment construction results. // @@ -1609,32 +1858,32 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS (Display::Inline, Float::None, _) => { let construction_result = self.build_fragments_for_inline(node); self.set_flow_construction_result(node, construction_result) - } + }, // Inline-block items contribute inline fragment construction results. (Display::InlineBlock, Float::None, _) => { - let construction_result = self.build_fragment_for_inline_block_or_inline_flex(node, - Display::InlineBlock); + let construction_result = + self.build_fragment_for_inline_block_or_inline_flex(node, Display::InlineBlock); self.set_flow_construction_result(node, construction_result) - } + }, // Table items contribute table flow construction results. (Display::TableCaption, _, _) => { let construction_result = self.build_flow_for_table_caption(node); self.set_flow_construction_result(node, construction_result) - } + }, // Table items contribute table flow construction results. (Display::TableColumnGroup, _, _) => { let construction_result = self.build_flow_for_table_colgroup(node); self.set_flow_construction_result(node, construction_result) - } + }, // Table items contribute table flow construction results. (Display::TableColumn, _, _) => { let construction_result = self.build_fragments_for_table_column(node); self.set_flow_construction_result(node, construction_result) - } + }, // Table items contribute table flow construction results. (Display::TableRowGroup, _, _) | @@ -1642,43 +1891,42 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS (Display::TableFooterGroup, _, _) => { let construction_result = self.build_flow_for_table_rowgroup(node); self.set_flow_construction_result(node, construction_result) - } + }, // Table items contribute table flow construction results. (Display::TableRow, _, _) => { let construction_result = self.build_flow_for_table_row(node); self.set_flow_construction_result(node, construction_result) - } + }, // Table items contribute table flow construction results. (Display::TableCell, _, _) => { let construction_result = self.build_flow_for_table_cell(node); self.set_flow_construction_result(node, construction_result) - } + }, // Flex items contribute flex flow construction results. (Display::Flex, float_value, _) => { let float_kind = FloatKind::from_property(float_value); let construction_result = self.build_flow_for_flex(node, float_kind); self.set_flow_construction_result(node, construction_result) - } + }, (Display::InlineFlex, _, _) => { - let construction_result = self.build_fragment_for_inline_block_or_inline_flex(node, - Display::InlineFlex); + let construction_result = + self.build_fragment_for_inline_block_or_inline_flex(node, Display::InlineFlex); self.set_flow_construction_result(node, construction_result) - } + }, // Block flows that are not floated contribute block flow construction results. // // TODO(pcwalton): Make this only trigger for blocks and handle the other `display` // properties separately. - (_, float_value, _) => { let float_kind = FloatKind::from_property(float_value); let construction_result = self.build_flow_for_block(node, float_kind); self.set_flow_construction_result(node, construction_result) - } + }, } } } @@ -1698,7 +1946,9 @@ trait NodeUtils { } impl<ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNode - where ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode { +where + ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode, +{ fn is_replaced_content(&self) -> bool { match self.type_id() { Some(LayoutNodeType::Text) | @@ -1706,7 +1956,9 @@ impl<ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNode Some(LayoutNodeType::Element(LayoutElementType::HTMLIFrameElement)) | Some(LayoutNodeType::Element(LayoutElementType::HTMLCanvasElement)) | Some(LayoutNodeType::Element(LayoutElementType::SVGSVGElement)) => true, - Some(LayoutNodeType::Element(LayoutElementType::HTMLObjectElement)) => self.has_object_data(), + Some(LayoutNodeType::Element(LayoutElementType::HTMLObjectElement)) => { + self.has_object_data() + }, Some(LayoutNodeType::Element(_)) => false, None => self.get_pseudo_element_type().is_replaced_content(), } @@ -1718,7 +1970,7 @@ impl<ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNode PseudoElementType::After => &mut data.after_flow_construction_result, PseudoElementType::DetailsSummary => &mut data.details_summary_flow_construction_result, PseudoElementType::DetailsContent => &mut data.details_content_flow_construction_result, - PseudoElementType::Normal => &mut data.flow_construction_result, + PseudoElementType::Normal => &mut data.flow_construction_result, } } @@ -1745,7 +1997,10 @@ trait ObjectElement { fn object_data(&self) -> Option<ServoUrl>; } -impl<N> ObjectElement for N where N: ThreadSafeLayoutNode { +impl<N> ObjectElement for N +where + N: ThreadSafeLayoutNode, +{ fn has_object_data(&self) -> bool { let elem = self.as_element().unwrap(); let type_and_data = ( @@ -1754,7 +2009,7 @@ impl<N> ObjectElement for N where N: ThreadSafeLayoutNode { ); match type_and_data { (None, Some(uri)) => is_image_data(uri), - _ => false + _ => false, } } @@ -1766,7 +2021,7 @@ impl<N> ObjectElement for N where N: ThreadSafeLayoutNode { ); match type_and_data { (None, Some(uri)) if is_image_data(uri) => ServoUrl::parse(uri).ok(), - _ => None + _ => None, } } } @@ -1809,7 +2064,10 @@ impl FlowConstructionUtils for FlowRef { fn finish(&mut self) { if !opts::get().bubble_inline_sizes_separately { FlowRef::deref_mut(self).bubble_inline_sizes(); - FlowRef::deref_mut(self).mut_base().restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES); + FlowRef::deref_mut(self) + .mut_base() + .restyle_damage + .remove(ServoRestyleDamage::BUBBLE_ISIZES); } } } @@ -1817,48 +2075,61 @@ impl FlowConstructionUtils for FlowRef { /// Strips ignorable whitespace from the start of a list of fragments. pub fn strip_ignorable_whitespace_from_start(this: &mut LinkedList<Fragment>) { if this.is_empty() { - return // Fast path. + return; // Fast path. } let mut leading_fragments_consisting_of_solely_bidi_control_characters = LinkedList::new(); while !this.is_empty() { - match this.front_mut().as_mut().unwrap().strip_leading_whitespace_if_necessary() { + match this + .front_mut() + .as_mut() + .unwrap() + .strip_leading_whitespace_if_necessary() + { WhitespaceStrippingResult::RetainFragment => break, WhitespaceStrippingResult::FragmentContainedOnlyBidiControlCharacters => { - leading_fragments_consisting_of_solely_bidi_control_characters.push_back( - this.pop_front().unwrap()) - } + leading_fragments_consisting_of_solely_bidi_control_characters + .push_back(this.pop_front().unwrap()) + }, WhitespaceStrippingResult::FragmentContainedOnlyWhitespace => { let removed_fragment = this.pop_front().unwrap(); if let Some(ref mut remaining_fragment) = this.front_mut() { remaining_fragment.meld_with_prev_inline_fragment(&removed_fragment); } - } + }, } } - prepend_from(this, &mut leading_fragments_consisting_of_solely_bidi_control_characters); + prepend_from( + this, + &mut leading_fragments_consisting_of_solely_bidi_control_characters, + ); } /// Strips ignorable whitespace from the end of a list of fragments. pub fn strip_ignorable_whitespace_from_end(this: &mut LinkedList<Fragment>) { if this.is_empty() { - return + return; } let mut trailing_fragments_consisting_of_solely_bidi_control_characters = LinkedList::new(); while !this.is_empty() { - match this.back_mut().as_mut().unwrap().strip_trailing_whitespace_if_necessary() { + match this + .back_mut() + .as_mut() + .unwrap() + .strip_trailing_whitespace_if_necessary() + { WhitespaceStrippingResult::RetainFragment => break, WhitespaceStrippingResult::FragmentContainedOnlyBidiControlCharacters => { - trailing_fragments_consisting_of_solely_bidi_control_characters.push_front( - this.pop_back().unwrap()) - } + trailing_fragments_consisting_of_solely_bidi_control_characters + .push_front(this.pop_back().unwrap()) + }, WhitespaceStrippingResult::FragmentContainedOnlyWhitespace => { 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); } - } + }, } } this.append(&mut trailing_fragments_consisting_of_solely_bidi_control_characters); @@ -1875,16 +2146,16 @@ fn bidi_control_chars(style: &ServoArc<ComputedValues>) -> Option<(&'static str, // See the table in http://dev.w3.org/csswg/css-writing-modes/#unicode-bidi match (unicode_bidi, direction) { - (Normal, _) => None, - (Embed, Ltr) => Some(("\u{202A}", "\u{202C}")), - (Embed, Rtl) => Some(("\u{202B}", "\u{202C}")), - (Isolate, Ltr) => Some(("\u{2066}", "\u{2069}")), - (Isolate, Rtl) => Some(("\u{2067}", "\u{2069}")), - (BidiOverride, Ltr) => Some(("\u{202D}", "\u{202C}")), - (BidiOverride, Rtl) => Some(("\u{202E}", "\u{202C}")), - (IsolateOverride, Ltr) => Some(("\u{2068}\u{202D}", "\u{202C}\u{2069}")), - (IsolateOverride, Rtl) => Some(("\u{2068}\u{202E}", "\u{202C}\u{2069}")), - (Plaintext, _) => Some(("\u{2068}", "\u{2069}")), + (Normal, _) => None, + (Embed, Ltr) => Some(("\u{202A}", "\u{202C}")), + (Embed, Rtl) => Some(("\u{202B}", "\u{202C}")), + (Isolate, Ltr) => Some(("\u{2066}", "\u{2069}")), + (Isolate, Rtl) => Some(("\u{2067}", "\u{2069}")), + (BidiOverride, Ltr) => Some(("\u{202D}", "\u{202C}")), + (BidiOverride, Rtl) => Some(("\u{202E}", "\u{202C}")), + (IsolateOverride, Ltr) => Some(("\u{2068}\u{202D}", "\u{202C}\u{2069}")), + (IsolateOverride, Rtl) => Some(("\u{2068}\u{202E}", "\u{202C}\u{2069}")), + (Plaintext, _) => Some(("\u{2068}", "\u{2069}")), } } @@ -1897,21 +2168,24 @@ fn control_chars_to_fragment<E>( where E: TElement, { - let info = SpecificFragmentInfo::UnscannedText( - Box::new(UnscannedTextFragmentInfo::new(Box::<str>::from(text), None)) - ); + let info = SpecificFragmentInfo::UnscannedText(Box::new(UnscannedTextFragmentInfo::new( + Box::<str>::from(text), + None, + ))); let text_style = context.stylist.style_for_anonymous::<E>( &context.guards, &PseudoElement::ServoText, &node.style, ); - Fragment::from_opaque_node_and_style(node.address, - node.pseudo, - text_style, - node.selected_style.clone(), - restyle_damage, - info) + Fragment::from_opaque_node_and_style( + node.address, + node.pseudo, + text_style, + node.selected_style.clone(), + restyle_damage, + info, + ) } /// Convenience methods for computed CSS values @@ -1926,13 +2200,13 @@ impl ComputedValueUtils for ComputedValues { let border = self.get_border(); !padding.padding_top.is_definitely_zero() || - !padding.padding_right.is_definitely_zero() || - !padding.padding_bottom.is_definitely_zero() || - !padding.padding_left.is_definitely_zero() || - border.border_top_width.px() != 0. || - border.border_right_width.px() != 0. || - border.border_bottom_width.px() != 0. || - border.border_left_width.px() != 0. + !padding.padding_right.is_definitely_zero() || + !padding.padding_bottom.is_definitely_zero() || + !padding.padding_left.is_definitely_zero() || + border.border_top_width.px() != 0. || + border.border_right_width.px() != 0. || + border.border_bottom_width.px() != 0. || + border.border_left_width.px() != 0. } } @@ -1955,9 +2229,7 @@ struct Legalizer { impl Legalizer { /// Creates a new legalizer. fn new() -> Legalizer { - Legalizer { - stack: vec![], - } + Legalizer { stack: vec![] } } /// Makes the `child` flow a new child of `parent`. Anonymous flows are automatically inserted @@ -1967,13 +2239,12 @@ impl Legalizer { context: &SharedStyleContext, parent: &mut FlowRef, mut child: FlowRef, - ) - where + ) where E: TElement, { while !self.stack.is_empty() { if self.try_to_add_child::<E>(context, parent, &mut child) { - return + return; } self.flush_top_of_stack(parent) } @@ -2017,7 +2288,7 @@ impl Legalizer { (FlowClass::TableRow, FlowClass::TableCell) => { parent.add_new_child((*child).clone()); true - } + }, (FlowClass::TableWrapper, _) | (FlowClass::Table, _) | @@ -2028,12 +2299,13 @@ impl Legalizer { (_, FlowClass::TableRowGroup) | (_, FlowClass::TableRow) | (_, FlowClass::TableCaption) | - (_, FlowClass::TableCell) => { - false - } + (_, FlowClass::TableCell) => false, (FlowClass::Flex, FlowClass::Inline) => { - FlowRef::deref_mut(child).mut_base().flags.insert(FlowFlags::MARGINS_CANNOT_COLLAPSE); + FlowRef::deref_mut(child) + .mut_base() + .flags + .insert(FlowFlags::MARGINS_CANNOT_COLLAPSE); let mut block_wrapper = Legalizer::create_anonymous_flow::<E, _>( context, parent, @@ -2056,7 +2328,7 @@ impl Legalizer { block_wrapper.finish(); parent.add_new_child(block_wrapper); true - } + }, (FlowClass::Flex, _) => { { @@ -2071,12 +2343,12 @@ impl Legalizer { } parent.add_new_child((*child).clone()); true - } + }, _ => { parent.add_new_child((*child).clone()); true - } + }, } } @@ -2089,53 +2361,43 @@ impl Legalizer { /// Adds the anonymous flow that would be necessary to make an illegal child of `parent` legal /// to the stack. - fn push_next_anonymous_flow<E>( - &mut self, - context: &SharedStyleContext, - parent: &FlowRef, - ) + fn push_next_anonymous_flow<E>(&mut self, context: &SharedStyleContext, parent: &FlowRef) where E: TElement, { let parent_class = self.stack.last().unwrap_or(parent).class(); match parent_class { - FlowClass::TableRow => { - self.push_new_anonymous_flow::<E, _>( - context, - parent, - &[PseudoElement::ServoAnonymousTableCell], - SpecificFragmentInfo::TableCell, - TableCellFlow::from_fragment, - ) - } - FlowClass::Table | FlowClass::TableRowGroup => { - self.push_new_anonymous_flow::<E, _>( - context, - parent, - &[PseudoElement::ServoAnonymousTableRow], - SpecificFragmentInfo::TableRow, - TableRowFlow::from_fragment, - ) - } - FlowClass::TableWrapper => { - self.push_new_anonymous_flow::<E, _>( - context, - parent, - &[PseudoElement::ServoAnonymousTable], - SpecificFragmentInfo::Table, - TableFlow::from_fragment, - ) - } - _ => { - self.push_new_anonymous_flow::<E, _>( - context, - parent, - &[PseudoElement::ServoTableWrapper, - PseudoElement::ServoAnonymousTableWrapper], - SpecificFragmentInfo::TableWrapper, - TableWrapperFlow::from_fragment, - ) - } + FlowClass::TableRow => self.push_new_anonymous_flow::<E, _>( + context, + parent, + &[PseudoElement::ServoAnonymousTableCell], + SpecificFragmentInfo::TableCell, + TableCellFlow::from_fragment, + ), + FlowClass::Table | FlowClass::TableRowGroup => self.push_new_anonymous_flow::<E, _>( + context, + parent, + &[PseudoElement::ServoAnonymousTableRow], + SpecificFragmentInfo::TableRow, + TableRowFlow::from_fragment, + ), + FlowClass::TableWrapper => self.push_new_anonymous_flow::<E, _>( + context, + parent, + &[PseudoElement::ServoAnonymousTable], + SpecificFragmentInfo::Table, + TableFlow::from_fragment, + ), + _ => self.push_new_anonymous_flow::<E, _>( + context, + parent, + &[ + PseudoElement::ServoTableWrapper, + PseudoElement::ServoAnonymousTableWrapper, + ], + SpecificFragmentInfo::TableWrapper, + TableWrapperFlow::from_fragment, + ), } } @@ -2146,9 +2408,8 @@ impl Legalizer { reference: &FlowRef, pseudos: &[PseudoElement], specific_fragment_info: SpecificFragmentInfo, - constructor: extern "Rust" fn(Fragment) -> F, - ) - where + constructor: fn(Fragment) -> F, + ) where E: TElement, F: Flow, { @@ -2172,7 +2433,7 @@ impl Legalizer { reference: &FlowRef, pseudos: &[PseudoElement], specific_fragment_info: SpecificFragmentInfo, - constructor: extern "Rust" fn(Fragment) -> F, + constructor: fn(Fragment) -> F, ) -> FlowRef where E: TElement, @@ -2181,18 +2442,14 @@ impl Legalizer { let reference_block = reference.as_block(); let mut new_style = reference_block.fragment.style.clone(); for pseudo in pseudos { - new_style = context.stylist.style_for_anonymous::<E>( - &context.guards, - pseudo, - &new_style, - ); + new_style = + context + .stylist + .style_for_anonymous::<E>(&context.guards, pseudo, &new_style); } - let fragment = - reference_block.fragment.create_similar_anonymous_fragment( - new_style, - specific_fragment_info, - ); + let fragment = reference_block + .fragment + .create_similar_anonymous_fragment(new_style, specific_fragment_info); FlowRef::new(Arc::new(constructor(fragment))) } } - diff --git a/components/layout/context.rs b/components/layout/context.rs index f851d06799d..a87173d633e 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -32,7 +32,8 @@ pub type LayoutFontContext = FontContext<FontCacheThread>; thread_local!(static FONT_CONTEXT_KEY: RefCell<Option<LayoutFontContext>> = RefCell::new(None)); pub fn with_thread_local_font_context<F, R>(layout_context: &LayoutContext, f: F) -> R - where F: FnOnce(&mut LayoutFontContext) -> R +where + F: FnOnce(&mut LayoutFontContext) -> R, { FONT_CONTEXT_KEY.with(|k| { let mut font_context = k.borrow_mut(); @@ -69,9 +70,11 @@ pub struct LayoutContext<'a> { pub font_cache_thread: Mutex<FontCacheThread>, /// A cache of WebRender image info. - pub webrender_image_cache: Arc<RwLock<HashMap<(ServoUrl, UsePlaceholder), - WebRenderImageInfo, - BuildHasherDefault<FnvHasher>>>>, + pub webrender_image_cache: Arc< + RwLock< + HashMap<(ServoUrl, UsePlaceholder), WebRenderImageInfo, BuildHasherDefault<FnvHasher>>, + >, + >, /// Paint worklets pub registered_painters: &'a RegisteredPainters, @@ -101,11 +104,12 @@ impl<'a> LayoutContext<'a> { &self.style_context } - pub fn get_or_request_image_or_meta(&self, - node: OpaqueNode, - url: ServoUrl, - use_placeholder: UsePlaceholder) - -> Option<ImageOrMetadataAvailable> { + pub fn get_or_request_image_or_meta( + &self, + node: OpaqueNode, + url: ServoUrl, + use_placeholder: UsePlaceholder, + ) -> Option<ImageOrMetadataAvailable> { //XXXjdm For cases where we do not request an image, we still need to // ensure the node gets another script-initiated reflow or it // won't be requested at all. @@ -116,9 +120,9 @@ impl<'a> LayoutContext<'a> { }; // See if the image is already available - let result = self.image_cache.find_image_or_metadata(url.clone(), - use_placeholder, - can_request); + let result = + self.image_cache + .find_image_or_metadata(url.clone(), use_placeholder, can_request); match result { Ok(image_or_metadata) => Some(image_or_metadata), // Image failed to load, so just return nothing @@ -130,9 +134,14 @@ impl<'a> LayoutContext<'a> { node: node.to_untrusted_node_address(), id: id, }; - self.pending_images.as_ref().unwrap().lock().unwrap().push(image); + self.pending_images + .as_ref() + .unwrap() + .lock() + .unwrap() + .push(image); None - } + }, // Image has been requested, is still pending. Return no image for this paint loop. // When the image loads it will trigger a reflow and/or repaint. Err(ImageState::Pending(id)) => { @@ -148,19 +157,22 @@ impl<'a> LayoutContext<'a> { pending_images.lock().unwrap().push(image); } None - } + }, } } - pub fn get_webrender_image_for_url(&self, - node: OpaqueNode, - url: ServoUrl, - use_placeholder: UsePlaceholder) - -> Option<WebRenderImageInfo> { - if let Some(existing_webrender_image) = self.webrender_image_cache - .read() - .get(&(url.clone(), use_placeholder)) { - return Some((*existing_webrender_image).clone()) + pub fn get_webrender_image_for_url( + &self, + node: OpaqueNode, + url: ServoUrl, + use_placeholder: UsePlaceholder, + ) -> Option<WebRenderImageInfo> { + if let Some(existing_webrender_image) = self + .webrender_image_cache + .read() + .get(&(url.clone(), use_placeholder)) + { + return Some((*existing_webrender_image).clone()); } match self.get_or_request_image_or_meta(node, url.clone(), use_placeholder) { @@ -170,11 +182,10 @@ impl<'a> LayoutContext<'a> { Some(image_info) } else { let mut webrender_image_cache = self.webrender_image_cache.write(); - webrender_image_cache.insert((url, use_placeholder), - image_info); + webrender_image_cache.insert((url, use_placeholder), image_info); Some(image_info) } - } + }, None | Some(ImageOrMetadataAvailable::MetadataAvailable(_)) => None, } } diff --git a/components/layout/data.rs b/components/layout/data.rs index 20ff5ef2b71..2df8ea6432b 100644 --- a/components/layout/data.rs +++ b/components/layout/data.rs @@ -24,7 +24,6 @@ impl StyleAndLayoutData { } } - /// Data that layout associates with a node. #[repr(C)] pub struct LayoutData { diff --git a/components/layout/display_list/background.rs b/components/layout/display_list/background.rs index f66f70ee17a..6e4751f3012 100644 --- a/components/layout/display_list/background.rs +++ b/components/layout/display_list/background.rs @@ -444,8 +444,7 @@ fn convert_gradient_stops( .filter_map(|item| match *item { GenericGradientItem::ColorStop(ref stop) => Some(*stop), _ => None, - }) - .collect::<Vec<_>>(); + }).collect::<Vec<_>>(); assert!(stop_items.len() >= 2); diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs index 2d481d2ceff..4a9a77a7fb1 100644 --- a/components/layout/display_list/builder.rs +++ b/components/layout/display_list/builder.rs @@ -1414,8 +1414,7 @@ impl FragmentDisplayListBuilding for Fragment { url.clone(), UsePlaceholder::No, ) - }) - .and_then(|image| { + }).and_then(|image| { build_image_border_details(image, border_style_struct, outset_layout) }), }; @@ -1957,8 +1956,7 @@ impl FragmentDisplayListBuilding for Fragment { .send(CanvasMsg::FromLayout( FromLayoutMsg::SendData(sender), canvas_fragment_info.canvas_id.clone(), - )) - .unwrap(); + )).unwrap(); receiver.recv().unwrap().image_key }, None => return, @@ -2070,10 +2068,12 @@ impl FragmentDisplayListBuilding for Fragment { // FIXME(pcwalton): Get the real container size. let container_size = Size2D::zero(); let metrics = &text_fragment.run.font_metrics; - let baseline_origin = stacking_relative_content_box.origin + - LogicalPoint::new(self.style.writing_mode, Au(0), metrics.ascent) - .to_physical(self.style.writing_mode, container_size) - .to_vector(); + let baseline_origin = stacking_relative_content_box.origin + LogicalPoint::new( + self.style.writing_mode, + Au(0), + metrics.ascent, + ).to_physical(self.style.writing_mode, container_size) + .to_vector(); // Base item for all text/shadows let base = state.create_base_display_item( diff --git a/components/layout/display_list/items.rs b/components/layout/display_list/items.rs index de5e324aee8..51e44e25cdb 100644 --- a/components/layout/display_list/items.rs +++ b/components/layout/display_list/items.rs @@ -513,27 +513,29 @@ impl ClippingRegion { /// This is a quick, not a precise, test; it can yield false positives. #[inline] pub fn might_intersect_point(&self, point: &LayoutPoint) -> bool { - self.main.contains(point) && - self.complex - .iter() - .all(|complex| complex.rect.contains(point)) + self.main.contains(point) && self + .complex + .iter() + .all(|complex| complex.rect.contains(point)) } /// Returns true if this clipping region might intersect the given rectangle and false /// otherwise. This is a quick, not a precise, test; it can yield false positives. #[inline] pub fn might_intersect_rect(&self, rect: &LayoutRect) -> bool { - self.main.intersects(rect) && - self.complex - .iter() - .all(|complex| complex.rect.intersects(rect)) + self.main.intersects(rect) && self + .complex + .iter() + .all(|complex| complex.rect.intersects(rect)) } /// Returns true if this clipping region completely surrounds the given rect. #[inline] pub fn does_not_clip_rect(&self, rect: &LayoutRect) -> bool { - self.main.contains(&rect.origin) && self.main.contains(&rect.bottom_right()) && - self.complex.iter().all(|complex| { + self.main.contains(&rect.origin) && self.main.contains(&rect.bottom_right()) && self + .complex + .iter() + .all(|complex| { complex.rect.contains(&rect.origin) && complex.rect.contains(&rect.bottom_right()) }) } @@ -588,8 +590,7 @@ impl ClippingRegion { rect: complex.rect.translate(delta), radii: complex.radii, mode: complex.mode, - }) - .collect(), + }).collect(), } } diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 2864c922874..e1baa390382 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -45,25 +45,25 @@ enum AxisSize { impl AxisSize { /// Generate a new available cross or main axis size from the specified size of the container, /// containing block size, min constraint, and max constraint - pub fn new(size: LengthOrPercentageOrAuto, content_size: Option<Au>, min: LengthOrPercentage, - max: LengthOrPercentageOrNone) -> AxisSize { + pub fn new( + size: LengthOrPercentageOrAuto, + content_size: Option<Au>, + min: LengthOrPercentage, + max: LengthOrPercentageOrNone, + ) -> AxisSize { match size { LengthOrPercentageOrAuto::Length(length) => AxisSize::Definite(Au::from(length)), - LengthOrPercentageOrAuto::Percentage(percent) => { - match content_size { - Some(size) => AxisSize::Definite(size.scale_by(percent.0)), - None => AxisSize::Infinite - } - } - LengthOrPercentageOrAuto::Calc(calc) => { - match calc.to_used_value(content_size) { - Some(length) => AxisSize::Definite(length), - None => AxisSize::Infinite, - } - } + LengthOrPercentageOrAuto::Percentage(percent) => match content_size { + Some(size) => AxisSize::Definite(size.scale_by(percent.0)), + None => AxisSize::Infinite, + }, + LengthOrPercentageOrAuto::Calc(calc) => match calc.to_used_value(content_size) { + Some(length) => AxisSize::Definite(length), + None => AxisSize::Infinite, + }, LengthOrPercentageOrAuto::Auto => { AxisSize::MinMax(SizeConstraint::new(content_size, min, max, None)) - } + }, } } } @@ -112,7 +112,7 @@ struct FlexItem { /// Whether the main size has met its constraint. pub is_frozen: bool, /// True if this flow has property 'visibility::collapse'. - pub is_strut: bool + pub is_strut: bool, } impl FlexItem { @@ -133,7 +133,7 @@ impl FlexItem { flex_shrink: flex_shrink.into(), order: order, is_frozen: false, - is_strut: false + is_strut: false, } } @@ -147,41 +147,61 @@ impl FlexItem { // should change to LengthOrPercentageOrAuto for automatic implied minimal size. // https://drafts.csswg.org/css-flexbox-1/#min-size-auto Direction::Inline => { - let basis = from_flex_basis(block.fragment.style.get_position().flex_basis, - block.fragment.style.content_inline_size(), - containing_length); + let basis = from_flex_basis( + block.fragment.style.get_position().flex_basis, + block.fragment.style.content_inline_size(), + containing_length, + ); // These methods compute auto margins to zero length, which is exactly what we want. block.fragment.compute_border_and_padding(containing_length); - block.fragment.compute_inline_direction_margins(containing_length); - block.fragment.compute_block_direction_margins(containing_length); + block + .fragment + .compute_inline_direction_margins(containing_length); + block + .fragment + .compute_block_direction_margins(containing_length); let (border_padding, margin) = block.fragment.surrounding_intrinsic_inline_size(); - let content_size = block.base.intrinsic_inline_sizes.preferred_inline_size - - border_padding - - margin - + block.fragment.box_sizing_boundary(direction); + let content_size = block.base.intrinsic_inline_sizes.preferred_inline_size - + border_padding - + margin + + block.fragment.box_sizing_boundary(direction); self.base_size = basis.specified_or_default(content_size); - self.max_size = - block.fragment.style.max_inline_size() - .to_used_value(containing_length) - .unwrap_or(MAX_AU); - self.min_size = block.fragment.style.min_inline_size().to_used_value(containing_length); - } + self.max_size = block + .fragment + .style + .max_inline_size() + .to_used_value(containing_length) + .unwrap_or(MAX_AU); + self.min_size = block + .fragment + .style + .min_inline_size() + .to_used_value(containing_length); + }, Direction::Block => { - let basis = from_flex_basis(block.fragment.style.get_position().flex_basis, - block.fragment.style.content_block_size(), - containing_length); - let content_size = block.fragment.border_box.size.block - - block.fragment.border_padding.block_start_end() - + block.fragment.box_sizing_boundary(direction); + let basis = from_flex_basis( + block.fragment.style.get_position().flex_basis, + block.fragment.style.content_block_size(), + containing_length, + ); + let content_size = block.fragment.border_box.size.block - + block.fragment.border_padding.block_start_end() + + block.fragment.box_sizing_boundary(direction); self.base_size = basis.specified_or_default(content_size); - self.max_size = - block.fragment.style.max_block_size() - .to_used_value(containing_length) - .unwrap_or(MAX_AU); - self.min_size = block.fragment.style.min_block_size().to_used_value(containing_length); - } + self.max_size = block + .fragment + .style + .max_block_size() + .to_used_value(containing_length) + .unwrap_or(MAX_AU); + self.min_size = block + .fragment + .style + .min_block_size() + .to_used_value(containing_length); + }, } } @@ -192,13 +212,14 @@ impl FlexItem { let outer_width = match direction { Direction::Inline => { fragment.border_padding.inline_start_end() + fragment.margin.inline_start_end() - } + }, Direction::Block => { fragment.border_padding.block_start_end() + fragment.margin.block_start_end() - } + }, }; - max(self.min_size, min(self.base_size, self.max_size)) - - fragment.box_sizing_boundary(direction) + outer_width + max(self.min_size, min(self.base_size, self.max_size)) - + fragment.box_sizing_boundary(direction) + + outer_width } /// Returns the number of auto margins in given direction. @@ -213,7 +234,7 @@ impl FlexItem { if margin.inline_end == LengthOrPercentageOrAuto::Auto { margin_count += 1; } - } + }, Direction::Block => { if margin.block_start == LengthOrPercentageOrAuto::Auto { margin_count += 1; @@ -221,7 +242,7 @@ impl FlexItem { if margin.block_end == LengthOrPercentageOrAuto::Auto { margin_count += 1; } - } + }, } margin_count } @@ -247,7 +268,7 @@ impl FlexLine { range: range, auto_margin_count: auto_margin_count, free_space: free_space, - cross_size: Au(0) + cross_size: Au(0), } } @@ -265,17 +286,20 @@ impl FlexLine { // https://drafts.csswg.org/css-flexbox/#resolve-flexible-lengths for item in items.iter_mut().filter(|i| !(i.is_strut && collapse)) { item.main_size = max(item.min_size, min(item.base_size, item.max_size)); - if (self.free_space > Au(0) && (item.flex_grow == 0.0 || item.base_size >= item.max_size)) || - (self.free_space < Au(0) && (item.flex_shrink == 0.0 || item.base_size <= item.min_size)) { - item.is_frozen = true; - } else { - item.is_frozen = false; - total_grow += item.flex_grow; - total_shrink += item.flex_shrink; - // The scaled factor is used to calculate flex shrink - total_scaled += item.flex_shrink * item.base_size.0 as f32; - active_count += 1; - } + if (self.free_space > Au(0) && + (item.flex_grow == 0.0 || item.base_size >= item.max_size)) || + (self.free_space < Au(0) && + (item.flex_shrink == 0.0 || item.base_size <= item.min_size)) + { + item.is_frozen = true; + } else { + item.is_frozen = false; + total_grow += item.flex_grow; + total_shrink += item.flex_shrink; + // The scaled factor is used to calculate flex shrink + total_scaled += item.flex_shrink * item.base_size.0 as f32; + active_count += 1; + } } let initial_free_space = self.free_space; @@ -291,12 +315,19 @@ impl FlexLine { }; total_variation = Au(0); - for item in items.iter_mut().filter(|i| !i.is_frozen).filter(|i| !(i.is_strut && collapse)) { + for item in items + .iter_mut() + .filter(|i| !i.is_frozen) + .filter(|i| !(i.is_strut && collapse)) + { // Use this and the 'abs()' below to make the code work in both grow and shrink scenarios. let (factor, end_size) = if self.free_space > Au(0) { (item.flex_grow / total_grow, item.max_size) } else { - (item.flex_shrink * item.base_size.0 as f32 / total_scaled, item.min_size) + ( + item.flex_shrink * item.base_size.0 as f32 / total_scaled, + item.min_size, + ) }; let variation = self.free_space.scale_by(factor); if variation.0.abs() >= (end_size - item.main_size).0.abs() { @@ -343,13 +374,11 @@ pub struct FlexFlow { /// True if this flex container can be multiline. is_wrappable: bool, /// True if the cross direction is reversed. - cross_reverse: bool + cross_reverse: bool, } impl FlexFlow { - pub fn from_fragment(fragment: Fragment, - flotation: Option<FloatKind>) - -> FlexFlow { + pub fn from_fragment(fragment: Fragment, flotation: Option<FloatKind>) -> FlexFlow { let main_mode; let main_reverse; let is_wrappable; @@ -363,8 +392,7 @@ impl FlexFlow { FlexDirection::ColumnReverse => (Direction::Block, true), }; main_mode = mode; - main_reverse = - reverse == style.writing_mode.is_bidi_ltr(); + main_reverse = reverse == style.writing_mode.is_bidi_ltr(); let (wrappable, reverse) = match fragment.style.get_position().flex_wrap { FlexWrap::Nowrap => (false, false), FlexWrap::Wrap => (true, false), @@ -384,7 +412,7 @@ impl FlexFlow { items: Vec::new(), main_reverse: main_reverse, is_wrappable: is_wrappable, - cross_reverse: cross_reverse + cross_reverse: cross_reverse, } } @@ -414,7 +442,10 @@ impl FlexFlow { let kid = children.get(item.index); item.init_sizes(kid, container_size, self.main_mode); let outer_main_size = item.outer_main_size(kid, self.main_mode); - if total_line_size + outer_main_size > container_size && end != start && self.is_wrappable { + if total_line_size + outer_main_size > container_size && + end != start && + self.is_wrappable + { break; } margin_count += item.auto_margin_count(kid, self.main_mode); @@ -439,7 +470,8 @@ impl FlexFlow { if !fixed_width { for kid in self.block_flow.base.children.iter_mut() { let base = kid.mut_base(); - let is_absolutely_positioned = base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); + let is_absolutely_positioned = + base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); if !is_absolutely_positioned { let flex_item_inline_sizes = IntrinsicISizes { minimum_inline_size: base.intrinsic_inline_sizes.minimum_inline_size, @@ -465,15 +497,18 @@ impl FlexFlow { if !fixed_width { for kid in self.block_flow.base.children.iter_mut() { let base = kid.mut_base(); - let is_absolutely_positioned = base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); + let is_absolutely_positioned = + base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); if !is_absolutely_positioned { - computation.content_intrinsic_sizes.minimum_inline_size = - max(computation.content_intrinsic_sizes.minimum_inline_size, - base.intrinsic_inline_sizes.minimum_inline_size); - - computation.content_intrinsic_sizes.preferred_inline_size = - max(computation.content_intrinsic_sizes.preferred_inline_size, - base.intrinsic_inline_sizes.preferred_inline_size); + computation.content_intrinsic_sizes.minimum_inline_size = max( + computation.content_intrinsic_sizes.minimum_inline_size, + base.intrinsic_inline_sizes.minimum_inline_size, + ); + + computation.content_intrinsic_sizes.preferred_inline_size = max( + computation.content_intrinsic_sizes.preferred_inline_size, + base.intrinsic_inline_sizes.preferred_inline_size, + ); } } } @@ -483,11 +518,13 @@ impl FlexFlow { // TODO(zentner): This function needs to be radically different for multi-line flexbox. // Currently, this is the core of BlockFlow::propagate_assigned_inline_size_to_children() with // all float and table logic stripped out. - fn block_mode_assign_inline_sizes(&mut self, - _layout_context: &LayoutContext, - inline_start_content_edge: Au, - inline_end_content_edge: Au, - content_inline_size: Au) { + fn block_mode_assign_inline_sizes( + &mut self, + _layout_context: &LayoutContext, + inline_start_content_edge: Au, + inline_end_content_edge: Au, + content_inline_size: Au, + ) { let _scope = layout_debug_scope!("flex::block_mode_assign_inline_sizes"); debug!("flex::block_mode_assign_inline_sizes"); @@ -496,19 +533,22 @@ impl FlexFlow { let container_block_size = match self.available_main_size { AxisSize::Definite(length) => Some(length), - _ => None + _ => None, }; let container_inline_size = match self.available_cross_size { AxisSize::Definite(length) => length, AxisSize::MinMax(ref constraint) => constraint.clamp(content_inline_size), - AxisSize::Infinite => content_inline_size + AxisSize::Infinite => content_inline_size, }; let mut children = self.block_flow.base.children.random_access_mut(); for kid in &mut self.items { let kid_base = children.get(kid.index).mut_base(); kid_base.block_container_explicit_block_size = container_block_size; - if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { + if kid_base + .flags + .contains(FlowFlags::INLINE_POSITION_IS_STATIC) + { // The inline-start margin edge of the child flow is at our inline-start content // edge, and its inline-size is our content inline-size. kid_base.position.start.i = @@ -525,11 +565,13 @@ impl FlexFlow { } } - fn inline_mode_assign_inline_sizes(&mut self, - layout_context: &LayoutContext, - inline_start_content_edge: Au, - _inline_end_content_edge: Au, - content_inline_size: Au) { + fn inline_mode_assign_inline_sizes( + &mut self, + layout_context: &LayoutContext, + inline_start_content_edge: Au, + _inline_end_content_edge: Au, + content_inline_size: Au, + ) { let _scope = layout_debug_scope!("flex::inline_mode_assign_inline_sizes"); debug!("inline_mode_assign_inline_sizes"); @@ -551,17 +593,25 @@ impl FlexFlow { self.block_flow.base.position.size.inline = inline_size; // Calculate non-auto block size to pass to children. - let box_border = self.block_flow.fragment.box_sizing_boundary(Direction::Block); - - let parent_container_size = - self.block_flow.explicit_block_containing_size(layout_context.shared_context()); + let box_border = self + .block_flow + .fragment + .box_sizing_boundary(Direction::Block); + + let parent_container_size = self + .block_flow + .explicit_block_containing_size(layout_context.shared_context()); // https://drafts.csswg.org/css-ui-3/#box-sizing let explicit_content_size = self - .block_flow - .explicit_block_size(parent_container_size) - .map(|x| max(x - box_border, Au(0))); - let containing_block_text_align = - self.block_flow.fragment.style().get_inherited_text().text_align; + .block_flow + .explicit_block_size(parent_container_size) + .map(|x| max(x - box_border, Au(0))); + let containing_block_text_align = self + .block_flow + .fragment + .style() + .get_inherited_text() + .text_align; while let Some(mut line) = self.get_flex_line(inline_size) { let items = &mut self.items[line.range.clone()]; @@ -572,32 +622,42 @@ impl FlexFlow { let item_count = items.len() as i32; let mut cur_i = inline_start_content_edge; let item_interval = if line.free_space >= Au(0) && line.auto_margin_count == 0 { - match self.block_flow.fragment.style().get_position().justify_content { + match self + .block_flow + .fragment + .style() + .get_position() + .justify_content + { JustifyContent::SpaceBetween => { if item_count == 1 { Au(0) } else { line.free_space / (item_count - 1) } - } - JustifyContent::SpaceAround => { - line.free_space / item_count - } + }, + JustifyContent::SpaceAround => line.free_space / item_count, _ => Au(0), } } else { Au(0) }; - match self.block_flow.fragment.style().get_position().justify_content { + match self + .block_flow + .fragment + .style() + .get_position() + .justify_content + { // Overflow equally in both ends of line. JustifyContent::Center | JustifyContent::SpaceAround => { cur_i += (line.free_space - item_interval * (item_count - 1)) / 2; - } + }, JustifyContent::FlexEnd => { cur_i += line.free_space; - } - _ => {} + }, + _ => {}, } let mut children = self.block_flow.base.children.random_access_mut(); @@ -613,19 +673,18 @@ impl FlexFlow { block.base.flags.set_text_align(containing_block_text_align); let margin = block.fragment.style().logical_margin(); - let auto_len = - if line.auto_margin_count == 0 || line.free_space <= Au(0) { - Au(0) - } else { - line.free_space / line.auto_margin_count - }; + let auto_len = if line.auto_margin_count == 0 || line.free_space <= Au(0) { + Au(0) + } else { + line.free_space / line.auto_margin_count + }; let margin_inline_start = MaybeAuto::from_style(margin.inline_start, inline_size) .specified_or_default(auto_len); let margin_inline_end = MaybeAuto::from_style(margin.inline_end, inline_size) .specified_or_default(auto_len); - let item_inline_size = item.main_size - - block.fragment.box_sizing_boundary(self.main_mode) - + block.fragment.border_padding.inline_start_end(); + let item_inline_size = item.main_size - + block.fragment.box_sizing_boundary(self.main_mode) + + block.fragment.border_padding.inline_start_end(); let item_outer_size = item_inline_size + block.fragment.margin.inline_start_end(); block.fragment.margin.inline_start = margin_inline_start; @@ -635,7 +694,7 @@ impl FlexFlow { block.base.position.start.i = if !self.main_reverse { cur_i } else { - inline_start_content_edge * 2 + content_inline_size - cur_i - item_outer_size + inline_start_content_edge * 2 + content_inline_size - cur_i - item_outer_size }; block.base.position.size.inline = item_outer_size; cur_i += item_outer_size + item_interval; @@ -669,7 +728,12 @@ impl FlexFlow { let _scope = layout_debug_scope!("flex::inline_mode_assign_block_size"); let line_count = self.lines.len() as i32; - let line_align = self.block_flow.fragment.style().get_position().align_content; + let line_align = self + .block_flow + .fragment + .style() + .get_position() + .align_content; let mut cur_b = self.block_flow.fragment.border_padding.block_start; let mut total_cross_size = Au(0); let mut line_interval = Au(0); @@ -679,22 +743,27 @@ impl FlexFlow { for line in self.lines.iter_mut() { for item in &self.items[line.range.clone()] { let fragment = &children.get(item.index).as_block().fragment; - line.cross_size = max(line.cross_size, - fragment.border_box.size.block + - fragment.margin.block_start_end()); + line.cross_size = max( + line.cross_size, + fragment.border_box.size.block + fragment.margin.block_start_end(), + ); } total_cross_size += line.cross_size; } } - let box_border = self.block_flow.fragment.box_sizing_boundary(Direction::Block); - let parent_container_size = - self.block_flow.explicit_block_containing_size(layout_context.shared_context()); + let box_border = self + .block_flow + .fragment + .box_sizing_boundary(Direction::Block); + let parent_container_size = self + .block_flow + .explicit_block_containing_size(layout_context.shared_context()); // https://drafts.csswg.org/css-ui-3/#box-sizing let explicit_content_size = self - .block_flow - .explicit_block_size(parent_container_size) - .map(|x| max(x - box_border, Au(0))); + .block_flow + .explicit_block_size(parent_container_size) + .map(|x| max(x - box_border, Au(0))); if let Some(container_block_size) = explicit_content_size { let free_space = container_block_size - total_cross_size; @@ -713,25 +782,25 @@ impl FlexFlow { } else { free_space / (line_count - 1) } - } + }, AlignContent::SpaceAround => { if line_count == 0 { Au(0) } else { free_space / line_count } - } + }, _ => Au(0), }; match line_align { AlignContent::Center | AlignContent::SpaceAround => { cur_b += (free_space - line_interval * (line_count - 1)) / 2; - } + }, AlignContent::FlexEnd => { cur_b += free_space; - } - _ => {} + }, + _ => {}, } } @@ -744,8 +813,9 @@ impl FlexFlow { let mut margin_block_start = block.fragment.margin.block_start; let mut margin_block_end = block.fragment.margin.block_end; - let mut free_space = line.cross_size - block.base.position.size.block - - block.fragment.margin.block_start_end(); + let mut free_space = line.cross_size - + block.base.position.size.block - + block.fragment.margin.block_start_end(); // The spec is a little vague here, but if I understand it correctly, the outer // cross size of item should equal to the line size if any auto margin exists. @@ -758,29 +828,31 @@ impl FlexFlow { free_space / auto_margin_count }; } - margin_block_end = line.cross_size - margin_block_start - block.base.position.size.block; + margin_block_end = + line.cross_size - margin_block_start - block.base.position.size.block; free_space = Au(0); } let self_align = block.fragment.style().get_position().align_self; if self_align == AlignSelf::Stretch && - block.fragment.style().content_block_size() == LengthOrPercentageOrAuto::Auto { - free_space = Au(0); - block.base.block_container_explicit_block_size = Some(line.cross_size); - block.base.position.size.block = - line.cross_size - margin_block_start - margin_block_end; - block.fragment.border_box.size.block = block.base.position.size.block; - // FIXME(stshine): item with 'align-self: stretch' and auto cross size should act - // as if it has a fixed cross size, all child blocks should resolve against it. - // block.assign_block_size(layout_context); - } - block.base.position.start.b = margin_block_start + - if !self.cross_reverse { - cur_b - } else { - self.block_flow.fragment.border_padding.block_start * 2 - + total_cross_size - cur_b - line.cross_size - }; + block.fragment.style().content_block_size() == LengthOrPercentageOrAuto::Auto + { + free_space = Au(0); + block.base.block_container_explicit_block_size = Some(line.cross_size); + block.base.position.size.block = + line.cross_size - margin_block_start - margin_block_end; + block.fragment.border_box.size.block = block.base.position.size.block; + // FIXME(stshine): item with 'align-self: stretch' and auto cross size should act + // as if it has a fixed cross size, all child blocks should resolve against it. + // block.assign_block_size(layout_context); + } + block.base.position.start.b = margin_block_start + if !self.cross_reverse { + cur_b + } else { + self.block_flow.fragment.border_padding.block_start * 2 + total_cross_size - + cur_b - + line.cross_size + }; // TODO(stshine): support baseline alignment. if free_space != Au(0) { let flex_cross = match self_align { @@ -788,17 +860,17 @@ impl FlexFlow { AlignSelf::Center => free_space / 2, _ => Au(0), }; - block.base.position.start.b += - if !self.cross_reverse { - flex_cross - } else { - free_space - flex_cross - }; + block.base.position.start.b += if !self.cross_reverse { + flex_cross + } else { + free_space - flex_cross + }; } } cur_b += line_interval + line.cross_size; } - let total_block_size = total_cross_size + self.block_flow.fragment.border_padding.block_start_end(); + let total_block_size = + total_cross_size + self.block_flow.fragment.border_padding.block_start_end(); self.block_flow.fragment.border_box.size.block = total_block_size; self.block_flow.base.position.size.block = total_block_size; } @@ -830,72 +902,96 @@ impl Flow for FlexFlow { } fn bubble_inline_sizes(&mut self) { - let _scope = layout_debug_scope!("flex::bubble_inline_sizes {:x}", - self.block_flow.base.debug_id()); + let _scope = layout_debug_scope!( + "flex::bubble_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); // Flexbox Section 9.0: Generate anonymous flex items: // This part was handled in the flow constructor. // Flexbox Section 9.1: Re-order flex items according to their order. // FIXME(stshine): This should be done during flow construction. - let mut items: Vec<FlexItem> = - self.block_flow - .base - .children - .iter() - .enumerate() - .filter(|&(_, flow)| { - !flow.as_block().base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) - }) - .map(|(index, flow)| FlexItem::new(index, flow)) - .collect(); + let mut items: Vec<FlexItem> = self + .block_flow + .base + .children + .iter() + .enumerate() + .filter(|&(_, flow)| { + !flow + .as_block() + .base + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + }).map(|(index, flow)| FlexItem::new(index, flow)) + .collect(); items.sort_by_key(|item| item.order); self.items = items; match self.main_mode { Direction::Inline => self.inline_mode_bubble_inline_sizes(), - Direction::Block => self.block_mode_bubble_inline_sizes() + Direction::Block => self.block_mode_bubble_inline_sizes(), } } fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - let _scope = layout_debug_scope!("flex::assign_inline_sizes {:x}", self.block_flow.base.debug_id()); + let _scope = layout_debug_scope!( + "flex::assign_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); debug!("assign_inline_sizes"); - if !self.block_flow.base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | - ServoRestyleDamage::REFLOW) { - return + if !self + .block_flow + .base + .restyle_damage + .intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) + { + return; } - self.block_flow.initialize_container_size_for_root(layout_context.shared_context()); + self.block_flow + .initialize_container_size_for_root(layout_context.shared_context()); // Our inline-size was set to the inline-size of the containing block by the flow's parent. // Now compute the real value. let containing_block_inline_size = self.block_flow.base.block_container_inline_size; - self.block_flow.compute_used_inline_size(layout_context.shared_context(), - containing_block_inline_size); + self.block_flow.compute_used_inline_size( + layout_context.shared_context(), + containing_block_inline_size, + ); if self.block_flow.base.flags.is_float() { - self.block_flow.float.as_mut().unwrap().containing_inline_size = containing_block_inline_size + self.block_flow + .float + .as_mut() + .unwrap() + .containing_inline_size = containing_block_inline_size } let (available_block_size, available_inline_size) = { let style = &self.block_flow.fragment.style; - let (specified_block_size, specified_inline_size) = if style.writing_mode.is_vertical() { + let (specified_block_size, specified_inline_size) = if style.writing_mode.is_vertical() + { (style.get_position().width, style.get_position().height) } else { (style.get_position().height, style.get_position().width) }; - let available_inline_size = AxisSize::new(specified_inline_size, - Some(self.block_flow.base.block_container_inline_size), - style.min_inline_size(), - style.max_inline_size()); - - let available_block_size = AxisSize::new(specified_block_size, - self.block_flow.base.block_container_explicit_block_size, - style.min_block_size(), - style.max_block_size()); + let available_inline_size = AxisSize::new( + specified_inline_size, + Some(self.block_flow.base.block_container_inline_size), + style.min_inline_size(), + style.max_inline_size(), + ); + + let available_block_size = AxisSize::new( + specified_block_size, + self.block_flow.base.block_container_explicit_block_size, + style.min_block_size(), + style.max_block_size(), + ); (available_block_size, available_inline_size) }; @@ -903,37 +999,46 @@ impl Flow for FlexFlow { let inline_start_content_edge = self.block_flow.fragment.border_box.start.i + self.block_flow.fragment.border_padding.inline_start; - debug!("inline_start_content_edge = {:?}", inline_start_content_edge); + debug!( + "inline_start_content_edge = {:?}", + inline_start_content_edge + ); let padding_and_borders = self.block_flow.fragment.border_padding.inline_start_end(); // Distance from the inline-end margin edge to the inline-end content edge. - let inline_end_content_edge = - self.block_flow.fragment.margin.inline_end + + let inline_end_content_edge = self.block_flow.fragment.margin.inline_end + self.block_flow.fragment.border_padding.inline_end; debug!("padding_and_borders = {:?}", padding_and_borders); - debug!("self.block_flow.fragment.border_box.size.inline = {:?}", - self.block_flow.fragment.border_box.size.inline); - let content_inline_size = self.block_flow.fragment.border_box.size.inline - padding_and_borders; + debug!( + "self.block_flow.fragment.border_box.size.inline = {:?}", + self.block_flow.fragment.border_box.size.inline + ); + let content_inline_size = + self.block_flow.fragment.border_box.size.inline - padding_and_borders; match self.main_mode { Direction::Inline => { self.available_main_size = available_inline_size; self.available_cross_size = available_block_size; - self.inline_mode_assign_inline_sizes(layout_context, - inline_start_content_edge, - inline_end_content_edge, - content_inline_size) - } - Direction::Block => { + self.inline_mode_assign_inline_sizes( + layout_context, + inline_start_content_edge, + inline_end_content_edge, + content_inline_size, + ) + }, + Direction::Block => { self.available_main_size = available_block_size; self.available_cross_size = available_inline_size; - self.block_mode_assign_inline_sizes(layout_context, - inline_start_content_edge, - inline_end_content_edge, - content_inline_size) - } + self.block_mode_assign_inline_sizes( + layout_context, + inline_start_content_edge, + inline_end_content_edge, + content_inline_size, + ) + }, } } @@ -941,31 +1046,37 @@ impl Flow for FlexFlow { match self.main_mode { Direction::Inline => { self.inline_mode_assign_block_size(layout_context); - let block_start = AdjoiningMargins::from_margin(self.block_flow.fragment.margin.block_start); - let block_end = AdjoiningMargins::from_margin(self.block_flow.fragment.margin.block_end); - self.block_flow.base.collapsible_margins = CollapsibleMargins::Collapse(block_start, block_end); + let block_start = + AdjoiningMargins::from_margin(self.block_flow.fragment.margin.block_start); + let block_end = + AdjoiningMargins::from_margin(self.block_flow.fragment.margin.block_end); + self.block_flow.base.collapsible_margins = + CollapsibleMargins::Collapse(block_start, block_end); // TODO(stshine): assign proper static position for absolute descendants. if (&*self as &Flow).contains_roots_of_absolute_flow_tree() { // Assign block-sizes for all flows in this absolute flow tree. // This is preorder because the block-size of an absolute flow may depend on // the block-size of its containing block, which may also be an absolute flow. - let assign_abs_b_sizes = AbsoluteAssignBSizesTraversal(layout_context.shared_context()); + let assign_abs_b_sizes = + AbsoluteAssignBSizesTraversal(layout_context.shared_context()); assign_abs_b_sizes.traverse_absolute_flows(&mut *self); } - } - Direction::Block =>{ - self.block_flow - .assign_block_size_block_base(layout_context, - None, - MarginsMayCollapseFlag::MarginsMayNotCollapse); + }, + Direction::Block => { + self.block_flow.assign_block_size_block_base( + layout_context, + None, + MarginsMayCollapseFlag::MarginsMayNotCollapse, + ); self.block_mode_assign_block_size(); - } + }, } } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context) + self.block_flow + .compute_stacking_relative_position(layout_context) } fn place_float_if_applicable<'a>(&mut self) { @@ -973,11 +1084,13 @@ impl Flow for FlexFlow { } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn build_display_list(&mut self, state: &mut DisplayListBuildState) { @@ -1008,11 +1121,17 @@ impl Flow for FlexFlow { self.block_flow.generated_containing_block_size(flow) } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position); + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ); } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { diff --git a/components/layout/floats.rs b/components/layout/floats.rs index 58fe1bc59b8..a0f44c22a04 100644 --- a/components/layout/floats.rs +++ b/components/layout/floats.rs @@ -16,7 +16,7 @@ use style::values::computed::LengthOrPercentageOrAuto; #[derive(Clone, Copy, Debug, Serialize)] pub enum FloatKind { Left, - Right + Right, } impl FloatKind { @@ -78,7 +78,12 @@ impl FloatList { impl fmt::Debug for FloatList { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "max_block_start={:?} floats={}", self.max_block_start, self.floats.len())?; + write!( + f, + "max_block_start={:?} floats={}", + self.max_block_start, + self.floats.len() + )?; for float in self.floats.iter() { write!(f, " {:?}", float)?; } @@ -95,22 +100,29 @@ pub struct PlacementInfo { /// The maximum inline-end position of the float, generally determined by the containing block. pub max_inline_size: Au, /// The kind of float. - pub kind: FloatKind + pub kind: FloatKind, } impl fmt::Debug for PlacementInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "size={:?} ceiling={:?} max_inline_size={:?} kind={:?}", - self.size, - self.ceiling, - self.max_inline_size, - self.kind) + write!( + f, + "size={:?} ceiling={:?} max_inline_size={:?} kind={:?}", + self.size, self.ceiling, self.max_inline_size, self.kind + ) } } -fn range_intersect(block_start_1: Au, block_end_1: Au, block_start_2: Au, block_end_2: Au) -> (Au, Au) { - (max(block_start_1, block_start_2), min(block_end_1, block_end_2)) +fn range_intersect( + block_start_1: Au, + block_end_1: Au, + block_start_2: Au, + block_end_2: Au, +) -> (Au, Au) { + ( + max(block_start_1, block_start_2), + min(block_end_1, block_end_2), + ) } /// Encapsulates information about floats. This is optimized to avoid allocation if there are @@ -162,8 +174,12 @@ impl Floats { /// with inline-size small enough that it doesn't collide with any floats. max_x is the /// inline-size beyond which floats have no effect. (Generally this is the containing block /// inline-size.) - pub fn available_rect(&self, block_start: Au, block_size: Au, max_x: Au) - -> Option<LogicalRect<Au>> { + pub fn available_rect( + &self, + block_start: Au, + block_size: Au, + max_x: Au, + ) -> Option<LogicalRect<Au>> { let list = &self.list; let block_start = block_start - self.offset.block; @@ -186,30 +202,38 @@ impl Floats { debug!("float_pos: {:?}, float_size: {:?}", float_pos, float_size); match float.kind { - FloatKind::Left if float_pos.i + float_size.inline > max_inline_start && + FloatKind::Left + if float_pos.i + float_size.inline > max_inline_start && float_pos.b + float_size.block > block_start && - float_pos.b < block_start + block_size => { + float_pos.b < block_start + block_size => + { max_inline_start = float_pos.i + float_size.inline; l_block_start = Some(float_pos.b); l_block_end = Some(float_pos.b + float_size.block); - debug!("available_rect: collision with inline_start float: new \ - max_inline_start is {:?}", - max_inline_start); + debug!( + "available_rect: collision with inline_start float: new \ + max_inline_start is {:?}", + max_inline_start + ); } - FloatKind::Right if float_pos.i < min_inline_end && - float_pos.b + float_size.block > block_start && - float_pos.b < block_start + block_size => { + FloatKind::Right + if float_pos.i < min_inline_end && + float_pos.b + float_size.block > block_start && + float_pos.b < block_start + block_size => + { min_inline_end = float_pos.i; r_block_start = Some(float_pos.b); r_block_end = Some(float_pos.b + float_size.block); - debug!("available_rect: collision with inline_end float: new min_inline_end \ - is {:?}", - min_inline_end); + debug!( + "available_rect: collision with inline_end float: new min_inline_end \ + is {:?}", + min_inline_end + ); } - FloatKind::Left | FloatKind::Right => {} + FloatKind::Left | FloatKind::Right => {}, } } @@ -217,25 +241,28 @@ impl Floats { // If there are floats on both sides, take the intersection of the // two areas. Also make sure we never return a block-start smaller than the // given upper bound. - let (block_start, block_end) = match (r_block_start, - r_block_end, - l_block_start, - l_block_end) { - (Some(r_block_start), Some(r_block_end), Some(l_block_start), Some(l_block_end)) => { - range_intersect(max(block_start, r_block_start), - r_block_end, - max(block_start, l_block_start), - l_block_end) - } - (None, None, Some(l_block_start), Some(l_block_end)) => { - (max(block_start, l_block_start), l_block_end) - } - (Some(r_block_start), Some(r_block_end), None, None) => { - (max(block_start, r_block_start), r_block_end) - } - (None, None, None, None) => return None, - _ => panic!("Reached unreachable state when computing float area") - }; + let (block_start, block_end) = + match (r_block_start, r_block_end, l_block_start, l_block_end) { + ( + Some(r_block_start), + Some(r_block_end), + Some(l_block_start), + Some(l_block_end), + ) => range_intersect( + max(block_start, r_block_start), + r_block_end, + max(block_start, l_block_start), + l_block_end, + ), + (None, None, Some(l_block_start), Some(l_block_end)) => { + (max(block_start, l_block_start), l_block_end) + }, + (Some(r_block_start), Some(r_block_end), None, None) => { + (max(block_start, r_block_start), r_block_end) + }, + (None, None, None, None) => return None, + _ => panic!("Reached unreachable state when computing float area"), + }; // FIXME(eatkinson): This assertion is too strong and fails in some cases. It is OK to // return negative inline-sizes since we check against that inline-end away, but we should @@ -244,11 +271,13 @@ impl Floats { assert!(block_start <= block_end, "Float position error"); - Some(LogicalRect::new(self.writing_mode, - max_inline_start + self.offset.inline, - block_start + self.offset.block, - min_inline_end - max_inline_start, - block_end - block_start)) + Some(LogicalRect::new( + self.writing_mode, + max_inline_start + self.offset.inline, + block_start + self.offset.block, + min_inline_end - max_inline_start, + block_end - block_start, + )) } /// Adds a new float to the list. @@ -260,7 +289,7 @@ impl Floats { Some(max_block_start) => max(info.ceiling, max_block_start + self.offset.block), }, max_inline_size: info.max_inline_size, - kind: info.kind + kind: info.kind, }; debug!("add_float: added float with info {:?}", new_info); @@ -271,7 +300,7 @@ impl Floats { self.place_between_floats(&new_info).start - self.offset, info.size, ), - kind: info.kind + kind: info.kind, }; self.list.floats = self.list.floats.prepend_elem(new_float); @@ -284,8 +313,12 @@ impl Floats { /// Given the three sides of the bounding rectangle in the block-start direction, finds the /// largest block-size that will result in the rectangle not colliding with any floats. Returns /// `None` if that block-size is infinite. - fn max_block_size_for_bounds(&self, inline_start: Au, block_start: Au, inline_size: Au) - -> Option<Au> { + fn max_block_size_for_bounds( + &self, + inline_start: Au, + block_start: Au, + inline_size: Au, + ) -> Option<Au> { let list = &self.list; let block_start = block_start - self.offset.block; @@ -294,10 +327,11 @@ impl Floats { for float in list.floats.iter() { if float.bounds.start.b + float.bounds.size.block > block_start && - float.bounds.start.i + float.bounds.size.inline > inline_start && - float.bounds.start.i < inline_start + inline_size { - let new_y = float.bounds.start.b; - max_block_size = Some(min(max_block_size.unwrap_or(new_y), new_y)); + float.bounds.start.i + float.bounds.size.inline > inline_start && + float.bounds.start.i < inline_start + inline_size + { + let new_y = float.bounds.start.b; + max_block_size = Some(min(max_block_size.unwrap_or(new_y), new_y)); } } @@ -318,85 +352,88 @@ impl Floats { Au(0), info.ceiling, info.max_inline_size, - MAX_AU) - } + MAX_AU, + ) + }, FloatKind::Right => { return LogicalRect::new( self.writing_mode, info.max_inline_size - info.size.inline, info.ceiling, info.max_inline_size, - MAX_AU) - } + MAX_AU, + ) + }, } } // Can't go any higher than previous floats or previous elements in the document. let mut float_b = info.ceiling; loop { - let maybe_location = self.available_rect(float_b, - info.size.block, - info.max_inline_size); - debug!("place_float: got available rect: {:?} for block-pos: {:?}", - maybe_location, - float_b); + let maybe_location = + self.available_rect(float_b, info.size.block, info.max_inline_size); + debug!( + "place_float: got available rect: {:?} for block-pos: {:?}", + maybe_location, float_b + ); match maybe_location { // If there are no floats blocking us, return the current location // TODO(eatkinson): integrate with overflow None => { return match info.kind { - FloatKind::Left => { - LogicalRect::new( - self.writing_mode, - Au(0), - float_b, - info.max_inline_size, - MAX_AU) - } - FloatKind::Right => { - LogicalRect::new( - self.writing_mode, - info.max_inline_size - info.size.inline, - float_b, - info.max_inline_size, - MAX_AU) - } + FloatKind::Left => LogicalRect::new( + self.writing_mode, + Au(0), + float_b, + info.max_inline_size, + MAX_AU, + ), + FloatKind::Right => LogicalRect::new( + self.writing_mode, + info.max_inline_size - info.size.inline, + float_b, + info.max_inline_size, + MAX_AU, + ), } - } + }, Some(rect) => { - assert_ne!(rect.start.b + rect.size.block, float_b, - "Non-terminating float placement"); + assert_ne!( + rect.start.b + rect.size.block, + float_b, + "Non-terminating float placement" + ); // Place here if there is enough room if rect.size.inline >= info.size.inline { - let block_size = self.max_block_size_for_bounds(rect.start.i, - rect.start.b, - rect.size.inline); + let block_size = self.max_block_size_for_bounds( + rect.start.i, + rect.start.b, + rect.size.inline, + ); let block_size = block_size.unwrap_or(MAX_AU); return match info.kind { - FloatKind::Left => { - LogicalRect::new( - self.writing_mode, - rect.start.i, - float_b, - rect.size.inline, - block_size) - } - FloatKind::Right => { - LogicalRect::new( - self.writing_mode, - rect.start.i + rect.size.inline - info.size.inline, - float_b, - rect.size.inline, - block_size) - } - } + FloatKind::Left => LogicalRect::new( + self.writing_mode, + rect.start.i, + float_b, + rect.size.inline, + block_size, + ), + FloatKind::Right => LogicalRect::new( + self.writing_mode, + rect.start.i + rect.size.inline - info.size.inline, + float_b, + rect.size.inline, + block_size, + ), + }; } // Try to place at the next-lowest location. // Need to be careful of fencepost errors. float_b = rect.start.b + rect.size.block; - } + }, } } } @@ -411,8 +448,8 @@ impl Floats { (ClearType::Both, _) => { let b = self.offset.block + float.bounds.start.b + float.bounds.size.block; clearance = max(clearance, b); - } - _ => {} + }, + _ => {}, } } clearance @@ -486,14 +523,20 @@ impl SpeculatedFloatPlacement { } } - self.left = max(self.left, block_flow.base.speculated_float_placement_in.left); - self.right = max(self.right, block_flow.base.speculated_float_placement_in.right); + self.left = max( + self.left, + block_flow.base.speculated_float_placement_in.left, + ); + self.right = max( + self.right, + block_flow.base.speculated_float_placement_in.right, + ); } } let base_flow = flow.base(); if !base_flow.flags.is_float() { - return + return; } let mut float_inline_size = base_flow.intrinsic_inline_sizes.preferred_inline_size; @@ -504,7 +547,8 @@ impl SpeculatedFloatPlacement { // that the layout traversal logic will know that objects later in the document // might flow around this float. if let LengthOrPercentageOrAuto::Percentage(percentage) = - flow.as_block().fragment.style.content_inline_size() { + flow.as_block().fragment.style.content_inline_size() + { if percentage.0 > 0.0 { float_inline_size = Au::from_px(1) } @@ -513,7 +557,7 @@ impl SpeculatedFloatPlacement { } match base_flow.flags.float_kind() { - StyleFloat::None => {} + StyleFloat::None => {}, StyleFloat::Left => self.left = self.left + float_inline_size, StyleFloat::Right => self.right = self.right + float_inline_size, } @@ -522,17 +566,18 @@ impl SpeculatedFloatPlacement { /// Given a flow, computes the speculated inline size of the floats in of its first child. pub fn compute_floats_in_for_first_child(parent_flow: &mut Flow) -> SpeculatedFloatPlacement { if !parent_flow.is_block_like() { - return parent_flow.base().speculated_float_placement_in + return parent_flow.base().speculated_float_placement_in; } let parent_block_flow = parent_flow.as_block(); if parent_block_flow.formatting_context_type() != FormattingContextType::None { - return SpeculatedFloatPlacement::zero() + return SpeculatedFloatPlacement::zero(); } let mut placement = parent_block_flow.base.speculated_float_placement_in; - let speculated_inline_content_edge_offsets = - parent_block_flow.fragment.guess_inline_content_edge_offsets(); + let speculated_inline_content_edge_offsets = parent_block_flow + .fragment + .guess_inline_content_edge_offsets(); if speculated_inline_content_edge_offsets.start > Au(0) { placement.left = if placement.left > speculated_inline_content_edge_offsets.start { @@ -552,4 +597,3 @@ impl SpeculatedFloatPlacement { placement } } - diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 76ecf9db096..1b0781c527e 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -251,11 +251,15 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { /// and return a new flow similar to `self` with the rest of the content. /// /// The default is to make a flow "atomic": it can not be fragmented. - fn fragment(&mut self, - layout_context: &LayoutContext, - _fragmentation_context: Option<FragmentationContext>) - -> Option<Arc<Flow>> { - fn recursive_assign_block_size<F: ?Sized + Flow + GetBaseFlow>(flow: &mut F, ctx: &LayoutContext) { + fn fragment( + &mut self, + layout_context: &LayoutContext, + _fragmentation_context: Option<FragmentationContext>, + ) -> Option<Arc<Flow>> { + fn recursive_assign_block_size<F: ?Sized + Flow + GetBaseFlow>( + flow: &mut F, + ctx: &LayoutContext, + ) { for child in flow.mut_base().child_iter_mut() { recursive_assign_block_size(child, ctx) } @@ -277,17 +281,20 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { /// `parent_thread_id` is the thread ID of the parent. This is used for the layout tinting /// debug mode; if the block size of this flow was determined by its parent, we should treat /// it as laid out by its parent. - fn assign_block_size_for_inorder_child_if_necessary(&mut self, - layout_context: &LayoutContext, - parent_thread_id: u8, - _content_box: LogicalRect<Au>) - -> bool { - let might_have_floats_in_or_out = self.base().might_have_floats_in() || - self.base().might_have_floats_out(); + fn assign_block_size_for_inorder_child_if_necessary( + &mut self, + layout_context: &LayoutContext, + parent_thread_id: u8, + _content_box: LogicalRect<Au>, + ) -> bool { + let might_have_floats_in_or_out = + self.base().might_have_floats_in() || self.base().might_have_floats_out(); if might_have_floats_in_or_out { self.mut_base().thread_id = parent_thread_id; self.assign_block_size(layout_context); - self.mut_base().restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.mut_base() + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); } might_have_floats_in_or_out } @@ -295,23 +302,32 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { fn get_overflow_in_parent_coordinates(&self) -> Overflow { // FIXME(#2795): Get the real container size. let container_size = Size2D::zero(); - let position = self.base().position.to_physical(self.base().writing_mode, container_size); + let position = self + .base() + .position + .to_physical(self.base().writing_mode, container_size); let mut overflow = self.base().overflow; match self.class() { - FlowClass::Block | FlowClass::TableCaption | FlowClass::TableCell => {} + FlowClass::Block | FlowClass::TableCaption | FlowClass::TableCell => {}, _ => { overflow.translate(&position.origin.to_vector()); return overflow; - } + }, } let border_box = self.as_block().fragment.stacking_relative_border_box( &self.base().stacking_relative_position, - &self.base().early_absolute_position_info.relative_containing_block_size, - self.base().early_absolute_position_info.relative_containing_block_mode, - CoordinateSystem::Own); + &self + .base() + .early_absolute_position_info + .relative_containing_block_size, + self.base() + .early_absolute_position_info + .relative_containing_block_mode, + CoordinateSystem::Own, + ); if StyleOverflow::Visible != self.as_block().fragment.style.get_box().overflow_x { overflow.paint.origin.x = Au(0); overflow.paint.size.width = border_box.size.width; @@ -325,24 +341,35 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { overflow.scroll.size.height = border_box.size.height; } - if !self.as_block().fragment.establishes_stacking_context() || - self.as_block().fragment.style.get_box().transform.0.is_empty() { + if !self.as_block().fragment.establishes_stacking_context() || self + .as_block() + .fragment + .style + .get_box() + .transform + .0 + .is_empty() + { overflow.translate(&position.origin.to_vector()); return overflow; } // TODO: Take into account 3d transforms, even though it's a fairly // uncommon case. - let transform_2d = self.as_block() - .fragment - .transform_matrix(&position) - .unwrap_or(LayoutTransform::identity()) - .to_2d().to_untyped(); + let transform_2d = self + .as_block() + .fragment + .transform_matrix(&position) + .unwrap_or(LayoutTransform::identity()) + .to_2d() + .to_untyped(); let transformed_overflow = Overflow { - paint: f32_rect_to_au_rect(transform_2d.transform_rect( - &au_rect_to_f32_rect(overflow.paint))), - scroll: f32_rect_to_au_rect(transform_2d.transform_rect( - &au_rect_to_f32_rect(overflow.scroll))), + paint: f32_rect_to_au_rect( + transform_2d.transform_rect(&au_rect_to_f32_rect(overflow.paint)), + ), + scroll: f32_rect_to_au_rect( + transform_2d.transform_rect(&au_rect_to_f32_rect(overflow.scroll)), + ), }; // TODO: We are taking the union of the overflow and transformed overflow here, which @@ -369,14 +396,12 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { // Calculate overflow on a per-fragment basis. let mut overflow = self.compute_overflow(); match self.class() { - FlowClass::Block | - FlowClass::TableCaption | - FlowClass::TableCell => { + FlowClass::Block | FlowClass::TableCaption | FlowClass::TableCell => { for kid in self.mut_base().children.iter_mut() { overflow.union(&kid.get_overflow_in_parent_coordinates()); } - } - _ => {} + }, + _ => {}, } self.mut_base().overflow = overflow } @@ -396,17 +421,21 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { /// Iterates through border boxes of all of this flow's fragments. /// Level provides a zero based index indicating the current /// depth of the flow tree during fragment iteration. - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>); + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ); /// Mutably iterates through fragments in this flow. fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)); - fn compute_collapsible_block_start_margin(&mut self, - _layout_context: &mut LayoutContext, - _margin_collapse_info: &mut MarginCollapseInfo) { + fn compute_collapsible_block_start_margin( + &mut self, + _layout_context: &mut LayoutContext, + _margin_collapse_info: &mut MarginCollapseInfo, + ) { // The default implementation is a no-op. } @@ -436,8 +465,10 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { } fn contains_positioned_fragments(&self) -> bool { - self.contains_relatively_positioned_fragments() || - self.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + self.contains_relatively_positioned_fragments() || self + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) } fn contains_relatively_positioned_fragments(&self) -> bool { @@ -476,7 +507,7 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { /// Print any extra children (such as fragments) contained in this Flow /// for debugging purposes. Any items inserted into the tree will become /// children of this flow. - fn print_extra_flow_children(&self, _: &mut PrintTree) { } + fn print_extra_flow_children(&self, _: &mut PrintTree) {} fn clipping_and_scrolling(&self) -> ClippingAndScrolling { match self.base().clipping_and_scrolling { @@ -566,8 +597,10 @@ pub trait MutableOwnedFlowUtils { /// </span> /// </div> /// ``` - fn take_applicable_absolute_descendants(&mut self, - absolute_descendants: &mut AbsoluteDescendants); + fn take_applicable_absolute_descendants( + &mut self, + absolute_descendants: &mut AbsoluteDescendants, + ); } #[derive(Clone, Copy, Debug, PartialEq, Serialize)] @@ -590,9 +623,15 @@ pub enum FlowClass { impl FlowClass { fn is_block_like(self) -> bool { match self { - FlowClass::Block | FlowClass::ListItem | FlowClass::Table | FlowClass::TableRowGroup | - FlowClass::TableRow | FlowClass::TableCaption | FlowClass::TableCell | - FlowClass::TableWrapper | FlowClass::Flex => true, + FlowClass::Block | + FlowClass::ListItem | + FlowClass::Table | + FlowClass::TableRowGroup | + FlowClass::TableRow | + FlowClass::TableCaption | + FlowClass::TableCell | + FlowClass::TableWrapper | + FlowClass::Flex => true, _ => false, } } @@ -663,7 +702,7 @@ impl FlowFlags { #[inline] pub fn set_text_align(&mut self, value: TextAlign) { *self = (*self & !FlowFlags::TEXT_ALIGN) | - FlowFlags::from_bits((value as u32) << TEXT_ALIGN_SHIFT).unwrap(); + FlowFlags::from_bits((value as u32) << TEXT_ALIGN_SHIFT).unwrap(); } #[inline] @@ -776,7 +815,9 @@ pub struct AbsoluteDescendantIter<'a> { impl<'a> Iterator for AbsoluteDescendantIter<'a> { type Item = &'a mut Flow; fn next(&mut self) -> Option<&'a mut Flow> { - self.iter.next().map(|info| FlowRef::deref_mut(&mut info.flow)) + self.iter + .next() + .map(|info| FlowRef::deref_mut(&mut info.flow)) } fn size_hint(&self) -> (usize, Option<usize>) { @@ -953,22 +994,32 @@ impl fmt::Debug for BaseFlow { "".to_owned() }; - write!(f, - "\nsc={:?}\ - \npos={:?}{}{}\ - \nfloatspec-in={:?}\ - \nfloatspec-out={:?}\ - \noverflow={:?}{}{}{}", - self.stacking_context_id, - self.position, - if self.flags.contains(FlowFlags::FLOATS_LEFT) { "FL" } else { "" }, - if self.flags.contains(FlowFlags::FLOATS_RIGHT) { "FR" } else { "" }, - self.speculated_float_placement_in, - self.speculated_float_placement_out, - self.overflow, - child_count_string, - absolute_descendants_string, - damage_string) + write!( + f, + "\nsc={:?}\ + \npos={:?}{}{}\ + \nfloatspec-in={:?}\ + \nfloatspec-out={:?}\ + \noverflow={:?}{}{}{}", + self.stacking_context_id, + self.position, + if self.flags.contains(FlowFlags::FLOATS_LEFT) { + "FL" + } else { + "" + }, + if self.flags.contains(FlowFlags::FLOATS_RIGHT) { + "FR" + } else { + "" + }, + self.speculated_float_placement_in, + self.speculated_float_placement_out, + self.overflow, + child_count_string, + absolute_descendants_string, + damage_string + ) } } @@ -976,7 +1027,10 @@ impl Serialize for BaseFlow { fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { let mut serializer = serializer.serialize_struct("base", 5)?; serializer.serialize_field("id", &self.debug_id())?; - serializer.serialize_field("stacking_relative_position", &self.stacking_relative_position)?; + serializer.serialize_field( + "stacking_relative_position", + &self.stacking_relative_position, + )?; serializer.serialize_field("intrinsic_inline_sizes", &self.intrinsic_inline_sizes)?; serializer.serialize_field("position", &self.position)?; serializer.serialize_field("children", &self.children)?; @@ -996,10 +1050,11 @@ pub enum ForceNonfloatedFlag { impl BaseFlow { #[inline] - pub fn new(style: Option<&ComputedValues>, - writing_mode: WritingMode, - force_nonfloated: ForceNonfloatedFlag) - -> BaseFlow { + pub fn new( + style: Option<&ComputedValues>, + writing_mode: WritingMode, + force_nonfloated: ForceNonfloatedFlag, + ) -> BaseFlow { let mut flags = FlowFlags::empty(); match style { Some(style) => { @@ -1013,41 +1068,47 @@ impl BaseFlow { let logical_position = style.logical_position(); if logical_position.inline_start == LengthOrPercentageOrAuto::Auto && - logical_position.inline_end == LengthOrPercentageOrAuto::Auto { + logical_position.inline_end == LengthOrPercentageOrAuto::Auto + { flags.insert(FlowFlags::INLINE_POSITION_IS_STATIC); } if logical_position.block_start == LengthOrPercentageOrAuto::Auto && - logical_position.block_end == LengthOrPercentageOrAuto::Auto { + logical_position.block_end == LengthOrPercentageOrAuto::Auto + { flags.insert(FlowFlags::BLOCK_POSITION_IS_STATIC); } - } - _ => flags.insert(FlowFlags::BLOCK_POSITION_IS_STATIC | FlowFlags::INLINE_POSITION_IS_STATIC), + }, + _ => flags.insert( + FlowFlags::BLOCK_POSITION_IS_STATIC | FlowFlags::INLINE_POSITION_IS_STATIC, + ), } if force_nonfloated == ForceNonfloatedFlag::FloatIfNecessary { match style.get_box().float { - Float::None => {} + Float::None => {}, Float::Left => flags.insert(FlowFlags::FLOATS_LEFT), Float::Right => flags.insert(FlowFlags::FLOATS_RIGHT), } } match style.get_box().clear { - Clear::None => {} + Clear::None => {}, Clear::Left => flags.insert(FlowFlags::CLEARS_LEFT), Clear::Right => flags.insert(FlowFlags::CLEARS_RIGHT), Clear::Both => { flags.insert(FlowFlags::CLEARS_LEFT); flags.insert(FlowFlags::CLEARS_RIGHT); - } + }, } if !style.get_counters().counter_reset.is_empty() || - !style.get_counters().counter_increment.is_empty() { + !style.get_counters().counter_increment.is_empty() + { flags.insert(FlowFlags::AFFECTS_COUNTERS) } - } - None => flags.insert(FlowFlags::BLOCK_POSITION_IS_STATIC | FlowFlags::INLINE_POSITION_IS_STATIC), + }, + None => flags + .insert(FlowFlags::BLOCK_POSITION_IS_STATIC | FlowFlags::INLINE_POSITION_IS_STATIC), } // New flows start out as fully damaged. @@ -1089,17 +1150,24 @@ impl BaseFlow { pub fn update_flags_if_needed(&mut self, style: &ComputedValues) { // For absolutely-positioned flows, changes to top/bottom/left/right can cause these flags // to get out of date: - if self.restyle_damage.contains(ServoRestyleDamage::REFLOW_OUT_OF_FLOW) { + if self + .restyle_damage + .contains(ServoRestyleDamage::REFLOW_OUT_OF_FLOW) + { // Note: We don't need to check whether IS_ABSOLUTELY_POSITIONED has changed, because // changes to the 'position' property trigger flow reconstruction. if self.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { let logical_position = style.logical_position(); - self.flags.set(FlowFlags::INLINE_POSITION_IS_STATIC, + self.flags.set( + FlowFlags::INLINE_POSITION_IS_STATIC, logical_position.inline_start == LengthOrPercentageOrAuto::Auto && - logical_position.inline_end == LengthOrPercentageOrAuto::Auto); - self.flags.set(FlowFlags::BLOCK_POSITION_IS_STATIC, + logical_position.inline_end == LengthOrPercentageOrAuto::Auto, + ); + self.flags.set( + FlowFlags::BLOCK_POSITION_IS_STATIC, logical_position.block_start == LengthOrPercentageOrAuto::Auto && - logical_position.block_end == LengthOrPercentageOrAuto::Auto); + logical_position.block_end == LengthOrPercentageOrAuto::Auto, + ); } } } @@ -1108,8 +1176,10 @@ impl BaseFlow { pub fn clone_with_children(&self, children: FlowList) -> BaseFlow { BaseFlow { children: children, - restyle_damage: self.restyle_damage | ServoRestyleDamage::REPAINT | - ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW, + restyle_damage: self.restyle_damage | + ServoRestyleDamage::REPAINT | + ServoRestyleDamage::REFLOW_OUT_OF_FLOW | + ServoRestyleDamage::REFLOW, parallel: FlowParallelInfo::new(), floats: self.floats.clone(), abs_descendants: self.abs_descendants.clone(), @@ -1138,8 +1208,10 @@ impl BaseFlow { return self as *const BaseFlow as usize; } - pub fn collect_stacking_contexts_for_children(&mut self, - state: &mut StackingContextCollectionState) { + pub fn collect_stacking_contexts_for_children( + &mut self, + state: &mut StackingContextCollectionState, + ) { for kid in self.children.iter_mut() { kid.collect_stacking_contexts(state); } @@ -1157,15 +1229,17 @@ impl BaseFlow { self.speculated_float_placement_out.right > Au(0) } - /// Compute the fragment position relative to the parent stacking context. If the fragment /// itself establishes a stacking context, then the origin of its position will be (0, 0) /// for the purposes of this computation. pub fn stacking_relative_border_box_for_display_list(&self, fragment: &Fragment) -> Rect<Au> { fragment.stacking_relative_border_box( &self.stacking_relative_position, - &self.early_absolute_position_info.relative_containing_block_size, - self.early_absolute_position_info.relative_containing_block_mode, + &self + .early_absolute_position_info + .relative_containing_block_size, + self.early_absolute_position_info + .relative_containing_block_mode, CoordinateSystem::Own, ) } @@ -1182,8 +1256,10 @@ impl<'a> ImmutableFlowUtils for &'a Flow { /// table-column-group flow, or table-caption flow. fn is_proper_table_child(self) -> bool { match self.class() { - FlowClass::TableRow | FlowClass::TableRowGroup | - FlowClass::TableColGroup | FlowClass::TableCaption => true, + FlowClass::TableRow | + FlowClass::TableRowGroup | + FlowClass::TableColGroup | + FlowClass::TableCaption => true, _ => false, } } @@ -1239,9 +1315,13 @@ impl<'a> ImmutableFlowUtils for &'a Flow { /// Returns true if this flow is one of table-related flows. fn is_table_kind(self) -> bool { match self.class() { - FlowClass::TableWrapper | FlowClass::Table | - FlowClass::TableColGroup | FlowClass::TableRowGroup | - FlowClass::TableRow | FlowClass::TableCaption | FlowClass::TableCell => true, + FlowClass::TableWrapper | + FlowClass::Table | + FlowClass::TableColGroup | + FlowClass::TableRowGroup | + FlowClass::TableRow | + FlowClass::TableCaption | + FlowClass::TableCell => true, _ => false, } } @@ -1268,7 +1348,7 @@ impl<'a> ImmutableFlowUtils for &'a Flow { FlowClass::Block | FlowClass::TableCaption | FlowClass::TableCell => { // FIXME: Actually check the type of the node self.child_count() != 0 - } + }, _ => false, } } @@ -1307,13 +1387,13 @@ impl<'a> ImmutableFlowUtils for &'a Flow { fn floats_might_flow_through(self) -> bool { if !self.base().might_have_floats_in() && !self.base().might_have_floats_out() { - return false + return false; } if self.is_root() { - return false + return false; } if !self.is_block_like() { - return true + return true; } self.as_block().formatting_context_type() == FormattingContextType::None } @@ -1322,12 +1402,16 @@ impl<'a> ImmutableFlowUtils for &'a Flow { for kid in self.base().children.iter().rev() { if kid.is_inline_flow() { if let Some(baseline_offset) = kid.as_inline().baseline_offset_of_last_line() { - return Some(kid.base().position.start.b + baseline_offset) + return Some(kid.base().position.start.b + baseline_offset); } } - if kid.is_block_like() && !kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if kid.is_block_like() && !kid + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { if let Some(baseline_offset) = kid.baseline_offset_of_last_line_box_in_flow() { - return Some(kid.base().position.start.b + baseline_offset) + return Some(kid.base().position.start.b + baseline_offset); } } } @@ -1374,17 +1458,19 @@ impl MutableOwnedFlowUtils for FlowRef { /// </span> /// </div> /// ``` - fn take_applicable_absolute_descendants(&mut self, - absolute_descendants: &mut AbsoluteDescendants) { + fn take_applicable_absolute_descendants( + &mut self, + absolute_descendants: &mut AbsoluteDescendants, + ) { let mut applicable_absolute_descendants = AbsoluteDescendants::new(); for absolute_descendant in absolute_descendants.descendant_links.iter() { if absolute_descendant.has_reached_containing_block { applicable_absolute_descendants.push(absolute_descendant.flow.clone()); } } - absolute_descendants.descendant_links.retain(|descendant| { - !descendant.has_reached_containing_block - }); + absolute_descendants + .descendant_links + .retain(|descendant| !descendant.has_reached_containing_block); let this = self.clone(); let base = FlowRef::deref_mut(self).mut_base(); @@ -1412,9 +1498,7 @@ pub struct ContainingBlockLink { impl ContainingBlockLink { fn new() -> ContainingBlockLink { - ContainingBlockLink { - link: None, - } + ContainingBlockLink { link: None } } fn set(&mut self, link: FlowRef) { @@ -1424,34 +1508,38 @@ impl ContainingBlockLink { #[inline] pub fn generated_containing_block_size(&self, for_flow: OpaqueFlow) -> LogicalSize<Au> { match self.link { - None => { - panic!("Link to containing block not established; perhaps you forgot to call \ - `set_absolute_descendants`?") - } + None => panic!( + "Link to containing block not established; perhaps you forgot to call \ + `set_absolute_descendants`?" + ), Some(ref link) => { let flow = link.upgrade().unwrap(); flow.generated_containing_block_size(for_flow) - } + }, } } #[inline] - pub fn explicit_block_containing_size(&self, shared_context: &SharedStyleContext) -> Option<Au> { + pub fn explicit_block_containing_size( + &self, + shared_context: &SharedStyleContext, + ) -> Option<Au> { match self.link { - None => { - panic!("Link to containing block not established; perhaps you forgot to call \ - `set_absolute_descendants`?") - } + None => panic!( + "Link to containing block not established; perhaps you forgot to call \ + `set_absolute_descendants`?" + ), Some(ref link) => { let flow = link.upgrade().unwrap(); if flow.is_block_like() { - flow.as_block().explicit_block_containing_size(shared_context) + flow.as_block() + .explicit_block_containing_size(shared_context) } else if flow.is_inline_flow() { Some(flow.as_inline().minimum_line_metrics.space_above_baseline) } else { None } - } + }, } } } diff --git a/components/layout/flow_list.rs b/components/layout/flow_list.rs index 2960579762e..53ec0d8912a 100644 --- a/components/layout/flow_list.rs +++ b/components/layout/flow_list.rs @@ -38,10 +38,13 @@ impl Serialize for FlowList { FlowClass::TableRow => to_value(f.as_table_row()).unwrap(), FlowClass::TableCell => to_value(f.as_table_cell()).unwrap(), FlowClass::Flex => to_value(f.as_flex()).unwrap(), - FlowClass::ListItem | FlowClass::TableColGroup | FlowClass::TableCaption | - FlowClass::Multicol | FlowClass::MulticolColumn => { + FlowClass::ListItem | + FlowClass::TableColGroup | + FlowClass::TableCaption | + FlowClass::Multicol | + FlowClass::MulticolColumn => { Value::Null // Not implemented yet - } + }, }; flow_val.insert("data".to_owned(), data); serializer.serialize_element(&flow_val)?; @@ -152,7 +155,7 @@ impl FlowList { #[inline] pub fn split_off(&mut self, i: usize) -> Self { FlowList { - flows: self.flows.split_off(i) + flows: self.flows.split_off(i), } } } diff --git a/components/layout/flow_ref.rs b/components/layout/flow_ref.rs index d1cd093a707..b2da85b74ac 100644 --- a/components/layout/flow_ref.rs +++ b/components/layout/flow_ref.rs @@ -8,7 +8,6 @@ //! be superfluous. This design is largely duplicating logic of Arc<T> and //! Weak<T>; please see comments there for details. - use flow::Flow; use std::ops::Deref; use std::sync::{Arc, Weak}; @@ -63,4 +62,3 @@ impl WeakFlowRef { self.0.upgrade().map(FlowRef) } } - diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 34ef214c275..2e952a501fb 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -214,28 +214,27 @@ pub enum SpecificFragmentInfo { impl SpecificFragmentInfo { fn restyle_damage(&self) -> RestyleDamage { - let flow = - match *self { - SpecificFragmentInfo::Canvas(_) | - SpecificFragmentInfo::GeneratedContent(_) | - SpecificFragmentInfo::Iframe(_) | - SpecificFragmentInfo::Image(_) | - SpecificFragmentInfo::ScannedText(_) | - SpecificFragmentInfo::Svg(_) | - SpecificFragmentInfo::Table | - SpecificFragmentInfo::TableCell | - SpecificFragmentInfo::TableColumn(_) | - SpecificFragmentInfo::TableRow | - SpecificFragmentInfo::TableWrapper | - SpecificFragmentInfo::Multicol | - SpecificFragmentInfo::MulticolColumn | - SpecificFragmentInfo::UnscannedText(_) | - SpecificFragmentInfo::TruncatedFragment(_) | - SpecificFragmentInfo::Generic => return RestyleDamage::empty(), - SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => &info.flow_ref, - SpecificFragmentInfo::InlineAbsolute(ref info) => &info.flow_ref, - SpecificFragmentInfo::InlineBlock(ref info) => &info.flow_ref, - }; + let flow = match *self { + SpecificFragmentInfo::Canvas(_) | + SpecificFragmentInfo::GeneratedContent(_) | + SpecificFragmentInfo::Iframe(_) | + SpecificFragmentInfo::Image(_) | + SpecificFragmentInfo::ScannedText(_) | + SpecificFragmentInfo::Svg(_) | + SpecificFragmentInfo::Table | + SpecificFragmentInfo::TableCell | + SpecificFragmentInfo::TableColumn(_) | + SpecificFragmentInfo::TableRow | + SpecificFragmentInfo::TableWrapper | + SpecificFragmentInfo::Multicol | + SpecificFragmentInfo::MulticolColumn | + SpecificFragmentInfo::UnscannedText(_) | + SpecificFragmentInfo::TruncatedFragment(_) | + SpecificFragmentInfo::Generic => return RestyleDamage::empty(), + SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => &info.flow_ref, + SpecificFragmentInfo::InlineAbsolute(ref info) => &info.flow_ref, + SpecificFragmentInfo::InlineBlock(ref info) => &info.flow_ref, + }; flow.base().restyle_damage } @@ -250,7 +249,7 @@ impl SpecificFragmentInfo { SpecificFragmentInfo::InlineAbsolute(_) => "SpecificFragmentInfo::InlineAbsolute", SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => { "SpecificFragmentInfo::InlineAbsoluteHypothetical" - } + }, SpecificFragmentInfo::InlineBlock(_) => "SpecificFragmentInfo::InlineBlock", SpecificFragmentInfo::ScannedText(_) => "SpecificFragmentInfo::ScannedText", SpecificFragmentInfo::Svg(_) => "SpecificFragmentInfo::Svg", @@ -262,7 +261,7 @@ impl SpecificFragmentInfo { SpecificFragmentInfo::Multicol => "SpecificFragmentInfo::Multicol", SpecificFragmentInfo::MulticolColumn => "SpecificFragmentInfo::MulticolColumn", SpecificFragmentInfo::UnscannedText(_) => "SpecificFragmentInfo::UnscannedText", - SpecificFragmentInfo::TruncatedFragment(_) => "SpecificFragmentInfo::TruncatedFragment" + SpecificFragmentInfo::TruncatedFragment(_) => "SpecificFragmentInfo::TruncatedFragment", } } } @@ -272,7 +271,7 @@ impl fmt::Debug for SpecificFragmentInfo { match *self { SpecificFragmentInfo::ScannedText(ref info) => write!(f, "{:?}", info.text()), SpecificFragmentInfo::UnscannedText(ref info) => write!(f, "{:?}", info.text), - _ => Ok(()) + _ => Ok(()), } } } @@ -298,9 +297,7 @@ pub struct InlineAbsoluteHypotheticalFragmentInfo { impl InlineAbsoluteHypotheticalFragmentInfo { pub fn new(flow_ref: FlowRef) -> InlineAbsoluteHypotheticalFragmentInfo { - InlineAbsoluteHypotheticalFragmentInfo { - flow_ref: flow_ref, - } + InlineAbsoluteHypotheticalFragmentInfo { flow_ref: flow_ref } } } @@ -315,9 +312,7 @@ pub struct InlineBlockFragmentInfo { impl InlineBlockFragmentInfo { pub fn new(flow_ref: FlowRef) -> InlineBlockFragmentInfo { - InlineBlockFragmentInfo { - flow_ref: flow_ref, - } + InlineBlockFragmentInfo { flow_ref: flow_ref } } } @@ -333,16 +328,14 @@ pub struct InlineAbsoluteFragmentInfo { impl InlineAbsoluteFragmentInfo { pub fn new(flow_ref: FlowRef) -> InlineAbsoluteFragmentInfo { - InlineAbsoluteFragmentInfo { - flow_ref: flow_ref, - } + InlineAbsoluteFragmentInfo { flow_ref: flow_ref } } } #[derive(Clone)] pub enum CanvasFragmentSource { WebGL(webrender_api::ImageKey), - Image(Option<Arc<Mutex<IpcSender<CanvasMsg>>>>) + Image(Option<Arc<Mutex<IpcSender<CanvasMsg>>>>), } #[derive(Clone)] @@ -356,12 +349,10 @@ pub struct CanvasFragmentInfo { impl CanvasFragmentInfo { pub fn new(data: HTMLCanvasData) -> CanvasFragmentInfo { let source = match data.source { - HTMLCanvasDataSource::WebGL(texture_id) => { - CanvasFragmentSource::WebGL(texture_id) - }, - HTMLCanvasDataSource::Image(ipc_sender) => { - CanvasFragmentSource::Image(ipc_sender.map(|renderer| Arc::new(Mutex::new(renderer)))) - } + HTMLCanvasDataSource::WebGL(texture_id) => CanvasFragmentSource::WebGL(texture_id), + HTMLCanvasDataSource::Image(ipc_sender) => CanvasFragmentSource::Image( + ipc_sender.map(|renderer| Arc::new(Mutex::new(renderer))), + ), }; CanvasFragmentInfo { @@ -388,7 +379,6 @@ impl SvgFragmentInfo { } } - /// A fragment that represents a replaced content image and its accompanying borders, shadows, etc. #[derive(Clone)] pub struct ImageFragmentInfo { @@ -401,26 +391,25 @@ impl ImageFragmentInfo { /// /// FIXME(pcwalton): The fact that image fragments store the cache in the fragment makes little /// sense to me. - pub fn new<N: ThreadSafeLayoutNode>(url: Option<ServoUrl>, - node: &N, - layout_context: &LayoutContext) - -> ImageFragmentInfo { + pub fn new<N: ThreadSafeLayoutNode>( + url: Option<ServoUrl>, + node: &N, + layout_context: &LayoutContext, + ) -> ImageFragmentInfo { let image_or_metadata = url.and_then(|url| { - layout_context.get_or_request_image_or_meta(node.opaque(), - url, - UsePlaceholder::Yes) + layout_context.get_or_request_image_or_meta(node.opaque(), url, UsePlaceholder::Yes) }); let (image, metadata) = match image_or_metadata { - Some(ImageOrMetadataAvailable::ImageAvailable(i, _)) => { - (Some(i.clone()), Some(ImageMetadata { height: i.height, width: i.width } )) - } - Some(ImageOrMetadataAvailable::MetadataAvailable(m)) => { - (None, Some(m)) - } - None => { - (None, None) - } + Some(ImageOrMetadataAvailable::ImageAvailable(i, _)) => ( + Some(i.clone()), + Some(ImageMetadata { + height: i.height, + width: i.width, + }), + ), + Some(ImageOrMetadataAvailable::MetadataAvailable(m)) => (None, Some(m)), + None => (None, None), }; ImageFragmentInfo { @@ -496,12 +485,13 @@ bitflags! { impl ScannedTextFragmentInfo { /// Creates the information specific to a scanned text fragment from a range and a text run. - pub fn new(run: Arc<TextRun>, - range: Range<ByteIndex>, - content_size: LogicalSize<Au>, - insertion_point: Option<ByteIndex>, - flags: ScannedTextFlags) - -> ScannedTextFragmentInfo { + pub fn new( + run: Arc<TextRun>, + range: Range<ByteIndex>, + content_size: LogicalSize<Au>, + insertion_point: Option<ByteIndex>, + flags: ScannedTextFlags, + ) -> ScannedTextFragmentInfo { ScannedTextFragmentInfo { run: run, range: range, @@ -513,11 +503,12 @@ impl ScannedTextFragmentInfo { } pub fn text(&self) -> &str { - &self.run.text[self.range.begin().to_usize() .. self.range.end().to_usize()] + &self.run.text[self.range.begin().to_usize()..self.range.end().to_usize()] } pub fn requires_line_break_afterward_if_wrapping_on_newlines(&self) -> bool { - self.flags.contains(ScannedTextFlags::REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES) + self.flags + .contains(ScannedTextFlags::REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES) } pub fn selected(&self) -> bool { @@ -596,12 +587,11 @@ impl TableColumnFragmentInfo { /// Create the information specific to an table column fragment. pub fn new<N: ThreadSafeLayoutNode>(node: &N) -> TableColumnFragmentInfo { let element = node.as_element().unwrap(); - let span = element.get_attr(&ns!(), &local_name!("span")) - .and_then(|string| string.parse().ok()) - .unwrap_or(0); - TableColumnFragmentInfo { - span: span, - } + let span = element + .get_attr(&ns!(), &local_name!("span")) + .and_then(|string| string.parse().ok()) + .unwrap_or(0); + TableColumnFragmentInfo { span: span } } } @@ -616,7 +606,11 @@ pub struct TruncatedFragmentInfo { impl Fragment { /// Constructs a new `Fragment` instance. - pub fn new<N: ThreadSafeLayoutNode>(node: &N, specific: SpecificFragmentInfo, ctx: &LayoutContext) -> Fragment { + pub fn new<N: ThreadSafeLayoutNode>( + node: &N, + specific: SpecificFragmentInfo, + ctx: &LayoutContext, + ) -> Fragment { let shared_context = ctx.shared_context(); let style = node.style(shared_context); let writing_mode = style.writing_mode; @@ -643,13 +637,14 @@ impl Fragment { } /// Constructs a new `Fragment` instance from an opaque node. - pub fn from_opaque_node_and_style(node: OpaqueNode, - pseudo: PseudoElementType, - style: ServoArc<ComputedValues>, - selected_style: ServoArc<ComputedValues>, - mut restyle_damage: RestyleDamage, - specific: SpecificFragmentInfo) - -> Fragment { + pub fn from_opaque_node_and_style( + node: OpaqueNode, + pseudo: PseudoElementType, + style: ServoArc<ComputedValues>, + selected_style: ServoArc<ComputedValues>, + mut restyle_damage: RestyleDamage, + specific: SpecificFragmentInfo, + ) -> Fragment { let writing_mode = style.writing_mode; restyle_damage.remove(ServoRestyleDamage::RECONSTRUCT_FLOW); @@ -675,10 +670,11 @@ impl Fragment { /// Creates an anonymous fragment just like this one but with the given style and fragment /// type. For the new anonymous fragment, layout-related values (border box, etc.) are reset to /// initial values. - pub fn create_similar_anonymous_fragment(&self, - style: ServoArc<ComputedValues>, - specific: SpecificFragmentInfo) - -> Fragment { + pub fn create_similar_anonymous_fragment( + &self, + style: ServoArc<ComputedValues>, + specific: SpecificFragmentInfo, + ) -> Fragment { let writing_mode = style.writing_mode; Fragment { node: self.node, @@ -700,11 +696,9 @@ impl Fragment { /// Transforms this fragment into another fragment of the given type, with the given size, /// preserving all the other data. - pub fn transform(&self, size: LogicalSize<Au>, info: SpecificFragmentInfo) - -> Fragment { - let new_border_box = LogicalRect::from_point_size(self.style.writing_mode, - self.border_box.start, - size); + pub fn transform(&self, size: LogicalSize<Au>, info: SpecificFragmentInfo) -> Fragment { + let new_border_box = + LogicalRect::from_point_size(self.style.writing_mode, self.border_box.start, size); let mut restyle_damage = RestyleDamage::rebuild_and_reflow(); restyle_damage.remove(ServoRestyleDamage::RECONSTRUCT_FLOW); @@ -730,22 +724,30 @@ impl Fragment { /// Transforms this fragment using the given `SplitInfo`, preserving all the other data. /// /// If this is the first half of a split, `first` is true - pub fn transform_with_split_info(&self, split: &SplitInfo, text_run: Arc<TextRun>, - first: bool) -> Fragment { - let size = LogicalSize::new(self.style.writing_mode, - split.inline_size, - self.border_box.size.block); + pub fn transform_with_split_info( + &self, + split: &SplitInfo, + text_run: Arc<TextRun>, + first: bool, + ) -> Fragment { + let size = LogicalSize::new( + self.style.writing_mode, + split.inline_size, + self.border_box.size.block, + ); // Preserve the insertion point if it is in this fragment's range or it is at line end. let (mut flags, insertion_point) = match self.specific { - SpecificFragmentInfo::ScannedText(ref info) => { - match info.insertion_point { - Some(index) if split.range.contains(index) => (info.flags, info.insertion_point), - Some(index) if index == ByteIndex(text_run.text.chars().count() as isize - 1) && - index == split.range.end() => (info.flags, info.insertion_point), - _ => (info.flags, None) - } + SpecificFragmentInfo::ScannedText(ref info) => match info.insertion_point { + Some(index) if split.range.contains(index) => (info.flags, info.insertion_point), + Some(index) + if index == ByteIndex(text_run.text.chars().count() as isize - 1) && + index == split.range.end() => + { + (info.flags, info.insertion_point) + }, + _ => (info.flags, None), }, - _ => (ScannedTextFlags::empty(), None) + _ => (ScannedTextFlags::empty(), None), }; if !first { @@ -763,16 +765,18 @@ impl Fragment { } /// Transforms this fragment into an ellipsis fragment, preserving all the other data. - pub fn transform_into_ellipsis(&self, - layout_context: &LayoutContext, - text_overflow_string: String) - -> Fragment { + pub fn transform_into_ellipsis( + &self, + layout_context: &LayoutContext, + text_overflow_string: String, + ) -> Fragment { let mut unscanned_ellipsis_fragments = LinkedList::new(); let mut ellipsis_fragment = self.transform( self.border_box.size, - SpecificFragmentInfo::UnscannedText( - Box::new(UnscannedTextFragmentInfo::new(text_overflow_string.into_boxed_str(), None)) - ) + SpecificFragmentInfo::UnscannedText(Box::new(UnscannedTextFragmentInfo::new( + text_overflow_string.into_boxed_str(), + None, + ))), ); unscanned_ellipsis_fragments.push_back(ellipsis_fragment); let ellipsis_fragments = with_thread_local_font_context(layout_context, |font_context| { @@ -789,10 +793,10 @@ impl Fragment { } pub fn contains_node(&self, node_address: OpaqueNode) -> bool { - node_address == self.node || - self.inline_context.as_ref().map_or(false, |ctx| { - ctx.contains_node(node_address) - }) + node_address == self.node || self + .inline_context + .as_ref() + .map_or(false, |ctx| ctx.contains_node(node_address)) } /// Adds a style to the inline context for this fragment. If the inline context doesn't exist @@ -806,8 +810,9 @@ impl Fragment { /// Determines which quantities (border/padding/margin/specified) should be included in the /// intrinsic inline size of this fragment. - fn quantities_included_in_intrinsic_inline_size(&self) - -> QuantitiesIncludedInIntrinsicInlineSizes { + fn quantities_included_in_intrinsic_inline_size( + &self, + ) -> QuantitiesIncludedInIntrinsicInlineSizes { match self.specific { SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Generic | @@ -878,10 +883,11 @@ impl Fragment { // This will likely need to be done by pushing down definite sizes during selector // cascading. let margin = if flags.contains( - QuantitiesIncludedInIntrinsicInlineSizes::INTRINSIC_INLINE_SIZE_INCLUDES_MARGINS) { + QuantitiesIncludedInIntrinsicInlineSizes::INTRINSIC_INLINE_SIZE_INCLUDES_MARGINS, + ) { let margin = style.logical_margin(); (MaybeAuto::from_style(margin.inline_start, Au(0)).specified_or_zero() + - MaybeAuto::from_style(margin.inline_end, Au(0)).specified_or_zero()) + MaybeAuto::from_style(margin.inline_end, Au(0)).specified_or_zero()) } else { Au(0) }; @@ -890,16 +896,17 @@ impl Fragment { // This will likely need to be done by pushing down definite sizes during selector // cascading. let padding = if flags.contains( - QuantitiesIncludedInIntrinsicInlineSizes::INTRINSIC_INLINE_SIZE_INCLUDES_PADDING) { + QuantitiesIncludedInIntrinsicInlineSizes::INTRINSIC_INLINE_SIZE_INCLUDES_PADDING, + ) { let padding = style.logical_padding(); - (padding.inline_start.to_used_value(Au(0)) + - padding.inline_end.to_used_value(Au(0))) + (padding.inline_start.to_used_value(Au(0)) + padding.inline_end.to_used_value(Au(0))) } else { Au(0) }; let border = if flags.contains( - QuantitiesIncludedInIntrinsicInlineSizes::INTRINSIC_INLINE_SIZE_INCLUDES_BORDER) { + QuantitiesIncludedInIntrinsicInlineSizes::INTRINSIC_INLINE_SIZE_INCLUDES_BORDER, + ) { self.border_width().inline_start_end() } else { Au(0) @@ -918,9 +925,11 @@ impl Fragment { let (border_padding, margin) = self.surrounding_intrinsic_inline_size(); let mut specified = Au(0); - if flags.contains(QuantitiesIncludedInIntrinsicInlineSizes::INTRINSIC_INLINE_SIZE_INCLUDES_SPECIFIED) { - specified = MaybeAuto::from_style(style.content_inline_size(), - Au(0)).specified_or_zero(); + if flags.contains( + QuantitiesIncludedInIntrinsicInlineSizes::INTRINSIC_INLINE_SIZE_INCLUDES_SPECIFIED, + ) { + specified = + MaybeAuto::from_style(style.content_inline_size(), Au(0)).specified_or_zero(); specified = max(style.min_inline_size().to_used_value(Au(0)), specified); if let Some(max) = style.max_inline_size().to_used_value(Au(0)) { specified = min(specified, max) @@ -950,7 +959,7 @@ impl Fragment { } else { Au(0) } - } + }, SpecificFragmentInfo::Canvas(ref info) => info.dom_width, SpecificFragmentInfo::Svg(ref info) => info.dom_width, // Note: Currently for replaced element with no intrinsic size, @@ -959,7 +968,7 @@ impl Fragment { // sufficient, but we may need to investigate if this is enough for // use cases like SVG. SpecificFragmentInfo::Iframe(_) => Au::from_px(DEFAULT_REPLACED_WIDTH), - _ => panic!("Trying to get intrinsic width on non-replaced element!") + _ => panic!("Trying to get intrinsic width on non-replaced element!"), } } @@ -973,11 +982,11 @@ impl Fragment { } else { Au(0) } - } + }, SpecificFragmentInfo::Canvas(ref info) => info.dom_height, SpecificFragmentInfo::Svg(ref info) => info.dom_height, SpecificFragmentInfo::Iframe(_) => Au::from_px(DEFAULT_REPLACED_HEIGHT), - _ => panic!("Trying to get intrinsic height on non-replaced element!") + _ => panic!("Trying to get intrinsic height on non-replaced element!"), } } @@ -1001,11 +1010,13 @@ impl Fragment { /// When a parameter is `None` it means the specified size in certain direction /// is unconstrained. The inline containing size can also be `None` since this /// method is also used for calculating intrinsic inline size contribution. - pub fn calculate_replaced_sizes(&self, - containing_inline_size: Option<Au>, - containing_block_size: Option<Au>) - -> (Au, Au) { - let (intrinsic_inline_size, intrinsic_block_size) = if self.style.writing_mode.is_vertical() { + pub fn calculate_replaced_sizes( + &self, + containing_inline_size: Option<Au>, + containing_block_size: Option<Au>, + ) -> (Au, Au) { + let (intrinsic_inline_size, intrinsic_block_size) = if self.style.writing_mode.is_vertical() + { (self.intrinsic_height(), self.intrinsic_width()) } else { (self.intrinsic_width(), self.intrinsic_height()) @@ -1014,9 +1025,9 @@ impl Fragment { // Make sure the size we used here is for content box since they may be // transferred by the intrinsic aspect ratio. let inline_size = style_length(self.style.content_inline_size(), containing_inline_size) - .map(|x| x - self.box_sizing_boundary(Direction::Inline)); + .map(|x| x - self.box_sizing_boundary(Direction::Inline)); let block_size = style_length(self.style.content_block_size(), containing_block_size) - .map(|x| x - self.box_sizing_boundary(Direction::Block)); + .map(|x| x - self.box_sizing_boundary(Direction::Block)); let inline_constraint = self.size_constraint(containing_inline_size, Direction::Inline); let block_constraint = self.size_constraint(containing_block_size, Direction::Block); @@ -1024,8 +1035,10 @@ impl Fragment { match (inline_size, block_size) { // If the specified size is a definite width and height, the concrete // object size is given that width and height. - (MaybeAuto::Specified(inline_size), MaybeAuto::Specified(block_size)) => - (inline_constraint.clamp(inline_size), block_constraint.clamp(block_size)), + (MaybeAuto::Specified(inline_size), MaybeAuto::Specified(block_size)) => ( + inline_constraint.clamp(inline_size), + block_constraint.clamp(block_size), + ), // If the specified size is only a width or height (but not both) // then the concrete object size is given that specified width or @@ -1044,23 +1057,27 @@ impl Fragment { // Note: We can not precompute the ratio and store it as a float, because // doing so may result one pixel difference in calculation for certain // images, thus make some tests fail. - Au::new((inline_size.0 as i64 * intrinsic_block_size.0 as i64 / - intrinsic_inline_size.0 as i64) as i32) + Au::new( + (inline_size.0 as i64 * intrinsic_block_size.0 as i64 / + intrinsic_inline_size.0 as i64) as i32, + ) } else { intrinsic_block_size }; (inline_size, block_constraint.clamp(block_size)) - } + }, (MaybeAuto::Auto, MaybeAuto::Specified(block_size)) => { let block_size = block_constraint.clamp(block_size); let inline_size = if self.has_intrinsic_ratio() { - Au::new((block_size.0 as i64 * intrinsic_inline_size.0 as i64 / - intrinsic_block_size.0 as i64) as i32) + Au::new( + (block_size.0 as i64 * intrinsic_inline_size.0 as i64 / + intrinsic_block_size.0 as i64) as i32, + ) } else { intrinsic_inline_size }; (inline_constraint.clamp(inline_size), block_size) - } + }, // https://drafts.csswg.org/css2/visudet.html#min-max-widths (MaybeAuto::Auto, MaybeAuto::Auto) => { if self.has_intrinsic_ratio() { @@ -1070,48 +1087,54 @@ impl Fragment { // First, create two rectangles that keep aspect ratio while may be clamped // by the contraints; let first_isize = inline_constraint.clamp(intrinsic_inline_size); - let first_bsize = Au::new((first_isize.0 as i64 * intrinsic_block_size.0 as i64 / - intrinsic_inline_size.0 as i64) as i32); + let first_bsize = Au::new( + (first_isize.0 as i64 * intrinsic_block_size.0 as i64 / + intrinsic_inline_size.0 as i64) as i32, + ); let second_bsize = block_constraint.clamp(intrinsic_block_size); - let second_isize = Au::new((second_bsize.0 as i64 * intrinsic_inline_size.0 as i64 / - intrinsic_block_size.0 as i64) as i32); - let (inline_size, block_size) = match (first_isize.cmp(&intrinsic_inline_size) , - second_isize.cmp(&intrinsic_inline_size)) { - (Ordering::Equal, Ordering::Equal) => - (first_isize, first_bsize), + let second_isize = Au::new( + (second_bsize.0 as i64 * intrinsic_inline_size.0 as i64 / + intrinsic_block_size.0 as i64) as i32, + ); + let (inline_size, block_size) = match ( + first_isize.cmp(&intrinsic_inline_size), + second_isize.cmp(&intrinsic_inline_size), + ) { + (Ordering::Equal, Ordering::Equal) => (first_isize, first_bsize), // When only one rectangle is clamped, use it; - (Ordering::Equal, _) => - (second_isize, second_bsize), - (_, Ordering::Equal) => - (first_isize, first_bsize), + (Ordering::Equal, _) => (second_isize, second_bsize), + (_, Ordering::Equal) => (first_isize, first_bsize), // When both rectangles grow (smaller than min sizes), // Choose the larger one; - (Ordering::Greater, Ordering::Greater) => - if first_isize > second_isize { - (first_isize, first_bsize) - } else { - (second_isize, second_bsize) - }, + (Ordering::Greater, Ordering::Greater) => if first_isize > second_isize { + (first_isize, first_bsize) + } else { + (second_isize, second_bsize) + }, // When both rectangles shrink (larger than max sizes), // Choose the smaller one; - (Ordering::Less, Ordering::Less) => - if first_isize > second_isize { - (second_isize, second_bsize) - } else { - (first_isize, first_bsize) - }, + (Ordering::Less, Ordering::Less) => if first_isize > second_isize { + (second_isize, second_bsize) + } else { + (first_isize, first_bsize) + }, // It does not matter which we choose here, because both sizes // will be clamped to constraint; - (Ordering::Less, Ordering::Greater) | (Ordering::Greater, Ordering::Less) => - (first_isize, first_bsize) + (Ordering::Less, Ordering::Greater) | + (Ordering::Greater, Ordering::Less) => (first_isize, first_bsize), }; // Clamp the result and we are done :-) - (inline_constraint.clamp(inline_size), block_constraint.clamp(block_size)) + ( + inline_constraint.clamp(inline_size), + block_constraint.clamp(block_size), + ) } else { - (inline_constraint.clamp(intrinsic_inline_size), - block_constraint.clamp(intrinsic_block_size)) + ( + inline_constraint.clamp(intrinsic_inline_size), + block_constraint.clamp(intrinsic_block_size), + ) } - } + }, } } @@ -1120,10 +1143,14 @@ impl Fragment { /// must be initialized first. /// /// TODO(stshine): Maybe there is a more convenient way. - pub fn size_constraint(&self, containing_size: Option<Au>, direction: Direction) -> SizeConstraint { + pub fn size_constraint( + &self, + containing_size: Option<Au>, + direction: Direction, + ) -> SizeConstraint { let (style_min_size, style_max_size) = match direction { Direction::Inline => (self.style.min_inline_size(), self.style.max_inline_size()), - Direction::Block => (self.style.min_block_size(), self.style.max_block_size()) + Direction::Block => (self.style.min_block_size(), self.style.max_block_size()), }; let border = if self.style().get_position().box_sizing == BoxSizing::BorderBox { @@ -1165,19 +1192,26 @@ impl Fragment { let writing_mode = self.style.writing_mode; let context_border = match self.inline_context { None => LogicalMargin::zero(writing_mode), - Some(ref inline_fragment_context) => { - inline_fragment_context.nodes.iter().fold(style_border_width, |accumulator, node| { + Some(ref inline_fragment_context) => inline_fragment_context.nodes.iter().fold( + style_border_width, + |accumulator, node| { let mut this_border_width = node.style.border_width_for_writing_mode(writing_mode); - if !node.flags.contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) { + if !node + .flags + .contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) + { this_border_width.inline_start = Au(0) } - if !node.flags.contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) { + if !node + .flags + .contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) + { this_border_width.inline_end = Au(0) } accumulator + this_border_width - }) - } + }, + ), }; style_border_width + context_border } @@ -1186,13 +1220,9 @@ impl Fragment { /// 'box-sizing: border-box'. The `border_padding` field must have been initialized. pub fn box_sizing_boundary(&self, direction: Direction) -> Au { match (self.style().get_position().box_sizing, direction) { - (BoxSizing::BorderBox, Direction::Inline) => { - self.border_padding.inline_start_end() - } - (BoxSizing::BorderBox, Direction::Block) => { - self.border_padding.block_start_end() - } - _ => Au(0) + (BoxSizing::BorderBox, Direction::Inline) => self.border_padding.inline_start_end(), + (BoxSizing::BorderBox, Direction::Block) => self.border_padding.block_start_end(), + _ => Au(0), } } @@ -1210,35 +1240,39 @@ impl Fragment { SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => { self.margin.inline_start = Au(0); self.margin.inline_end = Au(0); - return - } + return; + }, _ => { let margin = self.style().logical_margin(); self.margin.inline_start = - MaybeAuto::from_style(margin.inline_start, - containing_block_inline_size).specified_or_zero(); + 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(); - } + 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(); - let this_inline_start_margin = if !node.flags.contains( - InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) { + let this_inline_start_margin = if !node + .flags + .contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) + { Au(0) } else { - MaybeAuto::from_style(margin.inline_start, - containing_block_inline_size).specified_or_zero() + MaybeAuto::from_style(margin.inline_start, containing_block_inline_size) + .specified_or_zero() }; - let this_inline_end_margin = if!node.flags.contains( - InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) { + let this_inline_end_margin = if !node + .flags + .contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) + { Au(0) } else { - MaybeAuto::from_style(margin.inline_end, - containing_block_inline_size).specified_or_zero() + MaybeAuto::from_style(margin.inline_end, containing_block_inline_size) + .specified_or_zero() }; self.margin.inline_start += this_inline_start_margin; @@ -1260,26 +1294,25 @@ impl Fragment { SpecificFragmentInfo::TableColumn(_) => { self.margin.block_start = Au(0); self.margin.block_end = Au(0) - } + }, _ => { // NB: Percentages are relative to containing block inline-size (not block-size) // per CSS 2.1. let margin = self.style().logical_margin(); self.margin.block_start = MaybeAuto::from_style(margin.block_start, containing_block_inline_size) - .specified_or_zero(); + .specified_or_zero(); self.margin.block_end = MaybeAuto::from_style(margin.block_end, containing_block_inline_size) - .specified_or_zero(); - } + .specified_or_zero(); + }, } } /// Computes the border and padding in both inline and block directions from the containing /// block inline-size and the style. After this call, the `border_padding` field will be /// correct. - pub fn compute_border_and_padding(&mut self, - containing_block_inline_size: Au) { + pub fn compute_border_and_padding(&mut self, containing_block_inline_size: Au) { // Compute border. let border = match self.style.get_inherited_table().border_collapse { BorderCollapse::Separate => self.border_width(), @@ -1291,7 +1324,11 @@ impl Fragment { SpecificFragmentInfo::TableColumn(_) | SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper => LogicalMargin::zero(self.style.writing_mode), - _ => model::padding_from_style(self.style(), containing_block_inline_size, self.style().writing_mode), + _ => model::padding_from_style( + self.style(), + containing_block_inline_size, + self.style().writing_mode, + ), }; // Compute padding from the inline fragment context. @@ -1301,21 +1338,31 @@ impl Fragment { (&SpecificFragmentInfo::TableRow, _) | (&SpecificFragmentInfo::TableWrapper, _) => { LogicalMargin::zero(self.style.writing_mode) - } + }, (_, &Some(ref inline_fragment_context)) => { let writing_mode = self.style.writing_mode; let zero_padding = LogicalMargin::zero(writing_mode); - inline_fragment_context.nodes.iter().fold(zero_padding, |accumulator, node| { - let mut padding = model::padding_from_style(&*node.style, Au(0), writing_mode); - if !node.flags.contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) { - padding.inline_start = Au(0) - } - if !node.flags.contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) { - padding.inline_end = Au(0) - } - accumulator + padding - }) - } + inline_fragment_context + .nodes + .iter() + .fold(zero_padding, |accumulator, node| { + let mut padding = + model::padding_from_style(&*node.style, Au(0), writing_mode); + if !node + .flags + .contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) + { + padding.inline_start = Au(0) + } + if !node + .flags + .contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) + { + padding.inline_end = Au(0) + } + accumulator + padding + }) + }, }; self.border_padding = border + padding_from_style + padding_from_inline_fragment_context @@ -1323,22 +1370,19 @@ impl Fragment { // Return offset from original position because of `position: relative`. pub fn relative_position(&self, containing_block_size: &LogicalSize<Au>) -> LogicalSize<Au> { - fn from_style(style: &ComputedValues, container_size: &LogicalSize<Au>) - -> LogicalSize<Au> { + fn from_style(style: &ComputedValues, container_size: &LogicalSize<Au>) -> LogicalSize<Au> { let offsets = style.logical_position(); let offset_i = if offsets.inline_start != LengthOrPercentageOrAuto::Auto { - MaybeAuto::from_style(offsets.inline_start, - container_size.inline).specified_or_zero() + MaybeAuto::from_style(offsets.inline_start, container_size.inline) + .specified_or_zero() } else { - -MaybeAuto::from_style(offsets.inline_end, - container_size.inline).specified_or_zero() + -MaybeAuto::from_style(offsets.inline_end, container_size.inline) + .specified_or_zero() }; let offset_b = if offsets.block_start != LengthOrPercentageOrAuto::Auto { - MaybeAuto::from_style(offsets.block_start, - container_size.block).specified_or_zero() + MaybeAuto::from_style(offsets.block_start, container_size.block).specified_or_zero() } else { - -MaybeAuto::from_style(offsets.block_end, - container_size.block).specified_or_zero() + -MaybeAuto::from_style(offsets.block_end, container_size.block).specified_or_zero() }; LogicalSize::new(style.writing_mode, offset_i, offset_b) } @@ -1456,8 +1500,9 @@ impl Fragment { pub fn suppress_line_break_before(&self) -> bool { match self.specific { - SpecificFragmentInfo::ScannedText(ref st) => - st.flags.contains(ScannedTextFlags::SUPPRESS_LINE_BREAK_BEFORE), + SpecificFragmentInfo::ScannedText(ref st) => st + .flags + .contains(ScannedTextFlags::SUPPRESS_LINE_BREAK_BEFORE), _ => false, } } @@ -1475,27 +1520,27 @@ impl Fragment { SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::Multicol | SpecificFragmentInfo::MulticolColumn | - SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {} + SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {}, SpecificFragmentInfo::InlineBlock(ref info) => { let block_flow = info.flow_ref.as_block(); result.union_block(&block_flow.base.intrinsic_inline_sizes) - } + }, SpecificFragmentInfo::InlineAbsolute(ref info) => { let block_flow = info.flow_ref.as_block(); result.union_block(&block_flow.base.intrinsic_inline_sizes) - } + }, SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Svg(_) => { let mut inline_size = match self.style.content_inline_size() { - LengthOrPercentageOrAuto::Auto | - LengthOrPercentageOrAuto::Percentage(_) => { + LengthOrPercentageOrAuto::Auto | LengthOrPercentageOrAuto::Percentage(_) => { // We have to initialize the `border_padding` field first to make // the size constraints work properly. // TODO(stshine): Find a cleaner way to do this. let padding = self.style.logical_padding(); - self.border_padding.inline_start = padding.inline_start.to_used_value(Au(0)); + self.border_padding.inline_start = + padding.inline_start.to_used_value(Au(0)); self.border_padding.inline_end = padding.inline_end.to_used_value(Au(0)); self.border_padding.block_start = padding.block_start.to_used_value(Au(0)); self.border_padding.block_end = padding.block_end.to_used_value(Au(0)); @@ -1506,7 +1551,7 @@ impl Fragment { self.border_padding.block_end += border.block_end; let (result_inline, _) = self.calculate_replaced_sizes(None, None); result_inline - } + }, LengthOrPercentageOrAuto::Length(length) => Au::from(length), LengthOrPercentageOrAuto::Calc(calc) => { // TODO(nox): This is probably wrong, because it accounts neither for @@ -1522,34 +1567,36 @@ impl Fragment { minimum_inline_size: inline_size, preferred_inline_size: inline_size, }); - } + }, SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { let text_fragment_info = t.text_info.as_ref().unwrap(); handle_text(text_fragment_info, self, &mut result) - } + }, SpecificFragmentInfo::ScannedText(ref text_fragment_info) => { handle_text(text_fragment_info, self, &mut result) - } + }, - SpecificFragmentInfo::TruncatedFragment(_) => { - return IntrinsicISizesContribution::new() - } + SpecificFragmentInfo::TruncatedFragment(_) => return IntrinsicISizesContribution::new(), SpecificFragmentInfo::UnscannedText(..) => { panic!("Unscanned text fragments should have been scanned by now!") - } + }, }; - fn handle_text(text_fragment_info: &ScannedTextFragmentInfo, self_: &Fragment, - result: &mut IntrinsicISizesContribution) { + fn handle_text( + text_fragment_info: &ScannedTextFragmentInfo, + self_: &Fragment, + result: &mut IntrinsicISizesContribution, + ) { let range = &text_fragment_info.range; // See http://dev.w3.org/csswg/css-sizing/#max-content-inline-size. // TODO: Account for soft wrap opportunities. - let max_line_inline_size = text_fragment_info.run - .metrics_for_range(range) - .advance_width; + let max_line_inline_size = text_fragment_info + .run + .metrics_for_range(range) + .advance_width; let min_line_inline_size = if self_.white_space().allow_wrap() { text_fragment_info.run.min_width_for_range(range) @@ -1570,19 +1617,24 @@ impl Fragment { let mut border_width = node.style.logical_border_width(); let mut padding = model::padding_from_style(&*node.style, Au(0), writing_mode); let mut margin = model::specified_margin_from_style(&*node.style, writing_mode); - if !node.flags.contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) { + if !node + .flags + .contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) + { border_width.inline_start = Au(0); padding.inline_start = Au(0); margin.inline_start = Au(0); } - if !node.flags.contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) { + if !node + .flags + .contains(InlineFragmentNodeFlags::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 + + result.surrounding_size = result.surrounding_size + border_width.inline_start_end() + padding.inline_start_end() + margin.inline_start_end(); @@ -1600,10 +1652,10 @@ impl Fragment { SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { let text = t.text_info.as_ref().unwrap(); text.run.minimum_splittable_inline_size(&text.range) - } + }, SpecificFragmentInfo::ScannedText(ref text) => { text.run.minimum_splittable_inline_size(&text.range) - } + }, _ => Au(0), } } @@ -1623,12 +1675,14 @@ impl Fragment { /// A return value of `None` indicates that the fragment could not be split. Otherwise the /// information pertaining to the split is returned. The inline-start and inline-end split /// information are both optional due to the possibility of them being whitespace. - pub fn calculate_split_position(&self, max_inline_size: Au, starts_line: bool) - -> Option<SplitResult> { + pub fn calculate_split_position( + &self, + max_inline_size: Au, + starts_line: bool, + ) -> Option<SplitResult> { let text_fragment_info = match self.specific { - SpecificFragmentInfo::ScannedText(ref text_fragment_info) - => text_fragment_info, - _ => return None, + SpecificFragmentInfo::ScannedText(ref text_fragment_info) => text_fragment_info, + _ => return None, }; let mut flags = SplitOptions::empty(); @@ -1642,34 +1696,39 @@ impl Fragment { match self.style().get_inherited_text().word_break { WordBreak::Normal | WordBreak::KeepAll => { // Break at normal word boundaries. keep-all forbids soft wrap opportunities. - let natural_word_breaking_strategy = - text_fragment_info.run.natural_word_slices_in_range(&text_fragment_info.range); + let natural_word_breaking_strategy = text_fragment_info + .run + .natural_word_slices_in_range(&text_fragment_info.range); self.calculate_split_position_using_breaking_strategy( natural_word_breaking_strategy, max_inline_size, - flags) - } + flags, + ) + }, WordBreak::BreakAll => { // Break at character boundaries. - let character_breaking_strategy = - text_fragment_info.run.character_slices_in_range(&text_fragment_info.range); + let character_breaking_strategy = text_fragment_info + .run + .character_slices_in_range(&text_fragment_info.range); flags.remove(SplitOptions::RETRY_AT_CHARACTER_BOUNDARIES); self.calculate_split_position_using_breaking_strategy( character_breaking_strategy, max_inline_size, - flags) - } + flags, + ) + }, } } /// Does this fragment start on a glyph run boundary? pub fn is_on_glyph_run_boundary(&self) -> bool { let text_fragment_info = match self.specific { - SpecificFragmentInfo::ScannedText(ref text_fragment_info) - => text_fragment_info, - _ => return true, + SpecificFragmentInfo::ScannedText(ref text_fragment_info) => text_fragment_info, + _ => return true, }; - text_fragment_info.run.on_glyph_run_boundary(text_fragment_info.range.begin()) + text_fragment_info + .run + .on_glyph_run_boundary(text_fragment_info.range.begin()) } /// Truncates this fragment to the given `max_inline_size`, using a character-based breaking @@ -1683,38 +1742,41 @@ impl Fragment { } let info = self.calculate_truncate_to_inline_size(max_inline_size); let (size, text_info) = match info { - Some(TruncationResult { split: SplitInfo { inline_size, range }, text_run } ) => { - let size = LogicalSize::new(self.style.writing_mode, - inline_size, - self.border_box.size.block); + Some(TruncationResult { + split: SplitInfo { inline_size, range }, + text_run, + }) => { + let size = LogicalSize::new( + self.style.writing_mode, + inline_size, + self.border_box.size.block, + ); // Preserve the insertion point if it is in this fragment's range or it is at line end. let (flags, insertion_point) = match self.specific { - SpecificFragmentInfo::ScannedText(ref info) => { - match info.insertion_point { - Some(index) if range.contains(index) => (info.flags, info.insertion_point), - Some(index) if index == ByteIndex(text_run.text.chars().count() as isize - 1) && - index == range.end() => (info.flags, info.insertion_point), - _ => (info.flags, None) - } + SpecificFragmentInfo::ScannedText(ref info) => match info.insertion_point { + Some(index) if range.contains(index) => (info.flags, info.insertion_point), + Some(index) + if index == ByteIndex(text_run.text.chars().count() as isize - 1) && + index == range.end() => + { + (info.flags, info.insertion_point) + }, + _ => (info.flags, None), }, - _ => (ScannedTextFlags::empty(), None) + _ => (ScannedTextFlags::empty(), None), }; - let text_info = ScannedTextFragmentInfo::new( - text_run, - range, - size, - insertion_point, - flags); + let text_info = + ScannedTextFragmentInfo::new(text_run, range, size, insertion_point, flags); (size, Some(text_info)) - } - None => - (LogicalSize::zero(self.style.writing_mode), None) + }, + None => (LogicalSize::zero(self.style.writing_mode), None), }; let mut result = self.transform(size, SpecificFragmentInfo::Generic); - result.specific = SpecificFragmentInfo::TruncatedFragment(Box::new(TruncatedFragmentInfo { - text_info: text_info, - full: self, - })); + result.specific = + SpecificFragmentInfo::TruncatedFragment(Box::new(TruncatedFragmentInfo { + text_info: text_info, + full: self, + })); result } @@ -1725,16 +1787,18 @@ impl Fragment { if let SpecificFragmentInfo::ScannedText(ref text_fragment_info) = self.specific { text_fragment_info } else { - return None + return None; }; - let character_breaking_strategy = - text_fragment_info.run.character_slices_in_range(&text_fragment_info.range); + let character_breaking_strategy = text_fragment_info + .run + .character_slices_in_range(&text_fragment_info.range); let split_info = self.calculate_split_position_using_breaking_strategy( - character_breaking_strategy, - max_inline_size, - SplitOptions::empty())?; + character_breaking_strategy, + max_inline_size, + SplitOptions::empty(), + )?; let split = split_info.inline_start?; Some(TruncationResult { @@ -1746,16 +1810,17 @@ impl Fragment { /// A helper method that uses the breaking strategy described by `slice_iterator` (at present, /// either natural word breaking or character breaking) to split this fragment. fn calculate_split_position_using_breaking_strategy<'a, I>( - &self, - slice_iterator: I, - max_inline_size: Au, - flags: SplitOptions) - -> Option<SplitResult> - where I: Iterator<Item=TextRunSlice<'a>> { + &self, + slice_iterator: I, + max_inline_size: Au, + flags: SplitOptions, + ) -> Option<SplitResult> + where + I: Iterator<Item = TextRunSlice<'a>>, + { let text_fragment_info = match self.specific { - SpecificFragmentInfo::ScannedText(ref text_fragment_info) - => text_fragment_info, - _ => return None, + SpecificFragmentInfo::ScannedText(ref text_fragment_info) => text_fragment_info, + _ => return None, }; let mut remaining_inline_size = max_inline_size - self.border_padding.inline_start_end(); @@ -1763,22 +1828,26 @@ impl Fragment { let mut inline_end_range = None; let mut overflowing = false; - debug!("calculate_split_position_using_breaking_strategy: splitting text fragment \ - (strlen={}, range={:?}, max_inline_size={:?})", - text_fragment_info.run.text.len(), - text_fragment_info.range, - max_inline_size); + debug!( + "calculate_split_position_using_breaking_strategy: splitting text fragment \ + (strlen={}, range={:?}, max_inline_size={:?})", + text_fragment_info.run.text.len(), + text_fragment_info.range, + max_inline_size + ); for slice in slice_iterator { - debug!("calculate_split_position_using_breaking_strategy: considering slice \ - (offset={:?}, slice range={:?}, remaining_inline_size={:?})", - slice.offset, - slice.range, - remaining_inline_size); + debug!( + "calculate_split_position_using_breaking_strategy: considering slice \ + (offset={:?}, slice range={:?}, remaining_inline_size={:?})", + slice.offset, slice.range, remaining_inline_size + ); // Use the `remaining_inline_size` to find a split point if possible. If not, go around // the loop again with the next slice. - let metrics = text_fragment_info.run.metrics_for_slice(slice.glyphs, &slice.range); + let metrics = text_fragment_info + .run + .metrics_for_slice(slice.glyphs, &slice.range); let advance = metrics.advance_width; // Have we found the split point? @@ -1787,15 +1856,15 @@ impl Fragment { debug!("calculate_split_position_using_breaking_strategy: enlarging span"); remaining_inline_size = remaining_inline_size - advance; inline_start_range.extend_by(slice.range.length()); - continue + continue; } // The advance is more than the remaining inline-size, so split here. First, check to // see if we're going to overflow the line. If so, perform a best-effort split. let mut remaining_range = slice.text_run_range(); - let split_is_empty = inline_start_range.is_empty() && - !(self.requires_line_break_afterward_if_wrapping_on_newlines() && - !self.white_space().allow_wrap()); + let split_is_empty = inline_start_range.is_empty() && !(self + .requires_line_break_afterward_if_wrapping_on_newlines() && + !self.white_space().allow_wrap()); if split_is_empty { // We're going to overflow the line. overflowing = true; @@ -1812,8 +1881,10 @@ impl Fragment { let mut inline_end = remaining_range; inline_end.extend_to(text_fragment_info.range.end()); inline_end_range = Some(inline_end); - debug!("calculate_split_position: splitting remainder with inline-end range={:?}", - inline_end); + debug!( + "calculate_split_position: splitting remainder with inline-end range={:?}", + inline_end + ); } // If we failed to find a suitable split point, we're on the verge of overflowing the @@ -1822,37 +1893,37 @@ impl Fragment { // If we've been instructed to retry at character boundaries (probably via // `overflow-wrap: break-word`), do so. if flags.contains(SplitOptions::RETRY_AT_CHARACTER_BOUNDARIES) { - let character_breaking_strategy = - text_fragment_info.run - .character_slices_in_range(&text_fragment_info.range); + let character_breaking_strategy = text_fragment_info + .run + .character_slices_in_range(&text_fragment_info.range); let mut flags = flags; flags.remove(SplitOptions::RETRY_AT_CHARACTER_BOUNDARIES); return self.calculate_split_position_using_breaking_strategy( character_breaking_strategy, max_inline_size, - flags) + flags, + ); } // We aren't at the start of the line, so don't overflow. Let inline layout wrap to // the next line instead. if !flags.contains(SplitOptions::STARTS_LINE) { - return None + return None; } } - break + break; } let split_is_empty = inline_start_range.is_empty() && - !self.requires_line_break_afterward_if_wrapping_on_newlines(); + !self.requires_line_break_afterward_if_wrapping_on_newlines(); let inline_start = if !split_is_empty { Some(SplitInfo::new(inline_start_range, &**text_fragment_info)) } else { None }; - let inline_end = inline_end_range.map(|inline_end_range| { - SplitInfo::new(inline_end_range, &**text_fragment_info) - }); + let inline_end = inline_end_range + .map(|inline_end_range| SplitInfo::new(inline_end_range, &**text_fragment_info)); Some(SplitResult { inline_start: inline_start, @@ -1865,20 +1936,24 @@ impl Fragment { /// with the next one. pub fn merge_with(&mut self, next_fragment: Fragment) { match (&mut self.specific, &next_fragment.specific) { - (&mut SpecificFragmentInfo::ScannedText(ref mut this_info), - &SpecificFragmentInfo::ScannedText(ref other_info)) => { + ( + &mut SpecificFragmentInfo::ScannedText(ref mut this_info), + &SpecificFragmentInfo::ScannedText(ref other_info), + ) => { debug_assert!(Arc::ptr_eq(&this_info.run, &other_info.run)); this_info.range_end_including_stripped_whitespace = other_info.range_end_including_stripped_whitespace; if other_info.requires_line_break_afterward_if_wrapping_on_newlines() { - this_info.flags.insert(ScannedTextFlags::REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES); + this_info.flags.insert( + ScannedTextFlags::REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES, + ); } if other_info.insertion_point.is_some() { this_info.insertion_point = other_info.insertion_point; } self.border_padding.inline_end = next_fragment.border_padding.inline_end; self.margin.inline_end = next_fragment.margin.inline_end; - } + }, _ => panic!("Can only merge two scanned-text fragments!"), } self.reset_text_range_and_inline_size(); @@ -1896,20 +1971,22 @@ impl Fragment { // FIXME (mbrubeck): Do we need to restore leading too? let range_end = info.range_end_including_stripped_whitespace; if info.range.end() == range_end { - return + return; } info.range.extend_to(range_end); info.content_size.inline = info.run.metrics_for_range(&info.range).advance_width; - self.border_box.size.inline = info.content_size.inline + - self.border_padding.inline_start_end(); + self.border_box.size.inline = + info.content_size.inline + self.border_padding.inline_start_end(); } } /// Assigns replaced inline-size, padding, and margins for this fragment only if it is replaced /// content per CSS 2.1 § 10.3.2. - pub fn assign_replaced_inline_size_if_necessary(&mut self, - container_inline_size: Au, - container_block_size: Option<Au>) { + pub fn assign_replaced_inline_size_if_necessary( + &mut self, + container_inline_size: Au, + container_block_size: Option<Au>, + ) { match self.specific { SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_none() => return, SpecificFragmentInfo::Generic | @@ -1922,10 +1999,10 @@ impl Fragment { SpecificFragmentInfo::MulticolColumn => return, SpecificFragmentInfo::TableColumn(_) => { panic!("Table column fragments do not have inline size") - } + }, SpecificFragmentInfo::UnscannedText(_) => { panic!("Unscanned text fragments should have been scanned by now!") - } + }, SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Iframe(_) | @@ -1934,7 +2011,7 @@ impl Fragment { SpecificFragmentInfo::InlineAbsolute(_) | SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::TruncatedFragment(_) | - SpecificFragmentInfo::Svg(_) => {} + SpecificFragmentInfo::Svg(_) => {}, }; match self.specific { @@ -1946,48 +2023,52 @@ impl Fragment { // This is a hypothetical box, so it takes up no space. self.border_box.size.inline = Au(0); - } + }, SpecificFragmentInfo::InlineBlock(ref mut info) => { let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_mut_block(); - self.border_box.size.inline = - max(block_flow.base.intrinsic_inline_sizes.minimum_inline_size, - block_flow.base.intrinsic_inline_sizes.preferred_inline_size); + self.border_box.size.inline = max( + block_flow.base.intrinsic_inline_sizes.minimum_inline_size, + block_flow.base.intrinsic_inline_sizes.preferred_inline_size, + ); block_flow.base.block_container_inline_size = self.border_box.size.inline; block_flow.base.block_container_writing_mode = self.style.writing_mode; - } + }, SpecificFragmentInfo::InlineAbsolute(ref mut info) => { let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_mut_block(); - self.border_box.size.inline = - max(block_flow.base.intrinsic_inline_sizes.minimum_inline_size, - block_flow.base.intrinsic_inline_sizes.preferred_inline_size); + self.border_box.size.inline = max( + block_flow.base.intrinsic_inline_sizes.minimum_inline_size, + block_flow.base.intrinsic_inline_sizes.preferred_inline_size, + ); block_flow.base.block_container_inline_size = self.border_box.size.inline; block_flow.base.block_container_writing_mode = self.style.writing_mode; - } + }, // Text SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { let info = t.text_info.as_ref().unwrap(); // Scanned text fragments will have already had their content inline-sizes assigned // by this point. - self.border_box.size.inline = info.content_size.inline + - self.border_padding.inline_start_end(); - } + self.border_box.size.inline = + info.content_size.inline + self.border_padding.inline_start_end(); + }, SpecificFragmentInfo::ScannedText(ref info) => { // Scanned text fragments will have already had their content inline-sizes assigned // by this point. - self.border_box.size.inline = info.content_size.inline + - self.border_padding.inline_start_end(); - } + self.border_box.size.inline = + info.content_size.inline + self.border_padding.inline_start_end(); + }, // Replaced elements _ if self.is_replaced() => { - let (inline_size, block_size) = - self.calculate_replaced_sizes(Some(container_inline_size), container_block_size); + let (inline_size, block_size) = self + .calculate_replaced_sizes(Some(container_inline_size), container_block_size); self.border_box.size.inline = inline_size + self.border_padding.inline_start_end(); self.border_box.size.block = block_size + self.border_padding.block_start_end(); - } + }, - ref unhandled @ _ => panic!("this case should have been handled above: {:?}", unhandled), + ref unhandled @ _ => { + panic!("this case should have been handled above: {:?}", unhandled) + }, } } @@ -2008,10 +2089,10 @@ impl Fragment { SpecificFragmentInfo::MulticolColumn => return, SpecificFragmentInfo::TableColumn(_) => { panic!("Table column fragments do not have block size") - } + }, SpecificFragmentInfo::UnscannedText(_) => { panic!("Unscanned text fragments should have been scanned by now!") - } + }, SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | @@ -2020,7 +2101,7 @@ impl Fragment { SpecificFragmentInfo::InlineAbsolute(_) | SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::TruncatedFragment(_) | - SpecificFragmentInfo::Svg(_) => {} + SpecificFragmentInfo::Svg(_) => {}, } match self.specific { @@ -2029,15 +2110,15 @@ impl Fragment { let info = t.text_info.as_ref().unwrap(); // Scanned text fragments' content block-sizes are calculated by the text run // scanner during flow construction. - self.border_box.size.block = info.content_size.block + - self.border_padding.block_start_end(); - } + self.border_box.size.block = + info.content_size.block + self.border_padding.block_start_end(); + }, SpecificFragmentInfo::ScannedText(ref info) => { // Scanned text fragments' content block-sizes are calculated by the text run // scanner during flow construction. - self.border_box.size.block = info.content_size.block + - self.border_padding.block_start_end(); - } + self.border_box.size.block = + info.content_size.block + self.border_padding.block_start_end(); + }, // Inline blocks SpecificFragmentInfo::InlineBlock(ref mut info) => { @@ -2045,18 +2126,18 @@ impl Fragment { let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_block(); self.border_box.size.block = block_flow.base.position.size.block + block_flow.fragment.margin.block_start_end() - } + }, SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { // Not the primary fragment, so we do not take the noncontent size into account. let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_block(); self.border_box.size.block = block_flow.base.position.size.block; - } + }, SpecificFragmentInfo::InlineAbsolute(ref mut info) => { // Not the primary fragment, so we do not take the noncontent size into account. let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_block(); self.border_box.size.block = block_flow.base.position.size.block + block_flow.fragment.margin.block_start_end() - } + }, // Replaced elements _ if self.is_replaced() => {}, @@ -2072,7 +2153,7 @@ impl Fragment { SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Svg(_) => true, - _ => false + _ => false, } } @@ -2099,33 +2180,34 @@ impl Fragment { // fragment types should end up inside inlines. (In the case of `GeneratedContent`, those // fragment types should have been resolved by now…) let inline_metrics = match self.specific { - SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) | - SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Svg(_) | - SpecificFragmentInfo::Generic | SpecificFragmentInfo::GeneratedContent(_) => { + SpecificFragmentInfo::Canvas(_) | + SpecificFragmentInfo::Iframe(_) | + SpecificFragmentInfo::Image(_) | + SpecificFragmentInfo::Svg(_) | + SpecificFragmentInfo::Generic | + SpecificFragmentInfo::GeneratedContent(_) => { let ascent = self.border_box.size.block + self.margin.block_end; InlineMetrics { space_above_baseline: ascent + self.margin.block_start, space_below_baseline: Au(0), ascent: ascent, } - } + }, SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { let info = t.text_info.as_ref().unwrap(); inline_metrics_of_text(info, self, layout_context) - } + }, SpecificFragmentInfo::ScannedText(ref info) => { inline_metrics_of_text(info, self, layout_context) - } + }, SpecificFragmentInfo::InlineBlock(ref info) => { inline_metrics_of_block(&info.flow_ref, &*self.style) - } + }, SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => { inline_metrics_of_block(&info.flow_ref, &*self.style) - } + }, SpecificFragmentInfo::TruncatedFragment(..) | - SpecificFragmentInfo::InlineAbsolute(_) => { - InlineMetrics::new(Au(0), Au(0), Au(0)) - } + SpecificFragmentInfo::InlineAbsolute(_) => InlineMetrics::new(Au(0), Au(0), Au(0)), SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableColumn(_) | @@ -2135,12 +2217,15 @@ impl Fragment { SpecificFragmentInfo::MulticolColumn | SpecificFragmentInfo::UnscannedText(_) => { unreachable!("Shouldn't see fragments of this type here!") - } + }, }; return inline_metrics; - fn inline_metrics_of_text(info: &ScannedTextFragmentInfo, self_: &Fragment, - layout_context: &LayoutContext) -> InlineMetrics { + fn inline_metrics_of_text( + info: &ScannedTextFragmentInfo, + self_: &Fragment, + layout_context: &LayoutContext, + ) -> InlineMetrics { // Fragments with no glyphs don't contribute any inline metrics. // TODO: Filter out these fragments during flow construction? if info.insertion_point.is_none() && info.content_size.inline == Au(0) { @@ -2186,9 +2271,10 @@ impl Fragment { // § 10.8.1 says that the baseline (and thus ascent, which is the // distance from the baseline to the top) should be A if it has an // in-flow line box and if overflow: visible, and B otherwise. - let ascent = - match (flow.baseline_offset_of_last_line_box_in_flow(), - style.get_box().overflow_y) { + let ascent = match ( + flow.baseline_offset_of_last_line_box_in_flow(), + style.get_box().overflow_y, + ) { // Case A (Some(baseline_offset), StyleOverflow::Visible) => baseline_offset, // Case B @@ -2208,12 +2294,13 @@ impl Fragment { /// If `actual_line_metrics` is supplied, then these metrics are used to determine the /// displacement of the fragment when `top` or `bottom` `vertical-align` values are /// encountered. If this is not supplied, then `top` and `bottom` values are ignored. - fn vertical_alignment_offset(&self, - layout_context: &LayoutContext, - content_inline_metrics: &InlineMetrics, - minimum_line_metrics: &LineMetrics, - actual_line_metrics: Option<&LineMetrics>) - -> Au { + fn vertical_alignment_offset( + &self, + layout_context: &LayoutContext, + content_inline_metrics: &InlineMetrics, + minimum_line_metrics: &LineMetrics, + actual_line_metrics: Option<&LineMetrics>, + ) -> Au { let mut offset = Au(0); for style in self.inline_styles() { // If any of the inline styles say `top` or `bottom`, adjust the vertical align @@ -2222,52 +2309,59 @@ impl Fragment { // FIXME(#5624, pcwalton): This passes our current reftests but isn't the right thing // to do. match style.get_box().vertical_align { - VerticalAlign::Baseline => {} + VerticalAlign::Baseline => {}, VerticalAlign::Middle => { - let font_metrics = with_thread_local_font_context(layout_context, |font_context| { - text::font_metrics_for_style(font_context, self.style.clone_font()) - }); + let font_metrics = + with_thread_local_font_context(layout_context, |font_context| { + text::font_metrics_for_style(font_context, self.style.clone_font()) + }); offset += (content_inline_metrics.ascent - - content_inline_metrics.space_below_baseline - - font_metrics.x_height).scale_by(0.5) - } + content_inline_metrics.space_below_baseline - + font_metrics.x_height) + .scale_by(0.5) + }, VerticalAlign::Sub => { - offset += minimum_line_metrics.space_needed() - .scale_by(FONT_SUBSCRIPT_OFFSET_RATIO) - } + offset += minimum_line_metrics + .space_needed() + .scale_by(FONT_SUBSCRIPT_OFFSET_RATIO) + }, VerticalAlign::Super => { - offset -= minimum_line_metrics.space_needed() - .scale_by(FONT_SUPERSCRIPT_OFFSET_RATIO) - } + offset -= minimum_line_metrics + .space_needed() + .scale_by(FONT_SUPERSCRIPT_OFFSET_RATIO) + }, VerticalAlign::TextTop => { offset = self.content_inline_metrics(layout_context).ascent - minimum_line_metrics.space_above_baseline - } + }, VerticalAlign::TextBottom => { - offset = minimum_line_metrics.space_below_baseline - - self.content_inline_metrics(layout_context).space_below_baseline - } + offset = minimum_line_metrics.space_below_baseline - self + .content_inline_metrics(layout_context) + .space_below_baseline + }, VerticalAlign::Top => { if let Some(actual_line_metrics) = actual_line_metrics { - offset = content_inline_metrics.ascent - - actual_line_metrics.space_above_baseline + offset = + content_inline_metrics.ascent - actual_line_metrics.space_above_baseline } - } + }, VerticalAlign::Bottom => { if let Some(actual_line_metrics) = actual_line_metrics { offset = actual_line_metrics.space_below_baseline - content_inline_metrics.space_below_baseline } - } + }, VerticalAlign::Length(LengthOrPercentage::Length(length)) => { offset -= Au::from(length) - } + }, VerticalAlign::Length(LengthOrPercentage::Percentage(percentage)) => { offset -= minimum_line_metrics.space_needed().scale_by(percentage.0) - } + }, VerticalAlign::Length(LengthOrPercentage::Calc(formula)) => { - offset -= formula.to_used_value(Some(minimum_line_metrics.space_needed())).unwrap() - } + offset -= formula + .to_used_value(Some(minimum_line_metrics.space_needed())) + .unwrap() + }, } } offset @@ -2280,23 +2374,26 @@ impl Fragment { /// If `actual_line_metrics` is supplied, then these metrics are used to determine the /// displacement of the fragment when `top` or `bottom` `vertical-align` values are /// encountered. If this is not supplied, then `top` and `bottom` values are ignored. - pub fn aligned_inline_metrics(&self, - layout_context: &LayoutContext, - minimum_line_metrics: &LineMetrics, - actual_line_metrics: Option<&LineMetrics>) - -> InlineMetrics { + pub fn aligned_inline_metrics( + &self, + layout_context: &LayoutContext, + minimum_line_metrics: &LineMetrics, + actual_line_metrics: Option<&LineMetrics>, + ) -> InlineMetrics { let content_inline_metrics = self.content_inline_metrics(layout_context); - let vertical_alignment_offset = self.vertical_alignment_offset(layout_context, - &content_inline_metrics, - minimum_line_metrics, - actual_line_metrics); + let vertical_alignment_offset = self.vertical_alignment_offset( + layout_context, + &content_inline_metrics, + minimum_line_metrics, + actual_line_metrics, + ); let mut space_above_baseline = match actual_line_metrics { None => content_inline_metrics.space_above_baseline, Some(actual_line_metrics) => actual_line_metrics.space_above_baseline, }; space_above_baseline = space_above_baseline - vertical_alignment_offset; - let space_below_baseline = content_inline_metrics.space_below_baseline + - vertical_alignment_offset; + let space_below_baseline = + content_inline_metrics.space_below_baseline + vertical_alignment_offset; let ascent = content_inline_metrics.ascent - vertical_alignment_offset; InlineMetrics::new(space_above_baseline, space_below_baseline, ascent) } @@ -2313,37 +2410,45 @@ impl Fragment { /// 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(_)) => { + ( + &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_line() != other.text_decoration_line() || - self.white_space() != other.white_space() || - self.color() != other.color() { - return false + self.text_decoration_line() != other.text_decoration_line() || + self.white_space() != other.white_space() || + self.color() != other.color() + { + return false; } if first_unscanned_text.text.ends_with('\n') { - return false + 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(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) { - continue + if !inline_context_node + .flags + .contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) + { + continue; } if inline_context_node.style.logical_margin().inline_end != - LengthOrPercentageOrAuto::Length(Length::new(0.)) { - return false + LengthOrPercentageOrAuto::Length(Length::new(0.)) + { + return false; } if inline_context_node.style.logical_padding().inline_end != - LengthOrPercentage::Length(Length::new(0.)) { - return false + LengthOrPercentage::Length(Length::new(0.)) + { + return false; } if inline_context_node.style.logical_border_width().inline_end != Au(0) { - return false + return false; } } } @@ -2352,25 +2457,35 @@ impl Fragment { // 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(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) { - continue + if !inline_context_node + .flags + .contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) + { + continue; } if inline_context_node.style.logical_margin().inline_start != - LengthOrPercentageOrAuto::Length(Length::new(0.)) { - return false + LengthOrPercentageOrAuto::Length(Length::new(0.)) + { + return false; } if inline_context_node.style.logical_padding().inline_start != - LengthOrPercentage::Length(Length::new(0.)) { - return false + LengthOrPercentage::Length(Length::new(0.)) + { + return false; } - if inline_context_node.style.logical_border_width().inline_start != Au(0) { - return false + if inline_context_node + .style + .logical_border_width() + .inline_start != + Au(0) + { + return false; } } } true - } + }, _ => false, } } @@ -2450,17 +2565,20 @@ impl Fragment { /// /// This is the method you should use for display list construction as well as /// `getBoundingClientRect()` and so forth. - pub fn stacking_relative_border_box(&self, - stacking_relative_flow_origin: &Vector2D<Au>, - relative_containing_block_size: &LogicalSize<Au>, - relative_containing_block_mode: WritingMode, - coordinate_system: CoordinateSystem) - -> Rect<Au> { + pub fn stacking_relative_border_box( + &self, + stacking_relative_flow_origin: &Vector2D<Au>, + relative_containing_block_size: &LogicalSize<Au>, + relative_containing_block_mode: WritingMode, + coordinate_system: CoordinateSystem, + ) -> Rect<Au> { let container_size = relative_containing_block_size.to_physical(relative_containing_block_mode); - let border_box = self.border_box.to_physical(self.style.writing_mode, container_size); + let border_box = self + .border_box + .to_physical(self.style.writing_mode, container_size); if coordinate_system == CoordinateSystem::Own && self.establishes_stacking_context() { - return Rect::new(Point2D::zero(), border_box.size) + return Rect::new(Point2D::zero(), border_box.size); } // FIXME(pcwalton): This can double-count relative position sometimes for inlines (e.g. @@ -2468,32 +2586,41 @@ impl Fragment { // to the inline flow. Possibly we should extend the notion of "primary fragment" to fix // this. let relative_position = self.relative_position(relative_containing_block_size); - border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode)) - .translate(&stacking_relative_flow_origin) + border_box + .translate_by_size(&relative_position.to_physical(self.style.writing_mode)) + .translate(&stacking_relative_flow_origin) } /// Given the stacking-context-relative border box, returns the stacking-context-relative /// content box. - pub fn stacking_relative_content_box(&self, stacking_relative_border_box: Rect<Au>) - -> Rect<Au> { + pub fn stacking_relative_content_box( + &self, + stacking_relative_border_box: Rect<Au>, + ) -> Rect<Au> { let border_padding = self.border_padding.to_physical(self.style.writing_mode); - Rect::new(Point2D::new(stacking_relative_border_box.origin.x + border_padding.left, - stacking_relative_border_box.origin.y + border_padding.top), - Size2D::new(stacking_relative_border_box.size.width - border_padding.horizontal(), - stacking_relative_border_box.size.height - border_padding.vertical())) + Rect::new( + Point2D::new( + stacking_relative_border_box.origin.x + border_padding.left, + stacking_relative_border_box.origin.y + border_padding.top, + ), + Size2D::new( + stacking_relative_border_box.size.width - border_padding.horizontal(), + stacking_relative_border_box.size.height - border_padding.vertical(), + ), + ) } /// Returns true if this fragment may establish a reference frame. pub fn can_establish_reference_frame(&self) -> bool { - !self.style().get_box().transform.0.is_empty() || - self.style().get_box().perspective != Perspective::None + !self.style().get_box().transform.0.is_empty() || + self.style().get_box().perspective != Perspective::None } /// Returns true if this fragment has a filter, transform, or perspective property set. pub fn has_filter_transform_or_perspective(&self) -> bool { - !self.style().get_box().transform.0.is_empty() || - !self.style().get_effects().filter.0.is_empty() || - self.style().get_box().perspective != Perspective::None + !self.style().get_box().transform.0.is_empty() || + !self.style().get_effects().filter.0.is_empty() || + self.style().get_box().perspective != Perspective::None } /// Returns true if this fragment establishes a new stacking context and false otherwise. @@ -2503,15 +2630,15 @@ impl Fragment { SpecificFragmentInfo::TruncatedFragment(_) | SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::UnscannedText(_) => return false, - _ => {} + _ => {}, } if self.style().get_effects().opacity != 1.0 { - return true + return true; } if self.style().get_effects().mix_blend_mode != MixBlendMode::Normal { - return true + return true; } if self.has_filter_transform_or_perspective() { @@ -2519,14 +2646,16 @@ impl Fragment { } if self.style().get_box().transform_style == TransformStyle::Preserve3d || - self.style().overrides_transform_style() { - return true + self.style().overrides_transform_style() + { + return true; } // Fixed position and sticky position always create stacking contexts. if self.style().get_box().position == Position::Fixed || - self.style().get_box().position == Position::Sticky { - return true + self.style().get_box().position == Position::Sticky + { + return true; } // Statically positioned fragments don't establish stacking contexts if the previous @@ -2562,11 +2691,14 @@ impl Fragment { } /// Computes the overflow rect of this fragment relative to the start of the flow. - pub fn compute_overflow(&self, - flow_size: &Size2D<Au>, - relative_containing_block_size: &LogicalSize<Au>) - -> Overflow { - let mut border_box = self.border_box.to_physical(self.style.writing_mode, *flow_size); + pub fn compute_overflow( + &self, + flow_size: &Size2D<Au>, + relative_containing_block_size: &LogicalSize<Au>, + ) -> Overflow { + let mut border_box = self + .border_box + .to_physical(self.style.writing_mode, *flow_size); // Relative position can cause us to draw outside our border box. // @@ -2579,19 +2711,23 @@ impl Fragment { // Box shadows cause us to draw outside our border box. for box_shadow in &self.style().get_effects().box_shadow.0 { - let offset = Vector2D::new(Au::from(box_shadow.base.horizontal), - Au::from(box_shadow.base.vertical)); + let offset = Vector2D::new( + Au::from(box_shadow.base.horizontal), + Au::from(box_shadow.base.vertical), + ); let inflation = Au::from(box_shadow.spread) + - Au::from(box_shadow.base.blur) * BLUR_INFLATION_FACTOR; - overflow.paint = overflow.paint.union(&border_box.translate(&offset) - .inflate(inflation, inflation)) + Au::from(box_shadow.base.blur) * BLUR_INFLATION_FACTOR; + overflow.paint = overflow + .paint + .union(&border_box.translate(&offset).inflate(inflation, inflation)) } // Outlines cause us to draw outside our border box. let outline_width = Au::from(self.style.get_outline().outline_width); if outline_width != Au(0) { - overflow.paint = overflow.paint.union(&border_box.inflate(outline_width, - outline_width)) + overflow.paint = overflow + .paint + .union(&border_box.inflate(outline_width, outline_width)) } // Include the overflow of the block flow, if any. @@ -2599,11 +2735,11 @@ impl Fragment { SpecificFragmentInfo::InlineBlock(ref info) => { let block_flow = info.flow_ref.as_block(); overflow.union(&block_flow.base().overflow); - } + }, SpecificFragmentInfo::InlineAbsolute(ref info) => { let block_flow = info.flow_ref.as_block(); overflow.union(&block_flow.base().overflow); - } + }, _ => (), } @@ -2617,72 +2753,79 @@ impl Fragment { SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { let text = t.text_info.as_ref().unwrap(); text.requires_line_break_afterward_if_wrapping_on_newlines() - } + }, SpecificFragmentInfo::ScannedText(ref text) => { text.requires_line_break_afterward_if_wrapping_on_newlines() - } + }, _ => false, } } pub fn strip_leading_whitespace_if_necessary(&mut self) -> WhitespaceStrippingResult { if self.white_space().preserve_spaces() { - return WhitespaceStrippingResult::RetainFragment + return WhitespaceStrippingResult::RetainFragment; } return match self.specific { SpecificFragmentInfo::TruncatedFragment(ref mut t) if t.text_info.is_some() => { let scanned_text_fragment_info = t.text_info.as_mut().unwrap(); scanned_text(scanned_text_fragment_info, &mut self.border_box) - } + }, SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => { scanned_text(scanned_text_fragment_info, &mut self.border_box) - } + }, SpecificFragmentInfo::UnscannedText(ref mut unscanned_text_fragment_info) => { let mut new_text_string = String::new(); let mut modified = false; for (i, character) in unscanned_text_fragment_info.text.char_indices() { if gfx::text::util::is_bidi_control(character) { new_text_string.push(character); - continue + continue; } if char_is_whitespace(character) { modified = true; - continue + continue; } // Finished processing leading control chars and whitespace. if modified { new_text_string.push_str(&unscanned_text_fragment_info.text[i..]); } - break + break; } if modified { unscanned_text_fragment_info.text = new_text_string.into_boxed_str(); } WhitespaceStrippingResult::from_unscanned_text_fragment_info( - &unscanned_text_fragment_info) - } + &unscanned_text_fragment_info, + ) + }, _ => WhitespaceStrippingResult::RetainFragment, }; - fn scanned_text(scanned_text_fragment_info: &mut ScannedTextFragmentInfo, - border_box: &mut LogicalRect<Au>) - -> WhitespaceStrippingResult { - let leading_whitespace_byte_count = scanned_text_fragment_info.text() + fn scanned_text( + scanned_text_fragment_info: &mut ScannedTextFragmentInfo, + border_box: &mut LogicalRect<Au>, + ) -> WhitespaceStrippingResult { + let leading_whitespace_byte_count = scanned_text_fragment_info + .text() .find(|c| !char_is_whitespace(c)) .unwrap_or(scanned_text_fragment_info.text().len()); let whitespace_len = ByteIndex(leading_whitespace_byte_count as isize); - let whitespace_range = Range::new(scanned_text_fragment_info.range.begin(), - whitespace_len); - let text_bounds = - scanned_text_fragment_info.run.metrics_for_range(&whitespace_range).bounding_box; + let whitespace_range = + Range::new(scanned_text_fragment_info.range.begin(), whitespace_len); + let text_bounds = scanned_text_fragment_info + .run + .metrics_for_range(&whitespace_range) + .bounding_box; border_box.size.inline = border_box.size.inline - text_bounds.size.width; scanned_text_fragment_info.content_size.inline = scanned_text_fragment_info.content_size.inline - text_bounds.size.width; - scanned_text_fragment_info.range.adjust_by(whitespace_len, -whitespace_len); + scanned_text_fragment_info + .range + .adjust_by(whitespace_len, -whitespace_len); WhitespaceStrippingResult::RetainFragment } @@ -2691,31 +2834,31 @@ impl Fragment { /// Returns true if the entire fragment was stripped. pub fn strip_trailing_whitespace_if_necessary(&mut self) -> WhitespaceStrippingResult { if self.white_space().preserve_spaces() { - return WhitespaceStrippingResult::RetainFragment + return WhitespaceStrippingResult::RetainFragment; } return match self.specific { SpecificFragmentInfo::TruncatedFragment(ref mut t) if t.text_info.is_some() => { let scanned_text_fragment_info = t.text_info.as_mut().unwrap(); scanned_text(scanned_text_fragment_info, &mut self.border_box) - } + }, SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => { scanned_text(scanned_text_fragment_info, &mut self.border_box) - } + }, SpecificFragmentInfo::UnscannedText(ref mut unscanned_text_fragment_info) => { let mut trailing_bidi_control_characters_to_retain = Vec::new(); let (mut modified, mut last_character_index) = (true, 0); for (i, character) in unscanned_text_fragment_info.text.char_indices().rev() { if gfx::text::util::is_bidi_control(character) { trailing_bidi_control_characters_to_retain.push(character); - continue + continue; } if char_is_whitespace(character) { modified = true; - continue + continue; } last_character_index = i + character.len_utf8(); - break + break; } if modified { let mut text = unscanned_text_fragment_info.text.to_string(); @@ -2727,34 +2870,37 @@ impl Fragment { } WhitespaceStrippingResult::from_unscanned_text_fragment_info( - &unscanned_text_fragment_info) - } + &unscanned_text_fragment_info, + ) + }, _ => WhitespaceStrippingResult::RetainFragment, }; - fn scanned_text(scanned_text_fragment_info: &mut ScannedTextFragmentInfo, - border_box: &mut LogicalRect<Au>) - -> WhitespaceStrippingResult { - let mut trailing_whitespace_start_byte = 0; - for (i, c) in scanned_text_fragment_info.text().char_indices().rev() { - if !char_is_whitespace(c) { - trailing_whitespace_start_byte = i + c.len_utf8(); - break; - } + fn scanned_text( + scanned_text_fragment_info: &mut ScannedTextFragmentInfo, + border_box: &mut LogicalRect<Au>, + ) -> WhitespaceStrippingResult { + let mut trailing_whitespace_start_byte = 0; + for (i, c) in scanned_text_fragment_info.text().char_indices().rev() { + if !char_is_whitespace(c) { + trailing_whitespace_start_byte = i + c.len_utf8(); + break; } - let whitespace_start = ByteIndex(trailing_whitespace_start_byte as isize); - let whitespace_len = scanned_text_fragment_info.range.length() - whitespace_start; - let mut whitespace_range = Range::new(whitespace_start, whitespace_len); - whitespace_range.shift_by(scanned_text_fragment_info.range.begin()); + } + let whitespace_start = ByteIndex(trailing_whitespace_start_byte as isize); + let whitespace_len = scanned_text_fragment_info.range.length() - whitespace_start; + let mut whitespace_range = Range::new(whitespace_start, whitespace_len); + whitespace_range.shift_by(scanned_text_fragment_info.range.begin()); - let text_bounds = scanned_text_fragment_info.run - .metrics_for_range(&whitespace_range) - .bounding_box; - border_box.size.inline -= text_bounds.size.width; - scanned_text_fragment_info.content_size.inline -= text_bounds.size.width; + let text_bounds = scanned_text_fragment_info + .run + .metrics_for_range(&whitespace_range) + .bounding_box; + border_box.size.inline -= text_bounds.size.width; + scanned_text_fragment_info.content_size.inline -= text_bounds.size.width; - scanned_text_fragment_info.range.extend_by(-whitespace_len); - WhitespaceStrippingResult::RetainFragment + scanned_text_fragment_info.range.extend_by(-whitespace_len); + WhitespaceStrippingResult::RetainFragment } } @@ -2771,12 +2917,12 @@ impl Fragment { /// non-`static` `position`. pub fn is_positioned(&self) -> bool { if self.style.get_box().position != Position::Static { - return true + return true; } if let Some(ref inline_context) = self.inline_context { for node in inline_context.nodes.iter() { if node.style.get_box().position != Position::Static { - return true + return true; } } } @@ -2798,21 +2944,29 @@ impl Fragment { 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 (inline_context_node_from_this_fragment, - inline_context_node_from_next_fragment) - in inline_context_of_this_fragment.nodes.iter_mut().rev() - .zip(inline_context_of_next_fragment.nodes.iter().rev()) + for ( + inline_context_node_from_this_fragment, + inline_context_node_from_next_fragment, + ) in inline_context_of_this_fragment + .nodes + .iter_mut() + .rev() + .zip(inline_context_of_next_fragment.nodes.iter().rev()) { - if !inline_context_node_from_next_fragment.flags.contains( - InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) { - continue + if !inline_context_node_from_next_fragment + .flags + .contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) + { + continue; } if inline_context_node_from_next_fragment.address != - inline_context_node_from_this_fragment.address { - continue + inline_context_node_from_this_fragment.address + { + continue; } - inline_context_node_from_this_fragment.flags.insert( - InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); + inline_context_node_from_this_fragment + .flags + .insert(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); } } } @@ -2821,21 +2975,29 @@ impl Fragment { pub fn meld_with_prev_inline_fragment(&mut self, prev_fragment: &Fragment) { if let Some(ref mut inline_context_of_this_fragment) = self.inline_context { if let Some(ref inline_context_of_prev_fragment) = prev_fragment.inline_context { - for (inline_context_node_from_prev_fragment, - inline_context_node_from_this_fragment) - in inline_context_of_prev_fragment.nodes.iter().rev().zip( - inline_context_of_this_fragment.nodes.iter_mut().rev()) + for ( + inline_context_node_from_prev_fragment, + inline_context_node_from_this_fragment, + ) in inline_context_of_prev_fragment + .nodes + .iter() + .rev() + .zip(inline_context_of_this_fragment.nodes.iter_mut().rev()) { - if !inline_context_node_from_prev_fragment.flags.contains( - InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) { - continue + if !inline_context_node_from_prev_fragment + .flags + .contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT) + { + continue; } if inline_context_node_from_prev_fragment.address != - inline_context_node_from_this_fragment.address { - continue + inline_context_node_from_this_fragment.address + { + continue; } - inline_context_node_from_this_fragment.flags.insert( - InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT); + inline_context_node_from_this_fragment + .flags + .insert(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT); } } } @@ -2846,13 +3008,13 @@ impl Fragment { pub fn is_vertically_aligned_to_top_or_bottom(&self) -> bool { match self.style.get_box().vertical_align { VerticalAlign::Top | VerticalAlign::Bottom => return true, - _ => {} + _ => {}, } if let Some(ref inline_context) = self.inline_context { for node in &inline_context.nodes { match node.style.get_box().vertical_align { VerticalAlign::Top | VerticalAlign::Bottom => return true, - _ => {} + _ => {}, } } } @@ -2879,69 +3041,87 @@ impl Fragment { SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::TruncatedFragment(_) | SpecificFragmentInfo::Svg(_) | - SpecificFragmentInfo::UnscannedText(_) => true + SpecificFragmentInfo::UnscannedText(_) => true, } } /// Returns the 4D matrix representing this fragment's transform. - pub fn transform_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<LayoutTransform> { + pub fn transform_matrix( + &self, + stacking_relative_border_box: &Rect<Au>, + ) -> Option<LayoutTransform> { let list = &self.style.get_box().transform; let transform = LayoutTransform::from_untyped( - &list.to_transform_3d_matrix(Some(stacking_relative_border_box)).ok()?.0); + &list + .to_transform_3d_matrix(Some(stacking_relative_border_box)) + .ok()? + .0, + ); let transform_origin = &self.style.get_box().transform_origin; - let transform_origin_x = - transform_origin.horizontal - .to_used_value(stacking_relative_border_box.size.width) - .to_f32_px(); - let transform_origin_y = - transform_origin.vertical - .to_used_value(stacking_relative_border_box.size.height) - .to_f32_px(); + let transform_origin_x = transform_origin + .horizontal + .to_used_value(stacking_relative_border_box.size.width) + .to_f32_px(); + let transform_origin_y = transform_origin + .vertical + .to_used_value(stacking_relative_border_box.size.height) + .to_f32_px(); let transform_origin_z = transform_origin.depth.px(); let pre_transform = LayoutTransform::create_translation( transform_origin_x, transform_origin_y, - transform_origin_z); + transform_origin_z, + ); let post_transform = LayoutTransform::create_translation( -transform_origin_x, -transform_origin_y, - -transform_origin_z); + -transform_origin_z, + ); Some(pre_transform.pre_mul(&transform).pre_mul(&post_transform)) } /// Returns the 4D matrix representing this fragment's perspective. - pub fn perspective_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<LayoutTransform> { + pub fn perspective_matrix( + &self, + stacking_relative_border_box: &Rect<Au>, + ) -> Option<LayoutTransform> { match self.style().get_box().perspective { Perspective::Length(length) => { let perspective_origin = self.style().get_box().perspective_origin; - let perspective_origin = - Point2D::new( - perspective_origin.horizontal - .to_used_value(stacking_relative_border_box.size.width), - perspective_origin.vertical - .to_used_value(stacking_relative_border_box.size.height) - ).to_layout(); + let perspective_origin = Point2D::new( + perspective_origin + .horizontal + .to_used_value(stacking_relative_border_box.size.width), + perspective_origin + .vertical + .to_used_value(stacking_relative_border_box.size.height), + ).to_layout(); let pre_transform = LayoutTransform::create_translation( perspective_origin.x, perspective_origin.y, - 0.0); + 0.0, + ); let post_transform = LayoutTransform::create_translation( -perspective_origin.x, -perspective_origin.y, - 0.0); + 0.0, + ); let perspective_matrix = LayoutTransform::from_untyped( - &transform::create_perspective_matrix(length.px())); - - Some(pre_transform.pre_mul(&perspective_matrix).pre_mul(&post_transform)) - } - Perspective::None => { - None - } + &transform::create_perspective_matrix(length.px()), + ); + + Some( + pre_transform + .pre_mul(&perspective_matrix) + .pre_mul(&post_transform), + ) + }, + Perspective::None => None, } } } @@ -2966,14 +3146,17 @@ impl fmt::Debug for Fragment { "".to_owned() }; - write!(f, "\n{}({}) [{:?}]\nborder_box={:?}{}{}{}", + write!( + f, + "\n{}({}) [{:?}]\nborder_box={:?}{}{}{}", self.specific.get_type(), self.debug_id, self.specific, self.border_box, border_padding_string, margin_string, - damage_string) + damage_string + ) } } @@ -3030,12 +3213,12 @@ impl<'a> Iterator for InlineStyleIterator<'a> { fn next(&mut self) -> Option<&'a ComputedValues> { if !self.primary_style_yielded { self.primary_style_yielded = true; - return Some(&*self.fragment.style) + return Some(&*self.fragment.style); } let inline_context = self.fragment.inline_context.as_ref()?; let inline_style_index = self.inline_style_index; if inline_style_index == inline_context.nodes.len() { - return None + return None; } self.inline_style_index += 1; Some(&*inline_context.nodes[inline_style_index].style) @@ -3060,8 +3243,9 @@ pub enum WhitespaceStrippingResult { } impl WhitespaceStrippingResult { - fn from_unscanned_text_fragment_info(info: &UnscannedTextFragmentInfo) - -> WhitespaceStrippingResult { + fn from_unscanned_text_fragment_info( + info: &UnscannedTextFragmentInfo, + ) -> WhitespaceStrippingResult { if info.text.is_empty() { WhitespaceStrippingResult::FragmentContainedOnlyWhitespace } else if info.text.chars().all(gfx::text::util::is_bidi_control) { diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs index a006fdfa4b4..90341abe3d9 100644 --- a/components/layout/generated_content.rs +++ b/components/layout/generated_content.rs @@ -25,73 +25,103 @@ use text::TextRunScanner; use traversal::InorderFlowTraversal; // Decimal styles per CSS-COUNTER-STYLES § 6.1: -static DECIMAL: [char; 10] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]; +static DECIMAL: [char; 10] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; // TODO(pcwalton): `decimal-leading-zero` -static ARABIC_INDIC: [char; 10] = [ '٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩' ]; +static ARABIC_INDIC: [char; 10] = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩']; // TODO(pcwalton): `armenian`, `upper-armenian`, `lower-armenian` -static BENGALI: [char; 10] = [ '০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯' ]; -static CAMBODIAN: [char; 10] = [ '០', '១', '២', '៣', '៤', '៥', '៦', '៧', '៨', '៩' ]; +static BENGALI: [char; 10] = [ + '০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯', +]; +static CAMBODIAN: [char; 10] = [ + '០', '១', '២', '៣', '៤', '៥', '៦', '៧', '៨', '៩', +]; // TODO(pcwalton): Suffix for CJK decimal. -static CJK_DECIMAL: [char; 10] = [ '〇', '一', '二', '三', '四', '五', '六', '七', '八', '九' ]; -static DEVANAGARI: [char; 10] = [ '०', '१', '२', '३', '४', '५', '६', '७', '८', '९' ]; +static CJK_DECIMAL: [char; 10] = [ + '〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', +]; +static DEVANAGARI: [char; 10] = [ + '०', '१', '२', '३', '४', '५', '६', '७', '८', '९', +]; // TODO(pcwalton): `georgian` -static GUJARATI: [char; 10] = ['૦', '૧', '૨', '૩', '૪', '૫', '૬', '૭', '૮', '૯']; -static GURMUKHI: [char; 10] = ['੦', '੧', '੨', '੩', '੪', '੫', '੬', '੭', '੮', '੯']; +static GUJARATI: [char; 10] = [ + '૦', '૧', '૨', '૩', '૪', '૫', '૬', '૭', '૮', '૯', +]; +static GURMUKHI: [char; 10] = [ + '੦', '੧', '੨', '੩', '੪', '੫', '੬', '੭', '੮', '੯', +]; // TODO(pcwalton): `hebrew` -static KANNADA: [char; 10] = ['೦', '೧', '೨', '೩', '೪', '೫', '೬', '೭', '೮', '೯']; -static LAO: [char; 10] = ['໐', '໑', '໒', '໓', '໔', '໕', '໖', '໗', '໘', '໙']; -static MALAYALAM: [char; 10] = ['൦', '൧', '൨', '൩', '൪', '൫', '൬', '൭', '൮', '൯']; -static MONGOLIAN: [char; 10] = ['᠐', '᠑', '᠒', '᠓', '᠔', '᠕', '᠖', '᠗', '᠘', '᠙']; -static MYANMAR: [char; 10] = ['၀', '၁', '၂', '၃', '၄', '၅', '၆', '၇', '၈', '၉']; -static ORIYA: [char; 10] = ['୦', '୧', '୨', '୩', '୪', '୫', '୬', '୭', '୮', '୯']; +static KANNADA: [char; 10] = [ + '೦', '೧', '೨', '೩', '೪', '೫', '೬', '೭', '೮', '೯', +]; +static LAO: [char; 10] = [ + '໐', '໑', '໒', '໓', '໔', '໕', '໖', '໗', '໘', '໙', +]; +static MALAYALAM: [char; 10] = [ + '൦', '൧', '൨', '൩', '൪', '൫', '൬', '൭', '൮', '൯', +]; +static MONGOLIAN: [char; 10] = [ + '᠐', '᠑', '᠒', '᠓', '᠔', '᠕', '᠖', '᠗', '᠘', '᠙', +]; +static MYANMAR: [char; 10] = [ + '၀', '၁', '၂', '၃', '၄', '၅', '၆', '၇', '၈', '၉', +]; +static ORIYA: [char; 10] = [ + '୦', '୧', '୨', '୩', '୪', '୫', '୬', '୭', '୮', '୯', +]; static PERSIAN: [char; 10] = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']; // TODO(pcwalton): `lower-roman`, `upper-roman` -static TELUGU: [char; 10] = ['౦', '౧', '౨', '౩', '౪', '౫', '౬', '౭', '౮', '౯']; -static THAI: [char; 10] = ['๐', '๑', '๒', '๓', '๔', '๕', '๖', '๗', '๘', '๙']; -static TIBETAN: [char; 10] = ['༠', '༡', '༢', '༣', '༤', '༥', '༦', '༧', '༨', '༩']; +static TELUGU: [char; 10] = [ + '౦', '౧', '౨', '౩', '౪', '౫', '౬', '౭', '౮', '౯', +]; +static THAI: [char; 10] = [ + '๐', '๑', '๒', '๓', '๔', '๕', '๖', '๗', '๘', '๙', +]; +static TIBETAN: [char; 10] = [ + '༠', '༡', '༢', '༣', '༤', '༥', '༦', '༧', '༨', '༩', +]; // Alphabetic styles per CSS-COUNTER-STYLES § 6.2: static LOWER_ALPHA: [char; 26] = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', - 't', 'u', 'v', 'w', 'x', 'y', 'z' + 't', 'u', 'v', 'w', 'x', 'y', 'z', ]; static UPPER_ALPHA: [char; 26] = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', - 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ]; static CJK_EARTHLY_BRANCH: [char; 12] = [ - '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥' + '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥', ]; static CJK_HEAVENLY_STEM: [char; 10] = [ - '甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸' + '甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸', ]; static LOWER_GREEK: [char; 24] = [ - 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', 'ρ', 'σ', 'τ', - 'υ', 'φ', 'χ', 'ψ', 'ω' + 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', + 'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω', ]; static HIRAGANA: [char; 48] = [ - 'あ', 'い', 'う', 'え', 'お', 'か', 'き', 'く', 'け', 'こ', 'さ', 'し', 'す', 'せ', 'そ', - 'た', 'ち', 'つ', 'て', 'と', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ひ', 'ふ', 'へ', 'ほ', - 'ま', 'み', 'む', 'め', 'も', 'や', 'ゆ', 'よ', 'ら', 'り', 'る', 'れ', 'ろ', - 'わ', 'ゐ', 'ゑ', 'を', 'ん' + 'あ', 'い', 'う', 'え', 'お', 'か', 'き', 'く', 'け', 'こ', 'さ', 'し', 'す', + 'せ', 'そ', 'た', 'ち', 'つ', 'て', 'と', 'な', 'に', 'ぬ', 'ね', 'の', 'は', + 'ひ', 'ふ', 'へ', 'ほ', 'ま', 'み', 'む', 'め', 'も', 'や', 'ゆ', 'よ', 'ら', + 'り', 'る', 'れ', 'ろ', 'わ', 'ゐ', 'ゑ', 'を', 'ん', ]; static HIRAGANA_IROHA: [char; 47] = [ - 'い', 'ろ', 'は', 'に', 'ほ', 'へ', 'と', 'ち', 'り', 'ぬ', 'る', 'を', 'わ', 'か', 'よ', - 'た', 'れ', 'そ', 'つ', 'ね', 'な', 'ら', 'む', 'う', 'ゐ', 'の', 'お', 'く', 'や', 'ま', - 'け', 'ふ', 'こ', 'え', 'て', 'あ', 'さ', 'き', 'ゆ', 'め', 'み', 'し', 'ゑ', - 'ひ', 'も', 'せ', 'す' + 'い', 'ろ', 'は', 'に', 'ほ', 'へ', 'と', 'ち', 'り', 'ぬ', 'る', 'を', 'わ', + 'か', 'よ', 'た', 'れ', 'そ', 'つ', 'ね', 'な', 'ら', 'む', 'う', 'ゐ', 'の', + 'お', 'く', 'や', 'ま', 'け', 'ふ', 'こ', 'え', 'て', 'あ', 'さ', 'き', 'ゆ', + 'め', 'み', 'し', 'ゑ', 'ひ', 'も', 'せ', 'す', ]; static KATAKANA: [char; 48] = [ - 'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', 'セ', 'ソ', - 'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', - 'マ', 'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', - 'ワ', 'ヰ', 'ヱ', 'ヲ', 'ン' + 'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', + 'セ', 'ソ', 'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', + 'ヒ', 'フ', 'ヘ', 'ホ', 'マ', 'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', + 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ヰ', 'ヱ', 'ヲ', 'ン', ]; static KATAKANA_IROHA: [char; 47] = [ - 'イ', 'ロ', 'ハ', 'ニ', 'ホ', 'ヘ', 'ト', 'チ', 'リ', 'ヌ', 'ル', 'ヲ', 'ワ', 'カ', 'ヨ', - 'タ', 'レ', 'ソ', 'ツ', 'ネ', 'ナ', 'ラ', 'ム', 'ウ', 'ヰ', 'ノ', 'オ', 'ク', 'ヤ', 'マ', - 'ケ', 'フ', 'コ', 'エ', 'テ', 'ア', 'サ', 'キ', 'ユ', 'メ', 'ミ', 'シ', 'ヱ', - 'ヒ', 'モ', 'セ', 'ス' + 'イ', 'ロ', 'ハ', 'ニ', 'ホ', 'ヘ', 'ト', 'チ', 'リ', 'ヌ', 'ル', 'ヲ', 'ワ', + 'カ', 'ヨ', 'タ', 'レ', 'ソ', 'ツ', 'ネ', 'ナ', 'ラ', 'ム', 'ウ', 'ヰ', 'ノ', + 'オ', 'ク', 'ヤ', 'マ', 'ケ', 'フ', 'コ', 'エ', 'テ', 'ア', 'サ', 'キ', 'ユ', + 'メ', 'ミ', 'シ', 'ヱ', 'ヒ', 'モ', 'セ', 'ス', ]; /// The generated content resolution traversal. @@ -132,8 +162,12 @@ impl<'a> InorderFlowTraversal for ResolveGeneratedContent<'a> { #[inline] fn should_process_subtree(&mut self, flow: &mut Flow) -> bool { - flow.base().restyle_damage.intersects(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT) || - flow.base().flags.intersects(FlowFlags::AFFECTS_COUNTERS | FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN) + flow.base() + .restyle_damage + .intersects(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT) || + flow.base().flags.intersects( + FlowFlags::AFFECTS_COUNTERS | FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN, + ) } } @@ -168,81 +202,97 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { if let SpecificFragmentInfo::GeneratedContent(ref mut info) = fragment.specific { info } else { - return + return; }; match **info { GeneratedContentInfo::ListItem => { - new_info = self.traversal.list_item.render(self.traversal.layout_context, - fragment.node, - fragment.pseudo.clone(), - fragment.style.clone(), - list_style_type, - RenderingMode::Suffix(".\u{00a0}")) - } + new_info = self.traversal.list_item.render( + self.traversal.layout_context, + fragment.node, + fragment.pseudo.clone(), + fragment.style.clone(), + list_style_type, + RenderingMode::Suffix(".\u{00a0}"), + ) + }, GeneratedContentInfo::Empty | GeneratedContentInfo::ContentItem(ContentItem::String(_)) => { // Nothing to do here. - } - GeneratedContentInfo::ContentItem(ContentItem::Counter(ref counter_name, - counter_style)) => { + }, + GeneratedContentInfo::ContentItem(ContentItem::Counter( + ref counter_name, + counter_style, + )) => { let temporary_counter = Counter::new(); - let counter = self.traversal + let counter = self + .traversal .counters .get(&*counter_name.0) .unwrap_or(&temporary_counter); - new_info = counter.render(self.traversal.layout_context, - fragment.node, - fragment.pseudo.clone(), - fragment.style.clone(), - counter_style, - RenderingMode::Plain) - } - GeneratedContentInfo::ContentItem(ContentItem::Counters(ref counter_name, - ref separator, - counter_style)) => { + new_info = counter.render( + self.traversal.layout_context, + fragment.node, + fragment.pseudo.clone(), + fragment.style.clone(), + counter_style, + RenderingMode::Plain, + ) + }, + GeneratedContentInfo::ContentItem(ContentItem::Counters( + ref counter_name, + ref separator, + counter_style, + )) => { let temporary_counter = Counter::new(); - let counter = self.traversal + let counter = self + .traversal .counters .get(&*counter_name.0) .unwrap_or(&temporary_counter); - new_info = counter.render(self.traversal.layout_context, - fragment.node, - fragment.pseudo, - fragment.style.clone(), - counter_style, - RenderingMode::All(&separator)); - } + new_info = counter.render( + self.traversal.layout_context, + fragment.node, + fragment.pseudo, + fragment.style.clone(), + counter_style, + RenderingMode::All(&separator), + ); + }, GeneratedContentInfo::ContentItem(ContentItem::OpenQuote) => { - new_info = render_text(self.traversal.layout_context, - fragment.node, - fragment.pseudo, - fragment.style.clone(), - self.quote(&*fragment.style, false)); + new_info = render_text( + self.traversal.layout_context, + fragment.node, + fragment.pseudo, + fragment.style.clone(), + self.quote(&*fragment.style, false), + ); self.traversal.quote += 1 - } + }, GeneratedContentInfo::ContentItem(ContentItem::CloseQuote) => { if self.traversal.quote >= 1 { self.traversal.quote -= 1 } - new_info = render_text(self.traversal.layout_context, - fragment.node, - fragment.pseudo, - fragment.style.clone(), - self.quote(&*fragment.style, true)); - } + new_info = render_text( + self.traversal.layout_context, + fragment.node, + fragment.pseudo, + fragment.style.clone(), + self.quote(&*fragment.style, true), + ); + }, GeneratedContentInfo::ContentItem(ContentItem::NoOpenQuote) => { self.traversal.quote += 1 - } + }, GeneratedContentInfo::ContentItem(ContentItem::NoCloseQuote) => { if self.traversal.quote >= 1 { self.traversal.quote -= 1 } - } + }, GeneratedContentInfo::ContentItem(ContentItem::Url(..)) => { unreachable!("Servo doesn't parse content: url(..) yet") - } + }, } }; @@ -252,7 +302,7 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { // so that it isn't processed again on the next layout. FIXME (mbrubeck): When // processing an inline flow, this traversal should be allowed to insert or remove // fragments. Then we can just remove these fragments rather than adding placeholders. - None => SpecificFragmentInfo::GeneratedContent(Box::new(GeneratedContentInfo::Empty)) + None => SpecificFragmentInfo::GeneratedContent(Box::new(GeneratedContentInfo::Empty)), }; } @@ -263,9 +313,12 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { } match list_style_type { - ListStyleType::Disc | ListStyleType::None | ListStyleType::Circle | - ListStyleType::Square | ListStyleType::DisclosureOpen | - ListStyleType::DisclosureClosed => {} + ListStyleType::Disc | + ListStyleType::None | + ListStyleType::Circle | + ListStyleType::Square | + ListStyleType::DisclosureOpen | + ListStyleType::DisclosureClosed => {}, _ => self.traversal.list_item.increment(self.level, 1), } @@ -278,25 +331,29 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { for pair in &*fragment.style().get_counters().counter_reset { let counter_name = &*pair.name.0; if let Some(ref mut counter) = self.traversal.counters.get_mut(counter_name) { - counter.reset(self.level, pair.value); - continue + counter.reset(self.level, pair.value); + continue; } let mut counter = Counter::new(); counter.reset(self.level, pair.value); - self.traversal.counters.insert(counter_name.to_owned(), counter); + self.traversal + .counters + .insert(counter_name.to_owned(), counter); } for pair in &*fragment.style().get_counters().counter_increment { let counter_name = &*pair.name.0; if let Some(ref mut counter) = self.traversal.counters.get_mut(counter_name) { counter.increment(self.level, pair.value); - continue + continue; } let mut counter = Counter::new(); counter.increment(self.level, pair.value); - self.traversal.counters.insert(counter_name.to_owned(), counter); + self.traversal + .counters + .insert(counter_name.to_owned(), counter); } self.incremented = true @@ -305,14 +362,14 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { fn quote(&self, style: &ComputedValues, close: bool) -> String { let quotes = &style.get_list().quotes; if quotes.0.is_empty() { - return String::new() + return String::new(); } - let &(ref open_quote, ref close_quote) = - if self.traversal.quote as usize >= quotes.0.len() { - quotes.0.last().unwrap() - } else { - "es.0[self.traversal.quote as usize] - }; + let &(ref open_quote, ref close_quote) = if self.traversal.quote as usize >= quotes.0.len() + { + quotes.0.last().unwrap() + } else { + "es.0[self.traversal.quote as usize] + }; if close { close_quote.to_string() } else { @@ -329,9 +386,7 @@ struct Counter { impl Counter { fn new() -> Counter { - Counter { - values: Vec::new(), - } + Counter { values: Vec::new() } } fn reset(&mut self, level: u32, value: i32) { @@ -339,7 +394,7 @@ impl Counter { if let Some(ref mut existing_value) = self.values.last_mut() { if level == existing_value.level { existing_value.value = value; - return + return; } } @@ -359,7 +414,7 @@ impl Counter { fn increment(&mut self, level: u32, amount: i32) { if let Some(ref mut value) = self.values.last_mut() { value.value += amount; - return + return; } self.values.push(CounterValue { @@ -368,14 +423,15 @@ impl Counter { }) } - fn render(&self, - layout_context: &LayoutContext, - node: OpaqueNode, - pseudo: PseudoElementType, - style: ::ServoArc<ComputedValues>, - list_style_type: ListStyleType, - mode: RenderingMode) - -> Option<SpecificFragmentInfo> { + fn render( + &self, + layout_context: &LayoutContext, + node: OpaqueNode, + pseudo: PseudoElementType, + style: ::ServoArc<ComputedValues>, + list_style_type: ListStyleType, + mode: RenderingMode, + ) -> Option<SpecificFragmentInfo> { let mut string = String::new(); match mode { RenderingMode::Plain => { @@ -384,7 +440,7 @@ impl Counter { None => 0, }; push_representation(value, list_style_type, &mut string) - } + }, RenderingMode::Suffix(suffix) => { let value = match self.values.last() { Some(ref value) => value.value, @@ -392,7 +448,7 @@ impl Counter { }; push_representation(value, list_style_type, &mut string); string.push_str(suffix) - } + }, RenderingMode::All(separator) => { let mut first = true; for value in &self.values { @@ -402,7 +458,7 @@ impl Counter { first = false; push_representation(value.value, list_style_type, &mut string) } - } + }, } if string.is_empty() { @@ -432,22 +488,26 @@ struct CounterValue { } /// Creates fragment info for a literal string. -fn render_text(layout_context: &LayoutContext, - node: OpaqueNode, - pseudo: PseudoElementType, - style: ::ServoArc<ComputedValues>, - string: String) - -> Option<SpecificFragmentInfo> { +fn render_text( + layout_context: &LayoutContext, + node: OpaqueNode, + pseudo: PseudoElementType, + style: ::ServoArc<ComputedValues>, + string: String, +) -> Option<SpecificFragmentInfo> { let mut fragments = LinkedList::new(); - let info = SpecificFragmentInfo::UnscannedText( - Box::new(UnscannedTextFragmentInfo::new(string.into_boxed_str(), None)) - ); - fragments.push_back(Fragment::from_opaque_node_and_style(node, - pseudo, - style.clone(), - style, - RestyleDamage::rebuild_and_reflow(), - info)); + let info = SpecificFragmentInfo::UnscannedText(Box::new(UnscannedTextFragmentInfo::new( + string.into_boxed_str(), + None, + ))); + fragments.push_back(Fragment::from_opaque_node_and_style( + node, + pseudo, + style.clone(), + style, + RestyleDamage::rebuild_and_reflow(), + info, + )); // FIXME(pcwalton): This should properly handle multiple marker fragments. This could happen // due to text run splitting. let fragments = with_thread_local_font_context(layout_context, |font_context| { @@ -464,39 +524,28 @@ fn render_text(layout_context: &LayoutContext, /// `list-style-type` onto the given string. fn push_representation(value: i32, list_style_type: ListStyleType, accumulator: &mut String) { match list_style_type { - ListStyleType::None => {} + ListStyleType::None => {}, ListStyleType::Disc | ListStyleType::Circle | ListStyleType::Square | ListStyleType::DisclosureOpen | - ListStyleType::DisclosureClosed => { - accumulator.push(static_representation(list_style_type)) - } + ListStyleType::DisclosureClosed => accumulator.push(static_representation(list_style_type)), ListStyleType::Decimal => push_numeric_representation(value, &DECIMAL, accumulator), ListStyleType::ArabicIndic => { push_numeric_representation(value, &ARABIC_INDIC, accumulator) - } + }, ListStyleType::Bengali => push_numeric_representation(value, &BENGALI, accumulator), - ListStyleType::Cambodian | - ListStyleType::Khmer => { + ListStyleType::Cambodian | ListStyleType::Khmer => { push_numeric_representation(value, &CAMBODIAN, accumulator) - } - ListStyleType::CjkDecimal => { - push_numeric_representation(value, &CJK_DECIMAL, accumulator) - } - ListStyleType::Devanagari => { - push_numeric_representation(value, &DEVANAGARI, accumulator) - } + }, + ListStyleType::CjkDecimal => push_numeric_representation(value, &CJK_DECIMAL, accumulator), + ListStyleType::Devanagari => push_numeric_representation(value, &DEVANAGARI, accumulator), ListStyleType::Gujarati => push_numeric_representation(value, &GUJARATI, accumulator), ListStyleType::Gurmukhi => push_numeric_representation(value, &GURMUKHI, accumulator), ListStyleType::Kannada => push_numeric_representation(value, &KANNADA, accumulator), ListStyleType::Lao => push_numeric_representation(value, &LAO, accumulator), - ListStyleType::Malayalam => { - push_numeric_representation(value, &MALAYALAM, accumulator) - } - ListStyleType::Mongolian => { - push_numeric_representation(value, &MONGOLIAN, accumulator) - } + ListStyleType::Malayalam => push_numeric_representation(value, &MALAYALAM, accumulator), + ListStyleType::Mongolian => push_numeric_representation(value, &MONGOLIAN, accumulator), ListStyleType::Myanmar => push_numeric_representation(value, &MYANMAR, accumulator), ListStyleType::Oriya => push_numeric_representation(value, &ORIYA, accumulator), ListStyleType::Persian => push_numeric_representation(value, &PERSIAN, accumulator), @@ -505,31 +554,27 @@ fn push_representation(value: i32, list_style_type: ListStyleType, accumulator: ListStyleType::Tibetan => push_numeric_representation(value, &TIBETAN, accumulator), ListStyleType::LowerAlpha => { push_alphabetic_representation(value, &LOWER_ALPHA, accumulator) - } + }, ListStyleType::UpperAlpha => { push_alphabetic_representation(value, &UPPER_ALPHA, accumulator) - } + }, ListStyleType::CjkEarthlyBranch => { push_alphabetic_representation(value, &CJK_EARTHLY_BRANCH, accumulator) - } + }, ListStyleType::CjkHeavenlyStem => { push_alphabetic_representation(value, &CJK_HEAVENLY_STEM, accumulator) - } + }, ListStyleType::LowerGreek => { push_alphabetic_representation(value, &LOWER_GREEK, accumulator) - } - ListStyleType::Hiragana => { - push_alphabetic_representation(value, &HIRAGANA, accumulator) - } + }, + ListStyleType::Hiragana => push_alphabetic_representation(value, &HIRAGANA, accumulator), ListStyleType::HiraganaIroha => { push_alphabetic_representation(value, &HIRAGANA_IROHA, accumulator) - } - ListStyleType::Katakana => { - push_alphabetic_representation(value, &KATAKANA, accumulator) - } + }, + ListStyleType::Katakana => push_alphabetic_representation(value, &KATAKANA, accumulator), ListStyleType::KatakanaIroha => { push_alphabetic_representation(value, &KATAKANA_IROHA, accumulator) - } + }, } } @@ -572,7 +617,7 @@ fn push_numeric_representation(value: i32, system: &[char], accumulator: &mut St // Step 1. if abs_value == 0 { accumulator.push(system[0]); - return + return; } // Step 2. diff --git a/components/layout/incremental.rs b/components/layout/incremental.rs index ff1e0813ccd..f0f76453919 100644 --- a/components/layout/incremental.rs +++ b/components/layout/incremental.rs @@ -11,7 +11,7 @@ use style::servo::restyle_damage::ServoRestyleDamage; #[derive(Clone, Copy, PartialEq)] pub enum RelayoutMode { Incremental, - Force + Force, } bitflags! { @@ -30,7 +30,10 @@ pub trait LayoutDamageComputation { impl<'a> LayoutDamageComputation for &'a mut Flow { fn compute_layout_damage(self) -> SpecialRestyleDamage { let mut special_damage = SpecialRestyleDamage::empty(); - let is_absolutely_positioned = self.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); + let is_absolutely_positioned = self + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); // In addition to damage, we use this phase to compute whether nodes affect CSS counters. let mut has_counter_affecting_children = false; @@ -41,35 +44,47 @@ impl<'a> LayoutDamageComputation for &'a mut Flow { let parent_damage = self_base.restyle_damage; for kid in self_base.children.iter_mut() { - let child_is_absolutely_positioned = - kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); + let child_is_absolutely_positioned = kid + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); kid.mut_base().restyle_damage.insert( - parent_damage.damage_for_child(is_absolutely_positioned, - child_is_absolutely_positioned)); + parent_damage + .damage_for_child(is_absolutely_positioned, child_is_absolutely_positioned), + ); { let kid: &mut Flow = kid; special_damage.insert(kid.compute_layout_damage()); } - self_base.restyle_damage - .insert(kid.base().restyle_damage.damage_for_parent( - child_is_absolutely_positioned)); + self_base.restyle_damage.insert( + kid.base() + .restyle_damage + .damage_for_parent(child_is_absolutely_positioned), + ); - has_counter_affecting_children = has_counter_affecting_children || - kid.base().flags.intersects(FlowFlags::AFFECTS_COUNTERS | - FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN); + has_counter_affecting_children = + has_counter_affecting_children || kid.base().flags.intersects( + FlowFlags::AFFECTS_COUNTERS | FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN, + ); } } let self_base = self.mut_base(); - if self_base.flags.float_kind() != Float::None && - self_base.restyle_damage.intersects(ServoRestyleDamage::REFLOW) { + if self_base.flags.float_kind() != Float::None && self_base + .restyle_damage + .intersects(ServoRestyleDamage::REFLOW) + { special_damage.insert(SpecialRestyleDamage::REFLOW_ENTIRE_DOCUMENT); } if has_counter_affecting_children { - self_base.flags.insert(FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN) + self_base + .flags + .insert(FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN) } else { - self_base.flags.remove(FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN) + self_base + .flags + .remove(FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN) } special_damage @@ -77,8 +92,12 @@ impl<'a> LayoutDamageComputation for &'a mut Flow { fn reflow_entire_document(self) { let self_base = self.mut_base(); - self_base.restyle_damage.insert(RestyleDamage::rebuild_and_reflow()); - self_base.restyle_damage.remove(ServoRestyleDamage::RECONSTRUCT_FLOW); + self_base + .restyle_damage + .insert(RestyleDamage::rebuild_and_reflow()); + self_base + .restyle_damage + .remove(ServoRestyleDamage::RECONSTRUCT_FLOW); for kid in self_base.children.iter_mut() { kid.reflow_entire_document(); } diff --git a/components/layout/inline.rs b/components/layout/inline.rs index 58d6a498457..7a66ad84bac 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -181,12 +181,16 @@ impl Line { /// /// FIXME(pcwalton): this assumes that the tallest fragment in the line determines the line /// block-size. This might not be the case with some weird text fonts. - fn new_metrics_for_fragment(&self, new_fragment: &Fragment, layout_context: &LayoutContext) - -> LineMetrics { + fn new_metrics_for_fragment( + &self, + new_fragment: &Fragment, + layout_context: &LayoutContext, + ) -> LineMetrics { if !new_fragment.is_vertically_aligned_to_top_or_bottom() { let fragment_inline_metrics = new_fragment.aligned_inline_metrics(layout_context, &self.minimum_metrics, None); - self.metrics.new_metrics_for_fragment(&fragment_inline_metrics) + self.metrics + .new_metrics_for_fragment(&fragment_inline_metrics) } else { self.metrics } @@ -195,15 +199,19 @@ impl Line { /// Returns the new block size that this line would have if `new_fragment` were added to it. /// `new_inline_metrics` represents the new inline metrics that this line would have; it can /// be computed with `new_inline_metrics()`. - fn new_block_size_for_fragment(&self, - new_fragment: &Fragment, - new_line_metrics: &LineMetrics, - layout_context: &LayoutContext) - -> Au { + fn new_block_size_for_fragment( + &self, + new_fragment: &Fragment, + new_line_metrics: &LineMetrics, + layout_context: &LayoutContext, + ) -> Au { let new_block_size = if new_fragment.is_vertically_aligned_to_top_or_bottom() { - max(new_fragment.aligned_inline_metrics(layout_context, &self.minimum_metrics, None) - .space_needed(), - self.minimum_metrics.space_needed()) + max( + new_fragment + .aligned_inline_metrics(layout_context, &self.minimum_metrics, None) + .space_needed(), + self.minimum_metrics.space_needed(), + ) } else { new_line_metrics.space_needed() }; @@ -242,8 +250,11 @@ struct LineBreaker { impl LineBreaker { /// Creates a new `LineBreaker` with a set of floats and the indentation of the first line. - fn new(float_context: Floats, first_line_indentation: Au, minimum_line_metrics: &LineMetrics) - -> LineBreaker { + fn new( + float_context: Floats, + first_line_indentation: Au, + minimum_line_metrics: &LineMetrics, + ) -> LineBreaker { LineBreaker { new_fragments: Vec::new(), work_list: VecDeque::new(), @@ -273,13 +284,14 @@ impl LineBreaker { } /// Reflows fragments for the given inline flow. - fn scan_for_lines(&mut self, - flow: &mut InlineFlow, - layout_context: &LayoutContext) { + fn scan_for_lines(&mut self, flow: &mut InlineFlow, layout_context: &LayoutContext) { self.reset_scanner(); // Create our fragment iterator. - debug!("LineBreaker: scanning for lines, {} fragments", flow.fragments.len()); + debug!( + "LineBreaker: scanning for lines, {} fragments", + flow.fragments.len() + ); let mut old_fragments = mem::replace(&mut flow.fragments, InlineFragments::new()); let old_fragment_iter = old_fragments.fragments.into_iter(); @@ -300,12 +312,13 @@ impl LineBreaker { // (because we split fragments on level run boundaries during flow // construction), so we can build a level array with just one entry per // fragment. - let levels: Vec<bidi::Level> = self.new_fragments.iter().map( - |fragment| match fragment.specific { + let levels: Vec<bidi::Level> = self + .new_fragments + .iter() + .map(|fragment| match fragment.specific { SpecificFragmentInfo::ScannedText(ref info) => info.run.bidi_level, - _ => para_level - } - ).collect(); + _ => para_level, + }).collect(); let mut lines = mem::replace(&mut self.lines, Vec::new()); @@ -319,11 +332,14 @@ impl LineBreaker { // the original text and original BidiClass of its characters. #[allow(deprecated)] let runs = bidi::deprecated::visual_runs(range, &levels); - line.visual_runs = Some(runs.iter().map(|run| { - let start = FragmentIndex(run.start as isize); - let len = FragmentIndex(run.len() as isize); - (Range::new(start, len), levels[run.start]) - }).collect()); + line.visual_runs = Some( + runs.iter() + .map(|run| { + let start = FragmentIndex(run.start as isize); + let len = FragmentIndex(run.len() as isize); + (Range::new(start, len), levels[run.start]) + }).collect(), + ); } } @@ -334,11 +350,13 @@ impl LineBreaker { } /// Reflows the given fragments, which have been plucked out of the inline flow. - fn reflow_fragments<'a, I>(&mut self, - mut old_fragment_iter: I, - flow: &'a InlineFlow, - layout_context: &LayoutContext) - where I: Iterator<Item=Fragment>, + fn reflow_fragments<'a, I>( + &mut self, + mut old_fragment_iter: I, + flow: &'a InlineFlow, + layout_context: &LayoutContext, + ) where + I: Iterator<Item = Fragment>, { loop { // Acquire the next fragment to lay out from the work list or fragment list, as @@ -350,7 +368,7 @@ impl LineBreaker { // Do not reflow truncated fragments. Reflow the original fragment only. let fragment = if fragment.flags.contains(FragmentFlags::IS_ELLIPSIS) { - continue + continue; } else if let SpecificFragmentInfo::TruncatedFragment(info) = fragment.specific { info.full } else { @@ -362,8 +380,10 @@ impl LineBreaker { } if !self.pending_line_is_empty() { - debug!("LineBreaker: partially full line {} at end of scanning; committing it", - self.lines.len()); + debug!( + "LineBreaker: partially full line {} at end of scanning; committing it", + self.lines.len() + ); self.flush_current_line() } } @@ -371,12 +391,13 @@ impl LineBreaker { /// Acquires a new fragment to lay out from the work list or fragment list as appropriate. /// Note that you probably don't want to call this method directly in order to be incremental- /// reflow-safe; try `next_unbroken_fragment` instead. - fn next_fragment<I>(&mut self, - old_fragment_iter: &mut I) - -> Option<Fragment> - where I: Iterator<Item=Fragment>, + fn next_fragment<I>(&mut self, old_fragment_iter: &mut I) -> Option<Fragment> + where + I: Iterator<Item = Fragment>, { - self.work_list.pop_front().or_else(|| old_fragment_iter.next()) + self.work_list + .pop_front() + .or_else(|| old_fragment_iter.next()) } /// Acquires a new fragment to lay out from the work list or fragment list, @@ -384,10 +405,9 @@ impl LineBreaker { /// this method does is to return the next fragment to lay out, undoing line /// break operations that any previous reflows may have performed. You /// probably want to be using this method instead of `next_fragment`. - fn next_unbroken_fragment<I>(&mut self, - old_fragment_iter: &mut I) - -> Option<Fragment> - where I: Iterator<Item=Fragment>, + fn next_unbroken_fragment<I>(&mut self, old_fragment_iter: &mut I) -> Option<Fragment> + where + I: Iterator<Item = Fragment>, { let mut result = self.next_fragment(old_fragment_iter)?; @@ -398,34 +418,41 @@ impl LineBreaker { }; let need_to_merge = match (&mut result.specific, &candidate.specific) { - (&mut SpecificFragmentInfo::ScannedText(ref mut result_info), - &SpecificFragmentInfo::ScannedText(ref candidate_info)) => { + ( + &mut SpecificFragmentInfo::ScannedText(ref mut result_info), + &SpecificFragmentInfo::ScannedText(ref candidate_info), + ) => { result.margin.inline_end == Au(0) && - candidate.margin.inline_start == Au(0) && - result.border_padding.inline_end == Au(0) && - candidate.border_padding.inline_start == Au(0) && - result_info.selected() == candidate_info.selected() && - Arc::ptr_eq(&result_info.run, &candidate_info.run) && - inline_contexts_are_equal(&result.inline_context, - &candidate.inline_context) - } + candidate.margin.inline_start == Au(0) && + result.border_padding.inline_end == Au(0) && + candidate.border_padding.inline_start == Au(0) && + result_info.selected() == candidate_info.selected() && + Arc::ptr_eq(&result_info.run, &candidate_info.run) && + inline_contexts_are_equal( + &result.inline_context, + &candidate.inline_context, + ) + }, _ => false, }; - if need_to_merge { result.merge_with(candidate); - continue + continue; } self.work_list.push_front(candidate); - return Some(result) + return Some(result); } } /// Commits a line to the list. fn flush_current_line(&mut self) { - debug!("LineBreaker: flushing line {}: {:?}", self.lines.len(), self.pending_line); + debug!( + "LineBreaker: flushing line {}: {:?}", + self.lines.len(), + self.pending_line + ); self.strip_trailing_whitespace_from_pending_line_if_necessary(); self.lines.push(self.pending_line.clone()); self.cur_b = self.pending_line.bounds.start.b + self.pending_line.bounds.size.block; @@ -436,7 +463,7 @@ impl LineBreaker { /// flushing it. fn strip_trailing_whitespace_from_pending_line_if_necessary(&mut self) { if self.pending_line.range.is_empty() { - return + return; } let last_fragment_index = self.pending_line.range.end() - FragmentIndex(1); let fragment = &mut self.new_fragments[last_fragment_index.get() as usize]; @@ -452,16 +479,19 @@ impl LineBreaker { /// Computes the position of a line that has only the provided fragment. Returns the bounding /// rect of the line's green zone (whose origin coincides with the line's origin) and the /// actual inline-size of the first fragment after splitting. - fn initial_line_placement(&self, - flow: &InlineFlow, - first_fragment: &Fragment, - ceiling: Au) - -> (LogicalRect<Au>, Au) { - debug!("LineBreaker: trying to place first fragment of line {}; fragment size: {:?}, \ - splittable: {}", - self.lines.len(), - first_fragment.border_box.size, - first_fragment.can_split()); + fn initial_line_placement( + &self, + flow: &InlineFlow, + first_fragment: &Fragment, + ceiling: Au, + ) -> (LogicalRect<Au>, Au) { + debug!( + "LineBreaker: trying to place first fragment of line {}; fragment size: {:?}, \ + splittable: {}", + self.lines.len(), + first_fragment.border_box.size, + first_fragment.can_split() + ); // Initially, pretend a splittable fragment has zero inline-size. We will move it later if // it has nonzero inline-size and that causes problems. @@ -473,9 +503,11 @@ impl LineBreaker { // Try to place the fragment between floats. let line_bounds = self.floats.place_between_floats(&PlacementInfo { - size: LogicalSize::new(self.floats.writing_mode, - placement_inline_size, - first_fragment.border_box.size.block), + size: LogicalSize::new( + self.floats.writing_mode, + placement_inline_size, + first_fragment.border_box.size.block, + ), ceiling: ceiling, max_inline_size: flow.base.position.size.inline, kind: FloatKind::Left, @@ -511,33 +543,37 @@ impl LineBreaker { /// So we'll try to move the line whenever we can, but break if we have to. /// /// Returns false if and only if we should break the line. - fn avoid_floats(&mut self, - flow: &InlineFlow, - in_fragment: Fragment, - new_block_size: Au) - -> bool { + fn avoid_floats( + &mut self, + flow: &InlineFlow, + in_fragment: Fragment, + new_block_size: Au, + ) -> bool { debug!("LineBreaker: entering float collision avoider!"); // First predict where the next line is going to be. let (next_line, first_fragment_inline_size) = - self.initial_line_placement(flow, - &in_fragment, - self.pending_line.bounds.start.b); + self.initial_line_placement(flow, &in_fragment, self.pending_line.bounds.start.b); let next_green_zone = next_line.size; let new_inline_size = self.pending_line.bounds.size.inline + first_fragment_inline_size; // Now, see if everything can fit at the new location. if next_green_zone.inline >= new_inline_size && next_green_zone.block >= new_block_size { - debug!("LineBreaker: case=adding fragment collides vertically with floats: moving \ - line"); + debug!( + "LineBreaker: case=adding fragment collides vertically with floats: moving \ + line" + ); self.pending_line.bounds.start = next_line.start; self.pending_line.green_zone = next_green_zone; - debug_assert!(!self.pending_line_is_empty(), "Non-terminating line breaking"); + debug_assert!( + !self.pending_line_is_empty(), + "Non-terminating line breaking" + ); self.work_list.push_front(in_fragment); - return true + return true; } debug!("LineBreaker: case=adding fragment collides vertically with floats: breaking line"); @@ -547,10 +583,12 @@ impl LineBreaker { /// Tries to append the given fragment to the line, splitting it if necessary. Commits the /// current line if needed. - fn reflow_fragment(&mut self, - mut fragment: Fragment, - flow: &InlineFlow, - layout_context: &LayoutContext) { + fn reflow_fragment( + &mut self, + mut fragment: Fragment, + flow: &InlineFlow, + layout_context: &LayoutContext, + ) { // Undo any whitespace stripping from previous reflows. fragment.reset_text_range_and_inline_size(); // Determine initial placement for the fragment if we need to. @@ -573,37 +611,41 @@ impl LineBreaker { // is_on_glyph_run_boundary does a binary search, but this is ok // because the result will be cached and reused in // `calculate_split_position` later - if fragment.suppress_line_break_before() || - !fragment.is_on_glyph_run_boundary() { + if fragment.suppress_line_break_before() || !fragment.is_on_glyph_run_boundary() { false } else { fragment.white_space().allow_wrap() } }; - debug!("LineBreaker: trying to append to line {} \ - (fragment size: {:?}, green zone: {:?}): {:?}", - self.lines.len(), - fragment.border_box.size, - self.pending_line.green_zone, - fragment); + debug!( + "LineBreaker: trying to append to line {} \ + (fragment size: {:?}, green zone: {:?}): {:?}", + self.lines.len(), + fragment.border_box.size, + self.pending_line.green_zone, + fragment + ); // NB: At this point, if `green_zone.inline < // self.pending_line.bounds.size.inline` or `green_zone.block < // self.pending_line.bounds.size.block`, then we committed a line that // overlaps with floats. let green_zone = self.pending_line.green_zone; - let new_line_metrics = self.pending_line.new_metrics_for_fragment(&fragment, - layout_context); - let new_block_size = self.pending_line.new_block_size_for_fragment(&fragment, - &new_line_metrics, - layout_context); + let new_line_metrics = self + .pending_line + .new_metrics_for_fragment(&fragment, layout_context); + let new_block_size = self.pending_line.new_block_size_for_fragment( + &fragment, + &new_line_metrics, + layout_context, + ); if new_block_size > green_zone.block { // Uh-oh. Float collision imminent. Enter the float collision avoider! if !self.avoid_floats(flow, fragment, new_block_size) { self.flush_current_line(); } - return + return; } // Record the last known good line break opportunity if this is one. @@ -627,30 +669,32 @@ impl LineBreaker { // horizontally. We'll try to place the whole fragment on this line and break somewhere if // it doesn't fit. let indentation = self.indentation_for_pending_fragment(); - let new_inline_size = self.pending_line.bounds.size.inline + - fragment.margin_box_inline_size() + indentation; + let new_inline_size = + self.pending_line.bounds.size.inline + fragment.margin_box_inline_size() + indentation; if new_inline_size <= green_zone.inline { debug!("LineBreaker: fragment fits without splitting"); self.push_fragment_to_line(layout_context, fragment, line_flush_mode); - return + return; } // If the wrapping mode prevents us from splitting, then back up and split at the last // known good split point. if !fragment.white_space().allow_wrap() { - debug!("LineBreaker: fragment can't split; falling back to last known good split point"); + debug!( + "LineBreaker: fragment can't split; falling back to last known good split point" + ); self.split_line_at_last_known_good_position(layout_context, fragment, line_flush_mode); return; } // Split it up! - let available_inline_size = green_zone.inline - - self.pending_line.bounds.size.inline - - indentation; + let available_inline_size = + green_zone.inline - self.pending_line.bounds.size.inline - indentation; let inline_start_fragment; let inline_end_fragment; - let split_result = match fragment.calculate_split_position(available_inline_size, - self.pending_line_is_empty()) { + let split_result = match fragment + .calculate_split_position(available_inline_size, self.pending_line_is_empty()) + { None => { // We failed to split. Defer to the next line if we're allowed to; otherwise, // rewind to the last line breaking opportunity. @@ -659,21 +703,25 @@ impl LineBreaker { self.work_list.push_front(fragment); self.flush_current_line(); } else { - self.split_line_at_last_known_good_position(layout_context, - fragment, - LineFlushMode::No); + self.split_line_at_last_known_good_position( + layout_context, + fragment, + LineFlushMode::No, + ); } - return - } + return; + }, Some(split_result) => split_result, }; - inline_start_fragment = split_result.inline_start.as_ref().map(|x| { - fragment.transform_with_split_info(x, split_result.text_run.clone(), true) - }); - inline_end_fragment = split_result.inline_end.as_ref().map(|x| { - fragment.transform_with_split_info(x, split_result.text_run.clone(), false) - }); + inline_start_fragment = split_result + .inline_start + .as_ref() + .map(|x| fragment.transform_with_split_info(x, split_result.text_run.clone(), true)); + inline_end_fragment = split_result + .inline_end + .as_ref() + .map(|x| fragment.transform_with_split_info(x, split_result.text_run.clone(), false)); // Push the first fragment onto the line we're working on and start off the next line with // the second fragment. If there's no second fragment, the next line will start off empty. @@ -682,56 +730,69 @@ impl LineBreaker { inline_start_fragment.border_padding.inline_end = Au(0); if let Some(ref mut inline_context) = inline_start_fragment.inline_context { for node in &mut inline_context.nodes { - node.flags.remove(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); + node.flags + .remove(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); } } - inline_start_fragment.border_box.size.inline += inline_start_fragment.border_padding.inline_start; + inline_start_fragment.border_box.size.inline += + inline_start_fragment.border_padding.inline_start; inline_end_fragment.border_padding.inline_start = Au(0); if let Some(ref mut inline_context) = inline_end_fragment.inline_context { for node in &mut inline_context.nodes { - node.flags.remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT); + node.flags + .remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT); } } - inline_end_fragment.border_box.size.inline += inline_end_fragment.border_padding.inline_end; - - self.push_fragment_to_line(layout_context, - inline_start_fragment, - LineFlushMode::Flush); + inline_end_fragment.border_box.size.inline += + inline_end_fragment.border_padding.inline_end; + + self.push_fragment_to_line( + layout_context, + inline_start_fragment, + LineFlushMode::Flush, + ); self.work_list.push_front(inline_end_fragment) }, (Some(fragment), None) => { self.push_fragment_to_line(layout_context, fragment, line_flush_mode); - } + }, (None, Some(fragment)) => { // Yes, this can happen! self.flush_current_line(); self.work_list.push_front(fragment) - } - (None, None) => {} + }, + (None, None) => {}, } } /// Pushes a fragment to the current line unconditionally, possibly truncating it and placing /// an ellipsis based on the value of `text-overflow`. If `flush_line` is `Flush`, then flushes /// the line afterward; - fn push_fragment_to_line(&mut self, - layout_context: &LayoutContext, - fragment: Fragment, - line_flush_mode: LineFlushMode) { + fn push_fragment_to_line( + &mut self, + layout_context: &LayoutContext, + fragment: Fragment, + line_flush_mode: LineFlushMode, + ) { let indentation = self.indentation_for_pending_fragment(); if self.pending_line_is_empty() { debug_assert!(self.new_fragments.len() <= (isize::MAX as usize)); - self.pending_line.range.reset(FragmentIndex(self.new_fragments.len() as isize), - FragmentIndex(0)); + self.pending_line.range.reset( + FragmentIndex(self.new_fragments.len() as isize), + FragmentIndex(0), + ); } // Determine if an ellipsis will be necessary to account for `text-overflow`. let available_inline_size = self.pending_line.green_zone.inline - - self.pending_line.bounds.size.inline - indentation; + self.pending_line.bounds.size.inline - + indentation; - let ellipsis = match (&fragment.style().get_text().text_overflow.second, - fragment.style().get_box().overflow_x) { + let ellipsis = match ( + &fragment.style().get_text().text_overflow.second, + fragment.style().get_box().overflow_x, + ) { (&TextOverflowSide::Clip, _) | (_, StyleOverflow::Visible) => None, (&TextOverflowSide::Ellipsis, _) => { if fragment.margin_box_inline_size() > available_inline_size { @@ -746,13 +807,13 @@ impl LineBreaker { } else { None } - } + }, }; if let Some(string) = ellipsis { let ellipsis = fragment.transform_into_ellipsis(layout_context, string); - let truncated = fragment.truncate_to_inline_size(available_inline_size - - ellipsis.margin_box_inline_size()); + let truncated = fragment + .truncate_to_inline_size(available_inline_size - ellipsis.margin_box_inline_size()); self.push_fragment_to_line_ignoring_text_overflow(truncated, layout_context); self.push_fragment_to_line_ignoring_text_overflow(ellipsis, layout_context); } else { @@ -766,43 +827,50 @@ impl LineBreaker { /// Pushes a fragment to the current line unconditionally, without placing an ellipsis in the /// case of `text-overflow: ellipsis`. - fn push_fragment_to_line_ignoring_text_overflow(&mut self, - fragment: Fragment, - layout_context: &LayoutContext) { + fn push_fragment_to_line_ignoring_text_overflow( + &mut self, + fragment: Fragment, + layout_context: &LayoutContext, + ) { let indentation = self.indentation_for_pending_fragment(); self.pending_line.range.extend_by(FragmentIndex(1)); if !fragment.is_inline_absolute() && !fragment.is_hypothetical() { self.pending_line.bounds.size.inline = self.pending_line.bounds.size.inline + - fragment.margin_box_inline_size() + indentation; - self.pending_line.metrics = self.pending_line.new_metrics_for_fragment(&fragment, - layout_context); - self.pending_line.bounds.size.block = - self.pending_line.new_block_size_for_fragment(&fragment, - &self.pending_line.metrics, - layout_context); + fragment.margin_box_inline_size() + + indentation; + self.pending_line.metrics = self + .pending_line + .new_metrics_for_fragment(&fragment, layout_context); + self.pending_line.bounds.size.block = self.pending_line.new_block_size_for_fragment( + &fragment, + &self.pending_line.metrics, + layout_context, + ); } self.new_fragments.push(fragment); } - fn split_line_at_last_known_good_position(&mut self, - layout_context: &LayoutContext, - cur_fragment: Fragment, - line_flush_mode: LineFlushMode) { - let last_known_line_breaking_opportunity = - match self.last_known_line_breaking_opportunity { - None => { - // No line breaking opportunity exists at all for this line. Overflow. - self.push_fragment_to_line(layout_context, cur_fragment, line_flush_mode); - return; - } - Some(last_known_line_breaking_opportunity) => last_known_line_breaking_opportunity, - }; + fn split_line_at_last_known_good_position( + &mut self, + layout_context: &LayoutContext, + cur_fragment: Fragment, + line_flush_mode: LineFlushMode, + ) { + let last_known_line_breaking_opportunity = match self.last_known_line_breaking_opportunity { + None => { + // No line breaking opportunity exists at all for this line. Overflow. + self.push_fragment_to_line(layout_context, cur_fragment, line_flush_mode); + return; + }, + Some(last_known_line_breaking_opportunity) => last_known_line_breaking_opportunity, + }; self.work_list.push_front(cur_fragment); - for fragment_index in (last_known_line_breaking_opportunity.get().. - self.pending_line.range.end().get()).rev() { + for fragment_index in + (last_known_line_breaking_opportunity.get()..self.pending_line.range.end().get()).rev() + { debug_assert_eq!(fragment_index, (self.new_fragments.len() as isize) - 1); self.work_list.push_front(self.new_fragments.pop().unwrap()); } @@ -820,7 +888,9 @@ impl LineBreaker { // point. Unfortunately, the existing splitting API (`calculate_split_position`) // has no concept of "split right before the last non-whitespace position". We'll // need to add that feature to the API to handle this case correctly. - self.pending_line.range.extend_to(last_known_line_breaking_opportunity); + self.pending_line + .range + .extend_to(last_known_line_breaking_opportunity); self.flush_current_line(); } @@ -849,9 +919,7 @@ pub struct InlineFragments { impl InlineFragments { /// Creates an empty set of inline fragments. pub fn new() -> InlineFragments { - InlineFragments { - fragments: vec![], - } + InlineFragments { fragments: vec![] } } /// Returns the number of inline fragments. @@ -913,8 +981,15 @@ impl InlineFlow { first_line_indentation: Au(0), }; - if flow.fragments.fragments.iter().any(Fragment::is_unscanned_generated_content) { - flow.base.restyle_damage.insert(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT); + if flow + .fragments + .fragments + .iter() + .any(Fragment::is_unscanned_generated_content) + { + flow.base + .restyle_damage + .insert(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT); } flow @@ -922,19 +997,24 @@ impl InlineFlow { /// Sets fragment positions in the inline direction based on alignment for one line. This /// performs text justification if mandated by the style. - fn set_inline_fragment_positions(fragments: &mut InlineFragments, - line: &Line, - line_align: TextAlign, - indentation: Au, - is_last_line: bool) { + fn set_inline_fragment_positions( + fragments: &mut InlineFragments, + line: &Line, + line_align: TextAlign, + indentation: Au, + is_last_line: bool, + ) { // Figure out how much inline-size we have. let slack_inline_size = max(Au(0), line.green_zone.inline - line.bounds.size.inline); // Compute the value we're going to use for `text-justify`. if fragments.fragments.is_empty() { - return + return; } - let text_justify = fragments.fragments[0].style().get_inherited_text().text_justify; + let text_justify = fragments.fragments[0] + .style() + .get_inherited_text() + .text_justify; // Translate `left` and `right` to logical directions. let is_ltr = fragments.fragments[0].style().writing_mode.is_bidi_ltr(); @@ -947,7 +1027,7 @@ impl InlineFlow { (TextAlign::ServoLeft, false) | (TextAlign::Right, true) | (TextAlign::ServoRight, true) => TextAlign::End, - _ => line_align + _ => line_align, }; // Set the fragment inline positions based on that alignment, and justify the text if @@ -956,32 +1036,31 @@ impl InlineFlow { match line_align { TextAlign::Justify if !is_last_line && text_justify != TextJustify::None => { InlineFlow::justify_inline_fragments(fragments, line, slack_inline_size) - } - TextAlign::Justify | TextAlign::Start => {} + }, + TextAlign::Justify | TextAlign::Start => {}, TextAlign::Center | TextAlign::ServoCenter => { - inline_start_position_for_fragment = inline_start_position_for_fragment + - slack_inline_size.scale_by(0.5) - } + inline_start_position_for_fragment = + inline_start_position_for_fragment + slack_inline_size.scale_by(0.5) + }, TextAlign::End => { - inline_start_position_for_fragment = inline_start_position_for_fragment + - slack_inline_size - } - TextAlign::Left | - TextAlign::ServoLeft | - TextAlign::Right | - TextAlign::ServoRight => unreachable!() + inline_start_position_for_fragment = + inline_start_position_for_fragment + slack_inline_size + }, + TextAlign::Left | TextAlign::ServoLeft | TextAlign::Right | TextAlign::ServoRight => { + unreachable!() + }, } // Lay out the fragments in visual order. let run_count = match line.visual_runs { Some(ref runs) => runs.len(), - None => 1 + None => 1, }; for run_idx in 0..run_count { let (range, level) = match line.visual_runs { Some(ref runs) if is_ltr => runs[run_idx], Some(ref runs) => runs[run_count - run_idx - 1], // reverse order for RTL runs - None => (line.range, bidi::Level::ltr()) + None => (line.range, bidi::Level::ltr()), }; struct MaybeReverse<I> { @@ -1014,26 +1093,30 @@ impl InlineFlow { for fragment_index in fragment_indices { let fragment = fragments.get_mut(fragment_index as usize); - inline_start_position_for_fragment = inline_start_position_for_fragment + - fragment.margin.inline_start; + inline_start_position_for_fragment = + inline_start_position_for_fragment + fragment.margin.inline_start; let border_start = if fragment.style.writing_mode.is_bidi_ltr() == is_ltr { inline_start_position_for_fragment } else { - line.green_zone.inline - inline_start_position_for_fragment - - fragment.margin.inline_end - - fragment.border_box.size.inline + line.green_zone.inline - + inline_start_position_for_fragment - + fragment.margin.inline_end - + fragment.border_box.size.inline }; - fragment.border_box = LogicalRect::new(fragment.style.writing_mode, - border_start, - fragment.border_box.start.b, - fragment.border_box.size.inline, - fragment.border_box.size.block); + fragment.border_box = LogicalRect::new( + fragment.style.writing_mode, + border_start, + fragment.border_box.start.b, + fragment.border_box.size.inline, + fragment.border_box.size.block, + ); fragment.update_late_computed_inline_position_if_necessary(); if !fragment.is_inline_absolute() { inline_start_position_for_fragment = inline_start_position_for_fragment + - fragment.border_box.size.inline + fragment.margin.inline_end; + fragment.border_box.size.inline + + fragment.margin.inline_end; } } } @@ -1041,12 +1124,14 @@ impl InlineFlow { /// Justifies the given set of inline fragments, distributing the `slack_inline_size` among all /// of them according to the value of `text-justify`. - fn justify_inline_fragments(fragments: &mut InlineFragments, - line: &Line, - slack_inline_size: Au) { + fn justify_inline_fragments( + fragments: &mut InlineFragments, + line: &Line, + slack_inline_size: Au, + ) { // Fast path. if slack_inline_size == Au(0) { - return + return; } // First, calculate the number of expansion opportunities (spaces, normally). @@ -1055,17 +1140,20 @@ impl InlineFlow { let fragment = fragments.get(fragment_index.to_usize()); let scanned_text_fragment_info = match fragment.specific { SpecificFragmentInfo::ScannedText(ref info) if !info.range.is_empty() => info, - _ => continue + _ => continue, }; let fragment_range = scanned_text_fragment_info.range; - for slice in scanned_text_fragment_info.run.character_slices_in_range(&fragment_range) { + for slice in scanned_text_fragment_info + .run + .character_slices_in_range(&fragment_range) + { expansion_opportunities += slice.glyphs.space_count_in_range(&slice.range) } } if expansion_opportunities == 0 { - return + return; } // Then distribute all the space across the expansion opportunities. @@ -1074,7 +1162,7 @@ impl InlineFlow { let fragment = fragments.get_mut(fragment_index.to_usize()); let scanned_text_fragment_info = match fragment.specific { SpecificFragmentInfo::ScannedText(ref mut info) if !info.range.is_empty() => info, - _ => continue + _ => continue, }; let fragment_range = scanned_text_fragment_info.range; let run = Arc::make_mut(&mut scanned_text_fragment_info.run); @@ -1082,30 +1170,38 @@ impl InlineFlow { // Recompute the fragment's border box size. let new_inline_size = run.advance_for_range(&fragment_range); - let new_size = LogicalSize::new(fragment.style.writing_mode, - new_inline_size, - fragment.border_box.size.block); - fragment.border_box = LogicalRect::from_point_size(fragment.style.writing_mode, - fragment.border_box.start, - new_size); + let new_size = LogicalSize::new( + fragment.style.writing_mode, + new_inline_size, + fragment.border_box.size.block, + ); + fragment.border_box = LogicalRect::from_point_size( + fragment.style.writing_mode, + fragment.border_box.start, + new_size, + ); } } /// Sets final fragment positions in the block direction for one line. - fn set_block_fragment_positions(fragments: &mut InlineFragments, - line: &Line, - minimum_line_metrics: &LineMetrics, - layout_context: &LayoutContext) { + fn set_block_fragment_positions( + fragments: &mut InlineFragments, + line: &Line, + minimum_line_metrics: &LineMetrics, + layout_context: &LayoutContext, + ) { for fragment_index in line.range.each_index() { let fragment = fragments.get_mut(fragment_index.to_usize()); let line_metrics = LineMetrics::for_line_and_fragment(line, fragment, layout_context); - let inline_metrics = fragment.aligned_inline_metrics(layout_context, - minimum_line_metrics, - Some(&line_metrics)); + let inline_metrics = fragment.aligned_inline_metrics( + layout_context, + minimum_line_metrics, + Some(&line_metrics), + ); // Align the top of the fragment's border box with its ascent above the baseline. - fragment.border_box.start.b = line.bounds.start.b + line_metrics.space_above_baseline - - inline_metrics.ascent; + fragment.border_box.start.b = + line.bounds.start.b + line_metrics.space_above_baseline - inline_metrics.ascent; // CSS 2.1 § 10.8: "The height of each inline-level box in the line box is // calculated. For replaced elements, inline-block elements, and inline-table @@ -1131,25 +1227,31 @@ impl InlineFlow { /// Computes the minimum metrics for each line. This is done during flow construction. /// /// `style` is the style of the block. - pub fn minimum_line_metrics(&self, font_context: &mut LayoutFontContext, style: &ComputedValues) - -> LineMetrics { - InlineFlow::minimum_line_metrics_for_fragments(&self.fragments.fragments, - font_context, - style) + pub fn minimum_line_metrics( + &self, + font_context: &mut LayoutFontContext, + style: &ComputedValues, + ) -> LineMetrics { + InlineFlow::minimum_line_metrics_for_fragments( + &self.fragments.fragments, + font_context, + style, + ) } /// Computes the minimum line metrics for the given fragments. This is typically done during /// flow construction. /// /// `style` is the style of the block that these fragments belong to. - pub fn minimum_line_metrics_for_fragments(fragments: &[Fragment], - font_context: &mut LayoutFontContext, - style: &ComputedValues) - -> LineMetrics { + pub fn minimum_line_metrics_for_fragments( + fragments: &[Fragment], + font_context: &mut LayoutFontContext, + style: &ComputedValues, + ) -> LineMetrics { // As a special case, if this flow contains only hypothetical fragments, then the entire // flow is hypothetical and takes up no space. See CSS 2.1 § 10.3.7. if fragments.iter().all(Fragment::is_hypothetical) { - return LineMetrics::new(Au(0), Au(0)) + return LineMetrics::new(Au(0), Au(0)); } let font_style = style.clone_font(); @@ -1167,68 +1269,80 @@ impl InlineFlow { // We use `VerticalAlign::Baseline` here because `vertical-align` must // not apply to the inside of inline blocks. - update_line_metrics_for_fragment(&mut line_metrics, - &inline_metrics, - style.get_box().display, - GenericVerticalAlign::Baseline, - &mut largest_block_size_for_top_fragments, - &mut largest_block_size_for_bottom_fragments); + update_line_metrics_for_fragment( + &mut line_metrics, + &inline_metrics, + style.get_box().display, + GenericVerticalAlign::Baseline, + &mut largest_block_size_for_top_fragments, + &mut largest_block_size_for_bottom_fragments, + ); // According to CSS 2.1 § 10.8, `line-height` of any inline element specifies the minimal // height of line boxes within the element. - for inline_context in fragments.iter() - .filter_map(|fragment| fragment.inline_context.as_ref()) { + for inline_context in fragments + .iter() + .filter_map(|fragment| fragment.inline_context.as_ref()) + { for node in &inline_context.nodes { let font_style = node.style.clone_font(); let font_metrics = text::font_metrics_for_style(font_context, font_style); let line_height = text::line_height_from_style(&*node.style, &font_metrics); let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height); - update_line_metrics_for_fragment(&mut line_metrics, - &inline_metrics, - node.style.get_box().display, - node.style.get_box().vertical_align, - &mut largest_block_size_for_top_fragments, - &mut largest_block_size_for_bottom_fragments); - + update_line_metrics_for_fragment( + &mut line_metrics, + &inline_metrics, + node.style.get_box().display, + node.style.get_box().vertical_align, + &mut largest_block_size_for_top_fragments, + &mut largest_block_size_for_bottom_fragments, + ); } } - line_metrics.space_above_baseline = - max(line_metrics.space_above_baseline, - largest_block_size_for_bottom_fragments - max(line_metrics.space_below_baseline, - Au(0))); - line_metrics.space_below_baseline = - max(line_metrics.space_below_baseline, - largest_block_size_for_top_fragments - line_metrics.space_above_baseline); + line_metrics.space_above_baseline = max( + line_metrics.space_above_baseline, + largest_block_size_for_bottom_fragments - max(line_metrics.space_below_baseline, Au(0)), + ); + line_metrics.space_below_baseline = max( + line_metrics.space_below_baseline, + largest_block_size_for_top_fragments - line_metrics.space_above_baseline, + ); return line_metrics; - fn update_line_metrics_for_fragment(line_metrics: &mut LineMetrics, - inline_metrics: &InlineMetrics, - display_value: Display, - vertical_align_value: VerticalAlign, - largest_block_size_for_top_fragments: &mut Au, - largest_block_size_for_bottom_fragments: &mut Au) { + fn update_line_metrics_for_fragment( + line_metrics: &mut LineMetrics, + inline_metrics: &InlineMetrics, + display_value: Display, + vertical_align_value: VerticalAlign, + largest_block_size_for_top_fragments: &mut Au, + largest_block_size_for_bottom_fragments: &mut Au, + ) { match (display_value, vertical_align_value) { (Display::Inline, GenericVerticalAlign::Top) | (Display::Block, GenericVerticalAlign::Top) | (Display::InlineFlex, GenericVerticalAlign::Top) | - (Display::InlineBlock, GenericVerticalAlign::Top) if - inline_metrics.space_above_baseline >= Au(0) => { + (Display::InlineBlock, GenericVerticalAlign::Top) + if inline_metrics.space_above_baseline >= Au(0) => + { *largest_block_size_for_top_fragments = max( *largest_block_size_for_top_fragments, - inline_metrics.space_above_baseline + inline_metrics.space_below_baseline) - } + inline_metrics.space_above_baseline + inline_metrics.space_below_baseline, + ) + }, (Display::Inline, GenericVerticalAlign::Bottom) | (Display::Block, GenericVerticalAlign::Bottom) | (Display::InlineFlex, GenericVerticalAlign::Bottom) | - (Display::InlineBlock, GenericVerticalAlign::Bottom) if - inline_metrics.space_below_baseline >= Au(0) => { + (Display::InlineBlock, GenericVerticalAlign::Bottom) + if inline_metrics.space_below_baseline >= Au(0) => + { *largest_block_size_for_bottom_fragments = max( *largest_block_size_for_bottom_fragments, - inline_metrics.space_above_baseline + inline_metrics.space_below_baseline) - } + inline_metrics.space_above_baseline + inline_metrics.space_below_baseline, + ) + }, _ => *line_metrics = line_metrics.new_metrics_for_fragment(inline_metrics), } } @@ -1244,20 +1358,22 @@ impl InlineFlow { self.base.restyle_damage = damage; } - fn containing_block_range_for_flow_surrounding_fragment_at_index(&self, - fragment_index: FragmentIndex) - -> Range<FragmentIndex> { + fn containing_block_range_for_flow_surrounding_fragment_at_index( + &self, + fragment_index: FragmentIndex, + ) -> Range<FragmentIndex> { let mut start_index = fragment_index; - while start_index > FragmentIndex(0) && - self.fragments - .fragments[(start_index - FragmentIndex(1)).get() as usize] - .is_positioned() { + while start_index > FragmentIndex(0) && self.fragments.fragments + [(start_index - FragmentIndex(1)).get() as usize] + .is_positioned() + { start_index = start_index - FragmentIndex(1) } let mut end_index = fragment_index + FragmentIndex(1); while end_index < FragmentIndex(self.fragments.fragments.len() as isize) && - self.fragments.fragments[end_index.get() as usize].is_positioned() { + self.fragments.fragments[end_index.get() as usize].is_positioned() + { end_index = end_index + FragmentIndex(1) } @@ -1265,29 +1381,32 @@ impl InlineFlow { } fn containing_block_range_for_flow(&self, opaque_flow: OpaqueFlow) -> Range<FragmentIndex> { - match self.fragments.fragments.iter().position(|fragment| { - match fragment.specific { + match self + .fragments + .fragments + .iter() + .position(|fragment| match fragment.specific { SpecificFragmentInfo::InlineAbsolute(ref inline_absolute) => { OpaqueFlow::from_flow(&*inline_absolute.flow_ref) == opaque_flow - } + }, SpecificFragmentInfo::InlineAbsoluteHypothetical( - ref inline_absolute_hypothetical) => { - OpaqueFlow::from_flow(&*inline_absolute_hypothetical.flow_ref) == opaque_flow - } + ref inline_absolute_hypothetical, + ) => OpaqueFlow::from_flow(&*inline_absolute_hypothetical.flow_ref) == opaque_flow, _ => false, - } - }) { + }) { Some(index) => { let index = FragmentIndex(index as isize); self.containing_block_range_for_flow_surrounding_fragment_at_index(index) - } + }, None => { // FIXME(pcwalton): This is quite wrong. We should only return the range // surrounding the inline fragments that constitute the containing block. But this // suffices to get Google looking right. - Range::new(FragmentIndex(0), - FragmentIndex(self.fragments.fragments.len() as isize)) - } + Range::new( + FragmentIndex(0), + FragmentIndex(self.fragments.fragments.len() as isize), + ) + }, } } @@ -1300,10 +1419,10 @@ impl InlineFlow { // Returns the last line that doesn't consist entirely of hypothetical boxes. fn last_line_containing_real_fragments(&self) -> Option<&Line> { for line in self.lines.iter().rev() { - if (line.range.begin().get()..line.range.end().get()).any(|index| { - !self.fragments.fragments[index as usize].is_hypothetical() - }) { - return Some(line) + if (line.range.begin().get()..line.range.end().get()) + .any(|index| !self.fragments.fragments[index as usize].is_hypothetical()) + { + return Some(line); } } None @@ -1326,15 +1445,16 @@ impl Flow for InlineFlow { fn bubble_inline_sizes(&mut self) { self.update_restyle_damage(); - let _scope = layout_debug_scope!("inline::bubble_inline_sizes {:x}", - self.base.debug_id()); + let _scope = layout_debug_scope!("inline::bubble_inline_sizes {:x}", self.base.debug_id()); let writing_mode = self.base.writing_mode; for kid in self.base.child_iter_mut() { kid.mut_base().floats = Floats::new(writing_mode); } - self.base.flags.remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); + self.base + .flags + .remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); let mut intrinsic_sizes_for_flow = IntrinsicISizesContribution::new(); let mut intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new(); @@ -1342,31 +1462,28 @@ impl Flow for InlineFlow { for fragment in &mut self.fragments.fragments { let intrinsic_sizes_for_fragment = fragment.compute_intrinsic_inline_sizes().finish(); match fragment.style.get_inherited_text().white_space { - WhiteSpace::Nowrap => { - intrinsic_sizes_for_nonbroken_run.union_nonbreaking_inline( - &intrinsic_sizes_for_fragment) - } + WhiteSpace::Nowrap => intrinsic_sizes_for_nonbroken_run + .union_nonbreaking_inline(&intrinsic_sizes_for_fragment), WhiteSpace::Pre => { - intrinsic_sizes_for_nonbroken_run.union_nonbreaking_inline( - &intrinsic_sizes_for_fragment); + 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_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_flow + .union_block(&intrinsic_sizes_for_inline_run.finish()); intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new(); } - } - WhiteSpace::PreWrap | - WhiteSpace::PreLine => { + }, + WhiteSpace::PreWrap | WhiteSpace::PreLine => { // 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_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); @@ -1374,29 +1491,33 @@ impl Flow for InlineFlow { // 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_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_flow + .union_block(&intrinsic_sizes_for_inline_run.finish()); intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new(); } - } + }, WhiteSpace::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_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); - } + }, } - fragment.restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES); + fragment + .restyle_damage + .remove(ServoRestyleDamage::BUBBLE_ISIZES); if fragment.is_text_or_replaced() { - self.base.flags.insert(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); + self.base + .flags + .insert(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); } } @@ -1418,7 +1539,10 @@ impl Flow for InlineFlow { // TODO: Combine this with `LineBreaker`'s walk in the fragment list, or put this into // `Fragment`. - debug!("InlineFlow::assign_inline_sizes: floats in: {:?}", self.base.floats); + debug!( + "InlineFlow::assign_inline_sizes: floats in: {:?}", + self.base.floats + ); let inline_size = self.base.block_container_inline_size; let container_mode = self.base.block_container_writing_mode; @@ -1431,7 +1555,8 @@ impl Flow for InlineFlow { fragment.compute_border_and_padding(inline_size); fragment.compute_block_direction_margins(inline_size); fragment.compute_inline_direction_margins(inline_size); - fragment.assign_replaced_inline_size_if_necessary(inline_size, container_block_size); + fragment + .assign_replaced_inline_size_if_necessary(inline_size, container_block_size); } } @@ -1451,8 +1576,7 @@ impl Flow for InlineFlow { /// Note that we do not need to do in-order traversal because the children /// are always block formatting context. fn assign_block_size(&mut self, layout_context: &LayoutContext) { - let _scope = layout_debug_scope!("inline::assign_block_size {:x}", - self.base.debug_id()); + let _scope = layout_debug_scope!("inline::assign_block_size {:x}", self.base.debug_id()); // Divide the fragments into lines. // @@ -1465,7 +1589,10 @@ impl Flow for InlineFlow { // the line's own block-size. // // TODO(pcwalton): Cache the line scanner? - debug!("assign_block_size_inline: floats in: {:?}", self.base.floats); + debug!( + "assign_block_size_inline: floats in: {:?}", + self.base.floats + ); // Assign the block-size and late-computed inline-sizes for the inline fragments. for fragment in &mut self.fragments.fragments { @@ -1486,9 +1613,11 @@ impl Flow for InlineFlow { }; // Perform line breaking. - let mut scanner = LineBreaker::new(self.base.floats.clone(), - indentation, - &self.minimum_line_metrics); + let mut scanner = LineBreaker::new( + self.base.floats.clone(), + indentation, + &self.minimum_line_metrics, + ); scanner.scan_for_lines(self, layout_context); // Now, go through each line and lay out the fragments inside. @@ -1496,17 +1625,21 @@ impl Flow for InlineFlow { for (line_index, line) in self.lines.iter_mut().enumerate() { // Lay out fragments in the inline direction, and justify them if // necessary. - InlineFlow::set_inline_fragment_positions(&mut self.fragments, - line, - self.base.flags.text_align(), - indentation, - line_index + 1 == line_count); + InlineFlow::set_inline_fragment_positions( + &mut self.fragments, + line, + self.base.flags.text_align(), + indentation, + line_index + 1 == line_count, + ); // Compute the final positions in the block direction of each fragment. - InlineFlow::set_block_fragment_positions(&mut self.fragments, - line, - &self.minimum_line_metrics, - layout_context); + InlineFlow::set_block_fragment_positions( + &mut self.fragments, + line, + &self.minimum_line_metrics, + layout_context, + ); // This is used to set the block-start position of the next line in // the next iteration of the loop. We're no longer on the first @@ -1529,36 +1662,39 @@ impl Flow for InlineFlow { self.base.floats = scanner.floats.clone(); let writing_mode = self.base.floats.writing_mode; - self.base.floats.translate(LogicalSize::new(writing_mode, - Au(0), - -self.base.position.size.block)); - - let containing_block_size = LogicalSize::new(writing_mode, - Au(0), - self.base.position.size.block); - self.mutate_fragments(&mut |f: &mut Fragment| { - match f.specific { - SpecificFragmentInfo::InlineBlock(ref mut info) => { - let block = FlowRef::deref_mut(&mut info.flow_ref); - block.mut_base().early_absolute_position_info = EarlyAbsolutePositionInfo { - relative_containing_block_size: containing_block_size, - relative_containing_block_mode: writing_mode, - }; - } - SpecificFragmentInfo::InlineAbsolute(ref mut info) => { - let block = FlowRef::deref_mut(&mut info.flow_ref); - block.mut_base().early_absolute_position_info = EarlyAbsolutePositionInfo { - relative_containing_block_size: containing_block_size, - relative_containing_block_mode: writing_mode, - }; - } - _ => (), - } + self.base.floats.translate(LogicalSize::new( + writing_mode, + Au(0), + -self.base.position.size.block, + )); + + let containing_block_size = + LogicalSize::new(writing_mode, Au(0), self.base.position.size.block); + self.mutate_fragments(&mut |f: &mut Fragment| match f.specific { + SpecificFragmentInfo::InlineBlock(ref mut info) => { + let block = FlowRef::deref_mut(&mut info.flow_ref); + block.mut_base().early_absolute_position_info = EarlyAbsolutePositionInfo { + relative_containing_block_size: containing_block_size, + relative_containing_block_mode: writing_mode, + }; + }, + SpecificFragmentInfo::InlineAbsolute(ref mut info) => { + let block = FlowRef::deref_mut(&mut info.flow_ref); + block.mut_base().early_absolute_position_info = EarlyAbsolutePositionInfo { + relative_containing_block_size: containing_block_size, + relative_containing_block_mode: writing_mode, + }; + }, + _ => (), }); - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.base + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); for fragment in &mut self.fragments.fragments { - fragment.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + fragment + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); } } @@ -1577,45 +1713,51 @@ impl Flow for InlineFlow { for (fragment_index, fragment) in self.fragments.fragments.iter().enumerate() { match fragment.specific { SpecificFragmentInfo::InlineAbsolute(_) => { - let containing_block_range = - self.containing_block_range_for_flow_surrounding_fragment_at_index( - FragmentIndex(fragment_index as isize)); + let containing_block_range = self + .containing_block_range_for_flow_surrounding_fragment_at_index( + FragmentIndex(fragment_index as isize), + ); let first_fragment_index = containing_block_range.begin().get() as usize; debug_assert!(first_fragment_index < self.fragments.fragments.len()); let first_fragment = &self.fragments.fragments[first_fragment_index]; let padding_box_origin = (first_fragment.border_box - - first_fragment.style.logical_border_width()).start; + first_fragment.style.logical_border_width()).start; containing_block_positions.push( - padding_box_origin.to_physical(self.base.writing_mode, container_size)); - } + padding_box_origin.to_physical(self.base.writing_mode, container_size), + ); + }, SpecificFragmentInfo::InlineBlock(_) if fragment.is_positioned() => { - let containing_block_range = - self.containing_block_range_for_flow_surrounding_fragment_at_index( - FragmentIndex(fragment_index as isize)); + let containing_block_range = self + .containing_block_range_for_flow_surrounding_fragment_at_index( + FragmentIndex(fragment_index as isize), + ); let first_fragment_index = containing_block_range.begin().get() as usize; debug_assert!(first_fragment_index < self.fragments.fragments.len()); let first_fragment = &self.fragments.fragments[first_fragment_index]; let padding_box_origin = (first_fragment.border_box - - first_fragment.style.logical_border_width()).start; + first_fragment.style.logical_border_width()).start; containing_block_positions.push( - padding_box_origin.to_physical(self.base.writing_mode, container_size)); - } - _ => {} + padding_box_origin.to_physical(self.base.writing_mode, container_size), + ); + }, + _ => {}, } } // Then compute the positions of all of our fragments. let mut containing_block_positions = containing_block_positions.iter(); for fragment in &mut self.fragments.fragments { - let stacking_relative_border_box = - fragment.stacking_relative_border_box(&self.base.stacking_relative_position, - &self.base - .early_absolute_position_info - .relative_containing_block_size, - self.base - .early_absolute_position_info - .relative_containing_block_mode, - CoordinateSystem::Parent); + let stacking_relative_border_box = fragment.stacking_relative_border_box( + &self.base.stacking_relative_position, + &self + .base + .early_absolute_position_info + .relative_containing_block_size, + self.base + .early_absolute_position_info + .relative_containing_block_mode, + CoordinateSystem::Parent, + ); let stacking_relative_content_box = fragment.stacking_relative_content_box(stacking_relative_border_box); @@ -1630,9 +1772,10 @@ impl Flow for InlineFlow { let stacking_relative_position = self.base.stacking_relative_position; if is_positioned { let padding_box_origin = containing_block_positions.next().unwrap(); - block_flow.base - .late_absolute_position_info - .stacking_relative_position_of_absolute_containing_block = + block_flow + .base + .late_absolute_position_info + .stacking_relative_position_of_absolute_containing_block = *padding_box_origin + stacking_relative_position; } @@ -1642,7 +1785,7 @@ impl Flow for InlineFlow { // Write the clip in our coordinate system into the child flow. (The kid will // fix it up to be in its own coordinate system if necessary.) block_flow.base.clip = self.base.clip.clone() - } + }, SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { let flow = FlowRef::deref_mut(&mut info.flow_ref); let block_flow = flow.as_mut_block(); @@ -1654,7 +1797,7 @@ impl Flow for InlineFlow { // As above, this is in our coordinate system for now. block_flow.base.clip = self.base.clip.clone() - } + }, SpecificFragmentInfo::InlineAbsolute(ref mut info) => { let flow = FlowRef::deref_mut(&mut info.flow_ref); let block_flow = flow.as_mut_block(); @@ -1663,9 +1806,10 @@ impl Flow for InlineFlow { let stacking_relative_position = self.base.stacking_relative_position; let padding_box_origin = containing_block_positions.next().unwrap(); - block_flow.base - .late_absolute_position_info - .stacking_relative_position_of_absolute_containing_block = + block_flow + .base + .late_absolute_position_info + .stacking_relative_position_of_absolute_containing_block = *padding_box_origin + stacking_relative_position; block_flow.base.stacking_relative_position = @@ -1673,8 +1817,8 @@ impl Flow for InlineFlow { // As above, this is in our coordinate system for now. block_flow.base.clip = self.base.clip.clone() - } - _ => {} + }, + _ => {}, } } } @@ -1696,36 +1840,48 @@ impl Flow for InlineFlow { fn compute_overflow(&self) -> Overflow { let mut overflow = Overflow::new(); let flow_size = self.base.position.size.to_physical(self.base.writing_mode); - let relative_containing_block_size = - &self.base.early_absolute_position_info.relative_containing_block_size; + let relative_containing_block_size = &self + .base + .early_absolute_position_info + .relative_containing_block_size; for fragment in &self.fragments.fragments { overflow.union(&fragment.compute_overflow(&flow_size, &relative_containing_block_size)) } overflow } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { // FIXME(#2795): Get the real container size. for fragment in &self.fragments.fragments { if !iterator.should_process(fragment) { - continue + continue; } let stacking_relative_position = &self.base.stacking_relative_position; - let relative_containing_block_size = - &self.base.early_absolute_position_info.relative_containing_block_size; - let relative_containing_block_mode = - self.base.early_absolute_position_info.relative_containing_block_mode; - iterator.process(fragment, - level, - &fragment.stacking_relative_border_box(stacking_relative_position, - relative_containing_block_size, - relative_containing_block_mode, - CoordinateSystem::Own) - .translate(&stacking_context_position.to_vector())) + let relative_containing_block_size = &self + .base + .early_absolute_position_info + .relative_containing_block_size; + let relative_containing_block_mode = self + .base + .early_absolute_position_info + .relative_containing_block_mode; + iterator.process( + fragment, + level, + &fragment + .stacking_relative_border_box( + stacking_relative_position, + relative_containing_block_size, + relative_containing_block_mode, + CoordinateSystem::Own, + ).translate(&stacking_context_position.to_vector()), + ) } } @@ -1736,13 +1892,17 @@ impl Flow for InlineFlow { } fn contains_positioned_fragments(&self) -> bool { - self.fragments.fragments.iter().any(|fragment| fragment.is_positioned()) + self.fragments + .fragments + .iter() + .any(|fragment| fragment.is_positioned()) } fn contains_relatively_positioned_fragments(&self) -> bool { - self.fragments.fragments.iter().any(|fragment| { - fragment.style.get_box().position == Position::Relative - }) + self.fragments + .fragments + .iter() + .any(|fragment| fragment.style.get_box().position == Position::Relative) } fn generated_containing_block_size(&self, for_flow: OpaqueFlow) -> LogicalSize<Au> { @@ -1750,12 +1910,12 @@ impl Flow for InlineFlow { for index in self.containing_block_range_for_flow(for_flow).each_index() { let fragment = &self.fragments.fragments[index.get() as usize]; if fragment.is_absolutely_positioned() { - continue + continue; } - containing_block_size.inline = containing_block_size.inline + - fragment.border_box.size.inline; - containing_block_size.block = max(containing_block_size.block, - fragment.border_box.size.block); + containing_block_size.inline = + containing_block_size.inline + fragment.border_box.size.inline; + containing_block_size.block = + max(containing_block_size.block, fragment.border_box.size.block); } containing_block_size } @@ -1769,11 +1929,13 @@ impl Flow for InlineFlow { impl fmt::Debug for InlineFlow { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "{:?}({:x}) {:?}", - self.class(), - self.base.debug_id(), - self.base()) + write!( + f, + "{:?}({:x}) {:?}", + self.class(), + self.base.debug_id(), + self.base() + ) } } @@ -1808,36 +1970,38 @@ pub struct InlineFragmentContext { impl InlineFragmentContext { pub fn new() -> InlineFragmentContext { - InlineFragmentContext { - nodes: vec!(), - } + InlineFragmentContext { nodes: vec![] } } #[inline] pub fn contains_node(&self, node_address: OpaqueNode) -> bool { - self.nodes.iter().position(|node| node.address == node_address).is_some() + self.nodes + .iter() + .position(|node| node.address == node_address) + .is_some() } fn ptr_eq(&self, other: &InlineFragmentContext) -> bool { if self.nodes.len() != other.nodes.len() { - return false + return false; } for (this_node, other_node) in self.nodes.iter().zip(&other.nodes) { if this_node.address != other_node.address { - return false + return false; } } true } } -fn inline_contexts_are_equal(inline_context_a: &Option<InlineFragmentContext>, - inline_context_b: &Option<InlineFragmentContext>) - -> bool { +fn inline_contexts_are_equal( + inline_context_a: &Option<InlineFragmentContext>, + inline_context_b: &Option<InlineFragmentContext>, +) -> bool { match (inline_context_a, inline_context_b) { (&Some(ref inline_context_a), &Some(ref inline_context_b)) => { inline_context_a.ptr_eq(inline_context_b) - } + }, (&None, &None) => true, (&Some(_), &None) | (&None, &Some(_)) => false, } @@ -1916,27 +2080,33 @@ impl LineMetrics { /// with a fragment with the given metrics. fn new_metrics_for_fragment(&self, fragment_inline_metrics: &InlineMetrics) -> LineMetrics { LineMetrics { - space_above_baseline: max(self.space_above_baseline, - fragment_inline_metrics.space_above_baseline), - space_below_baseline: max(self.space_below_baseline, - fragment_inline_metrics.space_below_baseline), - } - } - - fn for_line_and_fragment(line: &Line, fragment: &Fragment, layout_context: &LayoutContext) - -> LineMetrics { + space_above_baseline: max( + self.space_above_baseline, + fragment_inline_metrics.space_above_baseline, + ), + space_below_baseline: max( + self.space_below_baseline, + fragment_inline_metrics.space_below_baseline, + ), + } + } + + fn for_line_and_fragment( + line: &Line, + fragment: &Fragment, + layout_context: &LayoutContext, + ) -> LineMetrics { if !fragment.is_hypothetical() { let space_above_baseline = line.metrics.space_above_baseline; return LineMetrics { space_above_baseline: space_above_baseline, space_below_baseline: line.bounds.size.block - space_above_baseline, - } + }; } let hypothetical_line_metrics = line.new_metrics_for_fragment(fragment, layout_context); - let hypothetical_block_size = line.new_block_size_for_fragment(fragment, - &hypothetical_line_metrics, - layout_context); + let hypothetical_block_size = + line.new_block_size_for_fragment(fragment, &hypothetical_line_metrics, layout_context); let hypothetical_space_above_baseline = hypothetical_line_metrics.space_above_baseline; LineMetrics { space_above_baseline: hypothetical_space_above_baseline, @@ -1949,4 +2119,3 @@ impl LineMetrics { self.space_above_baseline + self.space_below_baseline } } - diff --git a/components/layout/layout_debug.rs b/components/layout/layout_debug.rs index 26fd4fb3e3f..70b73d9b6fd 100644 --- a/components/layout/layout_debug.rs +++ b/components/layout/layout_debug.rs @@ -47,7 +47,7 @@ impl ScopeData { name: name, pre: pre, post: Value::Null, - children: vec!(), + children: vec![], } } } diff --git a/components/layout/lib.rs b/components/layout/lib.rs index c0c5633ca24..ce47eb72620 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -14,7 +14,8 @@ extern crate fnv; extern crate fxhash; extern crate gfx; extern crate gfx_traits; -#[macro_use] extern crate html5ever; +#[macro_use] +extern crate html5ever; extern crate ipc_channel; extern crate libc; #[macro_use] @@ -30,7 +31,8 @@ extern crate range; extern crate rayon; extern crate script_layout_interface; extern crate script_traits; -#[macro_use] extern crate serde; +#[macro_use] +extern crate serde; extern crate serde_json; extern crate servo_arc; extern crate servo_atoms; diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs index a658aebb3e9..72e87578635 100644 --- a/components/layout/list_item.rs +++ b/components/layout/list_item.rs @@ -40,10 +40,11 @@ pub struct ListItemFlow { } impl ListItemFlow { - pub fn from_fragments_and_flotation(main_fragment: Fragment, - marker_fragments: Vec<Fragment>, - flotation: Option<FloatKind>) - -> ListItemFlow { + pub fn from_fragments_and_flotation( + main_fragment: Fragment, + marker_fragments: Vec<Fragment>, + flotation: Option<FloatKind>, + ) -> ListItemFlow { let mut this = ListItemFlow { block_flow: BlockFlow::from_fragment_and_float_kind(main_fragment, flotation), marker_fragments: marker_fragments, @@ -56,8 +57,12 @@ impl ListItemFlow { ListStyleType::Circle | ListStyleType::Square | ListStyleType::DisclosureOpen | - ListStyleType::DisclosureClosed => {} - _ => this.block_flow.base.restyle_damage.insert(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT), + ListStyleType::DisclosureClosed => {}, + _ => this + .block_flow + .base + .restyle_damage + .insert(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT), } } @@ -77,20 +82,29 @@ impl ListItemFlow { let available_rect = base.floats.available_rect( -base.position.size.block, base.position.size.block, - base.block_container_inline_size); - let mut marker_inline_start = available_rect.unwrap_or(self.block_flow.fragment.border_box).start.i; + base.block_container_inline_size, + ); + let mut marker_inline_start = available_rect + .unwrap_or(self.block_flow.fragment.border_box) + .start + .i; for marker in self.marker_fragments.iter_mut().rev() { - let container_block_size = - self.block_flow.explicit_block_containing_size(layout_context.shared_context()); - marker.assign_replaced_inline_size_if_necessary(base.block_container_inline_size, container_block_size); + let container_block_size = self + .block_flow + .explicit_block_containing_size(layout_context.shared_context()); + marker.assign_replaced_inline_size_if_necessary( + base.block_container_inline_size, + container_block_size, + ); // Do this now. There's no need to do this in bubble-widths, since markers do not // contribute to the inline size of this flow. let intrinsic_inline_sizes = marker.compute_intrinsic_inline_sizes(); - marker.border_box.size.inline = - intrinsic_inline_sizes.content_intrinsic_sizes.preferred_inline_size; + marker.border_box.size.inline = intrinsic_inline_sizes + .content_intrinsic_sizes + .preferred_inline_size; marker_inline_start = marker_inline_start - marker.border_box.size.inline; marker.border_box.start.i = marker_inline_start; } @@ -99,18 +113,22 @@ impl ListItemFlow { fn assign_marker_block_sizes(&mut self, layout_context: &LayoutContext) { // FIXME(pcwalton): Do this during flow construction, like `InlineFlow` does? let marker_line_metrics = with_thread_local_font_context(layout_context, |font_context| { - InlineFlow::minimum_line_metrics_for_fragments(&self.marker_fragments, - font_context, - &*self.block_flow.fragment.style) + InlineFlow::minimum_line_metrics_for_fragments( + &self.marker_fragments, + font_context, + &*self.block_flow.fragment.style, + ) }); for marker in &mut self.marker_fragments { marker.assign_replaced_block_size_if_necessary(); - let marker_inline_metrics = marker.aligned_inline_metrics(layout_context, - &marker_line_metrics, - Some(&marker_line_metrics)); - marker.border_box.start.b = marker_line_metrics.space_above_baseline - - marker_inline_metrics.ascent; + let marker_inline_metrics = marker.aligned_inline_metrics( + layout_context, + &marker_line_metrics, + Some(&marker_line_metrics), + ); + marker.border_box.start.b = + marker_line_metrics.space_above_baseline - marker_inline_metrics.ascent; } } } @@ -144,7 +162,8 @@ impl Flow for ListItemFlow { } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context) + self.block_flow + .compute_stacking_relative_position(layout_context) } fn place_float_if_applicable<'a>(&mut self) { @@ -160,11 +179,13 @@ impl Flow for ListItemFlow { } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn build_display_list(&mut self, state: &mut DisplayListBuildState) { @@ -181,9 +202,17 @@ impl Flow for ListItemFlow { fn compute_overflow(&self) -> Overflow { let mut overflow = self.block_flow.compute_overflow(); - let flow_size = self.block_flow.base.position.size.to_physical(self.block_flow.base.writing_mode); - let relative_containing_block_size = - &self.block_flow.base.early_absolute_position_info.relative_containing_block_size; + let flow_size = self + .block_flow + .base + .position + .size + .to_physical(self.block_flow.base.writing_mode); + let relative_containing_block_size = &self + .block_flow + .base + .early_absolute_position_info + .relative_containing_block_size; for fragment in &self.marker_fragments { overflow.union(&fragment.compute_overflow(&flow_size, &relative_containing_block_size)) @@ -200,32 +229,38 @@ impl Flow for ListItemFlow { self.block_flow.positioning() } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, - level, - stacking_context_position); + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ); for marker in &self.marker_fragments { if iterator.should_process(marker) { iterator.process( marker, level, - &marker.stacking_relative_border_box(&self.block_flow - .base - .stacking_relative_position, - &self.block_flow - .base - .early_absolute_position_info - .relative_containing_block_size, - self.block_flow - .base - .early_absolute_position_info - .relative_containing_block_mode, - CoordinateSystem::Own) - .translate(&stacking_context_position.to_vector())); + &marker + .stacking_relative_border_box( + &self.block_flow.base.stacking_relative_position, + &self + .block_flow + .base + .early_absolute_position_info + .relative_containing_block_size, + self.block_flow + .base + .early_absolute_position_info + .relative_containing_block_mode, + CoordinateSystem::Own, + ).translate(&stacking_context_position.to_vector()), + ); } } } @@ -260,7 +295,7 @@ impl ListStyleTypeContent { ListStyleType::DisclosureClosed => { let text = generated_content::static_representation(list_style_type); ListStyleTypeContent::StaticText(text) - } + }, _ => ListStyleTypeContent::GeneratedContent(Box::new(GeneratedContentInfo::ListItem)), } } diff --git a/components/layout/model.rs b/components/layout/model.rs index 5d5238ece77..50959398f27 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -126,21 +126,22 @@ impl MarginCollapseInfo { } } - pub fn finish_and_compute_collapsible_margins(mut self, - fragment: &Fragment, - containing_block_size: Option<Au>, - can_collapse_block_end_margin_with_kids: bool, - mut may_collapse_through: bool) - -> (CollapsibleMargins, Au) { + pub fn finish_and_compute_collapsible_margins( + mut self, + fragment: &Fragment, + containing_block_size: Option<Au>, + can_collapse_block_end_margin_with_kids: bool, + mut may_collapse_through: bool, + ) -> (CollapsibleMargins, Au) { let state = match self.state { MarginCollapseState::AccumulatingCollapsibleTopMargin => { - may_collapse_through = may_collapse_through && - match fragment.style().content_block_size() { + may_collapse_through = + may_collapse_through && match fragment.style().content_block_size() { LengthOrPercentageOrAuto::Auto => true, LengthOrPercentageOrAuto::Length(l) => l.px() == 0., LengthOrPercentageOrAuto::Percentage(v) => { v.0 == 0. || containing_block_size.is_none() - } + }, LengthOrPercentageOrAuto::Calc(_) => false, }; @@ -156,14 +157,14 @@ impl MarginCollapseInfo { // If the fragment has non-zero min-block-size, margins may not // collapse through it. FinalMarginState::BottomMarginCollapses - } + }, } } else { // If the fragment has an explicitly specified block-size, margins may not // collapse through it. FinalMarginState::BottomMarginCollapses } - } + }, MarginCollapseState::AccumulatingMarginIn => FinalMarginState::BottomMarginCollapses, }; @@ -174,27 +175,41 @@ impl MarginCollapseInfo { match state { FinalMarginState::MarginsCollapseThrough => { let advance = self.block_start_margin.collapse(); - self.margin_in.union(AdjoiningMargins::from_margin(block_end_margin)); - (CollapsibleMargins::Collapse(self.block_start_margin, self.margin_in), - advance) - } + self.margin_in + .union(AdjoiningMargins::from_margin(block_end_margin)); + ( + CollapsibleMargins::Collapse(self.block_start_margin, self.margin_in), + advance, + ) + }, FinalMarginState::BottomMarginCollapses => { let advance = self.margin_in.collapse(); - self.margin_in.union(AdjoiningMargins::from_margin(block_end_margin)); - (CollapsibleMargins::Collapse(self.block_start_margin, self.margin_in), - advance) - } + self.margin_in + .union(AdjoiningMargins::from_margin(block_end_margin)); + ( + CollapsibleMargins::Collapse(self.block_start_margin, self.margin_in), + advance, + ) + }, } } else { match state { FinalMarginState::MarginsCollapseThrough => { - self.block_start_margin.union(AdjoiningMargins::from_margin(block_end_margin)); - (CollapsibleMargins::CollapseThrough(self.block_start_margin), Au(0)) - } + self.block_start_margin + .union(AdjoiningMargins::from_margin(block_end_margin)); + ( + CollapsibleMargins::CollapseThrough(self.block_start_margin), + Au(0), + ) + }, FinalMarginState::BottomMarginCollapses => { - self.margin_in.union(AdjoiningMargins::from_margin(block_end_margin)); - (CollapsibleMargins::Collapse(self.block_start_margin, self.margin_in), Au(0)) - } + self.margin_in + .union(AdjoiningMargins::from_margin(block_end_margin)); + ( + CollapsibleMargins::Collapse(self.block_start_margin, self.margin_in), + Au(0), + ) + }, } } } @@ -206,7 +221,7 @@ impl MarginCollapseInfo { // needs to be positioned relative to our *border box*, not our margin box. See // `tests/ref/float_under_top_margin_a.html`. Au(0) - } + }, MarginCollapseState::AccumulatingMarginIn => self.margin_in.collapse(), } } @@ -214,78 +229,99 @@ impl MarginCollapseInfo { /// Adds the child's potentially collapsible block-start margin to the current margin state and /// advances the Y offset by the appropriate amount to handle that margin. Returns the amount /// that should be added to the Y offset during block layout. - pub fn advance_block_start_margin(&mut self, - child_collapsible_margins: &CollapsibleMargins, - can_collapse_block_start_margin: bool) - -> Au { + pub fn advance_block_start_margin( + &mut self, + child_collapsible_margins: &CollapsibleMargins, + can_collapse_block_start_margin: bool, + ) -> Au { if !can_collapse_block_start_margin { self.state = MarginCollapseState::AccumulatingMarginIn } match (self.state, *child_collapsible_margins) { - (MarginCollapseState::AccumulatingCollapsibleTopMargin, - CollapsibleMargins::None(block_start, _)) => { + ( + MarginCollapseState::AccumulatingCollapsibleTopMargin, + CollapsibleMargins::None(block_start, _), + ) => { self.state = MarginCollapseState::AccumulatingMarginIn; block_start - } - (MarginCollapseState::AccumulatingCollapsibleTopMargin, - CollapsibleMargins::Collapse(block_start, _)) => { + }, + ( + MarginCollapseState::AccumulatingCollapsibleTopMargin, + CollapsibleMargins::Collapse(block_start, _), + ) => { self.block_start_margin.union(block_start); self.state = MarginCollapseState::AccumulatingMarginIn; Au(0) - } - (MarginCollapseState::AccumulatingMarginIn, - CollapsibleMargins::None(block_start, _)) => { + }, + ( + MarginCollapseState::AccumulatingMarginIn, + CollapsibleMargins::None(block_start, _), + ) => { let previous_margin_value = self.margin_in.collapse(); self.margin_in = AdjoiningMargins::new(); previous_margin_value + block_start - } - (MarginCollapseState::AccumulatingMarginIn, - CollapsibleMargins::Collapse(block_start, _)) => { + }, + ( + MarginCollapseState::AccumulatingMarginIn, + CollapsibleMargins::Collapse(block_start, _), + ) => { self.margin_in.union(block_start); let margin_value = self.margin_in.collapse(); self.margin_in = AdjoiningMargins::new(); margin_value - } + }, (_, CollapsibleMargins::CollapseThrough(_)) => { // For now, we ignore this; this will be handled by `advance_block_end_margin` // below. Au(0) - } + }, } } /// Adds the child's potentially collapsible block-end margin to the current margin state and /// advances the Y offset by the appropriate amount to handle that margin. Returns the amount /// that should be added to the Y offset during block layout. - pub fn advance_block_end_margin(&mut self, child_collapsible_margins: &CollapsibleMargins) - -> Au { + pub fn advance_block_end_margin( + &mut self, + child_collapsible_margins: &CollapsibleMargins, + ) -> Au { match (self.state, *child_collapsible_margins) { - (MarginCollapseState::AccumulatingCollapsibleTopMargin, CollapsibleMargins::None(..)) | - (MarginCollapseState::AccumulatingCollapsibleTopMargin, - CollapsibleMargins::Collapse(..)) => { + ( + MarginCollapseState::AccumulatingCollapsibleTopMargin, + CollapsibleMargins::None(..), + ) | + ( + MarginCollapseState::AccumulatingCollapsibleTopMargin, + CollapsibleMargins::Collapse(..), + ) => { // Can't happen because the state will have been replaced with // `MarginCollapseState::AccumulatingMarginIn` above. panic!("should not be accumulating collapsible block_start margins anymore!") - } - (MarginCollapseState::AccumulatingCollapsibleTopMargin, - CollapsibleMargins::CollapseThrough(margin)) => { + }, + ( + MarginCollapseState::AccumulatingCollapsibleTopMargin, + CollapsibleMargins::CollapseThrough(margin), + ) => { self.block_start_margin.union(margin); Au(0) - } - (MarginCollapseState::AccumulatingMarginIn, - CollapsibleMargins::None(_, block_end)) => { + }, + (MarginCollapseState::AccumulatingMarginIn, CollapsibleMargins::None(_, block_end)) => { assert_eq!(self.margin_in.most_positive, Au(0)); assert_eq!(self.margin_in.most_negative, Au(0)); block_end - } - (MarginCollapseState::AccumulatingMarginIn, - CollapsibleMargins::Collapse(_, block_end)) | - (MarginCollapseState::AccumulatingMarginIn, - CollapsibleMargins::CollapseThrough(block_end)) => { + }, + ( + MarginCollapseState::AccumulatingMarginIn, + CollapsibleMargins::Collapse(_, block_end), + ) | + ( + MarginCollapseState::AccumulatingMarginIn, + CollapsibleMargins::CollapseThrough(block_end), + ) => { self.margin_in.union(block_end); Au(0) - } + }, } } } @@ -309,7 +345,11 @@ pub struct IntrinsicISizes { impl fmt::Debug for IntrinsicISizes { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "min={:?}, pref={:?}", self.minimum_inline_size, self.preferred_inline_size) + write!( + f, + "min={:?}, pref={:?}", + self.minimum_inline_size, self.preferred_inline_size + ) } } @@ -345,9 +385,9 @@ impl IntrinsicISizesContribution { pub fn finish(self) -> IntrinsicISizes { IntrinsicISizes { minimum_inline_size: self.content_intrinsic_sizes.minimum_inline_size + - self.surrounding_size, + self.surrounding_size, preferred_inline_size: self.content_intrinsic_sizes.preferred_inline_size + - self.surrounding_size, + self.surrounding_size, } } @@ -358,8 +398,10 @@ impl IntrinsicISizesContribution { /// FIXME(pcwalton): This is incorrect when the inline fragment contains forced line breaks /// (e.g. `<br>` or `white-space: pre`). pub fn union_inline(&mut self, sizes: &IntrinsicISizes) { - self.content_intrinsic_sizes.minimum_inline_size = - max(self.content_intrinsic_sizes.minimum_inline_size, sizes.minimum_inline_size); + self.content_intrinsic_sizes.minimum_inline_size = max( + 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 } @@ -382,10 +424,14 @@ impl IntrinsicISizesContribution { /// /// This is used when contributing the intrinsic sizes for individual fragments. pub fn union_block(&mut self, sizes: &IntrinsicISizes) { - self.content_intrinsic_sizes.minimum_inline_size = - max(self.content_intrinsic_sizes.minimum_inline_size, sizes.minimum_inline_size); - self.content_intrinsic_sizes.preferred_inline_size = - max(self.content_intrinsic_sizes.preferred_inline_size, sizes.preferred_inline_size) + self.content_intrinsic_sizes.minimum_inline_size = max( + self.content_intrinsic_sizes.minimum_inline_size, + sizes.minimum_inline_size, + ); + self.content_intrinsic_sizes.preferred_inline_size = max( + self.content_intrinsic_sizes.preferred_inline_size, + sizes.preferred_inline_size, + ) } } @@ -398,17 +444,16 @@ pub enum MaybeAuto { impl MaybeAuto { #[inline] - pub fn from_style(length: LengthOrPercentageOrAuto, containing_length: Au) - -> MaybeAuto { + pub fn from_style(length: LengthOrPercentageOrAuto, containing_length: Au) -> MaybeAuto { match length { LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto, LengthOrPercentageOrAuto::Percentage(percent) => { MaybeAuto::Specified(containing_length.scale_by(percent.0)) - } + }, LengthOrPercentageOrAuto::Calc(calc) => { MaybeAuto::from_option(calc.to_used_value(Some(containing_length))) - } - LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(Au::from(length)) + }, + LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(Au::from(length)), } } @@ -442,7 +487,10 @@ impl MaybeAuto { } #[inline] - pub fn map<F>(&self, mapper: F) -> MaybeAuto where F: FnOnce(Au) -> Au { + pub fn map<F>(&self, mapper: F) -> MaybeAuto + where + F: FnOnce(Au) -> Au, + { match *self { MaybeAuto::Auto => MaybeAuto::Auto, MaybeAuto::Specified(value) => MaybeAuto::Specified(mapper(value)), @@ -453,15 +501,17 @@ impl MaybeAuto { /// Receive an optional container size and return used value for width or height. /// /// `style_length`: content size as given in the CSS. -pub fn style_length(style_length: LengthOrPercentageOrAuto, - container_size: Option<Au>) -> MaybeAuto { +pub fn style_length( + style_length: LengthOrPercentageOrAuto, + container_size: Option<Au>, +) -> MaybeAuto { match container_size { Some(length) => MaybeAuto::from_style(style_length, length), None => if let LengthOrPercentageOrAuto::Length(length) = style_length { MaybeAuto::Specified(Au::from(length)) } else { MaybeAuto::Auto - } + }, } } @@ -475,25 +525,37 @@ pub fn style_length(style_length: LengthOrPercentageOrAuto, /// [1]: https://drafts.csswg.org/css-backgrounds-3/#border-radius pub fn specified_border_radius( radius: BorderCornerRadius, - containing_size: Size2D<Au>) - -> Size2D<Au> -{ + containing_size: Size2D<Au>, +) -> Size2D<Au> { let w = radius.0.width().to_used_value(containing_size.width); let h = radius.0.height().to_used_value(containing_size.height); Size2D::new(w, h) } #[inline] -pub fn padding_from_style(style: &ComputedValues, - containing_block_inline_size: Au, - writing_mode: WritingMode) - -> LogicalMargin<Au> { +pub fn padding_from_style( + style: &ComputedValues, + containing_block_inline_size: Au, + writing_mode: WritingMode, +) -> LogicalMargin<Au> { let padding_style = style.get_padding(); - LogicalMargin::from_physical(writing_mode, SideOffsets2D::new( - padding_style.padding_top.to_used_value(containing_block_inline_size), - padding_style.padding_right.to_used_value(containing_block_inline_size), - padding_style.padding_bottom.to_used_value(containing_block_inline_size), - padding_style.padding_left.to_used_value(containing_block_inline_size))) + LogicalMargin::from_physical( + writing_mode, + SideOffsets2D::new( + padding_style + .padding_top + .to_used_value(containing_block_inline_size), + padding_style + .padding_right + .to_used_value(containing_block_inline_size), + padding_style + .padding_bottom + .to_used_value(containing_block_inline_size), + padding_style + .padding_left + .to_used_value(containing_block_inline_size), + ), + ) } /// Returns the explicitly-specified margin lengths from the given style. Percentage and auto @@ -501,14 +563,20 @@ pub fn padding_from_style(style: &ComputedValues, /// /// This is used when calculating intrinsic inline sizes. #[inline] -pub fn specified_margin_from_style(style: &ComputedValues, - writing_mode: WritingMode) -> LogicalMargin<Au> { +pub fn specified_margin_from_style( + style: &ComputedValues, + writing_mode: WritingMode, +) -> LogicalMargin<Au> { let margin_style = style.get_margin(); - LogicalMargin::from_physical(writing_mode, SideOffsets2D::new( - MaybeAuto::from_style(margin_style.margin_top, Au(0)).specified_or_zero(), - MaybeAuto::from_style(margin_style.margin_right, Au(0)).specified_or_zero(), - MaybeAuto::from_style(margin_style.margin_bottom, Au(0)).specified_or_zero(), - MaybeAuto::from_style(margin_style.margin_left, Au(0)).specified_or_zero())) + LogicalMargin::from_physical( + writing_mode, + SideOffsets2D::new( + MaybeAuto::from_style(margin_style.margin_top, Au(0)).specified_or_zero(), + MaybeAuto::from_style(margin_style.margin_right, Au(0)).specified_or_zero(), + MaybeAuto::from_style(margin_style.margin_bottom, Au(0)).specified_or_zero(), + MaybeAuto::from_style(margin_style.margin_left, Au(0)).specified_or_zero(), + ), + ) } /// A min-size and max-size constraint. The constructor has a optional `border` @@ -523,17 +591,19 @@ pub struct SizeConstraint { impl SizeConstraint { /// Create a `SizeConstraint` for an axis. - pub fn new(container_size: Option<Au>, - min_size: LengthOrPercentage, - max_size: LengthOrPercentageOrNone, - border: Option<Au>) -> SizeConstraint { + pub fn new( + container_size: Option<Au>, + min_size: LengthOrPercentage, + max_size: LengthOrPercentageOrNone, + border: Option<Au>, + ) -> SizeConstraint { let mut min_size = match container_size { Some(container_size) => min_size.to_used_value(container_size), None => if let LengthOrPercentage::Length(length) = min_size { Au::from(length) } else { Au(0) - } + }, }; let mut max_size = match container_size { @@ -542,7 +612,7 @@ impl SizeConstraint { Some(Au::from(length)) } else { None - } + }, }; // Make sure max size is not smaller than min size. max_size = max_size.map(|x| max(x, min_size)); @@ -554,7 +624,7 @@ impl SizeConstraint { SizeConstraint { min_size: min_size, - max_size: max_size + max_size: max_size, } } @@ -565,7 +635,7 @@ impl SizeConstraint { } else { match self.max_size { Some(max_size) if max_size < other => max_size, - _ => other + _ => other, } } } diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 487a878c08b..082fa1a1367 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -85,7 +85,10 @@ impl Flow for MulticolFlow { } fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - debug!("assign_inline_sizes({}): assigning inline_size for flow", "multicol"); + debug!( + "assign_inline_sizes({}): assigning inline_size for flow", + "multicol" + ); let shared_context = layout_context.shared_context(); self.block_flow.compute_inline_sizes(shared_context); @@ -94,8 +97,7 @@ impl Flow for MulticolFlow { self.block_flow.fragment.border_padding.inline_start; // Distance from the inline-end margin edge to the inline-end content edge. - let inline_end_content_edge = - self.block_flow.fragment.margin.inline_end + + let inline_end_content_edge = self.block_flow.fragment.margin.inline_end + self.block_flow.fragment.border_padding.inline_end; self.block_flow.assign_inline_sizes(layout_context); @@ -107,15 +109,19 @@ impl Flow for MulticolFlow { let style = &self.block_flow.fragment.style; let column_gap = match style.get_position().column_gap { Either::First(len) => len.0.to_pixel_length(content_inline_size).into(), - Either::Second(_normal) => self.block_flow.fragment.style.get_font().font_size.size(), + Either::Second(_normal) => { + self.block_flow.fragment.style.get_font().font_size.size() + }, }; let column_style = style.get_column(); let mut column_count; if let Either::First(column_width) = column_style.column_width { let column_width = Au::from(column_width); - column_count = - max(1, (content_inline_size + column_gap).0 / (column_width + column_gap).0); + column_count = max( + 1, + (content_inline_size + column_gap).0 / (column_width + column_gap).0, + ); if let ColumnCount::Integer(specified_column_count) = column_style.column_count { column_count = min(column_count, specified_column_count.0 as i32); } @@ -125,16 +131,22 @@ impl Flow for MulticolFlow { _ => unreachable!(), } } - column_width = - max(Au(0), (content_inline_size + column_gap) / column_count - column_gap); + column_width = max( + Au(0), + (content_inline_size + column_gap) / column_count - column_gap, + ); self.column_pitch = column_width + column_gap; } self.block_flow.fragment.border_box.size.inline = content_inline_size + padding_and_borders; self.block_flow.propagate_assigned_inline_size_to_children( - shared_context, inline_start_content_edge, inline_end_content_edge, column_width, - |_, _, _, _, _, _| {}); + shared_context, + inline_start_content_edge, + inline_end_content_edge, + column_width, + |_, _, _, _, _, _| {}, + ); } fn assign_block_size(&mut self, ctx: &LayoutContext) { @@ -156,7 +168,7 @@ impl Flow for MulticolFlow { ctx.shared_context().viewport_size(), ).block } - } + }, }); // Before layout, everything is in a single "column" @@ -167,17 +179,20 @@ impl Flow for MulticolFlow { self.block_flow.assign_block_size(ctx); loop { - let remaining = Arc::get_mut(&mut column).unwrap().fragment(ctx, fragmentation_context); + let remaining = Arc::get_mut(&mut column) + .unwrap() + .fragment(ctx, fragmentation_context); self.block_flow.base.children.push_back_arc(column); column = match remaining { Some(remaining) => remaining, - None => break + None => break, }; } } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context); + self.block_flow + .compute_stacking_relative_position(layout_context); let pitch = LogicalSize::new(self.block_flow.base.writing_mode, self.column_pitch, Au(0)); let pitch = pitch.to_physical(self.block_flow.base.writing_mode); for (i, child) in self.block_flow.base.children.iter_mut().enumerate() { @@ -187,11 +202,13 @@ impl Flow for MulticolFlow { } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn build_display_list(&mut self, state: &mut DisplayListBuildState) { @@ -223,11 +240,17 @@ impl Flow for MulticolFlow { self.block_flow.generated_containing_block_size(flow) } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position); + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ); } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { @@ -257,7 +280,10 @@ impl Flow for MulticolColumnFlow { } fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - debug!("assign_inline_sizes({}): assigning inline_size for flow", "multicol column"); + debug!( + "assign_inline_sizes({}): assigning inline_size for flow", + "multicol column" + ); self.block_flow.assign_inline_sizes(layout_context); } @@ -266,22 +292,27 @@ impl Flow for MulticolColumnFlow { self.block_flow.assign_block_size(ctx); } - fn fragment(&mut self, layout_context: &LayoutContext, - fragmentation_context: Option<FragmentationContext>) - -> Option<Arc<Flow>> { + fn fragment( + &mut self, + layout_context: &LayoutContext, + fragmentation_context: Option<FragmentationContext>, + ) -> Option<Arc<Flow>> { Flow::fragment(&mut self.block_flow, layout_context, fragmentation_context) } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context) + self.block_flow + .compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn build_display_list(&mut self, state: &mut DisplayListBuildState) { @@ -313,11 +344,17 @@ impl Flow for MulticolColumnFlow { self.block_flow.generated_containing_block_size(flow) } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position); + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ); } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { diff --git a/components/layout/parallel.rs b/components/layout/parallel.rs index b555a9f51dc..d8f46a0f83c 100644 --- a/components/layout/parallel.rs +++ b/components/layout/parallel.rs @@ -70,56 +70,57 @@ impl FlowParallelInfo { /// /// The only communication between siblings is that they both /// fetch-and-subtract the parent's children count. -fn bottom_up_flow(mut unsafe_flow: UnsafeFlow, - assign_bsize_traversal: &AssignBSizes) { +fn bottom_up_flow(mut unsafe_flow: UnsafeFlow, assign_bsize_traversal: &AssignBSizes) { loop { // Get a real flow. - let flow: &mut Flow = unsafe { - mem::transmute(unsafe_flow) - }; + let flow: &mut Flow = unsafe { mem::transmute(unsafe_flow) }; // Perform the appropriate traversal. if assign_bsize_traversal.should_process(flow) { assign_bsize_traversal.process(flow); } - let base = flow.mut_base(); // Reset the count of children for the next layout traversal. - base.parallel.children_count.store(base.children.len() as isize, - Ordering::Relaxed); + base.parallel + .children_count + .store(base.children.len() as isize, Ordering::Relaxed); // Possibly enqueue the parent. let unsafe_parent = base.parallel.parent; if unsafe_parent == null_unsafe_flow() { // We're done! - break + break; } // No, we're not at the root yet. Then are we the last child // of our parent to finish processing? If so, we can continue // on with our parent; otherwise, we've gotta wait. - let parent: &mut Flow = unsafe { - &mut *(unsafe_parent.0 as *mut Flow) - }; + let parent: &mut Flow = unsafe { &mut *(unsafe_parent.0 as *mut Flow) }; let parent_base = parent.mut_base(); - if parent_base.parallel.children_count.fetch_sub(1, Ordering::Relaxed) == 1 { + if parent_base + .parallel + .children_count + .fetch_sub(1, Ordering::Relaxed) == + 1 + { // We were the last child of our parent. Reflow our parent. unsafe_flow = unsafe_parent } else { // Stop. - break + break; } } } -fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow], - pool: &'scope rayon::ThreadPool, - scope: &rayon::Scope<'scope>, - assign_isize_traversal: &'scope AssignISizes, - assign_bsize_traversal: &'scope AssignBSizes) -{ +fn top_down_flow<'scope>( + unsafe_flows: &[UnsafeFlow], + pool: &'scope rayon::ThreadPool, + scope: &rayon::Scope<'scope>, + assign_isize_traversal: &'scope AssignISizes, + assign_bsize_traversal: &'scope AssignBSizes, +) { let mut discovered_child_flows = FlowList::new(); for unsafe_flow in unsafe_flows { @@ -127,8 +128,7 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow], unsafe { // Get a real flow. let flow: &mut Flow = mem::transmute(*unsafe_flow); - flow.mut_base().thread_id = - pool.current_thread_index().unwrap() as u8; + flow.mut_base().thread_id = pool.current_thread_index().unwrap() as u8; if assign_isize_traversal.should_process(flow) { // Perform the appropriate traversal. @@ -149,16 +149,18 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow], } if discovered_child_flows.is_empty() { - return + return; } if discovered_child_flows.len() <= CHUNK_SIZE { // We can handle all the children in this work unit. - top_down_flow(&discovered_child_flows, - pool, - scope, - &assign_isize_traversal, - &assign_bsize_traversal); + top_down_flow( + &discovered_child_flows, + pool, + scope, + &assign_isize_traversal, + &assign_bsize_traversal, + ); } else { // Spawn a new work unit for each chunk after the first. let mut chunks = discovered_child_flows.chunks(CHUNK_SIZE); @@ -166,37 +168,66 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow], for chunk in chunks { let nodes = chunk.iter().cloned().collect::<FlowList>(); scope.spawn(move |scope| { - top_down_flow(&nodes, pool, scope, &assign_isize_traversal, &assign_bsize_traversal); + top_down_flow( + &nodes, + pool, + scope, + &assign_isize_traversal, + &assign_bsize_traversal, + ); }); } if let Some(chunk) = first_chunk { - top_down_flow(chunk, pool, scope, &assign_isize_traversal, &assign_bsize_traversal); + top_down_flow( + chunk, + pool, + scope, + &assign_isize_traversal, + &assign_bsize_traversal, + ); } } } /// Run the main layout passes in parallel. pub fn reflow( - root: &mut Flow, - profiler_metadata: Option<TimerMetadata>, - time_profiler_chan: time::ProfilerChan, - context: &LayoutContext, - queue: &rayon::ThreadPool) { + root: &mut Flow, + profiler_metadata: Option<TimerMetadata>, + time_profiler_chan: time::ProfilerChan, + context: &LayoutContext, + queue: &rayon::ThreadPool, +) { if opts::get().bubble_inline_sizes_separately { - let bubble_inline_sizes = BubbleISizes { layout_context: &context }; + let bubble_inline_sizes = BubbleISizes { + layout_context: &context, + }; bubble_inline_sizes.traverse(root); } - let assign_isize_traversal = &AssignISizes { layout_context: &context }; - let assign_bsize_traversal = &AssignBSizes { layout_context: &context }; + let assign_isize_traversal = &AssignISizes { + layout_context: &context, + }; + let assign_bsize_traversal = &AssignBSizes { + layout_context: &context, + }; let nodes = [UnsafeFlow(root)]; queue.install(move || { rayon::scope(move |scope| { - profile(time::ProfilerCategory::LayoutParallelWarmup, - profiler_metadata, time_profiler_chan, move || { - top_down_flow(&nodes, queue, scope, assign_isize_traversal, assign_bsize_traversal); - }); + profile( + time::ProfilerCategory::LayoutParallelWarmup, + profiler_metadata, + time_profiler_chan, + move || { + top_down_flow( + &nodes, + queue, + scope, + assign_isize_traversal, + assign_bsize_traversal, + ); + }, + ); }); }); } diff --git a/components/layout/persistent_list.rs b/components/layout/persistent_list.rs index 8de9daa2ed4..0a8337bfaa7 100644 --- a/components/layout/persistent_list.rs +++ b/components/layout/persistent_list.rs @@ -18,7 +18,10 @@ struct PersistentListEntry<T> { type PersistentListLink<T> = Option<Arc<PersistentListEntry<T>>>; -impl<T> PersistentList<T> where T: Send + Sync { +impl<T> PersistentList<T> +where + T: Send + Sync, +{ #[inline] pub fn new() -> PersistentList<T> { PersistentList { @@ -58,7 +61,10 @@ impl<T> PersistentList<T> where T: Send + Sync { } } -impl<T> Clone for PersistentList<T> where T: Send + Sync { +impl<T> Clone for PersistentList<T> +where + T: Send + Sync, +{ fn clone(&self) -> PersistentList<T> { // This establishes the persistent nature of this list: we can clone a list by just cloning // its head. @@ -69,11 +75,17 @@ impl<T> Clone for PersistentList<T> where T: Send + Sync { } } -pub struct PersistentListIterator<'a, T> where T: 'a + Send + Sync { +pub struct PersistentListIterator<'a, T> +where + T: 'a + Send + Sync, +{ entry: Option<&'a PersistentListEntry<T>>, } -impl<'a, T> Iterator for PersistentListIterator<'a, T> where T: Send + Sync + 'static { +impl<'a, T> Iterator for PersistentListIterator<'a, T> +where + T: Send + Sync + 'static, +{ type Item = &'a T; #[inline] diff --git a/components/layout/query.rs b/components/layout/query.rs index 408e220dfe4..f43ff0d6166 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -94,13 +94,24 @@ pub struct LayoutRPCImpl(pub Arc<Mutex<LayoutThreadData>>); // https://drafts.csswg.org/cssom-view/#overflow-directions fn overflow_direction(writing_mode: &WritingMode) -> OverflowDirection { - match (writing_mode.block_flow_direction(), writing_mode.inline_base_direction()) { + match ( + writing_mode.block_flow_direction(), + writing_mode.inline_base_direction(), + ) { (BlockFlowDirection::TopToBottom, InlineBaseDirection::LeftToRight) | - (BlockFlowDirection::LeftToRight, InlineBaseDirection::LeftToRight) => OverflowDirection::RightAndDown, + (BlockFlowDirection::LeftToRight, InlineBaseDirection::LeftToRight) => { + OverflowDirection::RightAndDown + }, (BlockFlowDirection::TopToBottom, InlineBaseDirection::RightToLeft) | - (BlockFlowDirection::RightToLeft, InlineBaseDirection::LeftToRight) => OverflowDirection::LeftAndDown, - (BlockFlowDirection::RightToLeft, InlineBaseDirection::RightToLeft) => OverflowDirection::LeftAndUp, - (BlockFlowDirection::LeftToRight, InlineBaseDirection::RightToLeft) => OverflowDirection::RightAndUp + (BlockFlowDirection::RightToLeft, InlineBaseDirection::LeftToRight) => { + OverflowDirection::LeftAndDown + }, + (BlockFlowDirection::RightToLeft, InlineBaseDirection::RightToLeft) => { + OverflowDirection::LeftAndUp + }, + (BlockFlowDirection::LeftToRight, InlineBaseDirection::RightToLeft) => { + OverflowDirection::RightAndUp + }, } } @@ -130,20 +141,24 @@ impl LayoutRPC for LayoutRPCImpl { let &LayoutRPCImpl(ref rw_data) = self; let rw_data = rw_data.lock().unwrap(); NodeGeometryResponse { - client_rect: rw_data.client_rect_response + client_rect: rw_data.client_rect_response, } } fn node_scroll_area(&self) -> NodeGeometryResponse { NodeGeometryResponse { - client_rect: self.0.lock().unwrap().scroll_area_response + client_rect: self.0.lock().unwrap().scroll_area_response, } } fn node_scroll_id(&self) -> NodeScrollIdResponse { - NodeScrollIdResponse(self.0.lock() - .unwrap().scroll_id_response - .expect("scroll id is not correctly fetched")) + NodeScrollIdResponse( + self.0 + .lock() + .unwrap() + .scroll_id_response + .expect("scroll id is not correctly fetched"), + ) } /// Retrieves the resolved value for a CSS style property. @@ -187,7 +202,7 @@ impl UnioningFragmentBorderBoxIterator { fn new(node_address: OpaqueNode) -> UnioningFragmentBorderBoxIterator { UnioningFragmentBorderBoxIterator { node_address: node_address, - rect: None + rect: None, } } } @@ -195,12 +210,8 @@ impl UnioningFragmentBorderBoxIterator { impl FragmentBorderBoxIterator for UnioningFragmentBorderBoxIterator { fn process(&mut self, _: &Fragment, _: i32, border_box: &Rect<Au>) { self.rect = match self.rect { - Some(rect) => { - Some(rect.union(border_box)) - } - None => { - Some(*border_box) - } + Some(rect) => Some(rect.union(border_box)), + None => Some(*border_box), }; } @@ -237,12 +248,12 @@ enum Side { Left, Right, Bottom, - Top + Top, } enum MarginPadding { Margin, - Padding + Padding, } enum PositionProperty { @@ -270,9 +281,11 @@ struct PositionRetrievingFragmentBorderBoxIterator { } impl PositionRetrievingFragmentBorderBoxIterator { - fn new(node_address: OpaqueNode, - property: PositionProperty, - position: Point2D<Au>) -> PositionRetrievingFragmentBorderBoxIterator { + fn new( + node_address: OpaqueNode, + property: PositionProperty, + position: Point2D<Au>, + ) -> PositionRetrievingFragmentBorderBoxIterator { PositionRetrievingFragmentBorderBoxIterator { node_address: node_address, position: position, @@ -284,18 +297,19 @@ impl PositionRetrievingFragmentBorderBoxIterator { impl FragmentBorderBoxIterator for PositionRetrievingFragmentBorderBoxIterator { fn process(&mut self, fragment: &Fragment, _: i32, border_box: &Rect<Au>) { - let border_padding = fragment.border_padding.to_physical(fragment.style.writing_mode); - self.result = - Some(match self.property { - PositionProperty::Left => self.position.x, - PositionProperty::Top => self.position.y, - PositionProperty::Width => border_box.size.width - border_padding.horizontal(), - PositionProperty::Height => border_box.size.height - border_padding.vertical(), - // TODO: the following 2 calculations are completely wrong. - // They should return the difference between the parent's and this - // fragment's border boxes. - PositionProperty::Right => border_box.max_x() + self.position.x, - PositionProperty::Bottom => border_box.max_y() + self.position.y, + let border_padding = fragment + .border_padding + .to_physical(fragment.style.writing_mode); + self.result = Some(match self.property { + PositionProperty::Left => self.position.x, + PositionProperty::Top => self.position.y, + PositionProperty::Width => border_box.size.width - border_padding.horizontal(), + PositionProperty::Height => border_box.size.height - border_padding.vertical(), + // TODO: the following 2 calculations are completely wrong. + // They should return the difference between the parent's and this + // fragment's border boxes. + PositionProperty::Right => border_box.max_x() + self.position.x, + PositionProperty::Bottom => border_box.max_y() + self.position.y, }); } @@ -313,8 +327,12 @@ struct MarginRetrievingFragmentBorderBoxIterator { } impl MarginRetrievingFragmentBorderBoxIterator { - fn new(node_address: OpaqueNode, side: Side, margin_padding: - MarginPadding, writing_mode: WritingMode) -> MarginRetrievingFragmentBorderBoxIterator { + fn new( + node_address: OpaqueNode, + side: Side, + margin_padding: MarginPadding, + writing_mode: WritingMode, + ) -> MarginRetrievingFragmentBorderBoxIterator { MarginRetrievingFragmentBorderBoxIterator { node_address: node_address, side: side, @@ -329,13 +347,13 @@ impl FragmentBorderBoxIterator for MarginRetrievingFragmentBorderBoxIterator { fn process(&mut self, fragment: &Fragment, _: i32, _: &Rect<Au>) { let rect = match self.margin_padding { MarginPadding::Margin => &fragment.margin, - MarginPadding::Padding => &fragment.border_padding + MarginPadding::Padding => &fragment.border_padding, }; self.result = Some(match self.side { - Side::Left => rect.left(self.writing_mode), - Side::Right => rect.right(self.writing_mode), - Side::Bottom => rect.bottom(self.writing_mode), - Side::Top => rect.top(self.writing_mode) + Side::Left => rect.left(self.writing_mode), + Side::Right => rect.right(self.writing_mode), + Side::Bottom => rect.bottom(self.writing_mode), + Side::Top => rect.top(self.writing_mode), }); } @@ -345,7 +363,9 @@ impl FragmentBorderBoxIterator for MarginRetrievingFragmentBorderBoxIterator { } pub fn process_content_box_request<N: LayoutNode>( - requested_node: N, layout_root: &mut Flow) -> Option<Rect<Au>> { + requested_node: N, + layout_root: &mut Flow, +) -> Option<Rect<Au>> { // FIXME(pcwalton): This has not been updated to handle the stacking context relative // stuff. So the position is wrong in most cases. let mut iterator = UnioningFragmentBorderBoxIterator::new(requested_node.opaque()); @@ -353,8 +373,10 @@ pub fn process_content_box_request<N: LayoutNode>( iterator.rect } -pub fn process_content_boxes_request<N: LayoutNode>(requested_node: N, layout_root: &mut Flow) - -> Vec<Rect<Au>> { +pub fn process_content_boxes_request<N: LayoutNode>( + requested_node: N, + layout_root: &mut Flow, +) -> Vec<Rect<Au>> { // FIXME(pcwalton): This has not been updated to handle the stacking context relative // stuff. So the position is wrong in most cases. let mut iterator = CollectingFragmentBorderBoxIterator::new(requested_node.opaque()); @@ -371,7 +393,7 @@ impl FragmentLocatingFragmentIterator { fn new(node_address: OpaqueNode) -> FragmentLocatingFragmentIterator { FragmentLocatingFragmentIterator { node_address: node_address, - client_rect: Rect::zero() + client_rect: Rect::zero(), } } } @@ -382,7 +404,7 @@ struct UnioningFragmentScrollAreaIterator { origin_rect: Rect<i32>, level: Option<i32>, is_child: bool, - overflow_direction: OverflowDirection + overflow_direction: OverflowDirection, } impl UnioningFragmentScrollAreaIterator { @@ -394,7 +416,7 @@ impl UnioningFragmentScrollAreaIterator { level: None, is_child: false, // FIXME(#20867) - overflow_direction: OverflowDirection::RightAndDown + overflow_direction: OverflowDirection::RightAndDown, } } } @@ -469,29 +491,38 @@ impl FragmentBorderBoxIterator for UnioningFragmentScrollAreaIterator { let (left_border, right_border) = (left_border.px(), right_border.px()); let (top_border, bottom_border) = (top_border.px(), bottom_border.px()); let right_padding = (border_box.size.width.to_f32_px() - right_border - left_border) as i32; - let bottom_padding = (border_box.size.height.to_f32_px() - bottom_border - top_border) as i32; + let bottom_padding = + (border_box.size.height.to_f32_px() - bottom_border - top_border) as i32; let top_padding = top_border as i32; let left_padding = left_border as i32; match self.level { - Some(start_level) if level <= start_level => { self.is_child = false; } + Some(start_level) if level <= start_level => { + self.is_child = false; + }, Some(_) => { - let padding = Rect::new(Point2D::new(left_padding, top_padding), - Size2D::new(right_padding, bottom_padding)); + let padding = Rect::new( + Point2D::new(left_padding, top_padding), + Size2D::new(right_padding, bottom_padding), + ); let top_margin = fragment.margin.top(fragment.style.writing_mode).to_px(); let left_margin = fragment.margin.left(fragment.style.writing_mode).to_px(); let bottom_margin = fragment.margin.bottom(fragment.style.writing_mode).to_px(); let right_margin = fragment.margin.right(fragment.style.writing_mode).to_px(); - let margin = Rect::new(Point2D::new(left_margin, top_margin), - Size2D::new(right_margin, bottom_margin)); + let margin = Rect::new( + Point2D::new(left_margin, top_margin), + Size2D::new(right_margin, bottom_margin), + ); self.union_rect = self.union_rect.union(&margin).union(&padding); - } + }, None => { self.level = Some(level); self.is_child = true; self.overflow_direction = overflow_direction(&fragment.style.writing_mode); - self.origin_rect = Rect::new(Point2D::new(left_padding, top_padding), - Size2D::new(right_padding, bottom_padding)); + self.origin_rect = Rect::new( + Point2D::new(left_padding, top_padding), + Size2D::new(right_padding, bottom_padding), + ); }, }; } @@ -509,8 +540,11 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator { // for its parent. Remove all nodes at this level or // higher, as they can't be parents of this node. self.parent_nodes.truncate(level as usize); - assert_eq!(self.parent_nodes.len(), level as usize, - "Skipped at least one level in the flow tree!"); + assert_eq!( + self.parent_nodes.len(), + level as usize, + "Skipped at least one level in the flow tree!" + ); } if !fragment.is_primary_fragment() { @@ -530,8 +564,10 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator { // Found the fragment in the flow tree that matches the // DOM node being looked for. - assert!(self.node_offset_box.is_none(), - "Node was being treated as inline, but it has an associated fragment!"); + assert!( + self.node_offset_box.is_none(), + "Node was being treated as inline, but it has an associated fragment!" + ); self.has_processed_node = true; self.node_offset_box = Some(NodeOffsetBoxInfo { @@ -544,7 +580,10 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator { self.parent_nodes.clear(); } } else if let Some(node) = fragment.inline_context.as_ref().and_then(|inline_context| { - inline_context.nodes.iter().find(|node| node.address == self.node_address) + inline_context + .nodes + .iter() + .find(|node| node.address == self.node_address) }) { // TODO: Handle cases where the `offsetParent` is an inline // element. This will likely be impossible until @@ -554,7 +593,9 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator { // contains the DOM node we're looking for, i.e. the node // is inline and contains this fragment. match self.node_offset_box { - Some(NodeOffsetBoxInfo { ref mut rectangle, .. }) => { + Some(NodeOffsetBoxInfo { + ref mut rectangle, .. + }) => { *rectangle = rectangle.union(border_box); }, None => { @@ -571,7 +612,10 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator { }, } - if node.flags.contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) { + if node + .flags + .contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT) + { self.has_processed_node = true; } } else if self.node_offset_box.is_none() { @@ -580,9 +624,11 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator { // it's at level 1 (below the root node)? let is_body_element = level == 1; - let is_valid_parent = match (is_body_element, - fragment.style.get_box().position, - &fragment.specific) { + let is_valid_parent = match ( + is_body_element, + fragment.style.get_box().position, + &fragment.specific, + ) { // Spec says it's valid if any of these are true: // 1) Is the body element // 2) Is static position *and* is a table or table cell @@ -600,7 +646,9 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator { }; let parent_info = if is_valid_parent { - let border_width = fragment.border_width().to_physical(fragment.style.writing_mode); + let border_width = fragment + .border_width() + .to_physical(fragment.style.writing_mode); Some(ParentBorderBoxInfo { node_address: fragment.node, @@ -619,9 +667,10 @@ impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator { } } - -pub fn process_node_geometry_request<N: LayoutNode>(requested_node: N, layout_root: &mut Flow) - -> Rect<i32> { +pub fn process_node_geometry_request<N: LayoutNode>( + requested_node: N, + layout_root: &mut Flow, +) -> Rect<i32> { let mut iterator = FragmentLocatingFragmentIterator::new(requested_node.opaque()); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); iterator.client_rect @@ -629,28 +678,41 @@ pub fn process_node_geometry_request<N: LayoutNode>(requested_node: N, layout_ro pub fn process_node_scroll_id_request<N: LayoutNode>( id: PipelineId, - requested_node: N + requested_node: N, ) -> ExternalScrollId { let layout_node = requested_node.to_threadsafe(); layout_node.generate_scroll_id(id) } /// https://drafts.csswg.org/cssom-view/#scrolling-area -pub fn process_node_scroll_area_request< N: LayoutNode>(requested_node: N, layout_root: &mut Flow) - -> Rect<i32> { +pub fn process_node_scroll_area_request<N: LayoutNode>( + requested_node: N, + layout_root: &mut Flow, +) -> Rect<i32> { let mut iterator = UnioningFragmentScrollAreaIterator::new(requested_node.opaque()); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); match iterator.overflow_direction { OverflowDirection::RightAndDown => { - let right = max(iterator.union_rect.size.width, iterator.origin_rect.size.width); - let bottom = max(iterator.union_rect.size.height, iterator.origin_rect.size.height); + let right = max( + iterator.union_rect.size.width, + iterator.origin_rect.size.width, + ); + let bottom = max( + iterator.union_rect.size.height, + iterator.origin_rect.size.height, + ); Rect::new(iterator.origin_rect.origin, Size2D::new(right, bottom)) }, OverflowDirection::LeftAndDown => { - let bottom = max(iterator.union_rect.size.height, iterator.origin_rect.size.height); + let bottom = max( + iterator.union_rect.size.height, + iterator.origin_rect.size.height, + ); let left = min(iterator.union_rect.origin.x, iterator.origin_rect.origin.x); - Rect::new(Point2D::new(left, iterator.origin_rect.origin.y), - Size2D::new(iterator.origin_rect.size.width, bottom)) + Rect::new( + Point2D::new(left, iterator.origin_rect.origin.y), + Size2D::new(iterator.origin_rect.size.width, bottom), + ) }, OverflowDirection::LeftAndUp => { let top = min(iterator.union_rect.origin.y, iterator.origin_rect.origin.y); @@ -659,21 +721,29 @@ pub fn process_node_scroll_area_request< N: LayoutNode>(requested_node: N, layou }, OverflowDirection::RightAndUp => { let top = min(iterator.union_rect.origin.y, iterator.origin_rect.origin.y); - let right = max(iterator.union_rect.size.width, iterator.origin_rect.size.width); - Rect::new(Point2D::new(iterator.origin_rect.origin.x, top), - Size2D::new(right, iterator.origin_rect.size.height)) - } + let right = max( + iterator.union_rect.size.width, + iterator.origin_rect.size.width, + ); + Rect::new( + Point2D::new(iterator.origin_rect.origin.x, top), + Size2D::new(right, iterator.origin_rect.size.height), + ) + }, } } /// Return the resolved value of property for a given (pseudo)element. /// <https://drafts.csswg.org/cssom/#resolved-value> -pub fn process_resolved_style_request<'a, N>(context: &LayoutContext, - node: N, - pseudo: &Option<PseudoElement>, - property: &PropertyId, - layout_root: &mut Flow) -> String - where N: LayoutNode, +pub fn process_resolved_style_request<'a, N>( + context: &LayoutContext, + node: N, + pseudo: &Option<PseudoElement>, + property: &PropertyId, + layout_root: &mut Flow, +) -> String +where + N: LayoutNode, { use style::stylist::RuleInclusion; use style::traversal::resolve_style; @@ -700,15 +770,13 @@ pub fn process_resolved_style_request<'a, N>(context: &LayoutContext, let styles = resolve_style(&mut context, element, RuleInclusion::All, pseudo.as_ref()); let style = styles.primary(); let longhand_id = match *property { - PropertyId::LonghandAlias(id, _) | - PropertyId::Longhand(id) => id, + PropertyId::LonghandAlias(id, _) | PropertyId::Longhand(id) => id, // Firefox returns blank strings for the computed value of shorthands, // so this should be web-compatible. - PropertyId::ShorthandAlias(..) | - PropertyId::Shorthand(_) => return String::new(), + PropertyId::ShorthandAlias(..) | PropertyId::Shorthand(_) => return String::new(), PropertyId::Custom(ref name) => { return style.computed_value_to_string(PropertyDeclarationId::Custom(name)) - } + }, }; // No need to care about used values here, since we're on a display: none @@ -735,7 +803,7 @@ where Some(PseudoElement::Selection) => None, // FIXME(emilio): What about the other pseudos? Probably they shouldn't // just return the element's style! - _ => Some(layout_el) + _ => Some(layout_el), }; let layout_el = match layout_el { @@ -744,29 +812,24 @@ where // the element itself in this case, Firefox uses the resolved value. // https://www.w3.org/Bugs/Public/show_bug.cgi?id=29006 return String::new(); - } - Some(layout_el) => layout_el + }, + Some(layout_el) => layout_el, }; let style = &*layout_el.resolved_style(); let longhand_id = match *property { - PropertyId::LonghandAlias(id, _) | - PropertyId::Longhand(id) => id, + PropertyId::LonghandAlias(id, _) | PropertyId::Longhand(id) => id, // Firefox returns blank strings for the computed value of shorthands, // so this should be web-compatible. - PropertyId::ShorthandAlias(..) | - PropertyId::Shorthand(_) => return String::new(), + PropertyId::ShorthandAlias(..) | PropertyId::Shorthand(_) => return String::new(), PropertyId::Custom(ref name) => { return style.computed_value_to_string(PropertyDeclarationId::Custom(name)) - } + }, }; let positioned = match style.get_box().position { - Position::Relative | - Position::Sticky | - Position::Fixed | - Position::Absolute => true, - _ => false + Position::Relative | Position::Sticky | Position::Fixed | Position::Absolute => true, + _ => false, }; //TODO: determine whether requested property applies to the element. @@ -780,15 +843,20 @@ where layout_el: <N::ConcreteThreadSafeLayoutNode as ThreadSafeLayoutNode>::ConcreteThreadSafeLayoutElement, layout_root: &mut Flow, requested_node: N, - longhand_id: LonghandId) -> String { + longhand_id: LonghandId, + ) -> String + { let maybe_data = layout_el.borrow_layout_data(); let position = maybe_data.map_or(Point2D::zero(), |data| { match (*data).flow_construction_result { - ConstructionResult::Flow(ref flow_ref, _) => - flow_ref.deref().base().stacking_relative_position.to_point(), + ConstructionResult::Flow(ref flow_ref, _) => flow_ref + .deref() + .base() + .stacking_relative_position + .to_point(), // TODO(dzbarsky) search parents until we find node with a flow ref. // https://github.com/servo/servo/issues/8307 - _ => Point2D::zero() + _ => Point2D::zero(), } }); let property = match longhand_id { @@ -798,24 +866,32 @@ where LonghandId::Right => PositionProperty::Right, LonghandId::Width => PositionProperty::Width, LonghandId::Height => PositionProperty::Height, - _ => unreachable!() + _ => unreachable!(), }; - let mut iterator = - PositionRetrievingFragmentBorderBoxIterator::new(requested_node.opaque(), - property, - position); - sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, - &mut iterator); - iterator.result.map(|r| r.to_css_string()).unwrap_or(String::new()) + let mut iterator = PositionRetrievingFragmentBorderBoxIterator::new( + requested_node.opaque(), + property, + position, + ); + sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); + iterator + .result + .map(|r| r.to_css_string()) + .unwrap_or(String::new()) } // TODO: we will return neither the computed nor used value for margin and padding. match longhand_id { - LonghandId::MarginBottom | LonghandId::MarginTop | - LonghandId::MarginLeft | LonghandId::MarginRight | - LonghandId::PaddingBottom | LonghandId::PaddingTop | - LonghandId::PaddingLeft | LonghandId::PaddingRight - if applies && style.get_box().display != Display::None => { + LonghandId::MarginBottom | + LonghandId::MarginTop | + LonghandId::MarginLeft | + LonghandId::MarginRight | + LonghandId::PaddingBottom | + LonghandId::PaddingTop | + LonghandId::PaddingLeft | + LonghandId::PaddingRight + if applies && style.get_box().display != Display::None => + { let (margin_padding, side) = match longhand_id { LonghandId::MarginBottom => (MarginPadding::Margin, Side::Bottom), LonghandId::MarginTop => (MarginPadding::Margin, Side::Top), @@ -825,40 +901,50 @@ where LonghandId::PaddingTop => (MarginPadding::Padding, Side::Top), LonghandId::PaddingLeft => (MarginPadding::Padding, Side::Left), LonghandId::PaddingRight => (MarginPadding::Padding, Side::Right), - _ => unreachable!() + _ => unreachable!(), }; - let mut iterator = - MarginRetrievingFragmentBorderBoxIterator::new(requested_node.opaque(), - side, - margin_padding, - style.writing_mode); - sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, - &mut iterator); - iterator.result.map(|r| r.to_css_string()).unwrap_or(String::new()) - }, + let mut iterator = MarginRetrievingFragmentBorderBoxIterator::new( + requested_node.opaque(), + side, + margin_padding, + style.writing_mode, + ); + sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); + iterator + .result + .map(|r| r.to_css_string()) + .unwrap_or(String::new()) + } LonghandId::Bottom | LonghandId::Top | LonghandId::Right | LonghandId::Left - if applies && positioned && style.get_box().display != Display::None => { + if applies && positioned && style.get_box().display != Display::None => + { used_value_for_position_property(layout_el, layout_root, requested_node, longhand_id) - } + }, LonghandId::Width | LonghandId::Height - if applies && style.get_box().display != Display::None => { + if applies && style.get_box().display != Display::None => + { used_value_for_position_property(layout_el, layout_root, requested_node, longhand_id) - } + }, // FIXME: implement used value computation for line-height - _ => { - style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id)) - } + _ => style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id)), } } -pub fn process_offset_parent_query<N: LayoutNode>(requested_node: N, layout_root: &mut Flow) - -> OffsetParentResponse { +pub fn process_offset_parent_query<N: LayoutNode>( + requested_node: N, + layout_root: &mut Flow, +) -> OffsetParentResponse { let mut iterator = ParentOffsetBorderBoxIterator::new(requested_node.opaque()); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); let node_offset_box = iterator.node_offset_box; - let parent_info = iterator.parent_nodes.into_iter().rev().filter_map(|info| info).next(); + let parent_info = iterator + .parent_nodes + .into_iter() + .rev() + .filter_map(|info| info) + .next(); match (node_offset_box, parent_info) { (Some(node_offset_box), Some(parent_info)) => { let origin = node_offset_box.offset - parent_info.origin.to_vector(); @@ -867,15 +953,12 @@ pub fn process_offset_parent_query<N: LayoutNode>(requested_node: N, layout_root node_address: Some(parent_info.node_address.to_untrusted_node_address()), rect: Rect::new(origin, size), } - } - _ => { - OffsetParentResponse::empty() - } + }, + _ => OffsetParentResponse::empty(), } } -pub fn process_style_query<N: LayoutNode>(requested_node: N) - -> StyleResponse { +pub fn process_style_query<N: LayoutNode>(requested_node: N) -> StyleResponse { let element = requested_node.as_element().unwrap(); let data = element.borrow_data(); @@ -888,8 +971,10 @@ enum InnerTextItem { } // https://html.spec.whatwg.org/multipage/#the-innertext-idl-attribute -pub fn process_element_inner_text_query<N: LayoutNode>(node: N, - indexable_text: &IndexableText) -> String { +pub fn process_element_inner_text_query<N: LayoutNode>( + node: N, + indexable_text: &IndexableText, +) -> String { // Step 1. let mut results = Vec::new(); // Step 2. @@ -923,7 +1008,7 @@ pub fn process_element_inner_text_query<N: LayoutNode>(node: N, if count > max_req_line_break_count { max_req_line_break_count = count; } - } + }, } } inner_text.into_iter().collect() @@ -931,22 +1016,21 @@ pub fn process_element_inner_text_query<N: LayoutNode>(node: N, // https://html.spec.whatwg.org/multipage/#inner-text-collection-steps #[allow(unsafe_code)] -fn inner_text_collection_steps<N: LayoutNode>(node: N, - indexable_text: &IndexableText, - results: &mut Vec<InnerTextItem>) { +fn inner_text_collection_steps<N: LayoutNode>( + node: N, + indexable_text: &IndexableText, + results: &mut Vec<InnerTextItem>, +) { let mut items = Vec::new(); for child in node.traverse_preorder() { let node = match child.type_id() { - LayoutNodeType::Text => { - child.parent_node().unwrap() - }, + LayoutNodeType::Text => child.parent_node().unwrap(), _ => child, }; let element_data = unsafe { - node.get_style_and_layout_data().map(|d| { - &(*(d.ptr.as_ptr() as *mut StyleData)).element_data - }) + node.get_style_and_layout_data() + .map(|d| &(*(d.ptr.as_ptr() as *mut StyleData)).element_data) }; if element_data.is_none() { @@ -980,15 +1064,16 @@ fn inner_text_collection_steps<N: LayoutNode>(node: N, }, LayoutNodeType::Element(LayoutElementType::HTMLBRElement) => { // Step 5. - items.push(InnerTextItem::Text(String::from("\u{000A}" /* line feed */))); + items.push(InnerTextItem::Text(String::from( + "\u{000A}", /* line feed */ + ))); }, LayoutNodeType::Element(LayoutElementType::HTMLParagraphElement) => { // Step 8. items.insert(0, InnerTextItem::RequiredLineBreakCount(2)); items.push(InnerTextItem::RequiredLineBreakCount(2)); - } + }, _ => {}, - } match display { diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs index e3984867a11..5da3f842656 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -25,10 +25,12 @@ pub fn resolve_generated_content(root: &mut Flow, layout_context: &LayoutContext /// Run the main layout passes sequentially. pub fn reflow(root: &mut Flow, layout_context: &LayoutContext, relayout_mode: RelayoutMode) { - fn doit(flow: &mut Flow, - assign_inline_sizes: AssignISizes, - assign_block_sizes: AssignBSizes, - relayout_mode: RelayoutMode) { + fn doit( + flow: &mut Flow, + assign_inline_sizes: AssignISizes, + assign_block_sizes: AssignBSizes, + relayout_mode: RelayoutMode, + ) { // Force reflow children during this traversal. This is needed when we failed // the float speculation of a block formatting context and need to fix it. if relayout_mode == RelayoutMode::Force { @@ -67,42 +69,47 @@ pub fn reflow(root: &mut Flow, layout_context: &LayoutContext, relayout_mode: Re doit(root, assign_inline_sizes, assign_block_sizes, relayout_mode); } -pub fn build_display_list_for_subtree<'a>(flow_root: &mut Flow, - layout_context: &'a LayoutContext) - -> DisplayListBuildState<'a> { +pub fn build_display_list_for_subtree<'a>( + flow_root: &mut Flow, + layout_context: &'a LayoutContext, +) -> DisplayListBuildState<'a> { let mut state = StackingContextCollectionState::new(layout_context.id); flow_root.collect_stacking_contexts(&mut state); let state = DisplayListBuildState::new(layout_context, state); - let mut build_display_list = BuildDisplayList { - state: state, - }; + let mut build_display_list = BuildDisplayList { state: state }; build_display_list.traverse(flow_root); build_display_list.state } -pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut Flow, iterator: &mut FragmentBorderBoxIterator) { - fn doit(flow: &mut Flow, - level: i32, - iterator: &mut FragmentBorderBoxIterator, - stacking_context_position: &Point2D<Au>) { +pub fn iterate_through_flow_tree_fragment_border_boxes( + root: &mut Flow, + iterator: &mut FragmentBorderBoxIterator, +) { + fn doit( + flow: &mut Flow, + level: i32, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>, + ) { flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position); for kid in flow.mut_base().child_iter_mut() { let mut stacking_context_position = *stacking_context_position; if kid.is_block_flow() && kid.as_block().fragment.establishes_stacking_context() { - stacking_context_position = Point2D::new(kid.as_block().fragment.margin.inline_start, Au(0)) + - kid.base().stacking_relative_position + - stacking_context_position.to_vector(); - let relative_position = kid.as_block() + stacking_context_position = + Point2D::new(kid.as_block().fragment.margin.inline_start, Au(0)) + + kid.base().stacking_relative_position + + stacking_context_position.to_vector(); + let relative_position = kid + .as_block() .stacking_relative_border_box(CoordinateSystem::Own); - if let Some(matrix) = kid.as_block() - .fragment - .transform_matrix(&relative_position) { + if let Some(matrix) = kid.as_block().fragment.transform_matrix(&relative_position) { let transform_matrix = matrix.transform_point2d(&LayoutPoint::zero()).unwrap(); - stacking_context_position = stacking_context_position + - Vector2D::new(Au::from_f32_px(transform_matrix.x), - Au::from_f32_px(transform_matrix.y)) + stacking_context_position = stacking_context_position + Vector2D::new( + Au::from_f32_px(transform_matrix.x), + Au::from_f32_px(transform_matrix.y), + ) } } doit(kid, level + 1, iterator, &stacking_context_position); @@ -113,7 +120,11 @@ pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut Flow, iterator } pub fn store_overflow(layout_context: &LayoutContext, flow: &mut Flow) { - if !flow.base().restyle_damage.contains(ServoRestyleDamage::STORE_OVERFLOW) { + if !flow + .base() + .restyle_damage + .contains(ServoRestyleDamage::STORE_OVERFLOW) + { return; } @@ -132,13 +143,21 @@ pub fn store_overflow(layout_context: &LayoutContext, flow: &mut Flow) { /// given flow. This is needed to speculatively calculate the inline sizes of block formatting /// contexts. The speculation typically succeeds, but if it doesn't we have to lay it out again. pub fn guess_float_placement(flow: &mut Flow) { - if !flow.base().restyle_damage.intersects(ServoRestyleDamage::REFLOW) { + if !flow + .base() + .restyle_damage + .intersects(ServoRestyleDamage::REFLOW) + { return; } let mut floats_in = SpeculatedFloatPlacement::compute_floats_in_for_first_child(flow); for kid in flow.mut_base().child_iter_mut() { - if kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + if kid + .base() + .flags + .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) + { // Do not propagate floats in or out, but do propogate between kids. guess_float_placement(kid); } else { diff --git a/components/layout/table.rs b/components/layout/table.rs index e36fd4b4e5a..cb80850e91e 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -79,7 +79,7 @@ impl TableFlow { column_computed_inline_sizes: Vec::new(), collapsed_inline_direction_border_widths_for_table: Vec::new(), collapsed_block_direction_border_widths_for_table: Vec::new(), - table_layout: table_layout + table_layout: table_layout, } } @@ -87,10 +87,10 @@ impl TableFlow { /// a larger value than one of `self_inline_sizes`. Returns the minimum and preferred inline /// sizes. fn update_automatic_column_inline_sizes( - parent_inline_sizes: &mut Vec<ColumnIntrinsicInlineSize>, - child_cell_inline_sizes: &[CellIntrinsicInlineSize], - surrounding_size: Au) - -> IntrinsicISizes { + parent_inline_sizes: &mut Vec<ColumnIntrinsicInlineSize>, + child_cell_inline_sizes: &[CellIntrinsicInlineSize], + surrounding_size: Au, + ) -> IntrinsicISizes { let mut total_inline_sizes = IntrinsicISizes { minimum_inline_size: surrounding_size, preferred_inline_size: surrounding_size, @@ -117,8 +117,10 @@ impl TableFlow { } else { let column_size = &child_cell_inline_size.column_size; *parent_sizes = ColumnIntrinsicInlineSize { - minimum_length: cmp::max(parent_sizes.minimum_length, - column_size.minimum_length), + minimum_length: cmp::max( + parent_sizes.minimum_length, + column_size.minimum_length, + ), percentage: parent_sizes.greatest_percentage(column_size), preferred: cmp::max(parent_sizes.preferred, column_size.preferred), constrained: parent_sizes.constrained || column_size.constrained, @@ -158,12 +160,14 @@ impl TableFlow { /// Updates the minimum and preferred inline-size calculation for a single row. This is /// factored out into a separate function because we process children of rowgroups too. - fn update_column_inline_sizes_for_row(row: &TableRowFlow, - column_inline_sizes: &mut Vec<ColumnIntrinsicInlineSize>, - computation: &mut IntrinsicISizesContribution, - first_row: bool, - table_layout: TableLayout, - surrounding_inline_size: Au) { + fn update_column_inline_sizes_for_row( + row: &TableRowFlow, + column_inline_sizes: &mut Vec<ColumnIntrinsicInlineSize>, + computation: &mut IntrinsicISizesContribution, + first_row: bool, + table_layout: TableLayout, + surrounding_inline_size: Au, + ) { // Read column inline-sizes from the table-row, and assign inline-size=0 for the columns // not defined in the column group. // @@ -178,13 +182,14 @@ impl TableFlow { column_inline_sizes.push(cell_inline_size.column_size); } } - } + }, TableLayout::Auto => { computation.union_block(&TableFlow::update_automatic_column_inline_sizes( column_inline_sizes, &row.cell_intrinsic_inline_sizes, - surrounding_inline_size)) - } + surrounding_inline_size, + )) + }, } } @@ -207,21 +212,31 @@ impl TableFlow { fn column_styles(&self) -> Vec<ColumnStyle> { let mut styles = vec![]; - for group in self.block_flow.base.child_iter() - .filter(|kid| kid.is_table_colgroup()) { + for group in self + .block_flow + .base + .child_iter() + .filter(|kid| kid.is_table_colgroup()) + { // XXXManishearth these as_foo methods should return options // so that we can filter_map let group = group.as_table_colgroup(); - let colgroup_style = group.fragment.as_ref() - .map(|f| f.style()); + let colgroup_style = group.fragment.as_ref().map(|f| f.style()); // The colgroup's span attribute is only relevant when // it has no children // https://html.spec.whatwg.org/multipage/#forming-a-table if group.cols.is_empty() { - let span = group.fragment.as_ref() - .map(|f| f.column_span()).unwrap_or(1); - styles.push(ColumnStyle { span, colgroup_style, col_style: None }); + let span = group + .fragment + .as_ref() + .map(|f| f.column_span()) + .unwrap_or(1); + styles.push(ColumnStyle { + span, + colgroup_style, + col_style: None, + }); } else { for col in &group.cols { // XXXManishearth Arc-cloning colgroup_style is suboptimal @@ -267,45 +282,59 @@ impl Flow for TableFlow { /// The maximum min/pref inline-sizes of each column are set from the rows for the automatic /// table layout calculation. fn bubble_inline_sizes(&mut self) { - let _scope = layout_debug_scope!("table::bubble_inline_sizes {:x}", - self.block_flow.base.debug_id()); + let _scope = layout_debug_scope!( + "table::bubble_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); // Get column inline sizes from colgroups - for kid in self.block_flow.base.child_iter_mut().filter(|kid| kid.is_table_colgroup()) { + for kid in self + .block_flow + .base + .child_iter_mut() + .filter(|kid| kid.is_table_colgroup()) + { for specified_inline_size in &kid.as_mut_table_colgroup().inline_sizes { - self.column_intrinsic_inline_sizes.push(ColumnIntrinsicInlineSize { - minimum_length: match *specified_inline_size { - LengthOrPercentageOrAuto::Auto | - LengthOrPercentageOrAuto::Calc(_) | - LengthOrPercentageOrAuto::Percentage(_) => Au(0), - LengthOrPercentageOrAuto::Length(length) => Au::from(length), - }, - percentage: match *specified_inline_size { - LengthOrPercentageOrAuto::Auto | - LengthOrPercentageOrAuto::Calc(_) | - LengthOrPercentageOrAuto::Length(_) => 0.0, - LengthOrPercentageOrAuto::Percentage(percentage) => percentage.0, - }, - preferred: Au(0), - constrained: false, - }) + self.column_intrinsic_inline_sizes + .push(ColumnIntrinsicInlineSize { + minimum_length: match *specified_inline_size { + LengthOrPercentageOrAuto::Auto | + LengthOrPercentageOrAuto::Calc(_) | + LengthOrPercentageOrAuto::Percentage(_) => Au(0), + LengthOrPercentageOrAuto::Length(length) => Au::from(length), + }, + percentage: match *specified_inline_size { + LengthOrPercentageOrAuto::Auto | + LengthOrPercentageOrAuto::Calc(_) | + LengthOrPercentageOrAuto::Length(_) => 0.0, + LengthOrPercentageOrAuto::Percentage(percentage) => percentage.0, + }, + preferred: Au(0), + constrained: false, + }) } } self.collapsed_inline_direction_border_widths_for_table = Vec::new(); self.collapsed_block_direction_border_widths_for_table = vec![Au(0)]; - let collapsing_borders = self.block_flow - .fragment - .style - .get_inherited_table() - .border_collapse == border_collapse::T::Collapse; + let collapsing_borders = self + .block_flow + .fragment + .style + .get_inherited_table() + .border_collapse == + border_collapse::T::Collapse; let table_inline_collapsed_borders = if collapsing_borders { Some(TableInlineCollapsedBorders { - start: CollapsedBorder::inline_start(&*self.block_flow.fragment.style, - CollapsedBorderProvenance::FromTable), - end: CollapsedBorder::inline_end(&*self.block_flow.fragment.style, - CollapsedBorderProvenance::FromTable), + start: CollapsedBorder::inline_start( + &*self.block_flow.fragment.style, + CollapsedBorderProvenance::FromTable, + ), + end: CollapsedBorder::inline_end( + &*self.block_flow.fragment.style, + CollapsedBorderProvenance::FromTable, + ), }) } else { None @@ -314,8 +343,9 @@ impl Flow for TableFlow { let mut computation = IntrinsicISizesContribution::new(); let mut previous_collapsed_block_end_borders = PreviousBlockCollapsedBorders::FromTable(CollapsedBorder::block_start( - &*self.block_flow.fragment.style, - CollapsedBorderProvenance::FromTable)); + &*self.block_flow.fragment.style, + CollapsedBorderProvenance::FromTable, + )); let mut first_row = true; let (border_padding, _) = self.block_flow.fragment.surrounding_intrinsic_inline_size(); @@ -323,48 +353,50 @@ impl Flow for TableFlow { let mut iterator = TableRowIterator::new(&mut self.block_flow.base).peekable(); while let Some(row) = iterator.next() { TableFlow::update_column_inline_sizes_for_row( - row, - &mut self.column_intrinsic_inline_sizes, - &mut computation, - first_row, - self.table_layout, - border_padding); + row, + &mut self.column_intrinsic_inline_sizes, + &mut computation, + first_row, + self.table_layout, + border_padding, + ); if collapsing_borders { let next_index_and_sibling = iterator.peek(); - let next_collapsed_borders_in_block_direction = - match next_index_and_sibling { - Some(next_sibling) => { - NextBlockCollapsedBorders::FromNextRow( - &next_sibling.as_table_row() - .preliminary_collapsed_borders - .block_start) - } - None => { - NextBlockCollapsedBorders::FromTable( - CollapsedBorder::block_end(&*self.block_flow.fragment.style, - CollapsedBorderProvenance::FromTable)) - } - }; - perform_border_collapse_for_row(row, + let next_collapsed_borders_in_block_direction = match next_index_and_sibling { + Some(next_sibling) => NextBlockCollapsedBorders::FromNextRow( + &next_sibling + .as_table_row() + .preliminary_collapsed_borders + .block_start, + ), + None => NextBlockCollapsedBorders::FromTable(CollapsedBorder::block_end( + &*self.block_flow.fragment.style, + CollapsedBorderProvenance::FromTable, + )), + }; + perform_border_collapse_for_row( + row, table_inline_collapsed_borders.as_ref().unwrap(), previous_collapsed_block_end_borders, next_collapsed_borders_in_block_direction, &mut self.collapsed_inline_direction_border_widths_for_table, - &mut self.collapsed_block_direction_border_widths_for_table); + &mut self.collapsed_block_direction_border_widths_for_table, + ); previous_collapsed_block_end_borders = PreviousBlockCollapsedBorders::FromPreviousRow( - row.final_collapsed_borders.block_end.clone()); + row.final_collapsed_borders.block_end.clone(), + ); } first_row = false - }; + } } let total_horizontal_spacing = self.total_horizontal_spacing(); - let mut style_specified_intrinsic_inline_size = - self.block_flow - .fragment - .style_specified_intrinsic_inline_size() - .finish(); + let mut style_specified_intrinsic_inline_size = self + .block_flow + .fragment + .style_specified_intrinsic_inline_size() + .finish(); style_specified_intrinsic_inline_size.minimum_inline_size -= total_horizontal_spacing; style_specified_intrinsic_inline_size.preferred_inline_size -= total_horizontal_spacing; computation.union_block(&style_specified_intrinsic_inline_size); @@ -376,9 +408,14 @@ impl Flow for TableFlow { /// Recursively (top-down) determines the actual inline-size of child contexts and fragments. /// When called on this context, the context has had its inline-size set by the parent context. fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - let _scope = layout_debug_scope!("table::assign_inline_sizes {:x}", - self.block_flow.base.debug_id()); - debug!("assign_inline_sizes({}): assigning inline_size for flow", "table"); + let _scope = layout_debug_scope!( + "table::assign_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); + debug!( + "assign_inline_sizes({}): assigning inline_size for flow", + "table" + ); let shared_context = layout_context.shared_context(); // The position was set to the containing block by the flow's parent. @@ -396,9 +433,11 @@ impl Flow for TableFlow { } let inline_size_computer = InternalTable; - inline_size_computer.compute_used_inline_size(&mut self.block_flow, - shared_context, - containing_block_inline_size); + inline_size_computer.compute_used_inline_size( + &mut self.block_flow, + shared_context, + containing_block_inline_size, + ); let inline_start_content_edge = self.block_flow.fragment.border_padding.inline_start; let inline_end_content_edge = self.block_flow.fragment.border_padding.inline_end; @@ -406,7 +445,8 @@ impl Flow for TableFlow { let spacing_per_cell = self.spacing(); let total_horizontal_spacing = self.total_horizontal_spacing(); let content_inline_size = self.block_flow.fragment.border_box.size.inline - - padding_and_borders - total_horizontal_spacing; + padding_and_borders - + total_horizontal_spacing; let mut remaining_inline_size = content_inline_size; match self.table_layout { @@ -416,32 +456,32 @@ impl Flow for TableFlow { // https://drafts.csswg.org/css2/tables.html#fixed-table-layout for column_inline_size in &self.column_intrinsic_inline_sizes { if column_inline_size.constrained { - self.column_computed_inline_sizes.push(ColumnComputedInlineSize { - size: column_inline_size.minimum_length, - }); + self.column_computed_inline_sizes + .push(ColumnComputedInlineSize { + size: column_inline_size.minimum_length, + }); remaining_inline_size -= column_inline_size.minimum_length; } else if column_inline_size.percentage != 0.0 { let size = remaining_inline_size.scale_by(column_inline_size.percentage); - self.column_computed_inline_sizes.push(ColumnComputedInlineSize { - size: size, - }); + self.column_computed_inline_sizes + .push(ColumnComputedInlineSize { size: size }); remaining_inline_size -= size; } else { // Set the size to 0 now, distribute the remaining widths later - self.column_computed_inline_sizes.push(ColumnComputedInlineSize { - size: Au(0), - }); + self.column_computed_inline_sizes + .push(ColumnComputedInlineSize { size: Au(0) }); } } // Distribute remaining content inline size if unspecified_inline_sizes_indices.len() > 0 { for &index in &unspecified_inline_sizes_indices { - self.column_computed_inline_sizes[index].size = - remaining_inline_size.scale_by(1.0 / unspecified_inline_sizes_indices.len() as f32); + self.column_computed_inline_sizes[index].size = remaining_inline_size + .scale_by(1.0 / unspecified_inline_sizes_indices.len() as f32); } } else { - let total_minimum_size = self.column_intrinsic_inline_sizes + let total_minimum_size = self + .column_intrinsic_inline_sizes .iter() .filter(|size| size.constrained) .map(|size| size.minimum_length.0 as f32) @@ -453,57 +493,66 @@ impl Flow for TableFlow { remaining_inline_size.scale_by(inline_size as f32 / total_minimum_size); } } - } + }, _ => { // The table wrapper already computed the inline-sizes and propagated them down // to us. - } + }, } let column_computed_inline_sizes = &self.column_computed_inline_sizes; let collapsed_inline_direction_border_widths_for_table = &self.collapsed_inline_direction_border_widths_for_table; - let mut collapsed_block_direction_border_widths_for_table = - self.collapsed_block_direction_border_widths_for_table.iter().peekable(); + let mut collapsed_block_direction_border_widths_for_table = self + .collapsed_block_direction_border_widths_for_table + .iter() + .peekable(); let mut incoming_rowspan = vec![]; - self.block_flow.propagate_assigned_inline_size_to_children(shared_context, - inline_start_content_edge, - inline_end_content_edge, - content_inline_size, - |child_flow, - _child_index, - _content_inline_size, - writing_mode, - _inline_start_margin_edge, - _inline_end_margin_edge| { - table_row::propagate_column_inline_sizes_to_child( - child_flow, - writing_mode, - column_computed_inline_sizes, - &spacing_per_cell, - &mut incoming_rowspan); - if child_flow.is_table_row() { - let child_table_row = child_flow.as_mut_table_row(); - child_table_row.populate_collapsed_border_spacing( - collapsed_inline_direction_border_widths_for_table, - &mut collapsed_block_direction_border_widths_for_table); - } else if child_flow.is_table_rowgroup() { - let child_table_rowgroup = child_flow.as_mut_table_rowgroup(); - child_table_rowgroup.populate_collapsed_border_spacing( - collapsed_inline_direction_border_widths_for_table, - &mut collapsed_block_direction_border_widths_for_table); - } - }); + self.block_flow.propagate_assigned_inline_size_to_children( + shared_context, + inline_start_content_edge, + inline_end_content_edge, + content_inline_size, + |child_flow, + _child_index, + _content_inline_size, + writing_mode, + _inline_start_margin_edge, + _inline_end_margin_edge| { + table_row::propagate_column_inline_sizes_to_child( + child_flow, + writing_mode, + column_computed_inline_sizes, + &spacing_per_cell, + &mut incoming_rowspan, + ); + if child_flow.is_table_row() { + let child_table_row = child_flow.as_mut_table_row(); + child_table_row.populate_collapsed_border_spacing( + collapsed_inline_direction_border_widths_for_table, + &mut collapsed_block_direction_border_widths_for_table, + ); + } else if child_flow.is_table_rowgroup() { + let child_table_rowgroup = child_flow.as_mut_table_rowgroup(); + child_table_rowgroup.populate_collapsed_border_spacing( + collapsed_inline_direction_border_widths_for_table, + &mut collapsed_block_direction_border_widths_for_table, + ); + } + }, + ); } fn assign_block_size(&mut self, lc: &LayoutContext) { debug!("assign_block_size: assigning block_size for table"); let vertical_spacing = self.spacing().vertical(); - self.block_flow.assign_block_size_for_table_like_flow(vertical_spacing, lc) + self.block_flow + .assign_block_size_for_table_like_flow(vertical_spacing, lc) } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context) + self.block_flow + .compute_stacking_relative_position(layout_context) } fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize<Au> { @@ -511,24 +560,29 @@ impl Flow for TableFlow { } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn build_display_list(&mut self, state: &mut DisplayListBuildState) { - let border_painting_mode = match self.block_flow - .fragment - .style - .get_inherited_table() - .border_collapse { + let border_painting_mode = match self + .block_flow + .fragment + .style + .get_inherited_table() + .border_collapse + { border_collapse::T::Separate => BorderPaintingMode::Separate, border_collapse::T::Collapse => BorderPaintingMode::Hidden, }; - self.block_flow.build_display_list_for_block(state, border_painting_mode); + self.block_flow + .build_display_list_for_block(state, border_painting_mode); let iter = TableCellStyleIterator::new(&self); for style in iter { @@ -538,8 +592,10 @@ impl Flow for TableFlow { fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) { // Stacking contexts are collected by the table wrapper. - self.block_flow.collect_stacking_contexts_for_block(state, - StackingContextCollectionFlags::NEVER_CREATES_STACKING_CONTEXT); + self.block_flow.collect_stacking_contexts_for_block( + state, + StackingContextCollectionFlags::NEVER_CREATES_STACKING_CONTEXT, + ); } fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) { @@ -550,11 +606,17 @@ impl Flow for TableFlow { self.block_flow.compute_overflow() } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position) + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ) } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { @@ -592,15 +654,16 @@ impl ISizeAndMarginsComputer for InternalTable { &self, block: &mut BlockFlow, shared_context: &SharedStyleContext, - parent_flow_inline_size: Au + parent_flow_inline_size: Au, ) { - let mut input = self.compute_inline_size_constraint_inputs(block, - parent_flow_inline_size, - shared_context); + let mut input = self.compute_inline_size_constraint_inputs( + block, + parent_flow_inline_size, + shared_context, + ); // Tables are always at least as wide as their minimum inline size. - let minimum_inline_size = - block.base.intrinsic_inline_sizes.minimum_inline_size - + let minimum_inline_size = block.base.intrinsic_inline_sizes.minimum_inline_size - block.fragment.border_padding.inline_start_end(); input.available_inline_size = cmp::max(input.available_inline_size, minimum_inline_size); @@ -609,8 +672,11 @@ impl ISizeAndMarginsComputer for InternalTable { } /// Solve the inline-size and margins constraints for this block flow. - fn solve_inline_size_constraints(&self, _: &mut BlockFlow, input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + fn solve_inline_size_constraints( + &self, + _: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { ISizeConstraintSolution::new(input.available_inline_size, Au(0), Au(0)) } } @@ -697,20 +763,28 @@ impl<T> VecExt<T> for Vec<T> { /// Updates the border styles in the block direction for a single row. This function should /// only be called if border collapsing is on. It is factored out into a separate function /// because we process children of rowgroups too. -fn perform_border_collapse_for_row(child_table_row: &mut TableRowFlow, - table_inline_borders: &TableInlineCollapsedBorders, - previous_block_borders: PreviousBlockCollapsedBorders, - next_block_borders: NextBlockCollapsedBorders, - inline_spacing: &mut Vec<Au>, - block_spacing: &mut Vec<Au>) { +fn perform_border_collapse_for_row( + child_table_row: &mut TableRowFlow, + table_inline_borders: &TableInlineCollapsedBorders, + previous_block_borders: PreviousBlockCollapsedBorders, + next_block_borders: NextBlockCollapsedBorders, + inline_spacing: &mut Vec<Au>, + block_spacing: &mut Vec<Au>, +) { // TODO mbrubeck: Take rowspan and colspan into account. - let number_of_borders_inline_direction = child_table_row.preliminary_collapsed_borders.inline.len(); + let number_of_borders_inline_direction = + child_table_row.preliminary_collapsed_borders.inline.len(); // Compute interior inline borders. - for (i, this_inline_border) in child_table_row.preliminary_collapsed_borders - .inline - .iter_mut() - .enumerate() { - child_table_row.final_collapsed_borders.inline.push_or_set(i, *this_inline_border); + for (i, this_inline_border) in child_table_row + .preliminary_collapsed_borders + .inline + .iter_mut() + .enumerate() + { + child_table_row + .final_collapsed_borders + .inline + .push_or_set(i, *this_inline_border); if i == 0 { child_table_row.final_collapsed_borders.inline[i].combine(&table_inline_borders.start); } else if i + 1 == number_of_borders_inline_direction { @@ -718,22 +792,28 @@ fn perform_border_collapse_for_row(child_table_row: &mut TableRowFlow, } let inline_spacing = inline_spacing.get_mut_or_push(i, Au(0)); - *inline_spacing = cmp::max(*inline_spacing, child_table_row.final_collapsed_borders.inline[i].width) + *inline_spacing = cmp::max( + *inline_spacing, + child_table_row.final_collapsed_borders.inline[i].width, + ) } // Compute block-start borders. let block_start_borders = &mut child_table_row.final_collapsed_borders.block_start; - *block_start_borders = child_table_row.preliminary_collapsed_borders.block_start.clone(); + *block_start_borders = child_table_row + .preliminary_collapsed_borders + .block_start + .clone(); for (i, this_border) in block_start_borders.iter_mut().enumerate() { match previous_block_borders { PreviousBlockCollapsedBorders::FromPreviousRow(ref previous_block_borders) => { if previous_block_borders.len() > i { this_border.combine(&previous_block_borders[i]); } - } + }, PreviousBlockCollapsedBorders::FromTable(table_border) => { this_border.combine(&table_border); - } + }, } } @@ -741,20 +821,22 @@ fn perform_border_collapse_for_row(child_table_row: &mut TableRowFlow, let next_block = &mut child_table_row.final_collapsed_borders.block_end; block_spacing.push(Au(0)); let block_spacing = block_spacing.last_mut().unwrap(); - for (i, this_block_border) in child_table_row.preliminary_collapsed_borders - .block_end - .iter() - .enumerate() { + for (i, this_block_border) in child_table_row + .preliminary_collapsed_borders + .block_end + .iter() + .enumerate() + { let next_block = next_block.push_or_set(i, *this_block_border); match next_block_borders { NextBlockCollapsedBorders::FromNextRow(next_block_borders) => { if next_block_borders.len() > i { next_block.combine(&next_block_borders[i]) } - } + }, NextBlockCollapsedBorders::FromTable(ref next_block_borders) => { next_block.combine(next_block_borders); - } + }, } *block_spacing = cmp::max(*block_spacing, next_block.width) } @@ -764,27 +846,41 @@ fn perform_border_collapse_for_row(child_table_row: &mut TableRowFlow, /// rowgroups. pub trait TableLikeFlow { /// Lays out the rows of a table. - fn assign_block_size_for_table_like_flow(&mut self, block_direction_spacing: Au, - layout_context: &LayoutContext); + fn assign_block_size_for_table_like_flow( + &mut self, + block_direction_spacing: Au, + layout_context: &LayoutContext, + ); } impl TableLikeFlow for BlockFlow { - fn assign_block_size_for_table_like_flow(&mut self, block_direction_spacing: Au, - layout_context: &LayoutContext) { - debug_assert!(self.fragment.style.get_inherited_table().border_collapse == - border_collapse::T::Separate || block_direction_spacing == Au(0)); - - fn border_spacing_for_row(fragment: &Fragment, row: &TableRowFlow, - block_direction_spacing: Au) -> Au { + fn assign_block_size_for_table_like_flow( + &mut self, + block_direction_spacing: Au, + layout_context: &LayoutContext, + ) { + debug_assert!( + self.fragment.style.get_inherited_table().border_collapse == + border_collapse::T::Separate || + block_direction_spacing == Au(0) + ); + + fn border_spacing_for_row( + fragment: &Fragment, + row: &TableRowFlow, + block_direction_spacing: Au, + ) -> Au { match fragment.style.get_inherited_table().border_collapse { border_collapse::T::Separate => block_direction_spacing, - border_collapse::T::Collapse => { - row.collapsed_border_spacing.block_start - } + border_collapse::T::Collapse => row.collapsed_border_spacing.block_start, } } - if self.base.restyle_damage.contains(ServoRestyleDamage::REFLOW) { + if self + .base + .restyle_damage + .contains(ServoRestyleDamage::REFLOW) + { let mut sizes = vec![Default::default()]; // The amount of border spacing up to and including this row, // but not including the spacing beneath it @@ -803,14 +899,16 @@ impl TableLikeFlow for BlockFlow { first = false; continue; } - cumulative_border_spacing += - border_spacing_for_row(&self.fragment, kid.as_table_row(), - block_direction_spacing); + cumulative_border_spacing += border_spacing_for_row( + &self.fragment, + kid.as_table_row(), + block_direction_spacing, + ); sizes.push(TableRowSizeData { // we haven't calculated sizes yet size: Au(0), cumulative_border_spacing, - rowgroup_id + rowgroup_id, }); } else if kid.is_table_rowgroup() && !first { rowgroup_id += 1; @@ -822,17 +920,17 @@ impl TableLikeFlow for BlockFlow { let mut i = 0; for kid in self.base.child_iter_mut() { if kid.is_table_row() { - let size = kid.as_mut_table_row() - .compute_block_size_table_row_base(layout_context, - &mut incoming_rowspan_data, - &sizes, - i); + let size = kid.as_mut_table_row().compute_block_size_table_row_base( + layout_context, + &mut incoming_rowspan_data, + &sizes, + i, + ); sizes[i].size = size; i += 1; } } - // Our current border-box position. let block_start_border_padding = self.fragment.border_padding.block_start; let mut current_block_offset = block_start_border_padding; @@ -848,12 +946,12 @@ impl TableLikeFlow for BlockFlow { has_rows = true; let row = kid.as_mut_table_row(); row.assign_block_size_to_self_and_children(&sizes, i); - row.mut_base().restyle_damage - .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | - ServoRestyleDamage::REFLOW); - current_block_offset = current_block_offset + - border_spacing_for_row(&self.fragment, row, - block_direction_spacing); + row.mut_base().restyle_damage.remove( + ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW, + ); + current_block_offset = + current_block_offset + + border_spacing_for_row(&self.fragment, row, block_direction_spacing); i += 1; } @@ -873,13 +971,13 @@ impl TableLikeFlow for BlockFlow { let mut block_size = current_block_offset - block_start_border_padding; let mut candidate_block_size_iterator = CandidateBSizeIterator::new( &self.fragment, - self.base.block_container_explicit_block_size); + self.base.block_container_explicit_block_size, + ); while let Some(candidate_block_size) = candidate_block_size_iterator.next() { - candidate_block_size_iterator.candidate_value = - match candidate_block_size { - MaybeAuto::Auto => block_size, - MaybeAuto::Specified(value) => value - }; + candidate_block_size_iterator.candidate_value = match candidate_block_size { + MaybeAuto::Auto => block_size, + MaybeAuto::Specified(value) => value, + }; } // Adjust `current_block_offset` as necessary to account for the explicitly-specified @@ -889,8 +987,11 @@ impl TableLikeFlow for BlockFlow { current_block_offset = current_block_offset + delta; // Take border, padding, and spacing into account. - let block_end_offset = self.fragment.border_padding.block_end + - if has_rows { block_direction_spacing } else { Au(0) }; + let block_end_offset = self.fragment.border_padding.block_end + if has_rows { + block_direction_spacing + } else { + Au(0) + }; current_block_offset = current_block_offset + block_end_offset; // Now that `current_block_offset` is at the block-end of the border box, compute the @@ -910,7 +1011,9 @@ impl TableLikeFlow for BlockFlow { } } - self.base.restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); + self.base + .restyle_damage + .remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); } } @@ -937,7 +1040,7 @@ enum NextBlockCollapsedBorders<'a> { /// provides the Fragment for rowgroups if any struct TableRowAndGroupIterator<'a> { kids: FlowListIterator<'a>, - group: Option<(&'a Fragment, FlowListIterator<'a>)> + group: Option<(&'a Fragment, FlowListIterator<'a>)>, } impl<'a> TableRowAndGroupIterator<'a> { @@ -956,7 +1059,7 @@ impl<'a> Iterator for TableRowAndGroupIterator<'a> { // If we're inside a rowgroup, iterate through the rowgroup's children. if let Some(ref mut group) = self.group { if let Some(grandkid) = group.1.next() { - return Some((Some(group.0), grandkid.as_table_row())) + return Some((Some(group.0), grandkid.as_table_row())); } } // Otherwise, iterate through the table's children. @@ -973,8 +1076,8 @@ impl<'a> Iterator for TableRowAndGroupIterator<'a> { } else { self.next() // Skip children that are not rows or rowgroups } - } - None => None + }, + None => None, } } } @@ -983,7 +1086,7 @@ impl<'a> Iterator for TableRowAndGroupIterator<'a> { /// provides the Fragment for rowgroups if any struct MutTableRowAndGroupIterator<'a> { kids: MutFlowListIterator<'a>, - group: Option<(&'a Fragment, MutFlowListIterator<'a>)> + group: Option<(&'a Fragment, MutFlowListIterator<'a>)>, } impl<'a> MutTableRowAndGroupIterator<'a> { @@ -1002,7 +1105,7 @@ impl<'a> Iterator for MutTableRowAndGroupIterator<'a> { // If we're inside a rowgroup, iterate through the rowgroup's children. if let Some(ref mut group) = self.group { if let Some(grandkid) = group.1.next() { - return Some((Some(group.0), grandkid.as_mut_table_row())) + return Some((Some(group.0), grandkid.as_mut_table_row())); } } // Otherwise, iterate through the table's children. @@ -1019,8 +1122,8 @@ impl<'a> Iterator for MutTableRowAndGroupIterator<'a> { } else { self.next() // Skip children that are not rows or rowgroups } - } - None => None + }, + None => None, } } } @@ -1052,7 +1155,6 @@ struct TableCellStyleIterator<'table> { row_iterator: TableRowAndGroupIterator<'table>, row_info: Option<TableCellStyleIteratorRowInfo<'table>>, column_index: TableCellColumnIndexData, - } struct TableCellStyleIteratorRowInfo<'table> { @@ -1069,13 +1171,15 @@ impl<'table> TableCellStyleIterator<'table> { Some(TableCellStyleIteratorRowInfo { row: &row, rowgroup: group, - cell_iterator: row.block_flow.base.child_iter() + cell_iterator: row.block_flow.base.child_iter(), }) } else { None }; TableCellStyleIterator { - column_styles, row_iterator, row_info, + column_styles, + row_iterator, + row_info, column_index: Default::default(), } } @@ -1118,14 +1222,12 @@ impl TableCellColumnIndexData { fn advance(&mut self, amount: u32, column_styles: &[ColumnStyle]) { self.absolute += amount; self.relative_offset += amount; - if let Some(mut current_col) = - column_styles.get(self.relative as usize) { + if let Some(mut current_col) = column_styles.get(self.relative as usize) { while self.relative_offset >= current_col.span { // move to the next column self.relative += 1; self.relative_offset -= current_col.span; - if let Some(column_style) = - column_styles.get(self.relative as usize) { + if let Some(column_style) = column_styles.get(self.relative as usize) { current_col = column_style; } else { // we ran out of column_styles, @@ -1144,7 +1246,11 @@ impl<'table> Iterator for TableCellStyleIterator<'table> { // FIXME We do this awkward .take() followed by shoving it back in // because without NLL the row_info borrow lasts too long if let Some(mut row_info) = self.row_info.take() { - if let Some(rowspan) = row_info.row.incoming_rowspan.get(self.column_index.absolute as usize) { + if let Some(rowspan) = row_info + .row + .incoming_rowspan + .get(self.column_index.absolute as usize) + { // we are not allowed to use this column as a starting point. Try the next one. if *rowspan > 1 { self.column_index.advance(1, &self.column_styles); @@ -1159,9 +1265,14 @@ impl<'table> Iterator for TableCellStyleIterator<'table> { let row_style = row_info.row.block_flow.fragment.style(); let cell = cell.as_table_cell(); let (col_style, colgroup_style) = if let Some(column_style) = - self.column_styles.get(self.column_index.relative as usize) { - let styles = (column_style.col_style.clone(), column_style.colgroup_style.clone()); - self.column_index.advance(cell.column_span, &self.column_styles); + self.column_styles.get(self.column_index.relative as usize) + { + let styles = ( + column_style.col_style.clone(), + column_style.colgroup_style.clone(), + ); + self.column_index + .advance(cell.column_span, &self.column_styles); styles } else { @@ -1175,14 +1286,14 @@ impl<'table> Iterator for TableCellStyleIterator<'table> { col_style, rowgroup_style, row_style, - }) + }); } else { // next row if let Some((group, row)) = self.row_iterator.next() { self.row_info = Some(TableCellStyleIteratorRowInfo { row: &row, rowgroup: group, - cell_iterator: row.block_flow.base.child_iter() + cell_iterator: row.block_flow.base.child_iter(), }); self.column_index = Default::default(); self.next() @@ -1203,17 +1314,29 @@ impl<'table> TableCellStyleInfo<'table> { fn build_display_list(&self, mut state: &mut DisplayListBuildState) { use style::computed_values::visibility::T as Visibility; - if !self.cell.visible || self.cell.block_flow.fragment.style() - .get_inherited_box().visibility != Visibility::Visible { - return + if !self.cell.visible || + self.cell + .block_flow + .fragment + .style() + .get_inherited_box() + .visibility != + Visibility::Visible + { + return; } - let border_painting_mode = match self.cell.block_flow - .fragment - .style - .get_inherited_table() - .border_collapse { + let border_painting_mode = match self + .cell + .block_flow + .fragment + .style + .get_inherited_table() + .border_collapse + { border_collapse::T::Separate => BorderPaintingMode::Separate, - border_collapse::T::Collapse => BorderPaintingMode::Collapse(&self.cell.collapsed_borders), + border_collapse::T::Collapse => { + BorderPaintingMode::Collapse(&self.cell.collapsed_borders) + }, }; { let cell_flow = &self.cell.block_flow; @@ -1227,7 +1350,9 @@ impl<'table> TableCellStyleInfo<'table> { } let background_color = sty.resolve_color(background.background_color); cell_flow.build_display_list_for_background_if_applicable_with_background( - state, background, background_color + state, + background, + background_color, ); }; @@ -1243,6 +1368,8 @@ impl<'table> TableCellStyleInfo<'table> { build_dl(self.row_style, &mut state); } // the restyle damage will be set in TableCellFlow::build_display_list() - self.cell.block_flow.build_display_list_for_block_no_damage(state, border_painting_mode) + self.cell + .block_flow + .build_display_list_for_block_no_damage(state, border_painting_mode) } } diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs index 63292cfbb55..51a6078ec31 100644 --- a/components/layout/table_caption.rs +++ b/components/layout/table_caption.rs @@ -58,7 +58,10 @@ impl Flow for TableCaptionFlow { } fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_caption"); + debug!( + "assign_inline_sizes({}): assigning inline_size for flow", + "table_caption" + ); self.block_flow.assign_inline_sizes(layout_context); } @@ -68,15 +71,18 @@ impl Flow for TableCaptionFlow { } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context) + self.block_flow + .compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn build_display_list(&mut self, state: &mut DisplayListBuildState) { @@ -85,8 +91,8 @@ impl Flow for TableCaptionFlow { } fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) { - self.block_flow.collect_stacking_contexts_for_block(state, - StackingContextCollectionFlags::empty()); + self.block_flow + .collect_stacking_contexts_for_block(state, StackingContextCollectionFlags::empty()); } fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) { @@ -109,11 +115,17 @@ impl Flow for TableCaptionFlow { self.block_flow.generated_containing_block_size(flow) } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position) + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ) } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index fe8d453cb0b..1af32166a5f 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -63,7 +63,10 @@ impl TableCellFlow { } pub fn from_node_fragment_and_visibility_flag<N: ThreadSafeLayoutNode>( - node: &N, fragment: Fragment, visible: bool) -> TableCellFlow { + node: &N, + fragment: Fragment, + visible: bool, + ) -> TableCellFlow { TableCellFlow { block_flow: BlockFlow::from_fragment(fragment), collapsed_borders: CollapsedBordersForCell::new(), @@ -90,7 +93,8 @@ impl TableCellFlow { let remaining = self.block_flow.assign_block_size_block_base( layout_context, None, - MarginsMayCollapseFlag::MarginsMayNotCollapse); + MarginsMayCollapseFlag::MarginsMayNotCollapse, + ); debug_assert!(remaining.is_none()); } @@ -102,12 +106,14 @@ impl TableCellFlow { for kid in self.base().children.iter() { let kid_base = kid.base(); if kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { - continue + continue; } - let start = kid_base.position.start.b - - kid_base.collapsible_margins.block_start_margin_for_noncollapsible_context(); - let end = kid_base.position.start.b + kid_base.position.size.block + - kid_base.collapsible_margins.block_end_margin_for_noncollapsible_context(); + let start = kid_base.position.start.b - kid_base + .collapsible_margins + .block_start_margin_for_noncollapsible_context(); + let end = kid_base.position.start.b + kid_base.position.size.block + kid_base + .collapsible_margins + .block_end_margin_for_noncollapsible_context(); match extents { Some((ref mut first_start, ref mut last_end)) => { if start < *first_start { @@ -116,7 +122,7 @@ impl TableCellFlow { if end > *last_end { *last_end = end } - } + }, None => extents = Some((start, end)), } } @@ -138,7 +144,7 @@ impl TableCellFlow { _ => Au(0), }; if offset == Au(0) { - return + return; } for kid in self.mut_base().children.iter_mut() { @@ -154,9 +160,8 @@ impl TableCellFlow { // Call after block size calculation pub fn total_block_size(&mut self) -> Au { // TODO: Percentage block-size - let specified = MaybeAuto::from_style(self.fragment().style() - .content_block_size(), - Au(0)).specified_or_zero(); + let specified = MaybeAuto::from_style(self.fragment().style().content_block_size(), Au(0)) + .specified_or_zero(); specified + self.fragment().border_padding.block_start_end() } } @@ -185,23 +190,46 @@ impl Flow for TableCellFlow { /// Minimum/preferred inline-sizes set by this function are used in automatic table layout /// calculation. fn bubble_inline_sizes(&mut self) { - let _scope = layout_debug_scope!("table_cell::bubble_inline_sizes {:x}", - self.block_flow.base.debug_id()); + let _scope = layout_debug_scope!( + "table_cell::bubble_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); self.block_flow.bubble_inline_sizes_for_block(true); - let specified_inline_size = MaybeAuto::from_style(self.block_flow - .fragment - .style() - .content_inline_size(), - Au(0)).specified_or_zero(); - if self.block_flow.base.intrinsic_inline_sizes.minimum_inline_size < - specified_inline_size { - self.block_flow.base.intrinsic_inline_sizes.minimum_inline_size = specified_inline_size + let specified_inline_size = MaybeAuto::from_style( + self.block_flow.fragment.style().content_inline_size(), + Au(0), + ).specified_or_zero(); + if self + .block_flow + .base + .intrinsic_inline_sizes + .minimum_inline_size < + specified_inline_size + { + self.block_flow + .base + .intrinsic_inline_sizes + .minimum_inline_size = specified_inline_size } - if self.block_flow.base.intrinsic_inline_sizes.preferred_inline_size < - self.block_flow.base.intrinsic_inline_sizes.minimum_inline_size { - self.block_flow.base.intrinsic_inline_sizes.preferred_inline_size = - self.block_flow.base.intrinsic_inline_sizes.minimum_inline_size; + if self + .block_flow + .base + .intrinsic_inline_sizes + .preferred_inline_size < + self.block_flow + .base + .intrinsic_inline_sizes + .minimum_inline_size + { + self.block_flow + .base + .intrinsic_inline_sizes + .preferred_inline_size = self + .block_flow + .base + .intrinsic_inline_sizes + .minimum_inline_size; } } @@ -209,35 +237,42 @@ impl Flow for TableCellFlow { /// When called on this context, the context has had its inline-size set by the parent table /// row. fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - let _scope = layout_debug_scope!("table_cell::assign_inline_sizes {:x}", - self.block_flow.base.debug_id()); - debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_cell"); + let _scope = layout_debug_scope!( + "table_cell::assign_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); + debug!( + "assign_inline_sizes({}): assigning inline_size for flow", + "table_cell" + ); let shared_context = layout_context.shared_context(); // The position was set to the column inline-size by the parent flow, table row flow. let containing_block_inline_size = self.block_flow.base.block_container_inline_size; let inline_size_computer = InternalTable; - inline_size_computer.compute_used_inline_size(&mut self.block_flow, - shared_context, - containing_block_inline_size); + inline_size_computer.compute_used_inline_size( + &mut self.block_flow, + shared_context, + containing_block_inline_size, + ); - let inline_start_content_edge = - self.block_flow.fragment.border_box.start.i + + let inline_start_content_edge = self.block_flow.fragment.border_box.start.i + self.block_flow.fragment.border_padding.inline_start; - let inline_end_content_edge = - self.block_flow.base.block_container_inline_size - + let inline_end_content_edge = self.block_flow.base.block_container_inline_size - self.block_flow.fragment.border_padding.inline_start_end() - self.block_flow.fragment.border_box.size.inline; let padding_and_borders = self.block_flow.fragment.border_padding.inline_start_end(); let content_inline_size = self.block_flow.fragment.border_box.size.inline - padding_and_borders; - self.block_flow.propagate_assigned_inline_size_to_children(shared_context, - inline_start_content_edge, - inline_end_content_edge, - content_inline_size, - |_, _, _, _, _, _| {}); + self.block_flow.propagate_assigned_inline_size_to_children( + shared_context, + inline_start_content_edge, + inline_end_content_edge, + content_inline_size, + |_, _, _, _, _, _| {}, + ); } fn assign_block_size(&mut self, layout_context: &LayoutContext) { @@ -246,15 +281,18 @@ impl Flow for TableCellFlow { } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context) + self.block_flow + .compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn build_display_list(&mut self, _: &mut DisplayListBuildState) { @@ -264,12 +302,15 @@ impl Flow for TableCellFlow { // we skip setting the damage in TableCellStyleInfo::build_display_list() // because we only have immutable access - self.block_flow.fragment.restyle_damage.remove(ServoRestyleDamage::REPAINT); + self.block_flow + .fragment + .restyle_damage + .remove(ServoRestyleDamage::REPAINT); } fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) { - self.block_flow.collect_stacking_contexts_for_block(state, - StackingContextCollectionFlags::empty()); + self.block_flow + .collect_stacking_contexts_for_block(state, StackingContextCollectionFlags::empty()); } fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) { @@ -292,11 +333,17 @@ impl Flow for TableCellFlow { self.block_flow.generated_containing_block_size(flow) } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position) + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ) } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { @@ -379,67 +426,74 @@ impl CollapsedBordersForCell { } } - pub fn adjust_border_bounds_for_painting(&self, - border_bounds: &mut Rect<Au>, - writing_mode: WritingMode) { + pub fn adjust_border_bounds_for_painting( + &self, + border_bounds: &mut Rect<Au>, + writing_mode: WritingMode, + ) { let inline_start_divisor = if self.should_paint_inline_start_border() { 2 } else { -2 }; - let inline_start_offset = self.inline_start_width / 2 + self.inline_start_border.width / - inline_start_divisor; + let inline_start_offset = + self.inline_start_width / 2 + self.inline_start_border.width / inline_start_divisor; let inline_end_divisor = if self.should_paint_inline_end_border() { 2 } else { -2 }; - let inline_end_offset = self.inline_end_width / 2 + self.inline_end_border.width / - inline_end_divisor; + let inline_end_offset = + self.inline_end_width / 2 + self.inline_end_border.width / inline_end_divisor; let block_start_divisor = if self.should_paint_block_start_border() { 2 } else { -2 }; - let block_start_offset = self.block_start_width / 2 + self.block_start_border.width / - block_start_divisor; + let block_start_offset = + self.block_start_width / 2 + self.block_start_border.width / block_start_divisor; let block_end_divisor = if self.should_paint_block_end_border() { 2 } else { -2 }; - let block_end_offset = self.block_end_width / 2 + self.block_end_border.width / - block_end_divisor; + let block_end_offset = + self.block_end_width / 2 + self.block_end_border.width / block_end_divisor; // FIXME(pcwalton): Get the real container size. let mut logical_bounds = LogicalRect::from_physical(writing_mode, *border_bounds, Size2D::new(Au(0), Au(0))); logical_bounds.start.i = logical_bounds.start.i - inline_start_offset; logical_bounds.start.b = logical_bounds.start.b - block_start_offset; - logical_bounds.size.inline = logical_bounds.size.inline + inline_start_offset + - inline_end_offset; - logical_bounds.size.block = logical_bounds.size.block + block_start_offset + - block_end_offset; + logical_bounds.size.inline = + logical_bounds.size.inline + inline_start_offset + inline_end_offset; + logical_bounds.size.block = + logical_bounds.size.block + block_start_offset + block_end_offset; *border_bounds = logical_bounds.to_physical(writing_mode, Size2D::new(Au(0), Au(0))) } pub fn adjust_border_colors_and_styles_for_painting( - &self, - border_colors: &mut SideOffsets2D<Color>, - border_styles: &mut SideOffsets2D<BorderStyle>, - writing_mode: WritingMode) { - let logical_border_colors = LogicalMargin::new(writing_mode, - self.block_start_border.color, - self.inline_end_border.color, - self.block_end_border.color, - self.inline_start_border.color); + &self, + border_colors: &mut SideOffsets2D<Color>, + border_styles: &mut SideOffsets2D<BorderStyle>, + writing_mode: WritingMode, + ) { + let logical_border_colors = LogicalMargin::new( + writing_mode, + self.block_start_border.color, + self.inline_end_border.color, + self.block_end_border.color, + self.inline_start_border.color, + ); *border_colors = logical_border_colors.to_physical(writing_mode); - let logical_border_styles = LogicalMargin::new(writing_mode, - self.block_start_border.style, - self.inline_end_border.style, - self.block_end_border.style, - self.inline_start_border.style); + let logical_border_styles = LogicalMargin::new( + writing_mode, + self.block_start_border.style, + self.inline_end_border.style, + self.block_end_border.style, + self.inline_start_border.style, + ); *border_styles = logical_border_styles.to_physical(writing_mode); } } diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index cd1260098f1..7a3b54a2ed0 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -43,12 +43,14 @@ impl TableColGroupFlow { pub fn from_fragments(fragment: Fragment, fragments: Vec<Fragment>) -> TableColGroupFlow { let writing_mode = fragment.style().writing_mode; TableColGroupFlow { - base: BaseFlow::new(Some(fragment.style()), - writing_mode, - ForceNonfloatedFlag::ForceNonfloated), + base: BaseFlow::new( + Some(fragment.style()), + writing_mode, + ForceNonfloatedFlag::ForceNonfloated, + ), fragment: Some(fragment), cols: fragments, - inline_sizes: vec!(), + inline_sizes: vec![], } } } @@ -67,8 +69,10 @@ impl Flow for TableColGroupFlow { } fn bubble_inline_sizes(&mut self) { - let _scope = layout_debug_scope!("table_colgroup::bubble_inline_sizes {:x}", - self.base.debug_id()); + let _scope = layout_debug_scope!( + "table_colgroup::bubble_inline_sizes {:x}", + self.base.debug_id() + ); for fragment in &self.cols { // Retrieve the specified value from the appropriate CSS property. @@ -81,19 +85,17 @@ impl Flow for TableColGroupFlow { /// Table column inline-sizes are assigned in the table flow and propagated to table row flows /// and/or rowgroup flows. Therefore, table colgroup flows do not need to assign inline-sizes. - fn assign_inline_sizes(&mut self, _: &LayoutContext) { - } + fn assign_inline_sizes(&mut self, _: &LayoutContext) {} /// Table columns do not have block-size. - fn assign_block_size(&mut self, _: &LayoutContext) { - } + fn assign_block_size(&mut self, _: &LayoutContext) {} fn update_late_computed_inline_position_if_necessary(&mut self, _: Au) {} fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {} // Table columns are invisible. - fn build_display_list(&mut self, _: &mut DisplayListBuildState) { } + fn build_display_list(&mut self, _: &mut DisplayListBuildState) {} fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) { self.base.stacking_context_id = state.current_stacking_context_id; @@ -110,10 +112,13 @@ impl Flow for TableColGroupFlow { panic!("Table column groups can't be containing blocks!") } - fn iterate_through_fragment_border_boxes(&self, - _: &mut FragmentBorderBoxIterator, - _: i32, - _: &Point2D<Au>) {} + fn iterate_through_fragment_border_boxes( + &self, + _: &mut FragmentBorderBoxIterator, + _: i32, + _: &Point2D<Au>, + ) { + } fn mutate_fragments(&mut self, _: &mut FnMut(&mut Fragment)) {} } diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index ffecce5d6c7..9d5c3a15618 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -89,7 +89,6 @@ pub struct CellIntrinsicInlineSize { pub row_span: u32, } - impl TableRowFlow { pub fn from_fragment(fragment: Fragment) -> TableRowFlow { let writing_mode = fragment.style().writing_mode; @@ -111,14 +110,19 @@ impl TableRowFlow { /// TODO(pcwalton): This doesn't handle floats and positioned elements right. /// /// Returns the block size - pub fn compute_block_size_table_row_base<'a>(&'a mut self, layout_context: &LayoutContext, - incoming_rowspan_data: &mut Vec<Au>, - border_info: &[TableRowSizeData], - row_index: usize) -> Au { - fn include_sizes_from_previous_rows(col: &mut usize, - incoming_rowspan: &[u32], - incoming_rowspan_data: &mut Vec<Au>, - max_block_size: &mut Au) { + pub fn compute_block_size_table_row_base<'a>( + &'a mut self, + layout_context: &LayoutContext, + incoming_rowspan_data: &mut Vec<Au>, + border_info: &[TableRowSizeData], + row_index: usize, + ) -> Au { + fn include_sizes_from_previous_rows( + col: &mut usize, + incoming_rowspan: &[u32], + incoming_rowspan_data: &mut Vec<Au>, + max_block_size: &mut Au, + ) { while let Some(span) = incoming_rowspan.get(*col) { if *span == 1 { break; @@ -141,19 +145,28 @@ impl TableRowFlow { // all cells). let mut max_block_size = Au(0); let thread_id = self.block_flow.base.thread_id; - let content_box = self.block_flow.base.position - - self.block_flow.fragment.border_padding - - self.block_flow.fragment.margin; + let content_box = self.block_flow.base.position - + self.block_flow.fragment.border_padding - + self.block_flow.fragment.margin; let mut col = 0; for kid in self.block_flow.base.child_iter_mut() { - include_sizes_from_previous_rows(&mut col, &self.incoming_rowspan, - incoming_rowspan_data, &mut max_block_size); + include_sizes_from_previous_rows( + &mut col, + &self.incoming_rowspan, + incoming_rowspan_data, + &mut max_block_size, + ); kid.place_float_if_applicable(); - debug_assert!(!kid.base().flags.is_float(), "table cells should never float"); - kid.assign_block_size_for_inorder_child_if_necessary(layout_context, - thread_id, - content_box); + debug_assert!( + !kid.base().flags.is_float(), + "table cells should never float" + ); + kid.assign_block_size_for_inorder_child_if_necessary( + layout_context, + thread_id, + content_box, + ); let mut row_span; let column_span; @@ -172,7 +185,8 @@ impl TableRowFlow { if incoming_rowspan_data.len() <= col { incoming_rowspan_data.resize(col + 1, Au(0)); } - let border_sizes_spanned = get_spanned_border_size(border_info, row_index, &mut row_span); + let border_sizes_spanned = + get_spanned_border_size(border_info, row_index, &mut row_span); cell_block_size_pressure -= border_sizes_spanned; @@ -186,33 +200,41 @@ impl TableRowFlow { max_block_size = max(max_block_size, cell_block_size_pressure); col += column_span; } - include_sizes_from_previous_rows(&mut col, &self.incoming_rowspan, incoming_rowspan_data, &mut max_block_size); + include_sizes_from_previous_rows( + &mut col, + &self.incoming_rowspan, + incoming_rowspan_data, + &mut max_block_size, + ); let mut block_size = max_block_size; // TODO: Percentage block-size - block_size = match MaybeAuto::from_style(self.block_flow - .fragment - .style() - .content_block_size(), - Au(0)) { + block_size = match MaybeAuto::from_style( + self.block_flow.fragment.style().content_block_size(), + Au(0), + ) { MaybeAuto::Auto => block_size, MaybeAuto::Specified(value) => max(value, block_size), }; block_size } - pub fn assign_block_size_to_self_and_children(&mut self, sizes: &[TableRowSizeData], index: usize) { + pub fn assign_block_size_to_self_and_children( + &mut self, + sizes: &[TableRowSizeData], + index: usize, + ) { // Assign the block-size of kid fragments, which is the same value as own block-size. let block_size = sizes[index].size; for kid in self.block_flow.base.child_iter_mut() { let child_table_cell = kid.as_mut_table_cell(); let block_size = if child_table_cell.row_span != 1 { let mut row_span = child_table_cell.row_span; - let border_sizes_spanned = - get_spanned_border_size(sizes, index, &mut row_span); - let row_sizes = sizes[index..].iter() - .take(row_span as usize) - .fold(Au(0), |accum, r| accum + r.size); + let border_sizes_spanned = get_spanned_border_size(sizes, index, &mut row_span); + let row_sizes = sizes[index..] + .iter() + .take(row_span as usize) + .fold(Au(0), |accum, r| accum + r.size); row_sizes + border_sizes_spanned } else { block_size @@ -232,17 +254,13 @@ impl TableRowFlow { // Write in the size of the relative containing block for children. (This // information is also needed to handle RTL.) - child_table_cell.block_flow.base.early_absolute_position_info = - EarlyAbsolutePositionInfo { - relative_containing_block_size: self.block_flow - .fragment - .content_box() - .size, - relative_containing_block_mode: self.block_flow - .fragment - .style() - .writing_mode, - }; + child_table_cell + .block_flow + .base + .early_absolute_position_info = EarlyAbsolutePositionInfo { + relative_containing_block_size: self.block_flow.fragment.content_box().size, + relative_containing_block_mode: self.block_flow.fragment.style().writing_mode, + }; } // Assign the block-size of own fragment @@ -253,22 +271,28 @@ impl TableRowFlow { } pub fn populate_collapsed_border_spacing<'a, I>( - &mut self, - collapsed_inline_direction_border_widths_for_table: &[Au], - collapsed_block_direction_border_widths_for_table: &mut Peekable<I>) - where I: Iterator<Item=&'a Au> { + &mut self, + collapsed_inline_direction_border_widths_for_table: &[Au], + collapsed_block_direction_border_widths_for_table: &mut Peekable<I>, + ) where + I: Iterator<Item = &'a Au>, + { self.collapsed_border_spacing.inline.clear(); - self.collapsed_border_spacing - .inline - .extend(collapsed_inline_direction_border_widths_for_table.into_iter().map(|x| *x)); + self.collapsed_border_spacing.inline.extend( + collapsed_inline_direction_border_widths_for_table + .into_iter() + .map(|x| *x), + ); if let Some(collapsed_block_direction_border_width_for_table) = - collapsed_block_direction_border_widths_for_table.next() { + collapsed_block_direction_border_widths_for_table.next() + { self.collapsed_border_spacing.block_start = *collapsed_block_direction_border_width_for_table } if let Some(collapsed_block_direction_border_width_for_table) = - collapsed_block_direction_border_widths_for_table.peek() { + collapsed_block_direction_border_widths_for_table.peek() + { self.collapsed_border_spacing.block_end = **collapsed_block_direction_border_width_for_table } @@ -308,9 +332,10 @@ fn get_spanned_border_size(sizes: &[TableRowSizeData], row_index: usize, row_spa if sizes[last_row_idx].rowgroup_id != sizes[row_index].rowgroup_id { // XXXManishearth this loop can be avoided by also storing // a "last_rowgroup_at" index so we can leapfrog back quickly - *row_span = sizes[row_index..last_row_idx + 1].iter() - .position(|s| s.rowgroup_id != sizes[row_index].rowgroup_id) - .unwrap() as u32; + *row_span = sizes[row_index..last_row_idx + 1] + .iter() + .position(|s| s.rowgroup_id != sizes[row_index].rowgroup_id) + .unwrap() as u32; last_row_idx = row_index + *row_span as usize - 1; } sizes[last_row_idx].cumulative_border_spacing - sizes[row_index].cumulative_border_spacing @@ -345,20 +370,26 @@ impl Flow for TableRowFlow { /// The specified column inline-sizes of children cells are used in fixed table layout /// calculation. fn bubble_inline_sizes(&mut self) { - let _scope = layout_debug_scope!("table_row::bubble_inline_sizes {:x}", - self.block_flow.base.debug_id()); + let _scope = layout_debug_scope!( + "table_row::bubble_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); // Bubble up the specified inline-sizes from child table cells. let (mut min_inline_size, mut pref_inline_size) = (Au(0), Au(0)); - let collapsing_borders = self.block_flow - .fragment - .style() - .get_inherited_table() - .border_collapse == BorderCollapse::Collapse; + let collapsing_borders = self + .block_flow + .fragment + .style() + .get_inherited_table() + .border_collapse == + BorderCollapse::Collapse; let row_style = &*self.block_flow.fragment.style; - self.preliminary_collapsed_borders.reset( - CollapsedBorder::inline_start(&row_style, - CollapsedBorderProvenance::FromTableRow)); + self.preliminary_collapsed_borders + .reset(CollapsedBorder::inline_start( + &row_style, + CollapsedBorderProvenance::FromTableRow, + )); { let children_count = self.block_flow.base.children.len(); @@ -373,10 +404,11 @@ impl Flow for TableRowFlow { let child_row_span; { let child_table_cell = kid.as_mut_table_cell(); - child_specified_inline_size = child_table_cell.block_flow - .fragment - .style - .content_inline_size(); + child_specified_inline_size = child_table_cell + .block_flow + .fragment + .style + .content_inline_size(); child_column_span = child_table_cell.column_span; child_row_span = child_table_cell.row_span; @@ -388,7 +420,8 @@ impl Flow for TableRowFlow { i, child_table_cell, &mut iterator, - &mut self.preliminary_collapsed_borders) + &mut self.preliminary_collapsed_borders, + ) } } @@ -401,7 +434,7 @@ impl Flow for TableRowFlow { LengthOrPercentageOrAuto::Calc(_) | LengthOrPercentageOrAuto::Percentage(_) => { child_base.intrinsic_inline_sizes.minimum_inline_size - } + }, LengthOrPercentageOrAuto::Length(length) => Au::from(length), }, percentage: match child_specified_inline_size { @@ -420,23 +453,34 @@ impl Flow for TableRowFlow { }; min_inline_size = min_inline_size + child_column_inline_size.minimum_length; pref_inline_size = pref_inline_size + child_column_inline_size.preferred; - self.cell_intrinsic_inline_sizes.push(CellIntrinsicInlineSize { - column_size: child_column_inline_size, - column_span: child_column_span, - row_span: child_row_span, - }); + self.cell_intrinsic_inline_sizes + .push(CellIntrinsicInlineSize { + column_size: child_column_inline_size, + column_span: child_column_span, + row_span: child_row_span, + }); } } - self.block_flow.base.intrinsic_inline_sizes.minimum_inline_size = min_inline_size; - self.block_flow.base.intrinsic_inline_sizes.preferred_inline_size = max(min_inline_size, - pref_inline_size); + self.block_flow + .base + .intrinsic_inline_sizes + .minimum_inline_size = min_inline_size; + self.block_flow + .base + .intrinsic_inline_sizes + .preferred_inline_size = max(min_inline_size, pref_inline_size); } fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - let _scope = layout_debug_scope!("table_row::assign_inline_sizes {:x}", - self.block_flow.base.debug_id()); - debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_row"); + let _scope = layout_debug_scope!( + "table_row::assign_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); + debug!( + "assign_inline_sizes({}): assigning inline_size for flow", + "table_row" + ); let shared_context = layout_context.shared_context(); // The position was set to the containing block by the flow's parent. @@ -447,9 +491,11 @@ impl Flow for TableRowFlow { let inline_end_content_edge = Au(0); let inline_size_computer = InternalTable; - inline_size_computer.compute_used_inline_size(&mut self.block_flow, - shared_context, - containing_block_inline_size); + inline_size_computer.compute_used_inline_size( + &mut self.block_flow, + shared_context, + containing_block_inline_size, + ); // Spread out the completed inline sizes among columns with spans > 1. let num_columns = self.column_computed_inline_sizes.len(); @@ -461,26 +507,23 @@ impl Flow for TableRowFlow { while col < self.incoming_rowspan.len() && self.incoming_rowspan[col] != 1 { let size = match self.column_computed_inline_sizes.get(col) { Some(column_computed_inline_size) => *column_computed_inline_size, - None => ColumnComputedInlineSize { size: Au(0) } // See FIXME below. + None => ColumnComputedInlineSize { size: Au(0) }, // See FIXME below. }; computed_inline_size_for_cells.push(size); col += 1; } // Start with the computed inline size for the first column in the span. - let mut column_computed_inline_size = - match self.column_computed_inline_sizes.get(col) { - Some(column_computed_inline_size) => *column_computed_inline_size, - None => { - // We're in fixed layout mode and there are more cells in this row than - // columns we know about. According to CSS 2.1 § 17.5.2.1, the behavior is - // now undefined. So just use zero. - // - // FIXME(pcwalton): $10 says this isn't Web compatible. - ColumnComputedInlineSize { - size: Au(0), - } - } - }; + let mut column_computed_inline_size = match self.column_computed_inline_sizes.get(col) { + Some(column_computed_inline_size) => *column_computed_inline_size, + None => { + // We're in fixed layout mode and there are more cells in this row than + // columns we know about. According to CSS 2.1 § 17.5.2.1, the behavior is + // now undefined. So just use zero. + // + // FIXME(pcwalton): $10 says this isn't Web compatible. + ColumnComputedInlineSize { size: Au(0) } + }, + }; col += 1; // Add in computed inline sizes for any extra columns in the span. @@ -491,7 +534,8 @@ impl Flow for TableRowFlow { None => break, }; column_computed_inline_size.size = column_computed_inline_size.size + - extra_column_computed_inline_size.size + self.spacing.horizontal(); + extra_column_computed_inline_size.size + + self.spacing.horizontal(); col += 1; } @@ -499,16 +543,19 @@ impl Flow for TableRowFlow { } // Set up border collapse info. - let border_collapse_info = - match self.block_flow.fragment.style().get_inherited_table().border_collapse { - BorderCollapse::Collapse => { - Some(BorderCollapseInfoForChildTableCell { - collapsed_borders_for_row: &self.final_collapsed_borders, - collapsed_border_spacing_for_row: &self.collapsed_border_spacing, - }) - } - BorderCollapse::Separate => None, - }; + let border_collapse_info = match self + .block_flow + .fragment + .style() + .get_inherited_table() + .border_collapse + { + BorderCollapse::Collapse => Some(BorderCollapseInfoForChildTableCell { + collapsed_borders_for_row: &self.final_collapsed_borders, + collapsed_border_spacing_for_row: &self.collapsed_border_spacing, + }), + BorderCollapse::Separate => None, + }; // Push those inline sizes down to the cells. let spacing = self.spacing; @@ -517,30 +564,33 @@ impl Flow for TableRowFlow { let incoming_rowspan = &self.incoming_rowspan; let mut column_index = 0; - self.block_flow.propagate_assigned_inline_size_to_children(shared_context, - inline_start_content_edge, - inline_end_content_edge, - containing_block_inline_size, - |child_flow, - child_index, - content_inline_size, - _writing_mode, - inline_start_margin_edge, - inline_end_margin_edge| { - set_inline_position_of_child_flow( - child_flow, - child_index, - &mut column_index, - incoming_rowspan, - row_writing_mode, - table_writing_mode, - &computed_inline_size_for_cells, - &spacing, - &border_collapse_info, - content_inline_size, - inline_start_margin_edge, - inline_end_margin_edge); - }) + self.block_flow.propagate_assigned_inline_size_to_children( + shared_context, + inline_start_content_edge, + inline_end_content_edge, + containing_block_inline_size, + |child_flow, + child_index, + content_inline_size, + _writing_mode, + inline_start_margin_edge, + inline_end_margin_edge| { + set_inline_position_of_child_flow( + child_flow, + child_index, + &mut column_index, + incoming_rowspan, + row_writing_mode, + table_writing_mode, + &computed_inline_size_for_cells, + &spacing, + &border_collapse_info, + content_inline_size, + inline_start_margin_edge, + inline_end_margin_edge, + ); + }, + ) } fn assign_block_size(&mut self, _: &LayoutContext) { @@ -548,15 +598,18 @@ impl Flow for TableRowFlow { } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context) + self.block_flow + .compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn build_display_list(&mut self, _: &mut DisplayListBuildState) { @@ -564,12 +617,15 @@ impl Flow for TableRowFlow { // handled in TableCellStyleInfo::build_display_list // we skip setting the damage in TableCellStyleInfo::build_display_list() // because we only have immutable access - self.block_flow.fragment.restyle_damage.remove(ServoRestyleDamage::REPAINT); + self.block_flow + .fragment + .restyle_damage + .remove(ServoRestyleDamage::REPAINT); } fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) { - self.block_flow.collect_stacking_contexts_for_block(state, - StackingContextCollectionFlags::empty()); + self.block_flow + .collect_stacking_contexts_for_block(state, StackingContextCollectionFlags::empty()); } fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) { @@ -592,11 +648,17 @@ impl Flow for TableRowFlow { self.block_flow.generated_containing_block_size(flow) } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position) + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ) } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { @@ -711,8 +773,7 @@ impl CollapsedBorder { /// Creates a collapsed border from the block-start border described in the given CSS style /// object. - fn top(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) - -> CollapsedBorder { + fn top(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) -> CollapsedBorder { CollapsedBorder { style: css_style.get_border().border_top_style, width: Au::from(css_style.get_border().border_top_width), @@ -723,8 +784,7 @@ impl CollapsedBorder { /// Creates a collapsed border style from the right border described in the given CSS style /// object. - fn right(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) - -> CollapsedBorder { + fn right(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) -> CollapsedBorder { CollapsedBorder { style: css_style.get_border().border_right_style, width: Au::from(css_style.get_border().border_right_width), @@ -735,8 +795,10 @@ impl CollapsedBorder { /// Creates a collapsed border style from the bottom border described in the given CSS style /// object. - fn bottom(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) - -> CollapsedBorder { + fn bottom( + css_style: &ComputedValues, + provenance: CollapsedBorderProvenance, + ) -> CollapsedBorder { CollapsedBorder { style: css_style.get_border().border_bottom_style, width: Au::from(css_style.get_border().border_bottom_width), @@ -747,8 +809,7 @@ impl CollapsedBorder { /// Creates a collapsed border style from the left border described in the given CSS style /// object. - fn left(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) - -> CollapsedBorder { + fn left(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) -> CollapsedBorder { CollapsedBorder { style: css_style.get_border().border_left_style, width: Au::from(css_style.get_border().border_left_width), @@ -758,10 +819,11 @@ impl CollapsedBorder { } /// Creates a collapsed border style from the given physical side. - fn from_side(side: PhysicalSide, - css_style: &ComputedValues, - provenance: CollapsedBorderProvenance) - -> CollapsedBorder { + fn from_side( + side: PhysicalSide, + css_style: &ComputedValues, + provenance: CollapsedBorderProvenance, + ) -> CollapsedBorder { match side { PhysicalSide::Top => CollapsedBorder::top(css_style, provenance), PhysicalSide::Right => CollapsedBorder::right(css_style, provenance), @@ -772,56 +834,72 @@ impl CollapsedBorder { /// Creates a collapsed border style from the inline-start border described in the given CSS /// style object. - pub fn inline_start(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) - -> CollapsedBorder { - CollapsedBorder::from_side(css_style.writing_mode.inline_start_physical_side(), - css_style, - provenance) + pub fn inline_start( + css_style: &ComputedValues, + provenance: CollapsedBorderProvenance, + ) -> CollapsedBorder { + CollapsedBorder::from_side( + css_style.writing_mode.inline_start_physical_side(), + css_style, + provenance, + ) } /// Creates a collapsed border style from the inline-start border described in the given CSS /// style object. - pub fn inline_end(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) - -> CollapsedBorder { - CollapsedBorder::from_side(css_style.writing_mode.inline_end_physical_side(), - css_style, - provenance) + pub fn inline_end( + css_style: &ComputedValues, + provenance: CollapsedBorderProvenance, + ) -> CollapsedBorder { + CollapsedBorder::from_side( + css_style.writing_mode.inline_end_physical_side(), + css_style, + provenance, + ) } /// Creates a collapsed border style from the block-start border described in the given CSS /// style object. - pub fn block_start(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) - -> CollapsedBorder { - CollapsedBorder::from_side(css_style.writing_mode.block_start_physical_side(), - css_style, - provenance) + pub fn block_start( + css_style: &ComputedValues, + provenance: CollapsedBorderProvenance, + ) -> CollapsedBorder { + CollapsedBorder::from_side( + css_style.writing_mode.block_start_physical_side(), + css_style, + provenance, + ) } /// Creates a collapsed border style from the block-end border described in the given CSS style /// object. - pub fn block_end(css_style: &ComputedValues, provenance: CollapsedBorderProvenance) - -> CollapsedBorder { - CollapsedBorder::from_side(css_style.writing_mode.block_end_physical_side(), - css_style, - provenance) + pub fn block_end( + css_style: &ComputedValues, + provenance: CollapsedBorderProvenance, + ) -> CollapsedBorder { + CollapsedBorder::from_side( + css_style.writing_mode.block_end_physical_side(), + css_style, + provenance, + ) } /// If `other` has a higher priority per CSS 2.1 § 17.6.2.1, replaces `self` with it. pub fn combine(&mut self, other: &CollapsedBorder) { match (self.style, other.style) { // Step 1. - (BorderStyle::Hidden, _) => {} + (BorderStyle::Hidden, _) => {}, (_, BorderStyle::Hidden) => *self = *other, // Step 2. (BorderStyle::None, _) => *self = *other, - (_, BorderStyle::None) => {} + (_, BorderStyle::None) => {}, // Step 3. - _ if self.width > other.width => {} + _ if self.width > other.width => {}, _ if self.width < other.width => *self = *other, - (this_style, other_style) if this_style > other_style => {} + (this_style, other_style) if this_style > other_style => {}, (this_style, other_style) if this_style < other_style => *self = *other, // Step 4. - _ if (self.provenance as i8) >= other.provenance as i8 => {} + _ if (self.provenance as i8) >= other.provenance as i8 => {}, _ => *self = *other, } } @@ -829,11 +907,12 @@ impl CollapsedBorder { /// Pushes column inline size, incoming rowspan, and border collapse info down to a child. pub fn propagate_column_inline_sizes_to_child( - child_flow: &mut Flow, - table_writing_mode: WritingMode, - column_computed_inline_sizes: &[ColumnComputedInlineSize], - border_spacing: &BorderSpacing, - incoming_rowspan: &mut Vec<u32>) { + child_flow: &mut Flow, + table_writing_mode: WritingMode, + column_computed_inline_sizes: &[ColumnComputedInlineSize], + border_spacing: &BorderSpacing, + incoming_rowspan: &mut Vec<u32>, +) { // If the child is a row group or a row, the column inline-size and rowspan info should be copied from its // parent. // @@ -844,13 +923,15 @@ pub fn propagate_column_inline_sizes_to_child( let child_table_rowgroup_flow = child_flow.as_mut_table_rowgroup(); child_table_rowgroup_flow.spacing = *border_spacing; for kid in child_table_rowgroup_flow.block_flow.base.child_iter_mut() { - propagate_column_inline_sizes_to_child(kid, - table_writing_mode, - column_computed_inline_sizes, - border_spacing, - incoming_rowspan); + propagate_column_inline_sizes_to_child( + kid, + table_writing_mode, + column_computed_inline_sizes, + border_spacing, + incoming_rowspan, + ); } - } + }, FlowClass::TableRow => { let child_table_row_flow = child_flow.as_mut_table_row(); child_table_row_flow.column_computed_inline_sizes = @@ -887,27 +968,28 @@ pub fn propagate_column_inline_sizes_to_child( col += 1; } } - } - c => warn!("unexpected flow in table {:?}", c) + }, + c => warn!("unexpected flow in table {:?}", c), } } /// Lay out table cells inline according to the computer column sizes. fn set_inline_position_of_child_flow( - child_flow: &mut Flow, - child_index: usize, - column_index: &mut usize, - incoming_rowspan: &[u32], - row_writing_mode: WritingMode, - table_writing_mode: WritingMode, - column_computed_inline_sizes: &[ColumnComputedInlineSize], - border_spacing: &BorderSpacing, - border_collapse_info: &Option<BorderCollapseInfoForChildTableCell>, - parent_content_inline_size: Au, - inline_start_margin_edge: &mut Au, - inline_end_margin_edge: &mut Au) { + child_flow: &mut Flow, + child_index: usize, + column_index: &mut usize, + incoming_rowspan: &[u32], + row_writing_mode: WritingMode, + table_writing_mode: WritingMode, + column_computed_inline_sizes: &[ColumnComputedInlineSize], + border_spacing: &BorderSpacing, + border_collapse_info: &Option<BorderCollapseInfoForChildTableCell>, + parent_content_inline_size: Au, + inline_start_margin_edge: &mut Au, + inline_end_margin_edge: &mut Au, +) { if !child_flow.is_table_cell() { - return + return; } let reverse_column_order = table_writing_mode.is_bidi_ltr() != row_writing_mode.is_bidi_ltr(); @@ -933,33 +1015,42 @@ fn set_inline_position_of_child_flow( Some(ref border_collapse_info) => { // Write in the child's border collapse state. child_table_cell.collapsed_borders = CollapsedBordersForCell { - inline_start_border: border_collapse_info.collapsed_borders_for_row - .inline - .get(child_index) - .map_or(CollapsedBorder::new(), |x| *x), - inline_end_border: border_collapse_info.collapsed_borders_for_row - .inline - .get(child_index + 1) - .map_or(CollapsedBorder::new(), |x| *x), - block_start_border: border_collapse_info.collapsed_borders_for_row - .block_start - .get(child_index) - .map_or(CollapsedBorder::new(), |x| *x), - block_end_border: border_collapse_info.collapsed_borders_for_row - .block_end - .get(child_index) - .map_or(CollapsedBorder::new(), |x| *x), - inline_start_width: border_collapse_info.collapsed_border_spacing_for_row - .inline - .get(child_index) - .map_or(Au(0), |x| *x), - inline_end_width: border_collapse_info.collapsed_border_spacing_for_row - .inline - .get(child_index + 1) - .map_or(Au(0), |x| *x), - block_start_width: border_collapse_info.collapsed_border_spacing_for_row - .block_start, - block_end_width: border_collapse_info.collapsed_border_spacing_for_row.block_end, + inline_start_border: border_collapse_info + .collapsed_borders_for_row + .inline + .get(child_index) + .map_or(CollapsedBorder::new(), |x| *x), + inline_end_border: border_collapse_info + .collapsed_borders_for_row + .inline + .get(child_index + 1) + .map_or(CollapsedBorder::new(), |x| *x), + block_start_border: border_collapse_info + .collapsed_borders_for_row + .block_start + .get(child_index) + .map_or(CollapsedBorder::new(), |x| *x), + block_end_border: border_collapse_info + .collapsed_borders_for_row + .block_end + .get(child_index) + .map_or(CollapsedBorder::new(), |x| *x), + inline_start_width: border_collapse_info + .collapsed_border_spacing_for_row + .inline + .get(child_index) + .map_or(Au(0), |x| *x), + inline_end_width: border_collapse_info + .collapsed_border_spacing_for_row + .inline + .get(child_index + 1) + .map_or(Au(0), |x| *x), + block_start_width: border_collapse_info + .collapsed_border_spacing_for_row + .block_start, + block_end_width: border_collapse_info + .collapsed_border_spacing_for_row + .block_end, }; // Move over past the collapsed border. @@ -968,7 +1059,7 @@ fn set_inline_position_of_child_flow( } else { *inline_start_margin_edge += child_table_cell.collapsed_borders.inline_start_width; } - } + }, None => { // Take spacing into account. if reverse_column_order { @@ -976,7 +1067,7 @@ fn set_inline_position_of_child_flow( } else { *inline_start_margin_edge += border_spacing.horizontal(); } - } + }, } let column_inline_size = column_computed_inline_sizes[*column_index].size; @@ -1008,51 +1099,68 @@ pub struct BorderCollapseInfoForChildTableCell<'a> { /// table row. This is done eagerly here so that at least the inline inside border collapse /// computations can be parallelized across all the rows of the table. fn perform_inline_direction_border_collapse_for_row( - row_style: &ComputedValues, - children_count: usize, - child_index: usize, - child_table_cell: &mut TableCellFlow, - iterator: &mut Peekable<Enumerate<MutFlowListIterator>>, - preliminary_collapsed_borders: &mut CollapsedBordersForRow) { + row_style: &ComputedValues, + children_count: usize, + child_index: usize, + child_table_cell: &mut TableCellFlow, + iterator: &mut Peekable<Enumerate<MutFlowListIterator>>, + preliminary_collapsed_borders: &mut CollapsedBordersForRow, +) { // In the first cell, combine its border with the one coming from the row. if child_index == 0 { let first_inline_border = &mut preliminary_collapsed_borders.inline[0]; - first_inline_border.combine( - &CollapsedBorder::inline_start(&*child_table_cell.block_flow.fragment.style, - CollapsedBorderProvenance::FromNextTableCell)); + first_inline_border.combine(&CollapsedBorder::inline_start( + &*child_table_cell.block_flow.fragment.style, + CollapsedBorderProvenance::FromNextTableCell, + )); } let inline_collapsed_border = preliminary_collapsed_borders.inline.push_or_set( child_index + 1, - CollapsedBorder::inline_end(&*child_table_cell.block_flow.fragment.style, - CollapsedBorderProvenance::FromPreviousTableCell)); + CollapsedBorder::inline_end( + &*child_table_cell.block_flow.fragment.style, + CollapsedBorderProvenance::FromPreviousTableCell, + ), + ); if let Some(&(_, ref next_child_flow)) = iterator.peek() { let next_child_flow = next_child_flow.as_block(); - inline_collapsed_border.combine( - &CollapsedBorder::inline_start(&*next_child_flow.fragment.style, - CollapsedBorderProvenance::FromNextTableCell)) + inline_collapsed_border.combine(&CollapsedBorder::inline_start( + &*next_child_flow.fragment.style, + CollapsedBorderProvenance::FromNextTableCell, + )) }; // In the last cell, also take into account the border that may // come from the row. if child_index + 1 == children_count { - inline_collapsed_border.combine( - &CollapsedBorder::inline_end(&row_style, - CollapsedBorderProvenance::FromTableRow)); + inline_collapsed_border.combine(&CollapsedBorder::inline_end( + &row_style, + CollapsedBorderProvenance::FromTableRow, + )); } - let mut block_start_border = - CollapsedBorder::block_start(&*child_table_cell.block_flow.fragment.style, - CollapsedBorderProvenance::FromNextTableCell); - block_start_border.combine( - &CollapsedBorder::block_start(row_style, CollapsedBorderProvenance::FromTableRow)); - preliminary_collapsed_borders.block_start.push_or_set(child_index, block_start_border); - let mut block_end_border = - CollapsedBorder::block_end(&*child_table_cell.block_flow.fragment.style, - CollapsedBorderProvenance::FromPreviousTableCell); - block_end_border.combine( - &CollapsedBorder::block_end(row_style, CollapsedBorderProvenance::FromTableRow)); - - preliminary_collapsed_borders.block_end.push_or_set(child_index, block_end_border); + let mut block_start_border = CollapsedBorder::block_start( + &*child_table_cell.block_flow.fragment.style, + CollapsedBorderProvenance::FromNextTableCell, + ); + block_start_border.combine(&CollapsedBorder::block_start( + row_style, + CollapsedBorderProvenance::FromTableRow, + )); + preliminary_collapsed_borders + .block_start + .push_or_set(child_index, block_start_border); + let mut block_end_border = CollapsedBorder::block_end( + &*child_table_cell.block_flow.fragment.style, + CollapsedBorderProvenance::FromPreviousTableCell, + ); + block_end_border.combine(&CollapsedBorder::block_end( + row_style, + CollapsedBorderProvenance::FromTableRow, + )); + + preliminary_collapsed_borders + .block_end + .push_or_set(child_index, block_end_border); } diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index d11c38cc275..3d77aca9382 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -66,23 +66,32 @@ impl TableRowGroupFlow { } pub fn populate_collapsed_border_spacing<'a, I>( - &mut self, - collapsed_inline_direction_border_widths_for_table: &[Au], - collapsed_block_direction_border_widths_for_table: &mut Peekable<I>) - where I: Iterator<Item=&'a Au> { - self.collapsed_inline_direction_border_widths_for_table.clear(); + &mut self, + collapsed_inline_direction_border_widths_for_table: &[Au], + collapsed_block_direction_border_widths_for_table: &mut Peekable<I>, + ) where + I: Iterator<Item = &'a Au>, + { self.collapsed_inline_direction_border_widths_for_table - .extend(collapsed_inline_direction_border_widths_for_table.into_iter().map(|x| *x)); + .clear(); + self.collapsed_inline_direction_border_widths_for_table + .extend( + collapsed_inline_direction_border_widths_for_table + .into_iter() + .map(|x| *x), + ); for _ in 0..self.block_flow.base.children.len() { if let Some(collapsed_block_direction_border_width_for_table) = - collapsed_block_direction_border_widths_for_table.next() { + collapsed_block_direction_border_widths_for_table.next() + { self.collapsed_block_direction_border_widths_for_table .push(*collapsed_block_direction_border_width_for_table) } } if let Some(collapsed_block_direction_border_width_for_table) = - collapsed_block_direction_border_widths_for_table.peek() { + collapsed_block_direction_border_widths_for_table.peek() + { self.collapsed_block_direction_border_widths_for_table .push(**collapsed_block_direction_border_width_for_table) } @@ -111,8 +120,10 @@ impl Flow for TableRowGroupFlow { } fn bubble_inline_sizes(&mut self) { - let _scope = layout_debug_scope!("table_rowgroup::bubble_inline_sizes {:x}", - self.block_flow.base.debug_id()); + let _scope = layout_debug_scope!( + "table_rowgroup::bubble_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); // Proper calculation of intrinsic sizes in table layout requires access to the entire // table, which we don't have yet. Defer to our parent. } @@ -120,9 +131,14 @@ impl Flow for TableRowGroupFlow { /// Recursively (top-down) determines the actual inline-size of child contexts and fragments. /// When called on this context, the context has had its inline-size set by the parent context. fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - let _scope = layout_debug_scope!("table_rowgroup::assign_inline_sizes {:x}", - self.block_flow.base.debug_id()); - debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_rowgroup"); + let _scope = layout_debug_scope!( + "table_rowgroup::assign_inline_sizes {:x}", + self.block_flow.base.debug_id() + ); + debug!( + "assign_inline_sizes({}): assigning inline_size for flow", + "table_rowgroup" + ); let shared_context = layout_context.shared_context(); // The position was set to the containing block by the flow's parent. @@ -130,50 +146,66 @@ impl Flow for TableRowGroupFlow { let (inline_start_content_edge, inline_end_content_edge) = (Au(0), Au(0)); let content_inline_size = containing_block_inline_size; - let border_collapse = self.block_flow.fragment.style.get_inherited_table().border_collapse; + let border_collapse = self + .block_flow + .fragment + .style + .get_inherited_table() + .border_collapse; let inline_size_computer = InternalTable; - inline_size_computer.compute_used_inline_size(&mut self.block_flow, - shared_context, - containing_block_inline_size); + inline_size_computer.compute_used_inline_size( + &mut self.block_flow, + shared_context, + containing_block_inline_size, + ); let collapsed_inline_direction_border_widths_for_table = &self.collapsed_inline_direction_border_widths_for_table; - let mut collapsed_block_direction_border_widths_for_table = - self.collapsed_block_direction_border_widths_for_table.iter().peekable(); - self.block_flow.propagate_assigned_inline_size_to_children(shared_context, - inline_start_content_edge, - inline_end_content_edge, - content_inline_size, - |child_flow, - _child_index, - _content_inline_size, - _writing_mode, - _inline_start_margin_edge, - _inline_end_margin_edge| { - if border_collapse == border_collapse::T::Collapse { - let child_table_row = child_flow.as_mut_table_row(); - child_table_row.populate_collapsed_border_spacing( - collapsed_inline_direction_border_widths_for_table, - &mut collapsed_block_direction_border_widths_for_table); - } - }); + let mut collapsed_block_direction_border_widths_for_table = self + .collapsed_block_direction_border_widths_for_table + .iter() + .peekable(); + self.block_flow.propagate_assigned_inline_size_to_children( + shared_context, + inline_start_content_edge, + inline_end_content_edge, + content_inline_size, + |child_flow, + _child_index, + _content_inline_size, + _writing_mode, + _inline_start_margin_edge, + _inline_end_margin_edge| { + if border_collapse == border_collapse::T::Collapse { + let child_table_row = child_flow.as_mut_table_row(); + child_table_row.populate_collapsed_border_spacing( + collapsed_inline_direction_border_widths_for_table, + &mut collapsed_block_direction_border_widths_for_table, + ); + } + }, + ); } fn assign_block_size(&mut self, lc: &LayoutContext) { debug!("assign_block_size: assigning block_size for table_rowgroup"); - self.block_flow.assign_block_size_for_table_like_flow(self.spacing.vertical(), lc); + self.block_flow + .assign_block_size_for_table_like_flow(self.spacing.vertical(), lc); } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context) + self.block_flow + .compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn build_display_list(&mut self, _: &mut DisplayListBuildState) { @@ -181,12 +213,17 @@ impl Flow for TableRowGroupFlow { // we skip setting the damage in TableCellStyleInfo::build_display_list() // because we only have immutable access - self.block_flow.fragment.restyle_damage.remove(ServoRestyleDamage::REPAINT); + self.block_flow + .fragment + .restyle_damage + .remove(ServoRestyleDamage::REPAINT); } fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) { - self.block_flow.collect_stacking_contexts_for_block(state, - StackingContextCollectionFlags::POSITION_NEVER_CREATES_CONTAINING_BLOCK); + self.block_flow.collect_stacking_contexts_for_block( + state, + StackingContextCollectionFlags::POSITION_NEVER_CREATES_CONTAINING_BLOCK, + ); } fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) { @@ -209,11 +246,17 @@ impl Flow for TableRowGroupFlow { self.block_flow.generated_containing_block_size(flow) } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position) + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ) } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index 90be14876cc..65684f8e165 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -39,7 +39,7 @@ use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize}; #[derive(Clone, Copy, Debug, Serialize)] pub enum TableLayout { Fixed, - Auto + Auto, } #[allow(unsafe_code)] @@ -63,19 +63,21 @@ impl TableWrapperFlow { TableWrapperFlow::from_fragment_and_float_kind(fragment, None) } - pub fn from_fragment_and_float_kind(fragment: Fragment, float_kind: Option<FloatKind>) - -> TableWrapperFlow { + pub fn from_fragment_and_float_kind( + fragment: Fragment, + float_kind: Option<FloatKind>, + ) -> TableWrapperFlow { let mut block_flow = BlockFlow::from_fragment_and_float_kind(fragment, float_kind); - let table_layout = if block_flow.fragment().style().get_table().table_layout == - table_layout::T::Fixed { - TableLayout::Fixed - } else { - TableLayout::Auto - }; + let table_layout = + if block_flow.fragment().style().get_table().table_layout == table_layout::T::Fixed { + TableLayout::Fixed + } else { + TableLayout::Auto + }; TableWrapperFlow { block_flow: block_flow, - column_intrinsic_inline_sizes: vec!(), - table_layout: table_layout + column_intrinsic_inline_sizes: vec![], + table_layout: table_layout, } } @@ -85,9 +87,12 @@ impl TableWrapperFlow { if kid.is_table() { let kid_table = kid.as_table(); spacing = kid_table.total_horizontal_spacing(); - table_border_padding = - kid_table.block_flow.fragment.border_padding.inline_start_end(); - break + table_border_padding = kid_table + .block_flow + .fragment + .border_padding + .inline_start_end(); + break; } } (table_border_padding, spacing) @@ -103,41 +108,53 @@ impl TableWrapperFlow { let available_inline_size = self.block_flow.base.block_container_inline_size; for kid in self.block_flow.base.child_iter_mut() { if !kid.is_table() { - continue + continue; } let kid_table = kid.as_mut_table(); let kid_block_flow = &mut kid_table.block_flow; - kid_block_flow.fragment.compute_border_and_padding(available_inline_size); - kid_block_flow.fragment.compute_block_direction_margins(available_inline_size); - kid_block_flow.fragment.compute_inline_direction_margins(available_inline_size); - return + kid_block_flow + .fragment + .compute_border_and_padding(available_inline_size); + kid_block_flow + .fragment + .compute_block_direction_margins(available_inline_size); + kid_block_flow + .fragment + .compute_inline_direction_margins(available_inline_size); + return; } } /// Calculates table column sizes for automatic layout per INTRINSIC § 4.3. fn calculate_table_column_sizes_for_automatic_layout( - &mut self, - intermediate_column_inline_sizes: &mut [IntermediateColumnInlineSize]) { + &mut self, + intermediate_column_inline_sizes: &mut [IntermediateColumnInlineSize], + ) { let available_inline_size = self.available_inline_size(); // Compute all the guesses for the column sizes, and sum them. let mut total_guess = AutoLayoutCandidateGuess::new(); - let guesses: Vec<AutoLayoutCandidateGuess> = - self.column_intrinsic_inline_sizes.iter().map(|column_intrinsic_inline_size| { + let guesses: Vec<AutoLayoutCandidateGuess> = self + .column_intrinsic_inline_sizes + .iter() + .map(|column_intrinsic_inline_size| { let guess = AutoLayoutCandidateGuess::from_column_intrinsic_inline_size( column_intrinsic_inline_size, - available_inline_size); + available_inline_size, + ); total_guess = &total_guess + &guess; guess }).collect(); // Assign inline sizes. - let selection = SelectedAutoLayoutCandidateGuess::select(&total_guess, - available_inline_size); + let selection = + SelectedAutoLayoutCandidateGuess::select(&total_guess, available_inline_size); let mut total_used_inline_size = Au(0); - for (intermediate_column_inline_size, guess) in - intermediate_column_inline_sizes.iter_mut().zip(guesses.iter()) { + for (intermediate_column_inline_size, guess) in intermediate_column_inline_sizes + .iter_mut() + .zip(guesses.iter()) + { intermediate_column_inline_size.size = guess.calculate(selection); intermediate_column_inline_size.percentage = 0.0; total_used_inline_size = total_used_inline_size + intermediate_column_inline_size.size @@ -147,8 +164,10 @@ impl TableWrapperFlow { // // FIXME(pcwalton, spec): How do I deal with fractional excess? let excess_inline_size = available_inline_size - total_used_inline_size; - if excess_inline_size > Au(0) && selection == - SelectedAutoLayoutCandidateGuess::UsePreferredGuessAndDistributeExcessInlineSize { + if excess_inline_size > Au(0) && + selection == + SelectedAutoLayoutCandidateGuess::UsePreferredGuessAndDistributeExcessInlineSize + { let mut info = ExcessInlineSizeDistributionInfo::new(); for column_intrinsic_inline_size in &self.column_intrinsic_inline_sizes { info.update(column_intrinsic_inline_size) @@ -156,13 +175,16 @@ impl TableWrapperFlow { let mut total_distributed_excess_size = Au(0); for (intermediate_column_inline_size, column_intrinsic_inline_size) in - intermediate_column_inline_sizes.iter_mut() - .zip(self.column_intrinsic_inline_sizes - .iter()) { - info.distribute_excess_inline_size_to_column(intermediate_column_inline_size, - column_intrinsic_inline_size, - excess_inline_size, - &mut total_distributed_excess_size) + intermediate_column_inline_sizes + .iter_mut() + .zip(self.column_intrinsic_inline_sizes.iter()) + { + info.distribute_excess_inline_size_to_column( + intermediate_column_inline_size, + column_intrinsic_inline_size, + excess_inline_size, + &mut total_distributed_excess_size, + ) } total_used_inline_size = available_inline_size } @@ -179,9 +201,10 @@ impl TableWrapperFlow { // just use the shrink-to-fit inline size. let available_inline_size = match self.block_flow.fragment.style().content_inline_size() { LengthOrPercentageOrAuto::Auto => { - self.block_flow.get_shrink_to_fit_inline_size(available_inline_size) - + self.block_flow + .get_shrink_to_fit_inline_size(available_inline_size) - table_border_padding - } + }, // FIXME(mttr): This fixes #4421 without breaking our current reftests, but I'm not // completely sure this is "correct". // @@ -196,10 +219,12 @@ impl TableWrapperFlow { fn set_inline_size(&mut self, total_used_inline_size: Au) { let (table_border_padding, spacing) = self.border_padding_and_spacing(); - self.block_flow.fragment.border_box.size.inline = total_used_inline_size + - table_border_padding + spacing; + self.block_flow.fragment.border_box.size.inline = + total_used_inline_size + table_border_padding + spacing; self.block_flow.base.position.size.inline = total_used_inline_size + - table_border_padding + spacing + self.block_flow.fragment.margin.inline_start_end(); + table_border_padding + + spacing + + self.block_flow.fragment.margin.inline_start_end(); let writing_mode = self.block_flow.base.writing_mode; let container_mode = self.block_flow.base.block_container_writing_mode; @@ -209,29 +234,30 @@ impl TableWrapperFlow { // depends on `border_box.size.inline`. self.block_flow.fragment.border_box.start.i = self.block_flow.base.block_container_inline_size - - self.block_flow.fragment.margin.inline_end - - self.block_flow.fragment.border_box.size.inline; + self.block_flow.fragment.margin.inline_end - + self.block_flow.fragment.border_box.size.inline; } } fn compute_used_inline_size( - &mut self, - shared_context: &SharedStyleContext, - parent_flow_inline_size: Au, - intermediate_column_inline_sizes: &[IntermediateColumnInlineSize]) { + &mut self, + shared_context: &SharedStyleContext, + parent_flow_inline_size: Au, + intermediate_column_inline_sizes: &[IntermediateColumnInlineSize], + ) { let (border_padding, spacing) = self.border_padding_and_spacing(); - let minimum_width_of_all_columns = - intermediate_column_inline_sizes.iter() - .fold(border_padding + spacing, - |accumulator, intermediate_column_inline_sizes| { + let minimum_width_of_all_columns = intermediate_column_inline_sizes.iter().fold( + border_padding + spacing, + |accumulator, intermediate_column_inline_sizes| { accumulator + intermediate_column_inline_sizes.size - }); - let preferred_width_of_all_columns = - self.column_intrinsic_inline_sizes.iter() - .fold(border_padding + spacing, - |accumulator, column_intrinsic_inline_sizes| { + }, + ); + let preferred_width_of_all_columns = self.column_intrinsic_inline_sizes.iter().fold( + border_padding + spacing, + |accumulator, column_intrinsic_inline_sizes| { accumulator + column_intrinsic_inline_sizes.preferred - }); + }, + ); // Delegate to the appropriate inline size computer to find the constraint inputs and write // the constraint solutions in. @@ -241,38 +267,45 @@ impl TableWrapperFlow { preferred_width_of_all_columns: preferred_width_of_all_columns, table_border_padding: border_padding, }; - let input = - inline_size_computer.compute_inline_size_constraint_inputs(&mut self.block_flow, - parent_flow_inline_size, - shared_context); - - let solution = inline_size_computer.solve_inline_size_constraints(&mut self.block_flow, - &input); - inline_size_computer.set_inline_size_constraint_solutions(&mut self.block_flow, - solution); - inline_size_computer.set_inline_position_of_flow_if_necessary(&mut self.block_flow, - solution); - return + let input = inline_size_computer.compute_inline_size_constraint_inputs( + &mut self.block_flow, + parent_flow_inline_size, + shared_context, + ); + + let solution = + inline_size_computer.solve_inline_size_constraints(&mut self.block_flow, &input); + inline_size_computer + .set_inline_size_constraint_solutions(&mut self.block_flow, solution); + inline_size_computer + .set_inline_position_of_flow_if_necessary(&mut self.block_flow, solution); + return; } - if !self.block_flow.base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { + if !self + .block_flow + .base + .flags + .contains(FlowFlags::INLINE_POSITION_IS_STATIC) + { let inline_size_computer = AbsoluteTable { minimum_width_of_all_columns: minimum_width_of_all_columns, preferred_width_of_all_columns: preferred_width_of_all_columns, table_border_padding: border_padding, }; - let input = - inline_size_computer.compute_inline_size_constraint_inputs(&mut self.block_flow, - parent_flow_inline_size, - shared_context); - - let solution = inline_size_computer.solve_inline_size_constraints(&mut self.block_flow, - &input); - inline_size_computer.set_inline_size_constraint_solutions(&mut self.block_flow, - solution); - inline_size_computer.set_inline_position_of_flow_if_necessary(&mut self.block_flow, - solution); - return + let input = inline_size_computer.compute_inline_size_constraint_inputs( + &mut self.block_flow, + parent_flow_inline_size, + shared_context, + ); + + let solution = + inline_size_computer.solve_inline_size_constraints(&mut self.block_flow, &input); + inline_size_computer + .set_inline_size_constraint_solutions(&mut self.block_flow, solution); + inline_size_computer + .set_inline_position_of_flow_if_necessary(&mut self.block_flow, solution); + return; } let inline_size_computer = Table { @@ -280,16 +313,17 @@ impl TableWrapperFlow { preferred_width_of_all_columns: preferred_width_of_all_columns, table_border_padding: border_padding, }; - let input = - inline_size_computer.compute_inline_size_constraint_inputs(&mut self.block_flow, - parent_flow_inline_size, - shared_context); - - let solution = inline_size_computer.solve_inline_size_constraints(&mut self.block_flow, - &input); + let input = inline_size_computer.compute_inline_size_constraint_inputs( + &mut self.block_flow, + parent_flow_inline_size, + shared_context, + ); + + let solution = + inline_size_computer.solve_inline_size_constraints(&mut self.block_flow, &input); inline_size_computer.set_inline_size_constraint_solutions(&mut self.block_flow, solution); - inline_size_computer.set_inline_position_of_flow_if_necessary(&mut self.block_flow, - solution); + inline_size_computer + .set_inline_position_of_flow_if_necessary(&mut self.block_flow, solution); } } @@ -332,90 +366,96 @@ impl Flow for TableWrapperFlow { } fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { - debug!("assign_inline_sizes({}): assigning inline_size for flow", - if self.block_flow.base.flags.is_float() { - "floated table_wrapper" - } else { - "table_wrapper" - }); + debug!( + "assign_inline_sizes({}): assigning inline_size for flow", + if self.block_flow.base.flags.is_float() { + "floated table_wrapper" + } else { + "table_wrapper" + } + ); let shared_context = layout_context.shared_context(); - self.block_flow.initialize_container_size_for_root(shared_context); - - let mut intermediate_column_inline_sizes = self.column_intrinsic_inline_sizes - .iter() - .map(|column_intrinsic_inline_size| { - IntermediateColumnInlineSize { - size: column_intrinsic_inline_size.minimum_length, - percentage: column_intrinsic_inline_size.percentage, - } - }).collect::<Vec<_>>(); + self.block_flow + .initialize_container_size_for_root(shared_context); + + let mut intermediate_column_inline_sizes = self + .column_intrinsic_inline_sizes + .iter() + .map( + |column_intrinsic_inline_size| IntermediateColumnInlineSize { + size: column_intrinsic_inline_size.minimum_length, + percentage: column_intrinsic_inline_size.percentage, + }, + ).collect::<Vec<_>>(); // Our inline-size was set to the inline-size of the containing block by the flow's parent. // Now compute the real value. let containing_block_inline_size = self.block_flow.base.block_container_inline_size; if self.block_flow.base.flags.is_float() { - self.block_flow.float.as_mut().unwrap().containing_inline_size = - containing_block_inline_size; + self.block_flow + .float + .as_mut() + .unwrap() + .containing_inline_size = containing_block_inline_size; } // This has to be done before computing our inline size because `compute_used_inline_size` // internally consults the border and padding of the table. self.compute_border_and_padding_of_table(); - self.compute_used_inline_size(shared_context, - containing_block_inline_size, - &intermediate_column_inline_sizes); + self.compute_used_inline_size( + shared_context, + containing_block_inline_size, + &intermediate_column_inline_sizes, + ); match self.table_layout { - TableLayout::Auto => { - self.calculate_table_column_sizes_for_automatic_layout( - &mut intermediate_column_inline_sizes) - } - TableLayout::Fixed => {} + TableLayout::Auto => self.calculate_table_column_sizes_for_automatic_layout( + &mut intermediate_column_inline_sizes, + ), + TableLayout::Fixed => {}, } let inline_start_content_edge = self.block_flow.fragment.border_box.start.i; let content_inline_size = self.block_flow.fragment.border_box.size.inline; let inline_end_content_edge = self.block_flow.fragment.border_padding.inline_end + - self.block_flow.fragment.margin.inline_end; + self.block_flow.fragment.margin.inline_end; // In case of fixed layout, column inline-sizes are calculated in table flow. let assigned_column_inline_sizes = match self.table_layout { TableLayout::Fixed => None, - TableLayout::Auto => { - Some(intermediate_column_inline_sizes.iter().map(|sizes| { - ColumnComputedInlineSize { - size: sizes.size, - } - }).collect::<Vec<_>>()) - } + TableLayout::Auto => Some( + intermediate_column_inline_sizes + .iter() + .map(|sizes| ColumnComputedInlineSize { size: sizes.size }) + .collect::<Vec<_>>(), + ), }; match assigned_column_inline_sizes { - None => { - self.block_flow - .propagate_assigned_inline_size_to_children(shared_context, - inline_start_content_edge, - inline_end_content_edge, - content_inline_size, - |_, _, _, _, _, _| {}) - } + None => self.block_flow.propagate_assigned_inline_size_to_children( + shared_context, + inline_start_content_edge, + inline_end_content_edge, + content_inline_size, + |_, _, _, _, _, _| {}, + ), Some(ref assigned_column_inline_sizes) => { - self.block_flow - .propagate_assigned_inline_size_to_children(shared_context, - inline_start_content_edge, - inline_end_content_edge, - content_inline_size, - |child_flow, _, _, _, _, _| { - if child_flow.class() == FlowClass::Table { - child_flow.as_mut_table().column_computed_inline_sizes = - assigned_column_inline_sizes.to_vec(); - } - }) - } + self.block_flow.propagate_assigned_inline_size_to_children( + shared_context, + inline_start_content_edge, + inline_end_content_edge, + content_inline_size, + |child_flow, _, _, _, _, _| { + if child_flow.class() == FlowClass::Table { + child_flow.as_mut_table().column_computed_inline_sizes = + assigned_column_inline_sizes.to_vec(); + } + }, + ) + }, } - } fn assign_block_size(&mut self, layout_context: &LayoutContext) { @@ -423,34 +463,42 @@ impl Flow for TableWrapperFlow { let remaining = self.block_flow.assign_block_size_block_base( layout_context, None, - MarginsMayCollapseFlag::MarginsMayNotCollapse); + MarginsMayCollapseFlag::MarginsMayNotCollapse, + ); debug_assert!(remaining.is_none()); } fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_stacking_relative_position(layout_context) + self.block_flow + .compute_stacking_relative_position(layout_context) } fn place_float_if_applicable<'a>(&mut self) { self.block_flow.place_float_if_applicable() } - fn assign_block_size_for_inorder_child_if_necessary(&mut self, - layout_context: &LayoutContext, - parent_thread_id: u8, - content_box: LogicalRect<Au>) - -> bool { - self.block_flow.assign_block_size_for_inorder_child_if_necessary(layout_context, - parent_thread_id, - content_box) + fn assign_block_size_for_inorder_child_if_necessary( + &mut self, + layout_context: &LayoutContext, + parent_thread_id: u8, + content_box: LogicalRect<Au>, + ) -> bool { + self.block_flow + .assign_block_size_for_inorder_child_if_necessary( + layout_context, + parent_thread_id, + content_box, + ) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { - self.block_flow.update_late_computed_inline_position_if_necessary(inline_position) + self.block_flow + .update_late_computed_inline_position_if_necessary(inline_position) } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { - self.block_flow.update_late_computed_block_position_if_necessary(block_position) + self.block_flow + .update_late_computed_block_position_if_necessary(block_position) } fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize<Au> { @@ -465,7 +513,8 @@ impl Flow for TableWrapperFlow { self.block_flow.collect_stacking_contexts_for_block( state, StackingContextCollectionFlags::POSITION_NEVER_CREATES_CONTAINING_BLOCK | - StackingContextCollectionFlags::NEVER_CREATES_CLIP_SCROLL_NODE); + StackingContextCollectionFlags::NEVER_CREATES_CLIP_SCROLL_NODE, + ); } fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) { @@ -476,11 +525,17 @@ impl Flow for TableWrapperFlow { self.block_flow.compute_overflow() } - fn iterate_through_fragment_border_boxes(&self, - iterator: &mut FragmentBorderBoxIterator, - level: i32, - stacking_context_position: &Point2D<Au>) { - self.block_flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position) + fn iterate_through_fragment_border_boxes( + &self, + iterator: &mut FragmentBorderBoxIterator, + level: i32, + stacking_context_position: &Point2D<Au>, + ) { + self.block_flow.iterate_through_fragment_border_boxes( + iterator, + level, + stacking_context_position, + ) } fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { @@ -550,12 +605,14 @@ impl AutoLayoutCandidateGuess { } /// Fills in the inline-size guesses for this column per INTRINSIC § 4.3. - fn from_column_intrinsic_inline_size(column_intrinsic_inline_size: &ColumnIntrinsicInlineSize, - assignable_inline_size: Au) - -> AutoLayoutCandidateGuess { - let minimum_percentage_guess = - max(assignable_inline_size.scale_by(column_intrinsic_inline_size.percentage), - column_intrinsic_inline_size.minimum_length); + fn from_column_intrinsic_inline_size( + column_intrinsic_inline_size: &ColumnIntrinsicInlineSize, + assignable_inline_size: Au, + ) -> AutoLayoutCandidateGuess { + let minimum_percentage_guess = max( + assignable_inline_size.scale_by(column_intrinsic_inline_size.percentage), + column_intrinsic_inline_size.minimum_length, + ); AutoLayoutCandidateGuess { minimum_guess: column_intrinsic_inline_size.minimum_length, minimum_percentage_guess: minimum_percentage_guess, @@ -607,8 +664,8 @@ impl<'a> Add for &'a AutoLayoutCandidateGuess { fn add(self, other: &AutoLayoutCandidateGuess) -> AutoLayoutCandidateGuess { AutoLayoutCandidateGuess { minimum_guess: self.minimum_guess + other.minimum_guess, - minimum_percentage_guess: - self.minimum_percentage_guess + other.minimum_percentage_guess, + minimum_percentage_guess: self.minimum_percentage_guess + + other.minimum_percentage_guess, minimum_specified_guess: self.minimum_specified_guess + other.minimum_specified_guess, preferred_guess: self.preferred_guess + other.preferred_guess, } @@ -631,24 +688,32 @@ impl SelectedAutoLayoutCandidateGuess { /// /// FIXME(pcwalton, INTRINSIC spec): INTRINSIC doesn't specify whether these are exclusive or /// inclusive ranges. - fn select(guess: &AutoLayoutCandidateGuess, assignable_inline_size: Au) - -> SelectedAutoLayoutCandidateGuess { + fn select( + guess: &AutoLayoutCandidateGuess, + assignable_inline_size: Au, + ) -> SelectedAutoLayoutCandidateGuess { if assignable_inline_size < guess.minimum_guess { SelectedAutoLayoutCandidateGuess::UseMinimumGuess } else if assignable_inline_size < guess.minimum_percentage_guess { - let weight = weight(guess.minimum_guess, - assignable_inline_size, - guess.minimum_percentage_guess); + let weight = weight( + guess.minimum_guess, + assignable_inline_size, + guess.minimum_percentage_guess, + ); SelectedAutoLayoutCandidateGuess::InterpolateBetweenMinimumGuessAndMinimumPercentageGuess(weight) } else if assignable_inline_size < guess.minimum_specified_guess { - let weight = weight(guess.minimum_percentage_guess, - assignable_inline_size, - guess.minimum_specified_guess); + let weight = weight( + guess.minimum_percentage_guess, + assignable_inline_size, + guess.minimum_specified_guess, + ); SelectedAutoLayoutCandidateGuess::InterpolateBetweenMinimumPercentageGuessAndMinimumSpecifiedGuess(weight) } else if assignable_inline_size < guess.preferred_guess { - let weight = weight(guess.minimum_specified_guess, - assignable_inline_size, - guess.preferred_guess); + let weight = weight( + guess.minimum_specified_guess, + assignable_inline_size, + guess.preferred_guess, + ); SelectedAutoLayoutCandidateGuess::InterpolateBetweenMinimumSpecifiedGuessAndPreferredGuess(weight) } else { SelectedAutoLayoutCandidateGuess::UsePreferredGuessAndDistributeExcessInlineSize @@ -688,17 +753,19 @@ impl ExcessInlineSizeDistributionInfo { fn update(&mut self, column_intrinsic_inline_size: &ColumnIntrinsicInlineSize) { if !column_intrinsic_inline_size.constrained && - column_intrinsic_inline_size.percentage == 0.0 { + column_intrinsic_inline_size.percentage == 0.0 + { self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage = self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage + - column_intrinsic_inline_size.preferred; + column_intrinsic_inline_size.preferred; self.count_of_nonconstrained_columns_with_no_percentage += 1 } if column_intrinsic_inline_size.constrained && - column_intrinsic_inline_size.percentage == 0.0 { + column_intrinsic_inline_size.percentage == 0.0 + { self.preferred_inline_size_of_constrained_columns_with_no_percentage = self.preferred_inline_size_of_constrained_columns_with_no_percentage + - column_intrinsic_inline_size.preferred + column_intrinsic_inline_size.preferred } self.total_percentage += column_intrinsic_inline_size.percentage; self.column_count += 1 @@ -710,30 +777,32 @@ impl ExcessInlineSizeDistributionInfo { /// `#[inline]` so the compiler will hoist out the branch, which is loop-invariant. #[inline] fn distribute_excess_inline_size_to_column( - &self, - intermediate_column_inline_size: &mut IntermediateColumnInlineSize, - column_intrinsic_inline_size: &ColumnIntrinsicInlineSize, - excess_inline_size: Au, - total_distributed_excess_size: &mut Au) { + &self, + intermediate_column_inline_size: &mut IntermediateColumnInlineSize, + column_intrinsic_inline_size: &ColumnIntrinsicInlineSize, + excess_inline_size: Au, + total_distributed_excess_size: &mut Au, + ) { let proportion = if self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage > Au(0) { // FIXME(spec, pcwalton): Gecko and WebKit do *something* here when there are // nonconstrained columns with no percentage *and* no preferred width. What do they // do? if !column_intrinsic_inline_size.constrained && - column_intrinsic_inline_size.percentage == 0.0 { - column_intrinsic_inline_size.preferred.to_f32_px() / - self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage - .to_f32_px() + column_intrinsic_inline_size.percentage == 0.0 + { + column_intrinsic_inline_size.preferred.to_f32_px() / self + .preferred_inline_size_of_nonconstrained_columns_with_no_percentage + .to_f32_px() } else { 0.0 } } else if self.count_of_nonconstrained_columns_with_no_percentage > 0 { 1.0 / (self.count_of_nonconstrained_columns_with_no_percentage as CSSFloat) - } else if self.preferred_inline_size_of_constrained_columns_with_no_percentage > - Au(0) { - column_intrinsic_inline_size.preferred.to_f32_px() / - self.preferred_inline_size_of_constrained_columns_with_no_percentage.to_f32_px() + } else if self.preferred_inline_size_of_constrained_columns_with_no_percentage > Au(0) { + column_intrinsic_inline_size.preferred.to_f32_px() / self + .preferred_inline_size_of_constrained_columns_with_no_percentage + .to_f32_px() } else if self.total_percentage > 0.0 { column_intrinsic_inline_size.percentage / self.total_percentage } else { @@ -742,11 +811,13 @@ impl ExcessInlineSizeDistributionInfo { // The `min` here has the effect of throwing away fractional excess at the end of the // table. - let amount_to_distribute = min(excess_inline_size.scale_by(proportion), - excess_inline_size - *total_distributed_excess_size); + let amount_to_distribute = min( + excess_inline_size.scale_by(proportion), + excess_inline_size - *total_distributed_excess_size, + ); *total_distributed_excess_size = *total_distributed_excess_size + amount_to_distribute; - intermediate_column_inline_size.size = intermediate_column_inline_size.size + - amount_to_distribute + intermediate_column_inline_size.size = + intermediate_column_inline_size.size + amount_to_distribute } } @@ -760,28 +831,32 @@ struct IntermediateColumnInlineSize { /// /// `table_border_padding` is the sum of the sizes of all border and padding in the inline /// direction of the table contained within this table wrapper. -fn initial_computed_inline_size(block: &mut BlockFlow, - containing_block_inline_size: Au, - minimum_width_of_all_columns: Au, - preferred_width_of_all_columns: Au, - table_border_padding: Au) - -> MaybeAuto { - let inline_size_from_style = MaybeAuto::from_style(block.fragment.style.content_inline_size(), - containing_block_inline_size); +fn initial_computed_inline_size( + block: &mut BlockFlow, + containing_block_inline_size: Au, + minimum_width_of_all_columns: Au, + preferred_width_of_all_columns: Au, + table_border_padding: Au, +) -> MaybeAuto { + let inline_size_from_style = MaybeAuto::from_style( + block.fragment.style.content_inline_size(), + containing_block_inline_size, + ); match inline_size_from_style { MaybeAuto::Auto => { - if preferred_width_of_all_columns + table_border_padding <= containing_block_inline_size { + if preferred_width_of_all_columns + table_border_padding <= containing_block_inline_size + { MaybeAuto::Specified(preferred_width_of_all_columns + table_border_padding) } else if minimum_width_of_all_columns > containing_block_inline_size { MaybeAuto::Specified(minimum_width_of_all_columns) } else { MaybeAuto::Auto } - } - MaybeAuto::Specified(inline_size_from_style) => { - MaybeAuto::Specified(max(inline_size_from_style - table_border_padding, - minimum_width_of_all_columns)) - } + }, + MaybeAuto::Specified(inline_size_from_style) => MaybeAuto::Specified(max( + inline_size_from_style - table_border_padding, + minimum_width_of_all_columns, + )), } } @@ -793,27 +868,33 @@ struct Table { impl ISizeAndMarginsComputer for Table { fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) { - block.fragment.compute_border_and_padding(containing_block_inline_size) + block + .fragment + .compute_border_and_padding(containing_block_inline_size) } - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { + fn initial_computed_inline_size( + &self, + block: &mut BlockFlow, + parent_flow_inline_size: Au, + shared_context: &SharedStyleContext, + ) -> MaybeAuto { let containing_block_inline_size = self.containing_block_inline_size(block, parent_flow_inline_size, shared_context); - initial_computed_inline_size(block, - containing_block_inline_size, - self.minimum_width_of_all_columns, - self.preferred_width_of_all_columns, - self.table_border_padding) - } - - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + initial_computed_inline_size( + block, + containing_block_inline_size, + self.minimum_width_of_all_columns, + self.preferred_width_of_all_columns, + self.table_border_padding, + ) + } + + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { self.solve_block_inline_size_constraints(block, input) } } @@ -826,29 +907,33 @@ struct FloatedTable { impl ISizeAndMarginsComputer for FloatedTable { fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) { - block.fragment.compute_border_and_padding(containing_block_inline_size) + block + .fragment + .compute_border_and_padding(containing_block_inline_size) } - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { + fn initial_computed_inline_size( + &self, + block: &mut BlockFlow, + parent_flow_inline_size: Au, + shared_context: &SharedStyleContext, + ) -> MaybeAuto { let containing_block_inline_size = - self.containing_block_inline_size(block, - parent_flow_inline_size, - shared_context); - initial_computed_inline_size(block, - containing_block_inline_size, - self.minimum_width_of_all_columns, - self.preferred_width_of_all_columns, - self.table_border_padding) - } - - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + self.containing_block_inline_size(block, parent_flow_inline_size, shared_context); + initial_computed_inline_size( + block, + containing_block_inline_size, + self.minimum_width_of_all_columns, + self.preferred_width_of_all_columns, + self.table_border_padding, + ) + } + + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { FloatNonReplaced.solve_inline_size_constraints(block, input) } } @@ -861,46 +946,54 @@ struct AbsoluteTable { impl ISizeAndMarginsComputer for AbsoluteTable { fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) { - block.fragment.compute_border_and_padding(containing_block_inline_size) + block + .fragment + .compute_border_and_padding(containing_block_inline_size) } - fn initial_computed_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> MaybeAuto { + fn initial_computed_inline_size( + &self, + block: &mut BlockFlow, + parent_flow_inline_size: Au, + shared_context: &SharedStyleContext, + ) -> MaybeAuto { let containing_block_inline_size = - self.containing_block_inline_size(block, - parent_flow_inline_size, - shared_context); - initial_computed_inline_size(block, - containing_block_inline_size, - self.minimum_width_of_all_columns, - self.preferred_width_of_all_columns, - self.table_border_padding) - } - - fn containing_block_inline_size(&self, - block: &mut BlockFlow, - parent_flow_inline_size: Au, - shared_context: &SharedStyleContext) - -> Au { - AbsoluteNonReplaced.containing_block_inline_size(block, - parent_flow_inline_size, - shared_context) - } - - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + self.containing_block_inline_size(block, parent_flow_inline_size, shared_context); + initial_computed_inline_size( + block, + containing_block_inline_size, + self.minimum_width_of_all_columns, + self.preferred_width_of_all_columns, + self.table_border_padding, + ) + } + + fn containing_block_inline_size( + &self, + block: &mut BlockFlow, + parent_flow_inline_size: Au, + shared_context: &SharedStyleContext, + ) -> Au { + AbsoluteNonReplaced.containing_block_inline_size( + block, + parent_flow_inline_size, + shared_context, + ) + } + + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { AbsoluteNonReplaced.solve_inline_size_constraints(block, input) } - fn set_inline_position_of_flow_if_necessary(&self, - block: &mut BlockFlow, - solution: ISizeConstraintSolution) { + fn set_inline_position_of_flow_if_necessary( + &self, + block: &mut BlockFlow, + solution: ISizeConstraintSolution, + ) { AbsoluteNonReplaced.set_inline_position_of_flow_if_necessary(block, solution); } - } diff --git a/components/layout/tests/size_of.rs b/components/layout/tests/size_of.rs index f12b0049f4b..7d869271368 100644 --- a/components/layout/tests/size_of.rs +++ b/components/layout/tests/size_of.rs @@ -5,10 +5,15 @@ #![cfg(target_pointer_width = "64")] extern crate layout; -#[macro_use] extern crate size_of_test; +#[macro_use] +extern crate size_of_test; use layout::Fragment; use layout::SpecificFragmentInfo; size_of_test!(test_size_of_fragment, Fragment, 176); -size_of_test!(test_size_of_specific_fragment_info, SpecificFragmentInfo, 24); +size_of_test!( + test_size_of_specific_fragment_info, + SpecificFragmentInfo, + 24 +); diff --git a/components/layout/text.rs b/components/layout/text.rs index ac93eaed03f..c8321e9a03b 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -55,7 +55,6 @@ fn text(fragments: &LinkedList<Fragment>) -> String { text } - /// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextFragment`s. pub struct TextRunScanner { pub clump: LinkedList<Fragment>, @@ -68,16 +67,25 @@ impl TextRunScanner { } } - pub fn scan_for_runs(&mut self, - font_context: &mut LayoutFontContext, - mut fragments: LinkedList<Fragment>) - -> InlineFragments { - debug!("TextRunScanner: scanning {} fragments for text runs...", fragments.len()); + pub fn scan_for_runs( + &mut self, + font_context: &mut LayoutFontContext, + mut fragments: LinkedList<Fragment>, + ) -> InlineFragments { + debug!( + "TextRunScanner: scanning {} fragments for text runs...", + fragments.len() + ); debug_assert!(!fragments.is_empty()); // Calculate bidi embedding levels, so we can split bidirectional fragments for reordering. let text = text(&fragments); - let para_level = fragments.front().unwrap().style.writing_mode.to_bidi_level(); + let para_level = fragments + .front() + .unwrap() + .style + .writing_mode + .to_bidi_level(); let bidi_info = bidi::BidiInfo::new(&text, Some(para_level)); // Optimization: If all the text is LTR, don't bother splitting on bidi levels. @@ -106,22 +114,25 @@ impl TextRunScanner { // Create a clump. split_first_fragment_at_newline_if_necessary(&mut fragments); self.clump.append(&mut split_off_head(&mut fragments)); - while !fragments.is_empty() && self.clump - .back() - .unwrap() - .can_merge_with_fragment(fragments.front() - .unwrap()) { + while !fragments.is_empty() && self + .clump + .back() + .unwrap() + .can_merge_with_fragment(fragments.front().unwrap()) + { split_first_fragment_at_newline_if_necessary(&mut fragments); self.clump.append(&mut split_off_head(&mut fragments)); } // Flush that clump to the list of fragments we're building up. - last_whitespace = self.flush_clump_to_list(font_context, - &mut new_fragments, - &mut paragraph_bytes_processed, - bidi_levels, - last_whitespace, - &mut linebreaker); + last_whitespace = self.flush_clump_to_list( + font_context, + &mut new_fragments, + &mut paragraph_bytes_processed, + bidi_levels, + last_whitespace, + &mut linebreaker, + ); } debug!("TextRunScanner: complete."); @@ -136,25 +147,31 @@ impl TextRunScanner { /// The flow keeps track of the fragments contained by all non-leaf DOM nodes. This is necessary /// for correct painting order. Since we compress several leaf fragments here, the mapping must /// be adjusted. - fn flush_clump_to_list(&mut self, - mut font_context: &mut LayoutFontContext, - out_fragments: &mut Vec<Fragment>, - paragraph_bytes_processed: &mut usize, - bidi_levels: Option<&[bidi::Level]>, - mut last_whitespace: bool, - linebreaker: &mut Option<LineBreakLeafIter>) - -> bool { - debug!("TextRunScanner: flushing {} fragments in range", self.clump.len()); + fn flush_clump_to_list( + &mut self, + mut font_context: &mut LayoutFontContext, + out_fragments: &mut Vec<Fragment>, + paragraph_bytes_processed: &mut usize, + bidi_levels: Option<&[bidi::Level]>, + mut last_whitespace: bool, + linebreaker: &mut Option<LineBreakLeafIter>, + ) -> bool { + debug!( + "TextRunScanner: flushing {} fragments in range", + self.clump.len() + ); debug_assert!(!self.clump.is_empty()); match self.clump.front().unwrap().specific { - SpecificFragmentInfo::UnscannedText(_) => {} + SpecificFragmentInfo::UnscannedText(_) => {}, _ => { - debug_assert!(self.clump.len() == 1, - "WAT: can't coalesce non-text nodes in flush_clump_to_list()!"); + debug_assert!( + self.clump.len() == 1, + "WAT: can't coalesce non-text nodes in flush_clump_to_list()!" + ); out_fragments.push(self.clump.pop_front().unwrap()); - return false - } + return false; + }, } // Concatenate all of the transformed strings together, saving the new character indices. @@ -173,17 +190,19 @@ impl TextRunScanner { let inherited_text_style = in_fragment.style().get_inherited_text(); font_group = font_context.font_group(font_style); compression = match in_fragment.white_space() { - WhiteSpace::Normal | - WhiteSpace::Nowrap => CompressionMode::CompressWhitespaceNewline, - WhiteSpace::Pre | - WhiteSpace::PreWrap => CompressionMode::CompressNone, + WhiteSpace::Normal | WhiteSpace::Nowrap => { + CompressionMode::CompressWhitespaceNewline + }, + WhiteSpace::Pre | WhiteSpace::PreWrap => CompressionMode::CompressNone, WhiteSpace::PreLine => CompressionMode::CompressWhitespace, }; text_transform = inherited_text_style.text_transform; letter_spacing = inherited_text_style.letter_spacing; - word_spacing = inherited_text_style.word_spacing.value() - .map(|lop| lop.to_hash_key()) - .unwrap_or((Au(0), NotNan::new(0.0).unwrap())); + word_spacing = inherited_text_style + .word_spacing + .value() + .map(|lop| lop.to_hash_key()) + .unwrap_or((Au(0), NotNan::new(0.0).unwrap())); text_rendering = inherited_text_style.text_rendering; word_break = inherited_text_style.word_break; } @@ -201,7 +220,7 @@ impl TextRunScanner { SpecificFragmentInfo::UnscannedText(ref text_fragment_info) => { text = &text_fragment_info.text; selection = text_fragment_info.selection; - } + }, _ => panic!("Expected an unscanned text fragment!"), }; insertion_point = match selection { @@ -209,14 +228,16 @@ impl TextRunScanner { // `range` is the range within the current fragment. To get the range // within the text run, offset it by the length of the preceding fragments. Some(range.begin() + ByteIndex(run_info.text.len() as isize)) - } - _ => None + }, + _ => None, }; let (mut start_position, mut end_position) = (0, 0); for (byte_index, character) in text.char_indices() { if !character.is_control() { - let font = font_group.borrow_mut().find_by_codepoint(&mut font_context, character); + let font = font_group + .borrow_mut() + .find_by_codepoint(&mut font_context, character); let bidi_level = match bidi_levels { Some(levels) => levels[*paragraph_bytes_processed], @@ -230,19 +251,20 @@ impl TextRunScanner { // http://www.unicode.org/reports/tr24/#Common let script = get_script(character); let compatible_script = is_compatible(script, run_info.script); - if compatible_script && !is_specific(run_info.script) && is_specific(script) { + if compatible_script && !is_specific(run_info.script) && is_specific(script) + { run_info.script = script; } let selected = match selection { Some(range) => range.contains(ByteIndex(byte_index as isize)), - None => false + None => false, }; // Now, if necessary, flush the mapping we were building up. let flush_run = !run_info.has_font(&font) || - run_info.bidi_level != bidi_level || - !compatible_script; + run_info.bidi_level != bidi_level || + !compatible_script; let new_mapping_needed = flush_run || mapping.selected != selected; if new_mapping_needed { @@ -250,22 +272,23 @@ impl TextRunScanner { // The run info values are uninitialized at this point so // flushing an empty mapping is pointless. if end_position > 0 { - mapping.flush(&mut mappings, - &mut run_info, - &**text, - compression, - text_transform, - &mut last_whitespace, - &mut start_position, - end_position); + mapping.flush( + &mut mappings, + &mut run_info, + &**text, + compression, + text_transform, + &mut last_whitespace, + &mut start_position, + end_position, + ); } if run_info.text.len() > 0 { if flush_run { run_info.flush(&mut run_info_list, &mut insertion_point); run_info = RunInfo::new(); } - mapping = RunMapping::new(&run_info_list[..], - fragment_index); + mapping = RunMapping::new(&run_info_list[..], fragment_index); } run_info.font = font; run_info.bidi_level = bidi_level; @@ -280,14 +303,16 @@ impl TextRunScanner { } // Flush the last mapping we created for this fragment to the list. - mapping.flush(&mut mappings, - &mut run_info, - &**text, - compression, - text_transform, - &mut last_whitespace, - &mut start_position, - end_position); + mapping.flush( + &mut mappings, + &mut run_info, + &**text, + compression, + text_transform, + &mut last_whitespace, + &mut start_position, + end_position, + ); } // Push the final run info. @@ -326,20 +351,25 @@ impl TextRunScanner { } // If no font is found (including fallbacks), there's no way we can render. - let font = - run_info.font - .or_else(|| font_group.borrow_mut().first(&mut font_context)) - .expect("No font found for text run!"); - - let (run, break_at_zero) = TextRun::new(&mut *font.borrow_mut(), - run_info.text, - &options, - run_info.bidi_level, - linebreaker); - result.push((ScannedTextRun { - run: Arc::new(run), - insertion_point: run_info.insertion_point, - }, break_at_zero)) + let font = run_info + .font + .or_else(|| font_group.borrow_mut().first(&mut font_context)) + .expect("No font found for text run!"); + + let (run, break_at_zero) = TextRun::new( + &mut *font.borrow_mut(), + run_info.text, + &options, + run_info.bidi_level, + linebreaker, + ); + result.push(( + ScannedTextRun { + run: Arc::new(run), + insertion_point: run_info.insertion_point, + }, + break_at_zero, + )) } result }; @@ -349,12 +379,14 @@ impl TextRunScanner { let mut mappings = mappings.into_iter().peekable(); let mut prev_fragments_to_meld = Vec::new(); - for (logical_offset, old_fragment) in - mem::replace(&mut self.clump, LinkedList::new()).into_iter().enumerate() { + for (logical_offset, old_fragment) in mem::replace(&mut self.clump, LinkedList::new()) + .into_iter() + .enumerate() + { let mut is_first_mapping_of_this_old_fragment = true; loop { match mappings.peek() { - Some(mapping) if mapping.old_fragment_index == logical_offset => {} + Some(mapping) if mapping.old_fragment_index == logical_offset => {}, Some(_) | None => { if is_first_mapping_of_this_old_fragment { // There were no mappings for this unscanned fragment. Transfer its @@ -365,13 +397,15 @@ impl TextRunScanner { prev_fragments_to_meld.push(old_fragment); } break; - } + }, }; let mapping = mappings.next().unwrap(); let (scanned_run, break_at_zero) = runs[mapping.text_run_index].clone(); - let mut byte_range = Range::new(ByteIndex(mapping.byte_range.begin() as isize), - ByteIndex(mapping.byte_range.length() as isize)); + let mut byte_range = Range::new( + ByteIndex(mapping.byte_range.begin() as isize), + ByteIndex(mapping.byte_range.length() as isize), + ); let mut flags = ScannedTextFlags::empty(); if !break_at_zero && mapping.byte_range.begin() == 0 { @@ -381,31 +415,34 @@ impl TextRunScanner { } let text_size = old_fragment.border_box.size; - let requires_line_break_afterward_if_wrapping_on_newlines = - scanned_run.run.text[mapping.byte_range.begin()..mapping.byte_range.end()] + let requires_line_break_afterward_if_wrapping_on_newlines = scanned_run.run.text + [mapping.byte_range.begin()..mapping.byte_range.end()] .ends_with('\n'); if requires_line_break_afterward_if_wrapping_on_newlines { byte_range.extend_by(ByteIndex(-1)); // Trim the '\n' - flags.insert(ScannedTextFlags::REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES); + flags.insert( + ScannedTextFlags::REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES, + ); } if mapping.selected { flags.insert(ScannedTextFlags::SELECTED); } - let insertion_point = if mapping.contains_insertion_point(scanned_run.insertion_point) { - scanned_run.insertion_point - } else { - None - }; + let insertion_point = + if mapping.contains_insertion_point(scanned_run.insertion_point) { + scanned_run.insertion_point + } else { + None + }; let mut new_text_fragment_info = Box::new(ScannedTextFragmentInfo::new( scanned_run.run, byte_range, text_size, insertion_point, - flags + flags, )); let new_metrics = new_text_fragment_info.run.metrics_for_range(&byte_range); @@ -415,20 +452,23 @@ impl TextRunScanner { let mut new_fragment = old_fragment.transform( bounding_box_size, - SpecificFragmentInfo::ScannedText(new_text_fragment_info)); + SpecificFragmentInfo::ScannedText(new_text_fragment_info), + ); let is_last_mapping_of_this_old_fragment = match mappings.peek() { Some(mapping) if mapping.old_fragment_index == logical_offset => false, - _ => true + _ => true, }; if let Some(ref mut context) = new_fragment.inline_context { for node in &mut context.nodes { if !is_last_mapping_of_this_old_fragment { - node.flags.remove(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); + node.flags + .remove(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); } if !is_first_mapping_of_this_old_fragment { - node.flags.remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT); + node.flags + .remove(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT); } } } @@ -447,14 +487,17 @@ impl TextRunScanner { } #[inline] -fn bounding_box_for_run_metrics(metrics: &RunMetrics, writing_mode: WritingMode) - -> LogicalSize<Au> { +fn bounding_box_for_run_metrics( + metrics: &RunMetrics, + writing_mode: WritingMode, +) -> LogicalSize<Au> { // TODO: When the text-orientation property is supported, the block and inline directions may // be swapped for horizontal glyphs in vertical lines. LogicalSize::new( writing_mode, metrics.bounding_box.size.width, - metrics.bounding_box.size.height) + metrics.bounding_box.size.height, + ) } /// Returns the metrics of the font represented by the given `FontStyleStruct`. @@ -465,8 +508,10 @@ fn bounding_box_for_run_metrics(metrics: &RunMetrics, writing_mode: WritingMode) /// /// Panics if no font can be found for the given font style. #[inline] -pub fn font_metrics_for_style(mut font_context: &mut LayoutFontContext, style: ::ServoArc<FontStyleStruct>) - -> FontMetrics { +pub fn font_metrics_for_style( + mut font_context: &mut LayoutFontContext, + style: ::ServoArc<FontStyleStruct>, +) -> FontMetrics { let font_group = font_context.font_group(style); let font = font_group.borrow_mut().first(&mut font_context); let font = font.as_ref().unwrap().borrow(); @@ -480,13 +525,13 @@ pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) -> match style.get_inherited_text().line_height { LineHeight::Normal => Au::from(metrics.line_gap), LineHeight::Number(l) => font_size.scale_by(l.0), - LineHeight::Length(l) => Au::from(l) + LineHeight::Length(l) => Au::from(l), } } fn split_first_fragment_at_newline_if_necessary(fragments: &mut LinkedList<Fragment>) { if fragments.is_empty() { - return + return; } let new_fragment = { @@ -501,45 +546,46 @@ fn split_first_fragment_at_newline_if_necessary(fragments: &mut LinkedList<Fragm let unscanned_text_fragment_info = match first_fragment.specific { SpecificFragmentInfo::UnscannedText(ref mut unscanned_text_fragment_info) => { unscanned_text_fragment_info - } + }, _ => return, }; let position = match unscanned_text_fragment_info.text.find('\n') { Some(position) if position < unscanned_text_fragment_info.text.len() - 1 => { position - } + }, Some(_) | None => return, }; - string_before = - unscanned_text_fragment_info.text[..(position + 1)].to_owned(); - unscanned_text_fragment_info.text = - unscanned_text_fragment_info.text[(position + 1)..].to_owned().into_boxed_str(); + string_before = unscanned_text_fragment_info.text[..(position + 1)].to_owned(); + unscanned_text_fragment_info.text = unscanned_text_fragment_info.text[(position + 1)..] + .to_owned() + .into_boxed_str(); let offset = ByteIndex(string_before.len() as isize); match unscanned_text_fragment_info.selection { Some(ref mut selection) if selection.begin() >= offset => { // Selection is entirely in the second fragment. selection_before = None; selection.shift_by(-offset); - } + }, Some(ref mut selection) if selection.end() > offset => { // Selection is split across two fragments. selection_before = Some(Range::new(selection.begin(), offset)); *selection = Range::new(ByteIndex(0), selection.end() - offset); - } + }, _ => { // Selection is entirely in the first fragment. selection_before = unscanned_text_fragment_info.selection; unscanned_text_fragment_info.selection = None; - } + }, }; } first_fragment.transform( first_fragment.border_box.size, - SpecificFragmentInfo::UnscannedText(Box::new( - UnscannedTextFragmentInfo::new(string_before.into_boxed_str(), selection_before) - )) + SpecificFragmentInfo::UnscannedText(Box::new(UnscannedTextFragmentInfo::new( + string_before.into_boxed_str(), + selection_before, + ))), ) }; @@ -575,9 +621,7 @@ impl RunInfo { /// /// * `insertion_point`: The position of the insertion point, in characters relative to the start /// of this text run. - fn flush(mut self, - list: &mut Vec<RunInfo>, - insertion_point: &mut Option<ByteIndex>) { + fn flush(mut self, list: &mut Vec<RunInfo>, insertion_point: &mut Option<ByteIndex>) { if let Some(idx) = *insertion_point { let char_len = ByteIndex(self.text.len() as isize); if idx <= char_len { @@ -617,8 +661,7 @@ struct RunMapping { impl RunMapping { /// Given the current set of text runs, creates a run mapping for the next fragment. /// `run_info_list` describes the set of runs we've seen already. - fn new(run_info_list: &[RunInfo], fragment_index: usize) - -> RunMapping { + fn new(run_info_list: &[RunInfo], fragment_index: usize) -> RunMapping { RunMapping { byte_range: Range::new(0, 0), old_fragment_index: fragment_index, @@ -629,27 +672,36 @@ impl RunMapping { /// Flushes this run mapping to the list. `run_info` describes the text run that we're /// currently working on. `text` refers to the text of this fragment. - fn flush(mut self, - mappings: &mut Vec<RunMapping>, - run_info: &mut RunInfo, - text: &str, - compression: CompressionMode, - text_transform: TextTransform, - last_whitespace: &mut bool, - start_position: &mut usize, - end_position: usize) { + fn flush( + mut self, + mappings: &mut Vec<RunMapping>, + run_info: &mut RunInfo, + text: &str, + compression: CompressionMode, + text_transform: TextTransform, + last_whitespace: &mut bool, + start_position: &mut usize, + end_position: usize, + ) { let was_empty = *start_position == end_position; let old_byte_length = run_info.text.len(); - *last_whitespace = util::transform_text(&text[(*start_position)..end_position], - compression, - *last_whitespace, - &mut run_info.text); + *last_whitespace = util::transform_text( + &text[(*start_position)..end_position], + compression, + *last_whitespace, + &mut run_info.text, + ); // Account for `text-transform`. (Confusingly, this is not handled in "text // transformation" above, but we follow Gecko in the naming.) let is_first_run = *start_position == 0; - apply_style_transform_if_necessary(&mut run_info.text, old_byte_length, text_transform, - *last_whitespace, is_first_run); + apply_style_transform_if_necessary( + &mut run_info.text, + old_byte_length, + text_transform, + *last_whitespace, + is_first_run, + ); *start_position = end_position; let new_byte_length = run_info.text.len(); @@ -674,38 +726,39 @@ impl RunMapping { fn contains_insertion_point(&self, insertion_point: Option<ByteIndex>) -> bool { match insertion_point.map(ByteIndex::to_usize) { None => false, - Some(idx) => self.byte_range.begin() <= idx && idx <= self.byte_range.end() + Some(idx) => self.byte_range.begin() <= idx && idx <= self.byte_range.end(), } } } - /// Accounts for `text-transform`. /// /// FIXME(#4311, pcwalton): Title-case mapping can change length of the string; /// case mapping should be language-specific; `full-width`; /// use graphemes instead of characters. -fn apply_style_transform_if_necessary(string: &mut String, - first_character_position: usize, - text_transform: TextTransform, - last_whitespace: bool, - is_first_run: bool) { +fn apply_style_transform_if_necessary( + string: &mut String, + first_character_position: usize, + text_transform: TextTransform, + last_whitespace: bool, + is_first_run: bool, +) { match text_transform { - TextTransform::None => {} + TextTransform::None => {}, TextTransform::Uppercase => { let original = string[first_character_position..].to_owned(); string.truncate(first_character_position); for ch in original.chars().flat_map(|ch| ch.to_uppercase()) { string.push(ch); } - } + }, TextTransform::Lowercase => { let original = string[first_character_position..].to_owned(); string.truncate(first_character_position); for ch in original.chars().flat_map(|ch| ch.to_lowercase()) { string.push(ch); } - } + }, TextTransform::Capitalize => { let original = string[first_character_position..].to_owned(); string.truncate(first_character_position); @@ -719,7 +772,7 @@ fn apply_style_transform_if_necessary(string: &mut String, if capitalize_next_letter && character.is_alphabetic() { string.push(character.to_uppercase().next().unwrap()); capitalize_next_letter = false; - continue + continue; } string.push(character); @@ -729,7 +782,7 @@ fn apply_style_transform_if_necessary(string: &mut String, capitalize_next_letter = true } } - } + }, } } diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index 2d85ce23c9b..e1db809bd8f 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -33,9 +33,7 @@ impl<'a> RecalcStyleAndConstructFlows<'a> { impl<'a> RecalcStyleAndConstructFlows<'a> { /// Creates a traversal context, taking ownership of the shared layout context. pub fn new(context: LayoutContext<'a>) -> Self { - RecalcStyleAndConstructFlows { - context: context, - } + RecalcStyleAndConstructFlows { context: context } } /// Consumes this traversal context, returning ownership of the shared layout @@ -55,11 +53,11 @@ where fn process_preorder<F>( &self, traversal_data: &PerLevelTraversalData, - context: &mut StyleContext<E>, node: E::ConcreteNode, + context: &mut StyleContext<E>, + node: E::ConcreteNode, note_child: F, - ) - where - F: FnMut(E::ConcreteNode) + ) where + F: FnMut(E::ConcreteNode), { // FIXME(pcwalton): Stop allocating here. Ideally this should just be // done by the HTML parser. @@ -76,7 +74,7 @@ where construct_flows_at(&self.context, node); } - fn text_node_needs_traversal(node: E::ConcreteNode, parent_data: &ElementData) -> bool { + fn text_node_needs_traversal(node: E::ConcreteNode, parent_data: &ElementData) -> bool { // Text nodes never need styling. However, there are two cases they may need // flow construction: // (1) They child doesn't yet have layout data (preorder traversal initializes it). @@ -192,7 +190,8 @@ pub trait PostorderNodeMutTraversal<ConcreteThreadSafeLayoutNode: ThreadSafeLayo #[inline] #[allow(unsafe_code)] fn construct_flows_at<N>(context: &LayoutContext, node: N) - where N: LayoutNode, +where + N: LayoutNode, { debug!("construct_flows_at: {:?}", node); @@ -202,22 +201,32 @@ fn construct_flows_at<N>(context: &LayoutContext, node: N) // Always reconstruct if incremental layout is turned off. let nonincremental_layout = opts::get().nonincremental_layout; - if nonincremental_layout || tnode.restyle_damage() != RestyleDamage::empty() || - node.as_element().map_or(false, |el| el.has_dirty_descendants()) { + if nonincremental_layout || tnode.restyle_damage() != RestyleDamage::empty() || node + .as_element() + .map_or(false, |el| el.has_dirty_descendants()) + { let mut flow_constructor = FlowConstructor::new(context); if nonincremental_layout || !flow_constructor.repair_if_possible(&tnode) { flow_constructor.process(&tnode); - debug!("Constructed flow for {:?}: {:x}", - tnode, - tnode.flow_debug_id()); + debug!( + "Constructed flow for {:?}: {:x}", + tnode, + tnode.flow_debug_id() + ); } } - tnode.mutate_layout_data().unwrap().flags.insert(::data::LayoutDataFlags::HAS_BEEN_TRAVERSED); + tnode + .mutate_layout_data() + .unwrap() + .flags + .insert(::data::LayoutDataFlags::HAS_BEEN_TRAVERSED); } if let Some(el) = node.as_element() { - unsafe { el.unset_dirty_descendants(); } + unsafe { + el.unset_dirty_descendants(); + } } } @@ -231,12 +240,16 @@ impl<'a> PostorderFlowTraversal for BubbleISizes<'a> { #[inline] fn process(&self, flow: &mut Flow) { flow.bubble_inline_sizes(); - flow.mut_base().restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES); + flow.mut_base() + .restyle_damage + .remove(ServoRestyleDamage::BUBBLE_ISIZES); } #[inline] fn should_process(&self, flow: &mut Flow) -> bool { - flow.base().restyle_damage.contains(ServoRestyleDamage::BUBBLE_ISIZES) + flow.base() + .restyle_damage + .contains(ServoRestyleDamage::BUBBLE_ISIZES) } } @@ -254,7 +267,9 @@ impl<'a> PreorderFlowTraversal for AssignISizes<'a> { #[inline] fn should_process(&self, flow: &mut Flow) -> bool { - flow.base().restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) + flow.base() + .restyle_damage + .intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) } } @@ -275,7 +290,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizes<'a> { // NB: We must return without resetting the restyle bits for these, as we haven't actually // reflowed anything! if flow.floats_might_flow_through() { - return + return; } flow.assign_block_size(self.layout_context); @@ -298,13 +313,17 @@ pub struct ComputeStackingRelativePositions<'a> { impl<'a> PreorderFlowTraversal for ComputeStackingRelativePositions<'a> { #[inline] fn should_process_subtree(&self, flow: &mut Flow) -> bool { - flow.base().restyle_damage.contains(ServoRestyleDamage::REPOSITION) + flow.base() + .restyle_damage + .contains(ServoRestyleDamage::REPOSITION) } #[inline] fn process(&self, flow: &mut Flow) { flow.compute_stacking_relative_position(self.layout_context); - flow.mut_base().restyle_damage.remove(ServoRestyleDamage::REPOSITION) + flow.mut_base() + .restyle_damage + .remove(ServoRestyleDamage::REPOSITION) } } @@ -322,7 +341,9 @@ impl<'a> BuildDisplayList<'a> { self.state.current_clipping_and_scrolling = flow.clipping_and_scrolling(); flow.build_display_list(&mut self.state); - flow.mut_base().restyle_damage.remove(ServoRestyleDamage::REPAINT); + flow.mut_base() + .restyle_damage + .remove(ServoRestyleDamage::REPAINT); for kid in flow.mut_base().child_iter_mut() { self.traverse(kid); diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 63507127b07..1e3f30f3f7c 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -57,7 +57,8 @@ impl<T: GetLayoutData> LayoutNodeLayoutData for T { } fn flow_debug_id(self) -> usize { - self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id()) + self.borrow_layout_data() + .map_or(0, |d| d.flow_construction_result.debug_id()) } } @@ -114,12 +115,10 @@ impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T { if self.get_pseudo_element_type().is_replaced_content() { let style = self.as_element().unwrap().resolved_style(); - return TextContent::GeneratedContent( - match style.as_ref().get_counters().content { - Content::Items(ref value) => value.to_vec(), - _ => vec![], - } - ); + return TextContent::GeneratedContent(match style.as_ref().get_counters().content { + Content::Items(ref value) => value.to_vec(), + _ => vec![], + }); } TextContent::Text(self.node_text_content().into_boxed_str()) @@ -141,7 +140,12 @@ impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T { let damage = { let data = node.get_raw_data().unwrap(); - if !data.layout_data.borrow().flags.contains(::data::LayoutDataFlags::HAS_BEEN_TRAVERSED) { + if !data + .layout_data + .borrow() + .flags + .contains(::data::LayoutDataFlags::HAS_BEEN_TRAVERSED) + { // We're reflowing a node that was styled for the first time and // has never been visited by layout. Return rebuild_and_reflow, // because that's what the code expects. @@ -153,7 +157,6 @@ impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T { damage } - } pub enum TextContent { |