mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
Uncomment more stuff related to box construction
This commit is contained in:
parent
c08cfbb5f3
commit
9cef3eee65
4 changed files with 226 additions and 202 deletions
|
@ -9,7 +9,7 @@ use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, Te
|
|||
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
|
||||
use crate::positioned::AbsolutelyPositionedBox;
|
||||
use crate::style_ext::{DisplayGeneratingBox, DisplayInside, DisplayOutside};
|
||||
use crate::IndependentFormattingContext;
|
||||
use crate::{take, IndependentFormattingContext};
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use rayon_croissant::ParallelIteratorExt;
|
||||
use servo_arc::Arc;
|
||||
|
@ -152,8 +152,7 @@ impl BlockContainer {
|
|||
);
|
||||
return (container, builder.contains_floats);
|
||||
}
|
||||
// FIXME
|
||||
// builder.end_ongoing_inline_formatting_context();
|
||||
builder.end_ongoing_inline_formatting_context();
|
||||
}
|
||||
|
||||
let mut contains_floats = builder.contains_floats;
|
||||
|
@ -166,8 +165,7 @@ impl BlockContainer {
|
|||
|contains_floats, (intermediate, box_slot): (IntermediateBlockLevelBox<_>, BoxSlot<'_>)| {
|
||||
let (block_level_box, box_contains_floats) = intermediate.finish(context);
|
||||
*contains_floats |= box_contains_floats;
|
||||
// FIXME
|
||||
// box_slot.set(LayoutBox::BlockLevel(block_level_box.clone()));
|
||||
box_slot.set(LayoutBox::BlockLevel(block_level_box.clone()));
|
||||
block_level_box
|
||||
},
|
||||
|left, right| *left |= right,
|
||||
|
@ -195,21 +193,21 @@ where
|
|||
self.handle_inline_level_element(style, inside, contents),
|
||||
)),
|
||||
DisplayOutside::Block => {
|
||||
// FIXME
|
||||
let box_style = style.get_box();
|
||||
// Floats and abspos cause blockification, so they only happen in this case.
|
||||
// https://drafts.csswg.org/css2/visuren.html#dis-pos-flo
|
||||
// if style.box_.position.is_absolutely_positioned() {
|
||||
// self.handle_absolutely_positioned_element(
|
||||
// style.clone(),
|
||||
// inside,
|
||||
// contents,
|
||||
// box_slot,
|
||||
// )
|
||||
// } else if style.box_.float.is_floating() {
|
||||
// self.handle_float_element(style.clone(), inside, contents, box_slot)
|
||||
// } else {
|
||||
// self.handle_block_level_element(style.clone(), inside, contents, box_slot)
|
||||
// }
|
||||
if box_style.position.is_absolutely_positioned() {
|
||||
self.handle_absolutely_positioned_element(
|
||||
style.clone(),
|
||||
inside,
|
||||
contents,
|
||||
box_slot,
|
||||
)
|
||||
} else if box_style.float.is_floating() {
|
||||
self.handle_float_element(style.clone(), inside, contents, box_slot)
|
||||
} else {
|
||||
self.handle_block_level_element(style.clone(), inside, contents, box_slot)
|
||||
}
|
||||
},
|
||||
DisplayOutside::None => panic!(":("),
|
||||
},
|
||||
|
@ -362,80 +360,79 @@ where
|
|||
box_
|
||||
}
|
||||
|
||||
// FIXME
|
||||
// fn handle_block_level_element(
|
||||
// &mut self,
|
||||
// style: Arc<ComputedValues>,
|
||||
// display_inside: DisplayInside,
|
||||
// contents: Contents,
|
||||
// box_slot: BoxSlot<'a>,
|
||||
// ) {
|
||||
// // We just found a block level element, all ongoing inline level boxes
|
||||
// // need to be split around it. We iterate on the fragmented inline
|
||||
// // level box stack to take their contents and set their first_fragment
|
||||
// // field to false, for the fragmented inline level boxes that will
|
||||
// // come after the block level element.
|
||||
// let mut fragmented_inline_boxes =
|
||||
// self.ongoing_inline_boxes_stack
|
||||
// .iter_mut()
|
||||
// .rev()
|
||||
// .map(|ongoing| {
|
||||
// let fragmented = InlineBox {
|
||||
// style: ongoing.style.clone(),
|
||||
// first_fragment: ongoing.first_fragment,
|
||||
// // The fragmented boxes before the block level element
|
||||
// // are obviously not the last fragment.
|
||||
// last_fragment: false,
|
||||
// children: take(&mut ongoing.children),
|
||||
// };
|
||||
// ongoing.first_fragment = false;
|
||||
// fragmented
|
||||
// });
|
||||
fn handle_block_level_element(
|
||||
&mut self,
|
||||
style: Arc<ComputedValues>,
|
||||
display_inside: DisplayInside,
|
||||
contents: Contents<Node>,
|
||||
box_slot: BoxSlot<'dom>,
|
||||
) {
|
||||
// We just found a block level element, all ongoing inline level boxes
|
||||
// need to be split around it. We iterate on the fragmented inline
|
||||
// level box stack to take their contents and set their first_fragment
|
||||
// field to false, for the fragmented inline level boxes that will
|
||||
// come after the block level element.
|
||||
let mut fragmented_inline_boxes =
|
||||
self.ongoing_inline_boxes_stack
|
||||
.iter_mut()
|
||||
.rev()
|
||||
.map(|ongoing| {
|
||||
let fragmented = InlineBox {
|
||||
style: ongoing.style.clone(),
|
||||
first_fragment: ongoing.first_fragment,
|
||||
// The fragmented boxes before the block level element
|
||||
// are obviously not the last fragment.
|
||||
last_fragment: false,
|
||||
children: take(&mut ongoing.children),
|
||||
};
|
||||
ongoing.first_fragment = false;
|
||||
fragmented
|
||||
});
|
||||
|
||||
// if let Some(last) = fragmented_inline_boxes.next() {
|
||||
// // There were indeed some ongoing inline level boxes before
|
||||
// // the block, we accumulate them as a single inline level box
|
||||
// // to be pushed to the ongoing inline formatting context.
|
||||
// let mut fragmented_inline = InlineLevelBox::InlineBox(last);
|
||||
// for mut fragmented_parent_inline_box in fragmented_inline_boxes {
|
||||
// fragmented_parent_inline_box
|
||||
// .children
|
||||
// .push(Arc::new(fragmented_inline));
|
||||
// fragmented_inline = InlineLevelBox::InlineBox(fragmented_parent_inline_box);
|
||||
// }
|
||||
if let Some(last) = fragmented_inline_boxes.next() {
|
||||
// There were indeed some ongoing inline level boxes before
|
||||
// the block, we accumulate them as a single inline level box
|
||||
// to be pushed to the ongoing inline formatting context.
|
||||
let mut fragmented_inline = InlineLevelBox::InlineBox(last);
|
||||
for mut fragmented_parent_inline_box in fragmented_inline_boxes {
|
||||
fragmented_parent_inline_box
|
||||
.children
|
||||
.push(Arc::new(fragmented_inline));
|
||||
fragmented_inline = InlineLevelBox::InlineBox(fragmented_parent_inline_box);
|
||||
}
|
||||
|
||||
// self.ongoing_inline_formatting_context
|
||||
// .inline_level_boxes
|
||||
// .push(Arc::new(fragmented_inline));
|
||||
// }
|
||||
self.ongoing_inline_formatting_context
|
||||
.inline_level_boxes
|
||||
.push(Arc::new(fragmented_inline));
|
||||
}
|
||||
|
||||
// // We found a block level element, so the ongoing inline formatting
|
||||
// // context needs to be ended.
|
||||
// self.end_ongoing_inline_formatting_context();
|
||||
// We found a block level element, so the ongoing inline formatting
|
||||
// context needs to be ended.
|
||||
self.end_ongoing_inline_formatting_context();
|
||||
|
||||
// let intermediate_box = match contents.try_into() {
|
||||
// Ok(contents) => match display_inside {
|
||||
// DisplayInside::Flow => IntermediateBlockLevelBox::SameFormattingContextBlock {
|
||||
// style,
|
||||
// contents: IntermediateBlockContainer::Deferred { contents },
|
||||
// },
|
||||
// _ => IntermediateBlockLevelBox::Independent {
|
||||
// style,
|
||||
// display_inside,
|
||||
// contents: contents.into(),
|
||||
// },
|
||||
// },
|
||||
// Err(contents) => {
|
||||
// let contents = Contents::Replaced(contents);
|
||||
// IntermediateBlockLevelBox::Independent {
|
||||
// style,
|
||||
// display_inside,
|
||||
// contents,
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// self.block_level_boxes.push((intermediate_box, box_slot))
|
||||
// }
|
||||
let intermediate_box = match contents.try_into() {
|
||||
Ok(contents) => match display_inside {
|
||||
DisplayInside::Flow => IntermediateBlockLevelBox::SameFormattingContextBlock {
|
||||
style,
|
||||
contents: IntermediateBlockContainer::Deferred { contents },
|
||||
},
|
||||
_ => IntermediateBlockLevelBox::Independent {
|
||||
style,
|
||||
display_inside,
|
||||
contents: contents.into(),
|
||||
},
|
||||
},
|
||||
Err(contents) => {
|
||||
let contents = Contents::Replaced(contents);
|
||||
IntermediateBlockLevelBox::Independent {
|
||||
style,
|
||||
display_inside,
|
||||
contents,
|
||||
}
|
||||
},
|
||||
};
|
||||
self.block_level_boxes.push((intermediate_box, box_slot))
|
||||
}
|
||||
|
||||
fn handle_absolutely_positioned_element(
|
||||
&mut self,
|
||||
|
|
|
@ -2,7 +2,25 @@
|
|||
* 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 super::*;
|
||||
use crate::dom_traversal::{Contents, NodeExt};
|
||||
use crate::flow::construct::ContainsFloats;
|
||||
use crate::flow::float::FloatBox;
|
||||
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
|
||||
use crate::fragments::Fragment;
|
||||
use crate::geom;
|
||||
use crate::geom::flow_relative::Vec2;
|
||||
use crate::positioned::AbsolutelyPositionedBox;
|
||||
use crate::replaced::ReplacedContent;
|
||||
use crate::style_ext::{
|
||||
Direction, Display, DisplayGeneratingBox, DisplayInside, DisplayOutside, WritingMode,
|
||||
};
|
||||
use crate::{ContainingBlock, DefiniteContainingBlock, IndependentFormattingContext};
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelExtend, ParallelIterator};
|
||||
use servo_arc::Arc;
|
||||
use style::context::SharedStyleContext;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Length, LengthOrAuto};
|
||||
use style_traits::CSSPixel;
|
||||
|
||||
// FIXME
|
||||
// impl crate::dom::Document {
|
||||
|
@ -16,114 +34,107 @@ use super::*;
|
|||
|
||||
struct BoxTreeRoot(BlockFormattingContext);
|
||||
|
||||
// FIXME
|
||||
// impl BoxTreeRoot {
|
||||
// pub fn construct(document: &dom::Document) -> Self {
|
||||
// let author_styles = &document.parse_stylesheets();
|
||||
// let context = Context {
|
||||
// document,
|
||||
// author_styles,
|
||||
// };
|
||||
// let root_element = document.root_element();
|
||||
// let style = style_for_element(context.author_styles, context.document, root_element, None);
|
||||
// let (contains_floats, boxes) = construct_for_root_element(&context, root_element, style);
|
||||
// Self(BlockFormattingContext {
|
||||
// contains_floats: contains_floats == ContainsFloats::Yes,
|
||||
// contents: BlockContainer::BlockLevelBoxes(boxes),
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
impl BoxTreeRoot {
|
||||
pub fn construct<'dom>(
|
||||
context: &SharedStyleContext<'_>,
|
||||
root_element: impl NodeExt<'dom>,
|
||||
) -> Self {
|
||||
let (contains_floats, boxes) = construct_for_root_element(&context, root_element);
|
||||
Self(BlockFormattingContext {
|
||||
contains_floats: contains_floats == ContainsFloats::Yes,
|
||||
contents: BlockContainer::BlockLevelBoxes(boxes),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// fn construct_for_root_element(
|
||||
// context: &Context,
|
||||
// root_element: dom::NodeId,
|
||||
// style: Arc<ComputedValues>,
|
||||
// ) -> (ContainsFloats, Vec<Arc<BlockLevelBox>>) {
|
||||
// let replaced = ReplacedContent::for_element(root_element, context);
|
||||
fn construct_for_root_element<'dom>(
|
||||
context: &SharedStyleContext<'_>,
|
||||
root_element: impl NodeExt<'dom>,
|
||||
) -> (ContainsFloats, Vec<Arc<BlockLevelBox>>) {
|
||||
let style = root_element.style(context);
|
||||
let replaced = ReplacedContent::for_element(root_element, context);
|
||||
let box_style = style.get_box();
|
||||
|
||||
// let display_inside = match style.box_.display {
|
||||
// Display::None => return (ContainsFloats::No, Vec::new()),
|
||||
// Display::Contents if replaced.is_some() => {
|
||||
// // 'display: contents' computes to 'none' for replaced elements
|
||||
// return (ContainsFloats::No, Vec::new());
|
||||
// }
|
||||
// // https://drafts.csswg.org/css-display-3/#transformations
|
||||
// Display::Contents => DisplayInside::Flow,
|
||||
// // The root element is blockified, ignore DisplayOutside
|
||||
// Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { inside, .. }) => inside,
|
||||
// };
|
||||
let display_inside = match Display::from(box_style.display) {
|
||||
Display::None => return (ContainsFloats::No, Vec::new()),
|
||||
Display::Contents if replaced.is_some() => {
|
||||
// 'display: contents' computes to 'none' for replaced elements
|
||||
return (ContainsFloats::No, Vec::new());
|
||||
},
|
||||
// https://drafts.csswg.org/css-display-3/#transformations
|
||||
Display::Contents => DisplayInside::Flow,
|
||||
// The root element is blockified, ignore DisplayOutside
|
||||
Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { inside, .. }) => inside,
|
||||
};
|
||||
|
||||
// if let Some(replaced) = replaced {
|
||||
// let _box = match replaced {};
|
||||
// #[allow(unreachable_code)]
|
||||
// {
|
||||
// return (ContainsFloats::No, vec![Arc::new(_box)]);
|
||||
// }
|
||||
// }
|
||||
if let Some(replaced) = replaced {
|
||||
let _box = match replaced {};
|
||||
#[allow(unreachable_code)]
|
||||
{
|
||||
return (ContainsFloats::No, vec![Arc::new(_box)]);
|
||||
}
|
||||
}
|
||||
|
||||
// let contents = IndependentFormattingContext::construct(
|
||||
// context,
|
||||
// &style,
|
||||
// display_inside,
|
||||
// Contents::OfElement(root_element),
|
||||
// );
|
||||
// if style.box_.position.is_absolutely_positioned() {
|
||||
// (
|
||||
// ContainsFloats::No,
|
||||
// vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(
|
||||
// AbsolutelyPositionedBox { style, contents },
|
||||
// ))],
|
||||
// )
|
||||
// } else if style.box_.float.is_floating() {
|
||||
// (
|
||||
// ContainsFloats::Yes,
|
||||
// vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox {
|
||||
// contents,
|
||||
// style,
|
||||
// }))],
|
||||
// )
|
||||
// } else {
|
||||
// (
|
||||
// ContainsFloats::No,
|
||||
// vec![Arc::new(BlockLevelBox::Independent { style, contents })],
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
let contents = IndependentFormattingContext::construct(
|
||||
context,
|
||||
&style,
|
||||
display_inside,
|
||||
Contents::OfElement(root_element),
|
||||
);
|
||||
if box_style.position.is_absolutely_positioned() {
|
||||
(
|
||||
ContainsFloats::No,
|
||||
vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(
|
||||
AbsolutelyPositionedBox { style, contents },
|
||||
))],
|
||||
)
|
||||
} else if box_style.float.is_floating() {
|
||||
(
|
||||
ContainsFloats::Yes,
|
||||
vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox {
|
||||
contents,
|
||||
style,
|
||||
}))],
|
||||
)
|
||||
} else {
|
||||
(
|
||||
ContainsFloats::No,
|
||||
vec![Arc::new(BlockLevelBox::Independent { style, contents })],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// impl BoxTreeRoot {
|
||||
// fn layout(&self, viewport: crate::geom::Size<crate::geom::CssPx>) -> Vec<Fragment> {
|
||||
// let initial_containing_block_size = Vec2 {
|
||||
// inline: Length { px: viewport.width },
|
||||
// block: Length {
|
||||
// px: viewport.height,
|
||||
// },
|
||||
// };
|
||||
impl BoxTreeRoot {
|
||||
fn layout(&self, viewport: geom::Size<CSSPixel>) -> Vec<Fragment> {
|
||||
let initial_containing_block_size = Vec2 {
|
||||
inline: Length::new(viewport.width),
|
||||
block: Length::new(viewport.height),
|
||||
};
|
||||
|
||||
// let initial_containing_block = ContainingBlock {
|
||||
// inline_size: initial_containing_block_size.inline,
|
||||
// block_size: LengthOrAuto::Length(initial_containing_block_size.block),
|
||||
// // FIXME: use the document’s mode:
|
||||
// // https://drafts.csswg.org/css-writing-modes/#principal-flow
|
||||
// mode: (WritingMode::HorizontalTb, Direction::Ltr),
|
||||
// };
|
||||
// let dummy_tree_rank = 0;
|
||||
// let mut absolutely_positioned_fragments = vec![];
|
||||
// let mut fragments = self.0.layout(
|
||||
// &initial_containing_block,
|
||||
// &mut absolutely_positioned_fragments,
|
||||
// dummy_tree_rank,
|
||||
// &mut PlacementState::root(),
|
||||
// );
|
||||
let initial_containing_block = ContainingBlock {
|
||||
inline_size: initial_containing_block_size.inline,
|
||||
block_size: LengthOrAuto::LengthPercentage(initial_containing_block_size.block),
|
||||
// FIXME: use the document’s mode:
|
||||
// https://drafts.csswg.org/css-writing-modes/#principal-flow
|
||||
mode: (WritingMode::HorizontalTb, Direction::Ltr),
|
||||
};
|
||||
let dummy_tree_rank = 0;
|
||||
let mut absolutely_positioned_fragments = vec![];
|
||||
let mut flow_children = self.0.layout(
|
||||
&initial_containing_block,
|
||||
dummy_tree_rank,
|
||||
&mut absolutely_positioned_fragments,
|
||||
);
|
||||
|
||||
// let initial_containing_block = DefiniteContainingBlock {
|
||||
// size: initial_containing_block_size,
|
||||
// mode: initial_containing_block.mode,
|
||||
// };
|
||||
// fragments.par_extend(
|
||||
// absolutely_positioned_fragments
|
||||
// .par_iter()
|
||||
// .map(|a| a.layout(&initial_containing_block)),
|
||||
// );
|
||||
// fragments
|
||||
// }
|
||||
// }
|
||||
let initial_containing_block = DefiniteContainingBlock {
|
||||
size: initial_containing_block_size,
|
||||
mode: initial_containing_block.mode,
|
||||
};
|
||||
flow_children.fragments.par_extend(
|
||||
absolutely_positioned_fragments
|
||||
.par_iter()
|
||||
.map(|a| a.layout(&initial_containing_block)),
|
||||
);
|
||||
flow_children.fragments
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,15 +42,24 @@ ${helpers.single_keyword(
|
|||
spec="Internal (not web-exposed)",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
"position",
|
||||
"static absolute relative fixed" + (" sticky" if engine in ["gecko", "servo-2013"] else ""),
|
||||
engines="gecko servo-2013 servo-2020",
|
||||
animation_value_type="discrete",
|
||||
flags="CREATES_STACKING_CONTEXT ABSPOS_CB",
|
||||
spec="https://drafts.csswg.org/css-position/#position-property",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
<%helpers:single_keyword
|
||||
name="position"
|
||||
values="static absolute relative fixed ${'sticky' if engine in ['gecko', 'servo-2013'] else ''}"
|
||||
engines="gecko servo-2013 servo-2020"
|
||||
animation_value_type="discrete"
|
||||
flags="CREATES_STACKING_CONTEXT ABSPOS_CB"
|
||||
spec="https://drafts.csswg.org/css-position/#position-property"
|
||||
servo_restyle_damage="rebuild_and_reflow"
|
||||
>
|
||||
impl computed_value::T {
|
||||
pub fn is_absolutely_positioned(self) -> bool {
|
||||
match self {
|
||||
Self::Absolute | Self::Fixed => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
</%helpers:single_keyword>
|
||||
|
||||
${helpers.predefined_type(
|
||||
"float",
|
||||
|
|
|
@ -61,6 +61,13 @@ pub enum Float {
|
|||
None,
|
||||
}
|
||||
|
||||
impl Float {
|
||||
/// Returns true if `self` is not `None`.
|
||||
pub fn is_floating(self) -> bool {
|
||||
self != Self::None
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedFloat {
|
||||
type ComputedValue = Float;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue