Auto merge of #12330 - stshine:flexitem, r=pcwalton

Implement flexible box layout for row container

<!-- Please describe your changes on the following line: -->

This pull requests implements basic flexible box layout for row container.
It  has implemented most basic flexbox features, including grow, shrink, multi-line, *reverse properties, and alignment under `justify-content`, `align-items`, `align-self`, `align-content`.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X]  There are tests for these changes

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

r? @pcwalton

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12330)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-08-03 09:24:31 -05:00 committed by GitHub
commit 15947f8f73
200 changed files with 623 additions and 700 deletions

View file

@ -487,6 +487,7 @@ pub enum BlockType {
FloatNonReplaced,
InlineBlockReplaced,
InlineBlockNonReplaced,
FlexItem,
}
#[derive(Clone, PartialEq)]
@ -521,7 +522,9 @@ pub struct BlockFlow {
bitflags! {
flags BlockFlowFlags: u8 {
#[doc = "If this is set, then this block flow is the root flow."]
const IS_ROOT = 0x01,
const IS_ROOT = 0b0000_0001,
#[doc = "Whether this block flow is a child of a flex container."]
const IS_FLEX = 0b0001_0000,
}
}
@ -556,6 +559,8 @@ impl BlockFlow {
} else {
BlockType::AbsoluteNonReplaced
}
} else if self.is_flex() {
BlockType::FlexItem
} else if self.base.flags.is_float() {
if self.is_replaced_content() {
BlockType::FloatReplaced
@ -631,6 +636,12 @@ impl BlockFlow {
shared_context,
containing_block_inline_size);
}
BlockType::FlexItem => {
let inline_size_computer = FlexItem;
inline_size_computer.compute_used_inline_size(self,
shared_context,
containing_block_inline_size);
}
}
}
@ -1138,7 +1149,7 @@ impl BlockFlow {
}
}
fn explicit_block_size(&self, containing_block_size: Option<Au>) -> Option<Au> {
pub fn explicit_block_size(&self, containing_block_size: Option<Au>) -> Option<Au> {
let content_block_size = self.fragment.style().content_block_size();
match (content_block_size, containing_block_size) {
@ -1671,6 +1682,14 @@ impl BlockFlow {
let padding = self.fragment.style.logical_padding();
padding.block_start.is_definitely_zero() && padding.block_end.is_definitely_zero()
}
pub fn mark_as_flex(&mut self) {
self.flags.insert(IS_FLEX)
}
pub fn is_flex(&self) -> bool {
self.flags.contains(IS_FLEX)
}
}
impl Flow for BlockFlow {
@ -2557,6 +2576,7 @@ pub struct FloatNonReplaced;
pub struct FloatReplaced;
pub struct InlineBlockNonReplaced;
pub struct InlineBlockReplaced;
pub struct FlexItem;
impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
/// Solve the horizontal constraint equation for absolute non-replaced elements.
@ -3047,6 +3067,30 @@ impl ISizeAndMarginsComputer for InlineBlockReplaced {
}
}
impl ISizeAndMarginsComputer for FlexItem {
// 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) {
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);
}
// 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 {
let fragment = block.fragment();
ISizeConstraintSolution::new(fragment.border_box.size.inline,
fragment.margin.inline_start,
fragment.margin.inline_end)
}
}
/// A stacking context, a pseudo-stacking context, or a non-stacking context.
#[derive(Copy, Clone, PartialEq)]
pub enum BlockStackingContextType {