diff options
Diffstat (limited to 'components/layout_2020/fragments.rs')
-rw-r--r-- | components/layout_2020/fragments.rs | 131 |
1 files changed, 94 insertions, 37 deletions
diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index 70c65dd470d..35c21e6dace 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -2,11 +2,12 @@ * 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::cell::ArcRefCell; use crate::geom::flow_relative::{Rect, Sides}; use crate::geom::{PhysicalPoint, PhysicalRect}; #[cfg(debug_assertions)] use crate::layout_debug; -use crate::positioned::HoistedFragmentId; +use gfx::font::FontMetrics as GfxFontMetrics; use gfx::text::glyph::GlyphStore; use gfx_traits::print_tree::PrintTree; #[cfg(not(debug_assertions))] @@ -14,10 +15,12 @@ use serde::ser::{Serialize, Serializer}; use servo_arc::Arc as ServoArc; use std::sync::Arc; use style::computed_values::overflow_x::T as ComputedOverflow; +use style::computed_values::position::T as ComputedPosition; use style::dom::OpaqueNode; use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::Length; +use style::values::specified::text::TextDecorationLine; use style::Zero; use webrender_api::{FontInstanceKey, ImageKey}; @@ -31,7 +34,10 @@ pub(crate) enum Fragment { } #[derive(Serialize)] -pub(crate) struct AbsoluteOrFixedPositionedFragment(pub HoistedFragmentId); +pub(crate) struct AbsoluteOrFixedPositionedFragment { + pub position: ComputedPosition, + pub hoisted_fragment: ArcRefCell<Option<ArcRefCell<Fragment>>>, +} #[derive(Serialize)] pub(crate) struct BoxFragment { @@ -39,7 +45,7 @@ pub(crate) struct BoxFragment { pub debug_id: DebugId, #[serde(skip_serializing)] pub style: ServoArc<ComputedValues>, - pub children: Vec<Fragment>, + pub children: Vec<ArcRefCell<Fragment>>, /// From the containing block’s start corner…? /// This might be broken when the containing block is in a different writing mode: @@ -54,9 +60,6 @@ pub(crate) struct BoxFragment { /// The scrollable overflow of this box fragment. pub scrollable_overflow_from_children: PhysicalRect<Length>, - - /// XXX Add thsi - pub hoisted_fragment_id: Option<HoistedFragmentId>, } #[derive(Serialize)] @@ -77,13 +80,36 @@ pub(crate) struct CollapsedMargin { pub(crate) struct AnonymousFragment { pub debug_id: DebugId, pub rect: Rect<Length>, - pub children: Vec<Fragment>, + pub children: Vec<ArcRefCell<Fragment>>, pub mode: WritingMode, /// The scrollable overflow of this anonymous fragment's children. pub scrollable_overflow: PhysicalRect<Length>, } +#[derive(Clone, Copy, Serialize)] +pub(crate) struct FontMetrics { + pub ascent: Length, + pub line_gap: Length, + pub underline_offset: Length, + pub underline_size: Length, + pub strikeout_offset: Length, + pub strikeout_size: Length, +} + +impl From<&GfxFontMetrics> for FontMetrics { + fn from(metrics: &GfxFontMetrics) -> FontMetrics { + FontMetrics { + ascent: metrics.ascent.into(), + line_gap: metrics.line_gap.into(), + underline_offset: metrics.underline_offset.into(), + underline_size: metrics.underline_size.into(), + strikeout_offset: metrics.strikeout_offset.into(), + strikeout_size: metrics.strikeout_size.into(), + } + } +} + #[derive(Serialize)] pub(crate) struct TextFragment { pub debug_id: DebugId, @@ -91,10 +117,12 @@ pub(crate) struct TextFragment { #[serde(skip_serializing)] pub parent_style: ServoArc<ComputedValues>, pub rect: Rect<Length>, - pub ascent: Length, + pub font_metrics: FontMetrics, #[serde(skip_serializing)] pub font_key: FontInstanceKey, pub glyphs: Vec<Arc<GlyphStore>>, + /// A flag that represents the _used_ value of the text-decoration property. + pub text_decoration_line: TextDecorationLine, } #[derive(Serialize)] @@ -130,10 +158,10 @@ impl Fragment { } } - pub fn scrollable_overflow(&self) -> PhysicalRect<Length> { - // FIXME(mrobinson, bug 25564): We should be using the containing block - // here to properly convert scrollable overflow to physical geometry. - let containing_block = PhysicalRect::zero(); + pub fn scrollable_overflow( + &self, + containing_block: &PhysicalRect<Length>, + ) -> PhysicalRect<Length> { match self { Fragment::Box(fragment) => fragment.scrollable_overflow_for_parent(&containing_block), Fragment::AbsoluteOrFixedPositioned(_) => PhysicalRect::zero(), @@ -147,16 +175,36 @@ impl Fragment { } } - pub fn is_hoisted(&self) -> bool { - match self { - Fragment::Box(fragment) if fragment.hoisted_fragment_id.is_some() => true, - _ => false, + pub(crate) fn find<T>( + &self, + containing_block: &PhysicalRect<Length>, + process_func: &mut impl FnMut(&Fragment, &PhysicalRect<Length>) -> Option<T>, + ) -> Option<T> { + if let Some(result) = process_func(self, containing_block) { + return Some(result); } - } - pub fn hoisted_fragment_id(&self) -> Option<&HoistedFragmentId> { match self { - Fragment::Box(fragment) => fragment.hoisted_fragment_id.as_ref(), + Fragment::Box(fragment) => { + let new_containing_block = fragment + .content_rect + .to_physical(fragment.style.writing_mode, containing_block) + .translate(containing_block.origin.to_vector()); + fragment + .children + .iter() + .find_map(|child| child.borrow().find(&new_containing_block, process_func)) + }, + Fragment::Anonymous(fragment) => { + let new_containing_block = fragment + .rect + .to_physical(fragment.mode, containing_block) + .translate(containing_block.origin.to_vector()); + fragment + .children + .iter() + .find_map(|child| child.borrow().find(&new_containing_block, process_func)) + }, _ => None, } } @@ -164,7 +212,7 @@ impl Fragment { impl AbsoluteOrFixedPositionedFragment { pub fn print(&self, tree: &mut PrintTree) { - tree.add_item(format!("AbsoluteOrFixedPositionedFragment({:?})", self.0)); + tree.add_item(format!("AbsoluteOrFixedPositionedFragment")); } } @@ -180,18 +228,24 @@ impl AnonymousFragment { } pub fn new(rect: Rect<Length>, children: Vec<Fragment>, mode: WritingMode) -> Self { + // FIXME(mrobinson, bug 25564): We should be using the containing block + // here to properly convert scrollable overflow to physical geometry. + let containing_block = PhysicalRect::zero(); let content_origin = rect.start_corner.to_physical(mode); let scrollable_overflow = children.iter().fold(PhysicalRect::zero(), |acc, child| { acc.union( &child - .scrollable_overflow() + .scrollable_overflow(&containing_block) .translate(content_origin.to_vector()), ) }); AnonymousFragment { debug_id: DebugId::new(), rect, - children, + children: children + .into_iter() + .map(|fragment| ArcRefCell::new(fragment)) + .collect(), mode, scrollable_overflow, } @@ -206,7 +260,7 @@ impl AnonymousFragment { )); for child in &self.children { - child.print(tree); + child.borrow().print(tree); } tree.end_level(); } @@ -222,33 +276,38 @@ impl BoxFragment { border: Sides<Length>, margin: Sides<Length>, block_margins_collapsed_with_children: CollapsedBlockMargins, - hoisted_fragment_id: Option<HoistedFragmentId>, ) -> BoxFragment { + // FIXME(mrobinson, bug 25564): We should be using the containing block + // here to properly convert scrollable overflow to physical geometry. + let containing_block = PhysicalRect::zero(); let scrollable_overflow_from_children = children.iter().fold(PhysicalRect::zero(), |acc, child| { - acc.union(&child.scrollable_overflow()) + acc.union(&child.scrollable_overflow(&containing_block)) }); BoxFragment { tag, debug_id: DebugId::new(), style, - children, + children: children + .into_iter() + .map(|fragment| ArcRefCell::new(fragment)) + .collect(), content_rect, padding, border, margin, block_margins_collapsed_with_children, scrollable_overflow_from_children, - hoisted_fragment_id, } } - pub fn scrollable_overflow(&self) -> PhysicalRect<Length> { - // FIXME(mrobinson, bug 25564): We should be using the containing block - // here to properly convert scrollable overflow to physical geometry. + pub fn scrollable_overflow( + &self, + containing_block: &PhysicalRect<Length>, + ) -> PhysicalRect<Length> { let physical_padding_rect = self .padding_rect() - .to_physical(self.style.writing_mode, &PhysicalRect::zero()); + .to_physical(self.style.writing_mode, containing_block); let content_origin = self .content_rect @@ -277,20 +336,18 @@ impl BoxFragment { \nborder rect={:?}\ \nscrollable_overflow={:?}\ \noverflow={:?} / {:?}\ - \nstyle={:p}\ - \nhoisted_id={:?}", + \nstyle={:p}", self.content_rect, self.padding_rect(), self.border_rect(), - self.scrollable_overflow(), + self.scrollable_overflow(&PhysicalRect::zero()), self.style.get_box().overflow_x, self.style.get_box().overflow_y, self.style, - self.hoisted_fragment_id, )); for child in &self.children { - child.print(tree); + child.borrow().print(tree); } tree.end_level(); } @@ -311,7 +368,7 @@ impl BoxFragment { // https://www.w3.org/TR/css-overflow-3/#scrollable // Only include the scrollable overflow of a child box if it has overflow: visible. - let scrollable_overflow = self.scrollable_overflow(); + let scrollable_overflow = self.scrollable_overflow(&containing_block); let bottom_right = PhysicalPoint::new( overflow.max_x().max(scrollable_overflow.max_x()), overflow.max_y().max(scrollable_overflow.max_y()), |