aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout_2020/fragments.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout_2020/fragments.rs')
-rw-r--r--components/layout_2020/fragments.rs131
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()),