aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout_2020/lib.rs
diff options
context:
space:
mode:
authorAnthony Ramine <nox@nox.paris>2019-09-09 17:21:26 +0200
committerAnthony Ramine <nox@nox.paris>2019-09-11 10:36:30 +0200
commit4444c5a2adfec909e165497ca331c09e02ee54cc (patch)
treebc4fea59172122f5a08d6e8d231f5fe3cf616569 /components/layout_2020/lib.rs
parent86904757e66285412de162483f3ba2a6db35403e (diff)
downloadservo-4444c5a2adfec909e165497ca331c09e02ee54cc.tar.gz
servo-4444c5a2adfec909e165497ca331c09e02ee54cc.zip
Import victor's layout system 🍷
Diffstat (limited to 'components/layout_2020/lib.rs')
-rw-r--r--components/layout_2020/lib.rs148
1 files changed, 148 insertions, 0 deletions
diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs
index af5709eae38..05a5caa9771 100644
--- a/components/layout_2020/lib.rs
+++ b/components/layout_2020/lib.rs
@@ -2,11 +2,159 @@
* 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/. */
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+#![allow(unused_imports)]
+#![allow(unused_variables)]
#![deny(unsafe_code)]
+#[macro_use]
+extern crate serde;
+
+use style::properties::ComputedValues;
+use style::values::computed::{Length, LengthOrAuto};
+use style::Zero;
+
pub mod context;
pub mod data;
+pub mod dom_traversal;
+pub mod element_data;
+pub mod flow;
+pub mod fragments;
+pub mod geom;
pub mod opaque_node;
+pub mod positioned;
pub mod query;
+pub mod replaced;
+pub mod style_ext;
pub mod traversal;
pub mod wrapper;
+
+use crate::dom_traversal::{Contents, NodeExt};
+use crate::flow::{BlockFormattingContext, FlowChildren};
+use crate::geom::flow_relative::Vec2;
+use crate::positioned::AbsolutelyPositionedFragment;
+use crate::replaced::ReplacedContent;
+use crate::style_ext::{ComputedValuesExt, Direction, Position, WritingMode};
+use servo_arc::Arc;
+use std::convert::TryInto;
+use style::context::SharedStyleContext;
+use style::values::specified::box_::DisplayInside;
+
+/// https://drafts.csswg.org/css-display/#independent-formatting-context
+#[derive(Debug)]
+enum IndependentFormattingContext {
+ Flow(BlockFormattingContext),
+
+ // Not called FC in specs, but behaves close enough
+ Replaced(ReplacedContent),
+ // Other layout modes go here
+}
+
+enum NonReplacedIFC<'a> {
+ Flow(&'a BlockFormattingContext),
+}
+
+impl IndependentFormattingContext {
+ fn construct<'dom, 'style>(
+ context: &SharedStyleContext<'style>,
+ style: &Arc<ComputedValues>,
+ display_inside: DisplayInside,
+ contents: Contents<impl NodeExt<'dom>>,
+ ) -> Self {
+ match contents.try_into() {
+ Ok(non_replaced) => match display_inside {
+ DisplayInside::Flow | DisplayInside::FlowRoot => {
+ IndependentFormattingContext::Flow(BlockFormattingContext::construct(
+ context,
+ style,
+ non_replaced,
+ ))
+ },
+ DisplayInside::None | DisplayInside::Contents => panic!(":("),
+ },
+ Err(replaced) => IndependentFormattingContext::Replaced(replaced),
+ }
+ }
+
+ fn as_replaced(&self) -> Result<&ReplacedContent, NonReplacedIFC> {
+ match self {
+ IndependentFormattingContext::Replaced(r) => Ok(r),
+ IndependentFormattingContext::Flow(f) => Err(NonReplacedIFC::Flow(f)),
+ }
+ }
+
+ fn layout<'a>(
+ &'a self,
+ containing_block: &ContainingBlock,
+ tree_rank: usize,
+ absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
+ ) -> FlowChildren {
+ match self.as_replaced() {
+ Ok(replaced) => match *replaced {},
+ Err(ifc) => ifc.layout(containing_block, tree_rank, absolutely_positioned_fragments),
+ }
+ }
+}
+
+impl<'a> NonReplacedIFC<'a> {
+ fn layout(
+ &self,
+ containing_block: &ContainingBlock,
+ tree_rank: usize,
+ absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
+ ) -> FlowChildren {
+ match self {
+ NonReplacedIFC::Flow(bfc) => {
+ bfc.layout(containing_block, tree_rank, absolutely_positioned_fragments)
+ },
+ }
+ }
+}
+
+struct ContainingBlock {
+ inline_size: Length,
+ block_size: LengthOrAuto,
+ mode: (WritingMode, Direction),
+}
+
+struct DefiniteContainingBlock {
+ size: Vec2<Length>,
+ mode: (WritingMode, Direction),
+}
+
+/// https://drafts.csswg.org/css2/visuren.html#relative-positioning
+fn relative_adjustement(
+ style: &ComputedValues,
+ inline_size: Length,
+ block_size: LengthOrAuto,
+) -> Vec2<Length> {
+ if style.get_box().position != Position::Relative {
+ return Vec2::zero();
+ }
+ fn adjust(start: LengthOrAuto, end: LengthOrAuto) -> Length {
+ match (start, end) {
+ (LengthOrAuto::Auto, LengthOrAuto::Auto) => Length::zero(),
+ (LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(end)) => -end,
+ (LengthOrAuto::LengthPercentage(start), _) => start,
+ }
+ }
+ let block_size = block_size.auto_is(Length::zero);
+ let box_offsets = style.box_offsets().map_inline_and_block_axes(
+ |v| v.percentage_relative_to(inline_size),
+ |v| v.percentage_relative_to(block_size),
+ );
+ Vec2 {
+ inline: adjust(box_offsets.inline_start, box_offsets.inline_end),
+ block: adjust(box_offsets.block_start, box_offsets.block_end),
+ }
+}
+
+// FIXME: use std::mem::take when it’s stable.
+// https://github.com/rust-lang/rust/issues/61129
+fn take<T>(x: &mut T) -> T
+where
+ T: Default,
+{
+ std::mem::replace(x, Default::default())
+}