mirror of
https://github.com/servo/servo.git
synced 2025-06-26 01:54:33 +01:00
This applies some fixes for CSS Grid percentage sizing. These fixes are mostly within Taffy, but there are some changes in Servo to allow it to communicate whether an item is replaced to Taffy. It also updates Taffy to v0.8.0. Taffy has switched to a tagged pointer representation of length/size styles. Much of the diff here is updating Servo's type conversion code to use the new representation. --- <!-- 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 OR --------- Signed-off-by: Nico Burns <nico@nicoburns.com>
216 lines
7.2 KiB
Rust
216 lines
7.2 KiB
Rust
/* 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/. */
|
|
mod layout;
|
|
mod stylo_taffy;
|
|
use std::fmt;
|
|
|
|
use app_units::Au;
|
|
use malloc_size_of_derive::MallocSizeOf;
|
|
use script::layout_dom::ServoLayoutNode;
|
|
use servo_arc::Arc;
|
|
use style::context::SharedStyleContext;
|
|
use style::properties::ComputedValues;
|
|
use stylo_taffy::TaffyStyloStyle;
|
|
|
|
use crate::PropagatedBoxTreeData;
|
|
use crate::cell::ArcRefCell;
|
|
use crate::construct_modern::{ModernContainerBuilder, ModernItemKind};
|
|
use crate::context::LayoutContext;
|
|
use crate::dom::LayoutBox;
|
|
use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents};
|
|
use crate::formatting_contexts::{
|
|
IndependentFormattingContext, IndependentFormattingContextContents,
|
|
};
|
|
use crate::fragment_tree::Fragment;
|
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
|
|
|
#[derive(Debug, MallocSizeOf)]
|
|
pub(crate) struct TaffyContainer {
|
|
children: Vec<ArcRefCell<TaffyItemBox>>,
|
|
style: Arc<ComputedValues>,
|
|
}
|
|
|
|
impl TaffyContainer {
|
|
pub fn construct(
|
|
context: &LayoutContext,
|
|
info: &NodeAndStyleInfo,
|
|
contents: NonReplacedContents,
|
|
propagated_data: PropagatedBoxTreeData,
|
|
) -> Self {
|
|
let mut builder = ModernContainerBuilder::new(context, info, propagated_data);
|
|
contents.traverse(context, info, &mut builder);
|
|
let items = builder.finish();
|
|
|
|
let children = items
|
|
.into_iter()
|
|
.map(|item| {
|
|
let box_ = match item.kind {
|
|
ModernItemKind::InFlow => ArcRefCell::new(TaffyItemBox::new(
|
|
TaffyItemBoxInner::InFlowBox(item.formatting_context),
|
|
)),
|
|
ModernItemKind::OutOfFlow => {
|
|
let abs_pos_box =
|
|
ArcRefCell::new(AbsolutelyPositionedBox::new(item.formatting_context));
|
|
ArcRefCell::new(TaffyItemBox::new(
|
|
TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(abs_pos_box),
|
|
))
|
|
},
|
|
};
|
|
|
|
if let Some(box_slot) = item.box_slot {
|
|
box_slot.set(LayoutBox::TaffyItemBox(box_.clone()));
|
|
}
|
|
|
|
box_
|
|
})
|
|
.collect();
|
|
|
|
Self {
|
|
children,
|
|
style: info.style.clone(),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
|
|
self.style = new_style.clone();
|
|
}
|
|
}
|
|
|
|
#[derive(MallocSizeOf)]
|
|
pub(crate) struct TaffyItemBox {
|
|
pub(crate) taffy_layout: taffy::Layout,
|
|
pub(crate) child_fragments: Vec<Fragment>,
|
|
pub(crate) positioning_context: PositioningContext,
|
|
pub(crate) style: Arc<ComputedValues>,
|
|
pub(crate) taffy_level_box: TaffyItemBoxInner,
|
|
}
|
|
|
|
#[derive(Debug, MallocSizeOf)]
|
|
pub(crate) enum TaffyItemBoxInner {
|
|
InFlowBox(IndependentFormattingContext),
|
|
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
|
|
}
|
|
|
|
impl fmt::Debug for TaffyItemBox {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.debug_struct("TaffyItemBox")
|
|
.field("taffy_layout", &self.taffy_layout)
|
|
.field("child_fragments", &self.child_fragments.len())
|
|
.field("style", &self.style)
|
|
.field("taffy_level_box", &self.taffy_level_box)
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
impl TaffyItemBox {
|
|
fn new(inner: TaffyItemBoxInner) -> Self {
|
|
let style: Arc<ComputedValues> = match &inner {
|
|
TaffyItemBoxInner::InFlowBox(item) => item.style().clone(),
|
|
TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(absbox) => {
|
|
(*absbox).borrow().context.style().clone()
|
|
},
|
|
};
|
|
|
|
Self {
|
|
taffy_layout: Default::default(),
|
|
child_fragments: Vec::new(),
|
|
positioning_context: PositioningContext::default(),
|
|
style,
|
|
taffy_level_box: inner,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn invalidate_cached_fragment(&mut self) {
|
|
self.taffy_layout = Default::default();
|
|
self.positioning_context = PositioningContext::default();
|
|
match self.taffy_level_box {
|
|
TaffyItemBoxInner::InFlowBox(ref independent_formatting_context) => {
|
|
independent_formatting_context
|
|
.base
|
|
.invalidate_cached_fragment()
|
|
},
|
|
TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(ref positioned_box) => {
|
|
positioned_box
|
|
.borrow()
|
|
.context
|
|
.base
|
|
.invalidate_cached_fragment()
|
|
},
|
|
}
|
|
}
|
|
|
|
pub(crate) fn fragments(&self) -> Vec<Fragment> {
|
|
match self.taffy_level_box {
|
|
TaffyItemBoxInner::InFlowBox(ref independent_formatting_context) => {
|
|
independent_formatting_context.base.fragments()
|
|
},
|
|
TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(ref positioned_box) => {
|
|
positioned_box.borrow().context.base.fragments()
|
|
},
|
|
}
|
|
}
|
|
|
|
pub(crate) fn repair_style(
|
|
&mut self,
|
|
context: &SharedStyleContext,
|
|
node: &ServoLayoutNode,
|
|
new_style: &Arc<ComputedValues>,
|
|
) {
|
|
self.style = new_style.clone();
|
|
match &mut self.taffy_level_box {
|
|
TaffyItemBoxInner::InFlowBox(independent_formatting_context) => {
|
|
independent_formatting_context.repair_style(context, node, new_style)
|
|
},
|
|
TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(positioned_box) => positioned_box
|
|
.borrow_mut()
|
|
.context
|
|
.repair_style(context, node, new_style),
|
|
}
|
|
}
|
|
|
|
fn is_in_flow_replaced(&self) -> bool {
|
|
match &self.taffy_level_box {
|
|
TaffyItemBoxInner::InFlowBox(fc) => match fc.contents {
|
|
IndependentFormattingContextContents::NonReplaced(_) => false,
|
|
IndependentFormattingContextContents::Replaced(_) => true,
|
|
},
|
|
TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(_) => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Details from Taffy grid layout that will be stored
|
|
#[derive(Clone, Debug, MallocSizeOf)]
|
|
pub(crate) struct SpecificTaffyGridInfo {
|
|
pub rows: SpecificTaffyGridTrackInfo,
|
|
pub columns: SpecificTaffyGridTrackInfo,
|
|
}
|
|
|
|
impl SpecificTaffyGridInfo {
|
|
fn from_detailed_grid_layout(grid_info: taffy::DetailedGridInfo) -> Self {
|
|
Self {
|
|
rows: SpecificTaffyGridTrackInfo {
|
|
sizes: grid_info
|
|
.rows
|
|
.sizes
|
|
.iter()
|
|
.map(|size| Au::from_f32_px(*size))
|
|
.collect(),
|
|
},
|
|
columns: SpecificTaffyGridTrackInfo {
|
|
sizes: grid_info
|
|
.columns
|
|
.sizes
|
|
.iter()
|
|
.map(|size| Au::from_f32_px(*size))
|
|
.collect(),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, MallocSizeOf)]
|
|
pub(crate) struct SpecificTaffyGridTrackInfo {
|
|
pub sizes: Box<[Au]>,
|
|
}
|