mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #24243 - servo:box-construct, r=SimonSapin
Uncomment more stuff related to box construction <!-- 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/24243) <!-- Reviewable:end -->
This commit is contained in:
commit
ee17eedf3a
6 changed files with 323 additions and 278 deletions
|
@ -6,13 +6,15 @@ use crate::element_data::{LayoutBox, LayoutDataForElement};
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside};
|
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside};
|
||||||
use crate::wrapper::GetRawData;
|
use crate::wrapper::GetRawData;
|
||||||
use atomic_refcell::AtomicRefMut;
|
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
|
||||||
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
|
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::marker::PhantomData as marker;
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
use style::dom::TNode;
|
use style::dom::TNode;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
use style::selector_parser::PseudoElement;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub(super) enum WhichPseudoElement {
|
pub(super) enum WhichPseudoElement {
|
||||||
|
@ -43,7 +45,10 @@ pub(super) enum PseudoElementContentItem {
|
||||||
Replaced(ReplacedContent),
|
Replaced(ReplacedContent),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) trait TraversalHandler<Node> {
|
pub(super) trait TraversalHandler<'dom, Node>
|
||||||
|
where
|
||||||
|
Node: 'dom,
|
||||||
|
{
|
||||||
fn handle_text(&mut self, text: String, parent_style: &Arc<ComputedValues>);
|
fn handle_text(&mut self, text: String, parent_style: &Arc<ComputedValues>);
|
||||||
|
|
||||||
/// Or pseudo-element
|
/// Or pseudo-element
|
||||||
|
@ -52,14 +57,14 @@ pub(super) trait TraversalHandler<Node> {
|
||||||
style: &Arc<ComputedValues>,
|
style: &Arc<ComputedValues>,
|
||||||
display: DisplayGeneratingBox,
|
display: DisplayGeneratingBox,
|
||||||
contents: Contents<Node>,
|
contents: Contents<Node>,
|
||||||
box_slot: BoxSlot,
|
box_slot: BoxSlot<'dom>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traverse_children_of<'dom, Node>(
|
fn traverse_children_of<'dom, Node>(
|
||||||
parent_element: Node,
|
parent_element: Node,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
) where
|
) where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
|
@ -81,7 +86,7 @@ fn traverse_children_of<'dom, Node>(
|
||||||
fn traverse_element<'dom, Node>(
|
fn traverse_element<'dom, Node>(
|
||||||
element: Node,
|
element: Node,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
) where
|
) where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
|
@ -94,7 +99,7 @@ fn traverse_element<'dom, Node>(
|
||||||
// <https://drafts.csswg.org/css-display-3/#valdef-display-contents>
|
// <https://drafts.csswg.org/css-display-3/#valdef-display-contents>
|
||||||
element.unset_boxes_in_subtree()
|
element.unset_boxes_in_subtree()
|
||||||
} else {
|
} else {
|
||||||
element.layout_data_mut().self_box = Some(LayoutBox::DisplayContents);
|
*element.layout_data_mut().self_box.borrow_mut() = Some(LayoutBox::DisplayContents);
|
||||||
traverse_children_of(element, context, handler)
|
traverse_children_of(element, context, handler)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -116,7 +121,7 @@ fn traverse_pseudo_element<'dom, Node>(
|
||||||
which: WhichPseudoElement,
|
which: WhichPseudoElement,
|
||||||
element: Node,
|
element: Node,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
) where
|
) where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
|
@ -126,7 +131,7 @@ fn traverse_pseudo_element<'dom, Node>(
|
||||||
Display::Contents => {
|
Display::Contents => {
|
||||||
element.unset_pseudo_element_box(which);
|
element.unset_pseudo_element_box(which);
|
||||||
let items = generate_pseudo_element_content(&style, element, context);
|
let items = generate_pseudo_element_content(&style, element, context);
|
||||||
traverse_pseudo_element_contents(&style, items, handler);
|
traverse_pseudo_element_contents(&style, context, handler, items);
|
||||||
},
|
},
|
||||||
Display::GeneratingBox(display) => {
|
Display::GeneratingBox(display) => {
|
||||||
let items = generate_pseudo_element_content(&style, element, context);
|
let items = generate_pseudo_element_content(&style, element, context);
|
||||||
|
@ -140,33 +145,42 @@ fn traverse_pseudo_element<'dom, Node>(
|
||||||
|
|
||||||
fn traverse_pseudo_element_contents<'dom, Node>(
|
fn traverse_pseudo_element_contents<'dom, Node>(
|
||||||
pseudo_element_style: &Arc<ComputedValues>,
|
pseudo_element_style: &Arc<ComputedValues>,
|
||||||
|
context: &SharedStyleContext,
|
||||||
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
items: Vec<PseudoElementContentItem>,
|
items: Vec<PseudoElementContentItem>,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
|
||||||
) where
|
) where
|
||||||
Node: 'dom,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
// let mut anonymous_style = None;
|
let mut anonymous_style = None;
|
||||||
for item in items {
|
for item in items {
|
||||||
match item {
|
match item {
|
||||||
PseudoElementContentItem::Text(text) => handler.handle_text(text, pseudo_element_style),
|
PseudoElementContentItem::Text(text) => handler.handle_text(text, pseudo_element_style),
|
||||||
PseudoElementContentItem::Replaced(contents) => {
|
PseudoElementContentItem::Replaced(contents) => {
|
||||||
// FIXME
|
let item_style = anonymous_style.get_or_insert_with(|| {
|
||||||
// let item_style = anonymous_style.get_or_insert_with(|| {
|
context
|
||||||
// ComputedValues::anonymous_inheriting_from(Some(pseudo_element_style))
|
.stylist
|
||||||
// });
|
.style_for_anonymous::<Node::ConcreteElement>(
|
||||||
// let display_inline = DisplayGeneratingBox::OutsideInside {
|
&context.guards,
|
||||||
// outside: DisplayOutside::Inline,
|
&PseudoElement::ServoText,
|
||||||
// inside: DisplayInside::Flow,
|
&pseudo_element_style,
|
||||||
// };
|
)
|
||||||
// // `display` is not inherited, so we get the initial value
|
});
|
||||||
// debug_assert!(item_style.box_.display == Display::GeneratingBox(display_inline));
|
let display_inline = DisplayGeneratingBox::OutsideInside {
|
||||||
// handler.handle_element(
|
outside: DisplayOutside::Inline,
|
||||||
// item_style,
|
inside: DisplayInside::Flow,
|
||||||
// display_inline,
|
};
|
||||||
// Contents::Replaced(contents),
|
// `display` is not inherited, so we get the initial value
|
||||||
// // We don’t keep pointers to boxes generated by contents of pseudo-elements
|
debug_assert!(
|
||||||
// BoxSlot::dummy(),
|
Display::from(item_style.get_box().display) ==
|
||||||
// )
|
Display::GeneratingBox(display_inline)
|
||||||
|
);
|
||||||
|
handler.handle_element(
|
||||||
|
item_style,
|
||||||
|
display_inline,
|
||||||
|
Contents::Replaced(contents),
|
||||||
|
// We don’t keep pointers to boxes generated by contents of pseudo-elements
|
||||||
|
BoxSlot::dummy(),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,12 +215,12 @@ where
|
||||||
self,
|
self,
|
||||||
inherited_style: &Arc<ComputedValues>,
|
inherited_style: &Arc<ComputedValues>,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
NonReplacedContents::OfElement(node) => traverse_children_of(node, context, handler),
|
NonReplacedContents::OfElement(node) => traverse_children_of(node, context, handler),
|
||||||
NonReplacedContents::OfPseudoElement(items) => {
|
NonReplacedContents::OfPseudoElement(items) => {
|
||||||
traverse_pseudo_element_contents(inherited_style, items, handler)
|
traverse_pseudo_element_contents(inherited_style, context, handler, items)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,22 +253,25 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct BoxSlot<'dom> {
|
pub(super) struct BoxSlot<'dom> {
|
||||||
slot: Option<AtomicRefMut<'dom, Option<LayoutBox>>>,
|
slot: Option<Arc<AtomicRefCell<Option<LayoutBox>>>>,
|
||||||
|
marker: marker<&'dom ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom> BoxSlot<'dom> {
|
impl BoxSlot<'_> {
|
||||||
pub fn new(mut slot: AtomicRefMut<'dom, Option<LayoutBox>>) -> Self {
|
pub fn new(slot: Arc<AtomicRefCell<Option<LayoutBox>>>) -> Self {
|
||||||
*slot = None;
|
*slot.borrow_mut() = None;
|
||||||
Self { slot: Some(slot) }
|
let slot = Some(slot);
|
||||||
|
Self { slot, marker }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dummy() -> Self {
|
pub fn dummy() -> Self {
|
||||||
Self { slot: None }
|
let slot = None;
|
||||||
|
Self { slot, marker }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(mut self, box_: LayoutBox) {
|
pub fn set(mut self, box_: LayoutBox) {
|
||||||
if let Some(slot) = &mut self.slot {
|
if let Some(slot) = &mut self.slot {
|
||||||
**slot = Some(box_)
|
*slot.borrow_mut() = Some(box_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,12 +279,12 @@ impl<'dom> BoxSlot<'dom> {
|
||||||
impl Drop for BoxSlot<'_> {
|
impl Drop for BoxSlot<'_> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(slot) = &mut self.slot {
|
if let Some(slot) = &mut self.slot {
|
||||||
assert!(slot.is_some(), "failed to set a layout box")
|
assert!(slot.borrow().is_some(), "failed to set a layout box");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait NodeExt<'dom>: 'dom + Copy + Send + Sync {
|
pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode + Send + Sync {
|
||||||
fn is_element(self) -> bool;
|
fn is_element(self) -> bool;
|
||||||
fn as_text(self) -> Option<String>;
|
fn as_text(self) -> Option<String>;
|
||||||
fn first_child(self) -> Option<Self>;
|
fn first_child(self) -> Option<Self>;
|
||||||
|
@ -276,15 +293,15 @@ pub(crate) trait NodeExt<'dom>: 'dom + Copy + Send + Sync {
|
||||||
fn style(self, context: &SharedStyleContext) -> Arc<ComputedValues>;
|
fn style(self, context: &SharedStyleContext) -> Arc<ComputedValues>;
|
||||||
|
|
||||||
fn layout_data_mut(&self) -> AtomicRefMut<LayoutDataForElement>;
|
fn layout_data_mut(&self) -> AtomicRefMut<LayoutDataForElement>;
|
||||||
fn element_box_slot(&self) -> BoxSlot;
|
fn element_box_slot(&self) -> BoxSlot<'dom>;
|
||||||
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot;
|
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>;
|
||||||
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
||||||
fn unset_boxes_in_subtree(self);
|
fn unset_boxes_in_subtree(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, T> NodeExt<'dom> for T
|
impl<'dom, T> NodeExt<'dom> for T
|
||||||
where
|
where
|
||||||
T: 'dom + LayoutNode + Send + Sync,
|
T: 'dom + Copy + LayoutNode + Send + Sync,
|
||||||
{
|
{
|
||||||
fn is_element(self) -> bool {
|
fn is_element(self) -> bool {
|
||||||
self.to_threadsafe().as_element().is_some()
|
self.to_threadsafe().as_element().is_some()
|
||||||
|
@ -320,27 +337,25 @@ where
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn element_box_slot(&self) -> BoxSlot {
|
fn element_box_slot(&self) -> BoxSlot<'dom> {
|
||||||
BoxSlot::new(AtomicRefMut::map(self.layout_data_mut(), |data| {
|
BoxSlot::new(self.layout_data_mut().self_box.clone())
|
||||||
&mut data.self_box
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot {
|
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom> {
|
||||||
BoxSlot::new(AtomicRefMut::map(self.layout_data_mut(), |data| {
|
let mut data = self.layout_data_mut();
|
||||||
let pseudos = data.pseudo_elements.get_or_insert_with(Default::default);
|
let pseudos = data.pseudo_elements.get_or_insert_with(Default::default);
|
||||||
match which {
|
let cell = match which {
|
||||||
WhichPseudoElement::Before => &mut pseudos.before,
|
WhichPseudoElement::Before => &mut pseudos.before,
|
||||||
WhichPseudoElement::After => &mut pseudos.after,
|
WhichPseudoElement::After => &mut pseudos.after,
|
||||||
}
|
};
|
||||||
}))
|
BoxSlot::new(cell.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unset_pseudo_element_box(self, which: WhichPseudoElement) {
|
fn unset_pseudo_element_box(self, which: WhichPseudoElement) {
|
||||||
if let Some(pseudos) = &mut self.layout_data_mut().pseudo_elements {
|
if let Some(pseudos) = &mut self.layout_data_mut().pseudo_elements {
|
||||||
match which {
|
match which {
|
||||||
WhichPseudoElement::Before => pseudos.before = None,
|
WhichPseudoElement::Before => *pseudos.before.borrow_mut() = None,
|
||||||
WhichPseudoElement::After => pseudos.after = None,
|
WhichPseudoElement::After => *pseudos.after.borrow_mut() = None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,7 +367,8 @@ where
|
||||||
let traverse_children = {
|
let traverse_children = {
|
||||||
let mut layout_data = node.layout_data_mut();
|
let mut layout_data = node.layout_data_mut();
|
||||||
layout_data.pseudo_elements = None;
|
layout_data.pseudo_elements = None;
|
||||||
layout_data.self_box.take().is_some()
|
let self_box = layout_data.self_box.borrow_mut().take();
|
||||||
|
self_box.is_some()
|
||||||
};
|
};
|
||||||
if traverse_children {
|
if traverse_children {
|
||||||
// Only descend into children if we removed a box.
|
// Only descend into children if we removed a box.
|
||||||
|
|
|
@ -4,18 +4,19 @@
|
||||||
|
|
||||||
use crate::flow::inline::InlineLevelBox;
|
use crate::flow::inline::InlineLevelBox;
|
||||||
use crate::flow::BlockLevelBox;
|
use crate::flow::BlockLevelBox;
|
||||||
|
use atomic_refcell::AtomicRefCell;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct LayoutDataForElement {
|
pub(crate) struct LayoutDataForElement {
|
||||||
pub(super) self_box: Option<LayoutBox>,
|
pub(super) self_box: Arc<AtomicRefCell<Option<LayoutBox>>>,
|
||||||
pub(super) pseudo_elements: Option<Box<PseudoElementBoxes>>,
|
pub(super) pseudo_elements: Option<Box<PseudoElementBoxes>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct PseudoElementBoxes {
|
pub(super) struct PseudoElementBoxes {
|
||||||
pub before: Option<LayoutBox>,
|
pub before: Arc<AtomicRefCell<Option<LayoutBox>>>,
|
||||||
pub after: Option<LayoutBox>,
|
pub after: Arc<AtomicRefCell<Option<LayoutBox>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) enum LayoutBox {
|
pub(super) enum LayoutBox {
|
||||||
|
|
|
@ -9,13 +9,14 @@ use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, Te
|
||||||
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
|
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
|
||||||
use crate::positioned::AbsolutelyPositionedBox;
|
use crate::positioned::AbsolutelyPositionedBox;
|
||||||
use crate::style_ext::{DisplayGeneratingBox, DisplayInside, DisplayOutside};
|
use crate::style_ext::{DisplayGeneratingBox, DisplayInside, DisplayOutside};
|
||||||
use crate::IndependentFormattingContext;
|
use crate::{take, IndependentFormattingContext};
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
use rayon_croissant::ParallelIteratorExt;
|
use rayon_croissant::ParallelIteratorExt;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
use style::selector_parser::PseudoElement;
|
||||||
|
|
||||||
impl BlockFormattingContext {
|
impl BlockFormattingContext {
|
||||||
pub fn construct<'dom>(
|
pub fn construct<'dom>(
|
||||||
|
@ -152,8 +153,7 @@ impl BlockContainer {
|
||||||
);
|
);
|
||||||
return (container, builder.contains_floats);
|
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;
|
let mut contains_floats = builder.contains_floats;
|
||||||
|
@ -166,8 +166,7 @@ impl BlockContainer {
|
||||||
|contains_floats, (intermediate, box_slot): (IntermediateBlockLevelBox<_>, BoxSlot<'_>)| {
|
|contains_floats, (intermediate, box_slot): (IntermediateBlockLevelBox<_>, BoxSlot<'_>)| {
|
||||||
let (block_level_box, box_contains_floats) = intermediate.finish(context);
|
let (block_level_box, box_contains_floats) = intermediate.finish(context);
|
||||||
*contains_floats |= box_contains_floats;
|
*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
|
block_level_box
|
||||||
},
|
},
|
||||||
|left, right| *left |= right,
|
|left, right| *left |= right,
|
||||||
|
@ -178,7 +177,7 @@ impl BlockContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, Node> TraversalHandler<Node> for BlockContainerBuilder<'dom, '_, Node>
|
impl<'dom, Node> TraversalHandler<'dom, Node> for BlockContainerBuilder<'dom, '_, Node>
|
||||||
where
|
where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
|
@ -187,7 +186,7 @@ where
|
||||||
style: &Arc<ComputedValues>,
|
style: &Arc<ComputedValues>,
|
||||||
display: DisplayGeneratingBox,
|
display: DisplayGeneratingBox,
|
||||||
contents: Contents<Node>,
|
contents: Contents<Node>,
|
||||||
box_slot: BoxSlot,
|
box_slot: BoxSlot<'dom>,
|
||||||
) {
|
) {
|
||||||
match display {
|
match display {
|
||||||
DisplayGeneratingBox::OutsideInside { outside, inside } => match outside {
|
DisplayGeneratingBox::OutsideInside { outside, inside } => match outside {
|
||||||
|
@ -195,21 +194,21 @@ where
|
||||||
self.handle_inline_level_element(style, inside, contents),
|
self.handle_inline_level_element(style, inside, contents),
|
||||||
)),
|
)),
|
||||||
DisplayOutside::Block => {
|
DisplayOutside::Block => {
|
||||||
// FIXME
|
let box_style = style.get_box();
|
||||||
// Floats and abspos cause blockification, so they only happen in this case.
|
// Floats and abspos cause blockification, so they only happen in this case.
|
||||||
// https://drafts.csswg.org/css2/visuren.html#dis-pos-flo
|
// https://drafts.csswg.org/css2/visuren.html#dis-pos-flo
|
||||||
// if style.box_.position.is_absolutely_positioned() {
|
if box_style.position.is_absolutely_positioned() {
|
||||||
// self.handle_absolutely_positioned_element(
|
self.handle_absolutely_positioned_element(
|
||||||
// style.clone(),
|
style.clone(),
|
||||||
// inside,
|
inside,
|
||||||
// contents,
|
contents,
|
||||||
// box_slot,
|
box_slot,
|
||||||
// )
|
)
|
||||||
// } else if style.box_.float.is_floating() {
|
} else if box_style.float.is_floating() {
|
||||||
// self.handle_float_element(style.clone(), inside, contents, box_slot)
|
self.handle_float_element(style.clone(), inside, contents, box_slot)
|
||||||
// } else {
|
} else {
|
||||||
// self.handle_block_level_element(style.clone(), inside, contents, box_slot)
|
self.handle_block_level_element(style.clone(), inside, contents, box_slot)
|
||||||
// }
|
}
|
||||||
},
|
},
|
||||||
DisplayOutside::None => panic!(":("),
|
DisplayOutside::None => panic!(":("),
|
||||||
},
|
},
|
||||||
|
@ -362,80 +361,79 @@ where
|
||||||
box_
|
box_
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME
|
fn handle_block_level_element(
|
||||||
// fn handle_block_level_element(
|
&mut self,
|
||||||
// &mut self,
|
style: Arc<ComputedValues>,
|
||||||
// style: Arc<ComputedValues>,
|
display_inside: DisplayInside,
|
||||||
// display_inside: DisplayInside,
|
contents: Contents<Node>,
|
||||||
// contents: Contents,
|
box_slot: BoxSlot<'dom>,
|
||||||
// box_slot: BoxSlot<'a>,
|
) {
|
||||||
// ) {
|
// We just found a block level element, all ongoing inline level boxes
|
||||||
// // We just found a block level element, all ongoing inline level boxes
|
// need to be split around it. We iterate on the fragmented inline
|
||||||
// // need to be split around it. We iterate on the fragmented inline
|
// level box stack to take their contents and set their first_fragment
|
||||||
// // level box stack to take their contents and set their first_fragment
|
// field to false, for the fragmented inline level boxes that will
|
||||||
// // field to false, for the fragmented inline level boxes that will
|
// come after the block level element.
|
||||||
// // come after the block level element.
|
let mut fragmented_inline_boxes =
|
||||||
// let mut fragmented_inline_boxes =
|
self.ongoing_inline_boxes_stack
|
||||||
// self.ongoing_inline_boxes_stack
|
.iter_mut()
|
||||||
// .iter_mut()
|
.rev()
|
||||||
// .rev()
|
.map(|ongoing| {
|
||||||
// .map(|ongoing| {
|
let fragmented = InlineBox {
|
||||||
// let fragmented = InlineBox {
|
style: ongoing.style.clone(),
|
||||||
// style: ongoing.style.clone(),
|
first_fragment: ongoing.first_fragment,
|
||||||
// first_fragment: ongoing.first_fragment,
|
// The fragmented boxes before the block level element
|
||||||
// // The fragmented boxes before the block level element
|
// are obviously not the last fragment.
|
||||||
// // are obviously not the last fragment.
|
last_fragment: false,
|
||||||
// last_fragment: false,
|
children: take(&mut ongoing.children),
|
||||||
// children: take(&mut ongoing.children),
|
};
|
||||||
// };
|
ongoing.first_fragment = false;
|
||||||
// ongoing.first_fragment = false;
|
fragmented
|
||||||
// fragmented
|
});
|
||||||
// });
|
|
||||||
|
|
||||||
// if let Some(last) = fragmented_inline_boxes.next() {
|
if let Some(last) = fragmented_inline_boxes.next() {
|
||||||
// // There were indeed some ongoing inline level boxes before
|
// There were indeed some ongoing inline level boxes before
|
||||||
// // the block, we accumulate them as a single inline level box
|
// the block, we accumulate them as a single inline level box
|
||||||
// // to be pushed to the ongoing inline formatting context.
|
// to be pushed to the ongoing inline formatting context.
|
||||||
// let mut fragmented_inline = InlineLevelBox::InlineBox(last);
|
let mut fragmented_inline = InlineLevelBox::InlineBox(last);
|
||||||
// for mut fragmented_parent_inline_box in fragmented_inline_boxes {
|
for mut fragmented_parent_inline_box in fragmented_inline_boxes {
|
||||||
// fragmented_parent_inline_box
|
fragmented_parent_inline_box
|
||||||
// .children
|
.children
|
||||||
// .push(Arc::new(fragmented_inline));
|
.push(Arc::new(fragmented_inline));
|
||||||
// fragmented_inline = InlineLevelBox::InlineBox(fragmented_parent_inline_box);
|
fragmented_inline = InlineLevelBox::InlineBox(fragmented_parent_inline_box);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// self.ongoing_inline_formatting_context
|
self.ongoing_inline_formatting_context
|
||||||
// .inline_level_boxes
|
.inline_level_boxes
|
||||||
// .push(Arc::new(fragmented_inline));
|
.push(Arc::new(fragmented_inline));
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // We found a block level element, so the ongoing inline formatting
|
// We found a block level element, so the ongoing inline formatting
|
||||||
// // context needs to be ended.
|
// context needs to be ended.
|
||||||
// self.end_ongoing_inline_formatting_context();
|
self.end_ongoing_inline_formatting_context();
|
||||||
|
|
||||||
// let intermediate_box = match contents.try_into() {
|
let intermediate_box = match contents.try_into() {
|
||||||
// Ok(contents) => match display_inside {
|
Ok(contents) => match display_inside {
|
||||||
// DisplayInside::Flow => IntermediateBlockLevelBox::SameFormattingContextBlock {
|
DisplayInside::Flow => IntermediateBlockLevelBox::SameFormattingContextBlock {
|
||||||
// style,
|
style,
|
||||||
// contents: IntermediateBlockContainer::Deferred { contents },
|
contents: IntermediateBlockContainer::Deferred { contents },
|
||||||
// },
|
},
|
||||||
// _ => IntermediateBlockLevelBox::Independent {
|
_ => IntermediateBlockLevelBox::Independent {
|
||||||
// style,
|
style,
|
||||||
// display_inside,
|
display_inside,
|
||||||
// contents: contents.into(),
|
contents: contents.into(),
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
// Err(contents) => {
|
Err(contents) => {
|
||||||
// let contents = Contents::Replaced(contents);
|
let contents = Contents::Replaced(contents);
|
||||||
// IntermediateBlockLevelBox::Independent {
|
IntermediateBlockLevelBox::Independent {
|
||||||
// style,
|
style,
|
||||||
// display_inside,
|
display_inside,
|
||||||
// contents,
|
contents,
|
||||||
// }
|
}
|
||||||
// }
|
},
|
||||||
// };
|
};
|
||||||
// self.block_level_boxes.push((intermediate_box, box_slot))
|
self.block_level_boxes.push((intermediate_box, box_slot))
|
||||||
// }
|
}
|
||||||
|
|
||||||
fn handle_absolutely_positioned_element(
|
fn handle_absolutely_positioned_element(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -514,22 +512,25 @@ where
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let context = self.context;
|
||||||
let block_container_style = self.block_container_style;
|
let block_container_style = self.block_container_style;
|
||||||
// FIXME
|
let anonymous_style = self.anonymous_style.get_or_insert_with(|| {
|
||||||
// let anonymous_style = self.anonymous_style.get_or_insert_with(|| {
|
context
|
||||||
// // If parent_style is None, the parent is the document node,
|
.stylist
|
||||||
// // in which case anonymous inline boxes should inherit their
|
.style_for_anonymous::<Node::ConcreteElement>(
|
||||||
// // styles from initial values.
|
&context.guards,
|
||||||
// ComputedValues::anonymous_inheriting_from(Some(block_container_style))
|
&PseudoElement::ServoText,
|
||||||
// });
|
&block_container_style,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
// let box_ = IntermediateBlockLevelBox::SameFormattingContextBlock {
|
let box_ = IntermediateBlockLevelBox::SameFormattingContextBlock {
|
||||||
// style: anonymous_style.clone(),
|
style: anonymous_style.clone(),
|
||||||
// contents: IntermediateBlockContainer::InlineFormattingContext(take(
|
contents: IntermediateBlockContainer::InlineFormattingContext(take(
|
||||||
// &mut self.ongoing_inline_formatting_context,
|
&mut self.ongoing_inline_formatting_context,
|
||||||
// )),
|
)),
|
||||||
// };
|
};
|
||||||
// self.block_level_boxes.push((box_, BoxSlot::dummy()))
|
self.block_level_boxes.push((box_, BoxSlot::dummy()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_inline_level_boxes(&mut self) -> &mut Vec<Arc<InlineLevelBox>> {
|
fn current_inline_level_boxes(&mut self) -> &mut Vec<Arc<InlineLevelBox>> {
|
||||||
|
|
|
@ -2,7 +2,25 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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
|
// FIXME
|
||||||
// impl crate::dom::Document {
|
// impl crate::dom::Document {
|
||||||
|
@ -16,114 +34,107 @@ use super::*;
|
||||||
|
|
||||||
struct BoxTreeRoot(BlockFormattingContext);
|
struct BoxTreeRoot(BlockFormattingContext);
|
||||||
|
|
||||||
// FIXME
|
impl BoxTreeRoot {
|
||||||
// impl BoxTreeRoot {
|
pub fn construct<'dom>(
|
||||||
// pub fn construct(document: &dom::Document) -> Self {
|
context: &SharedStyleContext<'_>,
|
||||||
// let author_styles = &document.parse_stylesheets();
|
root_element: impl NodeExt<'dom>,
|
||||||
// let context = Context {
|
) -> Self {
|
||||||
// document,
|
let (contains_floats, boxes) = construct_for_root_element(&context, root_element);
|
||||||
// author_styles,
|
Self(BlockFormattingContext {
|
||||||
// };
|
contains_floats: contains_floats == ContainsFloats::Yes,
|
||||||
// let root_element = document.root_element();
|
contents: BlockContainer::BlockLevelBoxes(boxes),
|
||||||
// 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),
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn construct_for_root_element(
|
fn construct_for_root_element<'dom>(
|
||||||
// context: &Context,
|
context: &SharedStyleContext<'_>,
|
||||||
// root_element: dom::NodeId,
|
root_element: impl NodeExt<'dom>,
|
||||||
// style: Arc<ComputedValues>,
|
) -> (ContainsFloats, Vec<Arc<BlockLevelBox>>) {
|
||||||
// ) -> (ContainsFloats, Vec<Arc<BlockLevelBox>>) {
|
let style = root_element.style(context);
|
||||||
// let replaced = ReplacedContent::for_element(root_element, context);
|
let replaced = ReplacedContent::for_element(root_element, context);
|
||||||
|
let box_style = style.get_box();
|
||||||
|
|
||||||
// let display_inside = match style.box_.display {
|
let display_inside = match Display::from(box_style.display) {
|
||||||
// Display::None => return (ContainsFloats::No, Vec::new()),
|
Display::None => return (ContainsFloats::No, Vec::new()),
|
||||||
// Display::Contents if replaced.is_some() => {
|
Display::Contents if replaced.is_some() => {
|
||||||
// // 'display: contents' computes to 'none' for replaced elements
|
// 'display: contents' computes to 'none' for replaced elements
|
||||||
// return (ContainsFloats::No, Vec::new());
|
return (ContainsFloats::No, Vec::new());
|
||||||
// }
|
},
|
||||||
// // https://drafts.csswg.org/css-display-3/#transformations
|
// https://drafts.csswg.org/css-display-3/#transformations
|
||||||
// Display::Contents => DisplayInside::Flow,
|
Display::Contents => DisplayInside::Flow,
|
||||||
// // The root element is blockified, ignore DisplayOutside
|
// The root element is blockified, ignore DisplayOutside
|
||||||
// Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { inside, .. }) => inside,
|
Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { inside, .. }) => inside,
|
||||||
// };
|
};
|
||||||
|
|
||||||
// if let Some(replaced) = replaced {
|
if let Some(replaced) = replaced {
|
||||||
// let _box = match replaced {};
|
let _box = match replaced {};
|
||||||
// #[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
// {
|
{
|
||||||
// return (ContainsFloats::No, vec![Arc::new(_box)]);
|
return (ContainsFloats::No, vec![Arc::new(_box)]);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// let contents = IndependentFormattingContext::construct(
|
let contents = IndependentFormattingContext::construct(
|
||||||
// context,
|
context,
|
||||||
// &style,
|
&style,
|
||||||
// display_inside,
|
display_inside,
|
||||||
// Contents::OfElement(root_element),
|
Contents::OfElement(root_element),
|
||||||
// );
|
);
|
||||||
// if style.box_.position.is_absolutely_positioned() {
|
if box_style.position.is_absolutely_positioned() {
|
||||||
// (
|
(
|
||||||
// ContainsFloats::No,
|
ContainsFloats::No,
|
||||||
// vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(
|
vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(
|
||||||
// AbsolutelyPositionedBox { style, contents },
|
AbsolutelyPositionedBox { style, contents },
|
||||||
// ))],
|
))],
|
||||||
// )
|
)
|
||||||
// } else if style.box_.float.is_floating() {
|
} else if box_style.float.is_floating() {
|
||||||
// (
|
(
|
||||||
// ContainsFloats::Yes,
|
ContainsFloats::Yes,
|
||||||
// vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox {
|
vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox {
|
||||||
// contents,
|
contents,
|
||||||
// style,
|
style,
|
||||||
// }))],
|
}))],
|
||||||
// )
|
)
|
||||||
// } else {
|
} else {
|
||||||
// (
|
(
|
||||||
// ContainsFloats::No,
|
ContainsFloats::No,
|
||||||
// vec![Arc::new(BlockLevelBox::Independent { style, contents })],
|
vec![Arc::new(BlockLevelBox::Independent { style, contents })],
|
||||||
// )
|
)
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// impl BoxTreeRoot {
|
impl BoxTreeRoot {
|
||||||
// fn layout(&self, viewport: crate::geom::Size<crate::geom::CssPx>) -> Vec<Fragment> {
|
fn layout(&self, viewport: geom::Size<CSSPixel>) -> Vec<Fragment> {
|
||||||
// let initial_containing_block_size = Vec2 {
|
let initial_containing_block_size = Vec2 {
|
||||||
// inline: Length { px: viewport.width },
|
inline: Length::new(viewport.width),
|
||||||
// block: Length {
|
block: Length::new(viewport.height),
|
||||||
// px: viewport.height,
|
};
|
||||||
// },
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let initial_containing_block = ContainingBlock {
|
let initial_containing_block = ContainingBlock {
|
||||||
// inline_size: initial_containing_block_size.inline,
|
inline_size: initial_containing_block_size.inline,
|
||||||
// block_size: LengthOrAuto::Length(initial_containing_block_size.block),
|
block_size: LengthOrAuto::LengthPercentage(initial_containing_block_size.block),
|
||||||
// // FIXME: use the document’s mode:
|
// FIXME: use the document’s mode:
|
||||||
// // https://drafts.csswg.org/css-writing-modes/#principal-flow
|
// https://drafts.csswg.org/css-writing-modes/#principal-flow
|
||||||
// mode: (WritingMode::HorizontalTb, Direction::Ltr),
|
mode: (WritingMode::HorizontalTb, Direction::Ltr),
|
||||||
// };
|
};
|
||||||
// let dummy_tree_rank = 0;
|
let dummy_tree_rank = 0;
|
||||||
// let mut absolutely_positioned_fragments = vec![];
|
let mut absolutely_positioned_fragments = vec![];
|
||||||
// let mut fragments = self.0.layout(
|
let mut flow_children = self.0.layout(
|
||||||
// &initial_containing_block,
|
&initial_containing_block,
|
||||||
// &mut absolutely_positioned_fragments,
|
dummy_tree_rank,
|
||||||
// dummy_tree_rank,
|
&mut absolutely_positioned_fragments,
|
||||||
// &mut PlacementState::root(),
|
);
|
||||||
// );
|
|
||||||
|
|
||||||
// let initial_containing_block = DefiniteContainingBlock {
|
let initial_containing_block = DefiniteContainingBlock {
|
||||||
// size: initial_containing_block_size,
|
size: initial_containing_block_size,
|
||||||
// mode: initial_containing_block.mode,
|
mode: initial_containing_block.mode,
|
||||||
// };
|
};
|
||||||
// fragments.par_extend(
|
flow_children.fragments.par_extend(
|
||||||
// absolutely_positioned_fragments
|
absolutely_positioned_fragments
|
||||||
// .par_iter()
|
.par_iter()
|
||||||
// .map(|a| a.layout(&initial_containing_block)),
|
.map(|a| a.layout(&initial_containing_block)),
|
||||||
// );
|
);
|
||||||
// fragments
|
flow_children.fragments
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
|
@ -42,15 +42,24 @@ ${helpers.single_keyword(
|
||||||
spec="Internal (not web-exposed)",
|
spec="Internal (not web-exposed)",
|
||||||
)}
|
)}
|
||||||
|
|
||||||
${helpers.single_keyword(
|
<%helpers:single_keyword
|
||||||
"position",
|
name="position"
|
||||||
"static absolute relative fixed" + (" sticky" if engine in ["gecko", "servo-2013"] else ""),
|
values="static absolute relative fixed ${'sticky' if engine in ['gecko', 'servo-2013'] else ''}"
|
||||||
engines="gecko servo-2013 servo-2020",
|
engines="gecko servo-2013 servo-2020"
|
||||||
animation_value_type="discrete",
|
animation_value_type="discrete"
|
||||||
flags="CREATES_STACKING_CONTEXT ABSPOS_CB",
|
flags="CREATES_STACKING_CONTEXT ABSPOS_CB"
|
||||||
spec="https://drafts.csswg.org/css-position/#position-property",
|
spec="https://drafts.csswg.org/css-position/#position-property"
|
||||||
servo_restyle_damage="rebuild_and_reflow",
|
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(
|
${helpers.predefined_type(
|
||||||
"float",
|
"float",
|
||||||
|
|
|
@ -61,6 +61,13 @@ pub enum Float {
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Float {
|
||||||
|
/// Returns true if `self` is not `None`.
|
||||||
|
pub fn is_floating(self) -> bool {
|
||||||
|
self != Self::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedFloat {
|
impl ToComputedValue for SpecifiedFloat {
|
||||||
type ComputedValue = Float;
|
type ComputedValue = Float;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue