servo: Merge #10987 - Bug #10181 - Implement *-reverse flex-directions (from shinglyu:flex-reverse); r=shinglyu
authorShing Lyu <shing.lyu@gmail.com>
Tue, 10 May 2016 19:51:04 -0700
changeset 338763 d84fa4690e3578d6cc679382cc8b8d32a60c805e
parent 338762 05d2c33b8667e2e1bcad44660a10d097ef86dfd2
child 338764 040894d88b0ee33fdaecf53c0a10b9dc09d7c546
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshinglyu
servo: Merge #10987 - Bug #10181 - Implement *-reverse flex-directions (from shinglyu:flex-reverse); r=shinglyu Source-Repo: https://github.com/servo/servo Source-Revision: 20f0be20d702af3c6f99c929191669b183606eb5
servo/components/layout/flex.rs
--- a/servo/components/layout/flex.rs
+++ b/servo/components/layout/flex.rs
@@ -94,35 +94,40 @@ pub struct FlexFlow {
     /// The logical axis which the main axis will be parallel with.
     /// The cross axis will be parallel with the opposite logical axis.
     main_mode: Mode,
     /// The available main axis size
     available_main_size: AxisSize,
     /// The available cross axis size
     available_cross_size: AxisSize,
     /// List of flex-items that belong to this flex-container
-    items: Vec<FlexItem>
+    items: Vec<FlexItem>,
+    /// True if the flex-direction is *-reversed
+    is_reverse: bool
 }
 
 impl FlexFlow {
     pub fn from_fragment(fragment: Fragment,
                          flotation: Option<FloatKind>)
                          -> FlexFlow {
 
-        let main_mode = match fragment.style.get_position().flex_direction {
-            flex_direction::T::row_reverse | flex_direction::T::row => Mode::Inline,
-            flex_direction::T::column_reverse | flex_direction::T::column => Mode::Block
+        let (main_mode, is_reverse) = match fragment.style.get_position().flex_direction {
+            flex_direction::T::row            => (Mode::Inline, false),
+            flex_direction::T::row_reverse    => (Mode::Inline, true),
+            flex_direction::T::column         => (Mode::Block, false),
+            flex_direction::T::column_reverse => (Mode::Block, true),
         };
 
         FlexFlow {
             block_flow: BlockFlow::from_fragment(fragment, flotation),
             main_mode: main_mode,
             available_main_size: AxisSize::Infinite,
             available_cross_size: AxisSize::Infinite,
-            items: Vec::new()
+            items: Vec::new(),
+            is_reverse: is_reverse
         }
     }
 
     // TODO(zentner): This function should use flex-basis.
     // Currently, this is the core of BlockFlow::bubble_inline_sizes() with all float logic
     // stripped out, and max replaced with union_nonbreaking_inline.
     fn inline_mode_bubble_inline_sizes(&mut self) {
         let fixed_width = match self.block_flow.fragment.style().get_position().width {
@@ -246,35 +251,53 @@ impl FlexFlow {
         };
 
         let even_content_inline_size = inline_size / child_count;
 
         let container_mode = self.block_flow.base.block_container_writing_mode;
         self.block_flow.base.position.size.inline = inline_size;
 
         let block_container_explicit_block_size = self.block_flow.base.block_container_explicit_block_size;
-        let mut inline_child_start = inline_start_content_edge;
+        let mut inline_child_start = if !self.is_reverse {
+            inline_start_content_edge
+        } else {
+            self.block_flow.fragment.border_box.size.inline
+        };
         for kid in &mut self.items {
             let base = flow::mut_base(flow_ref::deref_mut(&mut kid.flow));
 
             base.block_container_inline_size = even_content_inline_size;
             base.block_container_writing_mode = container_mode;
             base.block_container_explicit_block_size = block_container_explicit_block_size;
-            base.position.start.i = inline_child_start;
-            inline_child_start = inline_child_start + even_content_inline_size;
+            if !self.is_reverse {
+              base.position.start.i = inline_child_start;
+              inline_child_start = inline_child_start + even_content_inline_size;
+            } else {
+              base.position.start.i = inline_child_start - base.intrinsic_inline_sizes.preferred_inline_size;
+              inline_child_start = inline_child_start - even_content_inline_size;
+            };
         }
     }
 
     // TODO(zentner): This function should actually flex elements!
     fn block_mode_assign_block_size<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
-        let mut cur_b = self.block_flow.fragment.border_padding.block_start;
+        let mut cur_b = if !self.is_reverse {
+            self.block_flow.fragment.border_padding.block_start
+        } else {
+            self.block_flow.fragment.border_box.size.block
+        };
         for kid in &mut self.items {
             let base = flow::mut_base(flow_ref::deref_mut(&mut kid.flow));
-            base.position.start.b = cur_b;
-            cur_b = cur_b + base.position.size.block;
+            if !self.is_reverse {
+                base.position.start.b = cur_b;
+                cur_b = cur_b + base.position.size.block;
+            } else {
+                cur_b = cur_b - base.position.size.block;
+                base.position.start.b = cur_b;
+            }
         }
         self.block_flow.assign_block_size(layout_context)
     }
 
     // TODO(zentner): This function should actually flex elements!
     // Currently, this is the core of TableRowFlow::assign_block_size() with
     // float related logic stripped out.
     fn inline_mode_assign_block_size<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {