mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Layout 2020 skeleton for display: flex
, behind a pref
This commit is contained in:
parent
d4f1f4641d
commit
64124f7a5e
8 changed files with 114 additions and 18 deletions
|
@ -454,6 +454,9 @@ mod gen {
|
||||||
columns: {
|
columns: {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
},
|
},
|
||||||
|
flexbox: {
|
||||||
|
enabled: bool,
|
||||||
|
},
|
||||||
#[serde(default = "default_layout_threads")]
|
#[serde(default = "default_layout_threads")]
|
||||||
threads: i64,
|
threads: i64,
|
||||||
viewport: {
|
viewport: {
|
||||||
|
|
62
components/layout_2020/flexbox.rs
Normal file
62
components/layout_2020/flexbox.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::context::LayoutContext;
|
||||||
|
use crate::dom_traversal::{NodeExt, NonReplacedContents};
|
||||||
|
use crate::formatting_contexts::IndependentLayout;
|
||||||
|
use crate::positioned::PositioningContext;
|
||||||
|
use crate::sizing::{BoxContentSizes, ContentSizesRequest};
|
||||||
|
use crate::ContainingBlock;
|
||||||
|
use servo_arc::Arc;
|
||||||
|
use style::properties::ComputedValues;
|
||||||
|
use style::values::specified::text::TextDecorationLine;
|
||||||
|
|
||||||
|
// FIXME: `min-width: auto` is not zero: https://drafts.csswg.org/css-flexbox/#min-size-auto
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub(crate) struct FlexContainer {
|
||||||
|
unimplemented_fallback: crate::flow::BlockFormattingContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FlexContainer {
|
||||||
|
pub fn construct<'dom>(
|
||||||
|
context: &LayoutContext,
|
||||||
|
node: impl NodeExt<'dom>,
|
||||||
|
style: &Arc<ComputedValues>,
|
||||||
|
contents: NonReplacedContents,
|
||||||
|
content_sizes: ContentSizesRequest,
|
||||||
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
|
) -> (Self, BoxContentSizes) {
|
||||||
|
let (unimplemented_fallback, content_sizes) =
|
||||||
|
crate::flow::BlockFormattingContext::construct(
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
style,
|
||||||
|
contents,
|
||||||
|
content_sizes,
|
||||||
|
propagated_text_decoration_line,
|
||||||
|
);
|
||||||
|
(
|
||||||
|
Self {
|
||||||
|
unimplemented_fallback,
|
||||||
|
},
|
||||||
|
content_sizes,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn layout(
|
||||||
|
&self,
|
||||||
|
layout_context: &LayoutContext,
|
||||||
|
positioning_context: &mut PositioningContext,
|
||||||
|
containing_block: &ContainingBlock,
|
||||||
|
tree_rank: usize,
|
||||||
|
) -> IndependentLayout {
|
||||||
|
self.unimplemented_fallback.layout(
|
||||||
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
|
containing_block,
|
||||||
|
tree_rank,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::{Contents, NodeExt};
|
use crate::dom_traversal::{Contents, NodeExt};
|
||||||
|
use crate::flexbox::FlexContainer;
|
||||||
use crate::flow::BlockFormattingContext;
|
use crate::flow::BlockFormattingContext;
|
||||||
use crate::fragments::Fragment;
|
use crate::fragments::Fragment;
|
||||||
use crate::positioned::PositioningContext;
|
use crate::positioned::PositioningContext;
|
||||||
|
@ -43,6 +44,7 @@ pub(crate) struct IndependentLayout {
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
enum IndependentFormattingContextContents {
|
enum IndependentFormattingContextContents {
|
||||||
Flow(BlockFormattingContext),
|
Flow(BlockFormattingContext),
|
||||||
|
Flex(FlexContainer),
|
||||||
|
|
||||||
// Not called FC in specs, but behaves close enough
|
// Not called FC in specs, but behaves close enough
|
||||||
Replaced(ReplacedContent),
|
Replaced(ReplacedContent),
|
||||||
|
@ -53,6 +55,7 @@ pub(crate) struct NonReplacedIFC<'a>(NonReplacedIFCKind<'a>);
|
||||||
|
|
||||||
enum NonReplacedIFCKind<'a> {
|
enum NonReplacedIFCKind<'a> {
|
||||||
Flow(&'a BlockFormattingContext),
|
Flow(&'a BlockFormattingContext),
|
||||||
|
Flex(&'a FlexContainer),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndependentFormattingContext {
|
impl IndependentFormattingContext {
|
||||||
|
@ -83,6 +86,22 @@ impl IndependentFormattingContext {
|
||||||
contents: IndependentFormattingContextContents::Flow(bfc),
|
contents: IndependentFormattingContextContents::Flow(bfc),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
DisplayInside::Flex => {
|
||||||
|
let (fc, content_sizes) = FlexContainer::construct(
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
&style,
|
||||||
|
non_replaced,
|
||||||
|
content_sizes,
|
||||||
|
propagated_text_decoration_line,
|
||||||
|
);
|
||||||
|
Self {
|
||||||
|
tag: node.as_opaque(),
|
||||||
|
style,
|
||||||
|
content_sizes,
|
||||||
|
contents: IndependentFormattingContextContents::Flex(fc),
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Err(replaced) => {
|
Err(replaced) => {
|
||||||
let content_sizes = content_sizes.compute(|| replaced.inline_content_sizes(&style));
|
let content_sizes = content_sizes.compute(|| replaced.inline_content_sizes(&style));
|
||||||
|
@ -103,6 +122,7 @@ impl IndependentFormattingContext {
|
||||||
match &self.contents {
|
match &self.contents {
|
||||||
Contents::Replaced(r) => Ok(r),
|
Contents::Replaced(r) => Ok(r),
|
||||||
Contents::Flow(f) => Err(NR(Kind::Flow(f))),
|
Contents::Flow(f) => Err(NR(Kind::Flow(f))),
|
||||||
|
Contents::Flex(f) => Err(NR(Kind::Flex(f))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,6 +142,12 @@ impl NonReplacedIFC<'_> {
|
||||||
containing_block,
|
containing_block,
|
||||||
tree_rank,
|
tree_rank,
|
||||||
),
|
),
|
||||||
|
NonReplacedIFCKind::Flex(fc) => fc.layout(
|
||||||
|
layout_context,
|
||||||
|
positioning_context,
|
||||||
|
containing_block,
|
||||||
|
tree_rank,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ pub mod data;
|
||||||
pub mod display_list;
|
pub mod display_list;
|
||||||
mod dom_traversal;
|
mod dom_traversal;
|
||||||
pub mod element_data;
|
pub mod element_data;
|
||||||
|
mod flexbox;
|
||||||
mod flow;
|
mod flow;
|
||||||
mod formatting_contexts;
|
mod formatting_contexts;
|
||||||
mod fragments;
|
mod fragments;
|
||||||
|
|
|
@ -48,6 +48,7 @@ pub(crate) enum DisplayOutside {
|
||||||
pub(crate) enum DisplayInside {
|
pub(crate) enum DisplayInside {
|
||||||
Flow,
|
Flow,
|
||||||
FlowRoot,
|
FlowRoot,
|
||||||
|
Flex,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Percentages resolved but not `auto` margins
|
/// Percentages resolved but not `auto` margins
|
||||||
|
@ -394,6 +395,7 @@ impl From<stylo::Display> for Display {
|
||||||
let inside = match packed.inside() {
|
let inside = match packed.inside() {
|
||||||
stylo::DisplayInside::Flow => DisplayInside::Flow,
|
stylo::DisplayInside::Flow => DisplayInside::Flow,
|
||||||
stylo::DisplayInside::FlowRoot => DisplayInside::FlowRoot,
|
stylo::DisplayInside::FlowRoot => DisplayInside::FlowRoot,
|
||||||
|
stylo::DisplayInside::Flex => DisplayInside::Flex,
|
||||||
|
|
||||||
// These should not be values of DisplayInside, but oh well
|
// These should not be values of DisplayInside, but oh well
|
||||||
stylo::DisplayInside::None => return Display::None,
|
stylo::DisplayInside::None => return Display::None,
|
||||||
|
|
|
@ -34,6 +34,17 @@ fn moz_box_display_values_enabled(context: &ParserContext) -> bool {
|
||||||
static_prefs::pref!("layout.css.xul-box-display-values.content.enabled")
|
static_prefs::pref!("layout.css.xul-box-display-values.content.enabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flexbox_enabled() -> bool {
|
||||||
|
if cfg!(feature = "servo-layout-2020") {
|
||||||
|
servo_config::prefs::pref_map()
|
||||||
|
.get("layout.flexbox.enabled")
|
||||||
|
.as_bool()
|
||||||
|
.unwrap_or(false)
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Defines an element’s display type, which consists of
|
/// Defines an element’s display type, which consists of
|
||||||
/// the two basic qualities of how an element generates boxes
|
/// the two basic qualities of how an element generates boxes
|
||||||
/// <https://drafts.csswg.org/css-display/#propdef-display>
|
/// <https://drafts.csswg.org/css-display/#propdef-display>
|
||||||
|
@ -63,7 +74,6 @@ pub enum DisplayInside {
|
||||||
Contents,
|
Contents,
|
||||||
Flow,
|
Flow,
|
||||||
FlowRoot,
|
FlowRoot,
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
|
||||||
Flex,
|
Flex,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
Grid,
|
Grid,
|
||||||
|
@ -146,9 +156,7 @@ impl Display {
|
||||||
pub const Block: Self = Self::new(DisplayOutside::Block, DisplayInside::Flow);
|
pub const Block: Self = Self::new(DisplayOutside::Block, DisplayInside::Flow);
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub const FlowRoot: Self = Self::new(DisplayOutside::Block, DisplayInside::FlowRoot);
|
pub const FlowRoot: Self = Self::new(DisplayOutside::Block, DisplayInside::FlowRoot);
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
|
||||||
pub const Flex: Self = Self::new(DisplayOutside::Block, DisplayInside::Flex);
|
pub const Flex: Self = Self::new(DisplayOutside::Block, DisplayInside::Flex);
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
|
||||||
pub const InlineFlex: Self = Self::new(DisplayOutside::Inline, DisplayInside::Flex);
|
pub const InlineFlex: Self = Self::new(DisplayOutside::Inline, DisplayInside::Flex);
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub const Grid: Self = Self::new(DisplayOutside::Block, DisplayInside::Grid);
|
pub const Grid: Self = Self::new(DisplayOutside::Block, DisplayInside::Grid);
|
||||||
|
@ -317,9 +325,9 @@ impl Display {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_atomic_inline_level(&self) -> bool {
|
pub fn is_atomic_inline_level(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Display::InlineBlock => true,
|
Display::InlineBlock | Display::InlineFlex => true,
|
||||||
#[cfg(any(feature = "servo-layout-2013"))]
|
#[cfg(any(feature = "servo-layout-2013"))]
|
||||||
Display::InlineFlex | Display::InlineTable => true,
|
Display::InlineTable => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +338,6 @@ impl Display {
|
||||||
/// This is used to implement various style fixups.
|
/// This is used to implement various style fixups.
|
||||||
pub fn is_item_container(&self) -> bool {
|
pub fn is_item_container(&self) -> bool {
|
||||||
match self.inside() {
|
match self.inside() {
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
|
||||||
DisplayInside::Flex => true,
|
DisplayInside::Flex => true,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
DisplayInside::Grid => true,
|
DisplayInside::Grid => true,
|
||||||
|
@ -432,12 +439,9 @@ impl ToCss for Display {
|
||||||
_ => match (outside, inside) {
|
_ => match (outside, inside) {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
(DisplayOutside::Inline, DisplayInside::Grid) => dest.write_str("inline-grid"),
|
(DisplayOutside::Inline, DisplayInside::Grid) => dest.write_str("inline-grid"),
|
||||||
|
(DisplayOutside::Inline, DisplayInside::Flex) => dest.write_str("inline-flex"),
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
||||||
(DisplayOutside::Inline, DisplayInside::Flex) |
|
(DisplayOutside::Inline, DisplayInside::Table) => dest.write_str("inline-table"),
|
||||||
(DisplayOutside::Inline, DisplayInside::Table) => {
|
|
||||||
dest.write_str("inline-")?;
|
|
||||||
inside.to_css(dest)
|
|
||||||
},
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
(DisplayOutside::Block, DisplayInside::Ruby) => dest.write_str("block ruby"),
|
(DisplayOutside::Block, DisplayInside::Ruby) => dest.write_str("block ruby"),
|
||||||
(_, inside) => {
|
(_, inside) => {
|
||||||
|
@ -467,12 +471,11 @@ fn parse_display_inside<'i, 't>(
|
||||||
) -> Result<DisplayInside, ParseError<'i>> {
|
) -> Result<DisplayInside, ParseError<'i>> {
|
||||||
Ok(try_match_ident_ignore_ascii_case! { input,
|
Ok(try_match_ident_ignore_ascii_case! { input,
|
||||||
"flow" => DisplayInside::Flow,
|
"flow" => DisplayInside::Flow,
|
||||||
|
"flex" if flexbox_enabled() => DisplayInside::Flex,
|
||||||
#[cfg(any(feature = "servo-layout-2020", feature = "gecko"))]
|
#[cfg(any(feature = "servo-layout-2020", feature = "gecko"))]
|
||||||
"flow-root" => DisplayInside::FlowRoot,
|
"flow-root" => DisplayInside::FlowRoot,
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
||||||
"table" => DisplayInside::Table,
|
"table" => DisplayInside::Table,
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
|
||||||
"flex" => DisplayInside::Flex,
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
"grid" => DisplayInside::Grid,
|
"grid" => DisplayInside::Grid,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
|
@ -575,10 +578,8 @@ impl Parse for Display {
|
||||||
"inline-block" => Display::InlineBlock,
|
"inline-block" => Display::InlineBlock,
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
||||||
"inline-table" => Display::InlineTable,
|
"inline-table" => Display::InlineTable,
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
"-webkit-flex" if flexbox_enabled() => Display::Flex,
|
||||||
"-webkit-flex" => Display::Flex,
|
"inline-flex" | "-webkit-inline-flex" if flexbox_enabled() => Display::InlineFlex,
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
|
||||||
"inline-flex" | "-webkit-inline-flex" => Display::InlineFlex,
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
"inline-grid" => Display::InlineGrid,
|
"inline-grid" => Display::InlineGrid,
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
||||||
|
|
|
@ -88,6 +88,7 @@
|
||||||
"js.werror.enabled": false,
|
"js.werror.enabled": false,
|
||||||
"layout.animations.test.enabled": false,
|
"layout.animations.test.enabled": false,
|
||||||
"layout.columns.enabled": false,
|
"layout.columns.enabled": false,
|
||||||
|
"layout.flexbox.enabled": false,
|
||||||
"layout.threads": 3,
|
"layout.threads": 3,
|
||||||
"layout.viewport.enabled": false,
|
"layout.viewport.enabled": false,
|
||||||
"layout.writing-mode.enabled": false,
|
"layout.writing-mode.enabled": false,
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
prefs: ["layout.columns.enabled:true"]
|
prefs: ["layout.columns.enabled:true", "layout.flexbox.enabled:true"]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue