diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-11-25 08:07:02 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-25 08:07:02 -0500 |
commit | a562808ebb0a7b30a570a0302c1f7e69e00a3b4a (patch) | |
tree | 4e1ccd3bd391b75e4c9840b7eeb40a6252f9a852 | |
parent | ea3249550467bd9f5a1de8271ed4fcaa70a7cdda (diff) | |
parent | 85b2a4dc6466cc2136f0caa5867803dcee253c8a (diff) | |
download | servo-a562808ebb0a7b30a570a0302c1f7e69e00a3b4a.tar.gz servo-a562808ebb0a7b30a570a0302c1f7e69e00a3b4a.zip |
Auto merge of #24822 - servo:fontcontext, r=SimonSapin
Start implementing text in layout 2020
-rw-r--r-- | Cargo.lock | 4 | ||||
-rw-r--r-- | components/gfx/text/glyph.rs | 5 | ||||
-rw-r--r-- | components/layout_2020/Cargo.toml | 4 | ||||
-rw-r--r-- | components/layout_2020/context.rs | 17 | ||||
-rw-r--r-- | components/layout_2020/display_list.rs | 55 | ||||
-rw-r--r-- | components/layout_2020/flow/inline.rs | 146 | ||||
-rw-r--r-- | components/layout_2020/flow/mod.rs | 25 | ||||
-rw-r--r-- | components/layout_2020/flow/root.rs | 10 | ||||
-rw-r--r-- | components/layout_2020/fragments.rs | 14 | ||||
-rw-r--r-- | components/layout_2020/lib.rs | 20 | ||||
-rw-r--r-- | components/layout_2020/positioned.rs | 12 | ||||
-rw-r--r-- | components/layout_thread_2020/lib.rs | 27 | ||||
-rw-r--r-- | components/style/properties/longhands/box.mako.rs | 1 | ||||
-rw-r--r-- | components/style/properties/longhands/font.mako.rs | 5 | ||||
-rw-r--r-- | components/style/properties/longhands/inherited_text.mako.rs | 7 | ||||
-rw-r--r-- | components/style/properties/shorthands/font.mako.rs | 1 |
16 files changed, 311 insertions, 42 deletions
diff --git a/Cargo.lock b/Cargo.lock index c216acf7031..a501e46e194 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2694,17 +2694,21 @@ dependencies = [ "cssparser", "euclid", "gfx", + "gfx_traits", "ipc-channel", "libc", "msg", + "range", "rayon", "rayon_croissant", "script_layout_interface", "script_traits", "serde", "servo_arc", + "servo_geometry", "style", "style_traits", + "unicode-script", "webrender_api", ] diff --git a/components/gfx/text/glyph.rs b/components/gfx/text/glyph.rs index 52faf0c5480..7492064e3f7 100644 --- a/components/gfx/text/glyph.rs +++ b/components/gfx/text/glyph.rs @@ -453,6 +453,11 @@ impl<'a> GlyphStore { } #[inline] + pub fn total_advance(&self) -> Au { + self.total_advance + } + + #[inline] pub fn len(&self) -> ByteIndex { ByteIndex(self.entry_buffer.len() as isize) } diff --git a/components/layout_2020/Cargo.toml b/components/layout_2020/Cargo.toml index 69b0bea014e..f7167b638d5 100644 --- a/components/layout_2020/Cargo.toml +++ b/components/layout_2020/Cargo.toml @@ -18,15 +18,19 @@ atomic_refcell = "0.1" cssparser = "0.27" euclid = "0.20" gfx = {path = "../gfx"} +gfx_traits = {path = "../gfx_traits"} ipc-channel = "0.12" libc = "0.2" msg = {path = "../msg"} +range = {path = "../range"} rayon = "1" rayon_croissant = "0.1.1" script_layout_interface = {path = "../script_layout_interface"} script_traits = {path = "../script_traits"} serde = "1.0" servo_arc = { path = "../servo_arc" } +servo_geometry = {path = "../geometry"} style = {path = "../style", features = ["servo", "servo-layout-2020"]} style_traits = {path = "../style_traits"} +unicode-script = {version = "0.3", features = ["harfbuzz"]} webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} diff --git a/components/layout_2020/context.rs b/components/layout_2020/context.rs index 0e96797f4d7..5bde114ca57 100644 --- a/components/layout_2020/context.rs +++ b/components/layout_2020/context.rs @@ -3,7 +3,9 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use gfx::font_cache_thread::FontCacheThread; +use gfx::font_context::FontContext; use msg::constellation_msg::PipelineId; +use std::cell::{RefCell, RefMut}; use std::sync::Mutex; use style::context::SharedStyleContext; @@ -19,3 +21,18 @@ impl<'a> LayoutContext<'a> { &self.style_context } } + +pub(crate) type LayoutFontContext = FontContext<FontCacheThread>; + +thread_local!(static FONT_CONTEXT: RefCell<Option<LayoutFontContext>> = RefCell::new(None)); + +pub(crate) fn with_thread_local_font_context<F, R>(layout_context: &LayoutContext, f: F) -> R +where + F: FnOnce(&mut LayoutFontContext) -> R, +{ + FONT_CONTEXT.with(|font_context| { + f(font_context.borrow_mut().get_or_insert_with(|| { + FontContext::new(layout_context.font_cache_thread.lock().unwrap().clone()) + })) + }) +} diff --git a/components/layout_2020/display_list.rs b/components/layout_2020/display_list.rs index c153b04294c..5dc5ecb96ad 100644 --- a/components/layout_2020/display_list.rs +++ b/components/layout_2020/display_list.rs @@ -6,7 +6,10 @@ use crate::fragments::{BoxFragment, Fragment}; use crate::geom::physical::{Rect, Vec2}; use crate::style_ext::ComputedValuesExt; use app_units::Au; -use euclid::{self, SideOffsets2D}; +use euclid::{Point2D, SideOffsets2D}; +use gfx::text::glyph::GlyphStore; +use servo_geometry::MaxRect; +use std::sync::Arc; use style::values::computed::{BorderStyle, Length}; use webrender_api::{self as wr, units, CommonItemProperties, PrimitiveFlags}; @@ -50,9 +53,30 @@ impl Fragment { child.build_display_list(builder, is_contentful, &rect) } }, - Fragment::Text(_) => { + Fragment::Text(t) => { is_contentful.0 = true; - // FIXME + let rect = t + .content_rect + .to_physical(t.parent_style.writing_mode(), containing_block) + .translate(&containing_block.top_left); + let mut baseline_origin = rect.top_left.clone(); + baseline_origin.y += t.ascent; + let common = CommonItemProperties { + clip_rect: rect.clone().into(), + clip_id: wr::ClipId::root(builder.pipeline_id), + spatial_id: wr::SpatialId::root_scroll_node(builder.pipeline_id), + hit_info: None, + // TODO(gw): Make use of the WR backface visibility functionality. + flags: PrimitiveFlags::default(), + }; + let glyphs = glyphs(&t.glyphs, baseline_origin); + if glyphs.is_empty() { + return; + } + let color = t.parent_style.clone_color(); + builder + .wr + .push_text(&common, rect.into(), &glyphs, t.font_key, rgba(color), None); }, } } @@ -154,3 +178,28 @@ fn rgba(rgba: cssparser::RGBA) -> wr::ColorF { rgba.alpha_f32(), ) } + +fn glyphs(glyph_runs: &[Arc<GlyphStore>], mut origin: Vec2<Length>) -> Vec<wr::GlyphInstance> { + use gfx_traits::ByteIndex; + use range::Range; + + let mut glyphs = vec![]; + for run in glyph_runs { + for glyph in run.iter_glyphs_for_byte_range(&Range::new(ByteIndex(0), run.len())) { + if !run.is_whitespace() { + let glyph_offset = glyph.offset().unwrap_or(Point2D::zero()); + let point = units::LayoutPoint::new( + origin.x.px() + glyph_offset.x.to_f32_px(), + origin.y.px() + glyph_offset.y.to_f32_px(), + ); + let glyph = wr::GlyphInstance { + index: glyph.id(), + point, + }; + glyphs.push(glyph); + } + origin.x += Length::from(glyph.advance()); + } + } + glyphs +} diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 133654f32b7..e410fa269ec 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -2,9 +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::context::LayoutContext; use crate::flow::float::FloatBox; use crate::flow::FlowChildren; -use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment}; +use crate::fragments::{ + AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment, TextFragment, +}; use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment}; use crate::replaced::ReplacedContent; @@ -81,6 +84,7 @@ struct LinesBoxes { impl InlineFormattingContext { pub(super) fn layout<'a>( &'a self, + layout_context: &LayoutContext, containing_block: &ContainingBlock, tree_rank: usize, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, @@ -107,7 +111,7 @@ impl InlineFormattingContext { let partial = inline.start_layout(&mut ifc); ifc.partial_inline_boxes_stack.push(partial) }, - InlineLevelBox::TextRun(run) => run.layout(&mut ifc), + InlineLevelBox::TextRun(run) => run.layout(layout_context, &mut ifc), InlineLevelBox::Atomic { style: _, contents } => { // FIXME match *contents {} @@ -284,7 +288,141 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> { } impl TextRun { - fn layout(&self, _ifc: &mut InlineFormattingContextState) { - // TODO + fn layout(&self, layout_context: &LayoutContext, ifc: &mut InlineFormattingContextState) { + use gfx::font::{ShapingFlags, ShapingOptions}; + use style::computed_values::text_rendering::T as TextRendering; + use style::computed_values::word_break::T as WordBreak; + use style::values::generics::text::LineHeight; + + let font_style = self.parent_style.clone_font(); + let inherited_text_style = self.parent_style.get_inherited_text(); + let letter_spacing = if inherited_text_style.letter_spacing.0.px() != 0. { + Some(app_units::Au::from(inherited_text_style.letter_spacing.0)) + } else { + None + }; + + let mut flags = ShapingFlags::empty(); + if letter_spacing.is_some() { + flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG); + } + if inherited_text_style.text_rendering == TextRendering::Optimizespeed { + flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG); + flags.insert(ShapingFlags::DISABLE_KERNING_SHAPING_FLAG) + } + if inherited_text_style.word_break == WordBreak::KeepAll { + flags.insert(ShapingFlags::KEEP_ALL_FLAG); + } + + let shaping_options = gfx::font::ShapingOptions { + letter_spacing, + word_spacing: inherited_text_style.word_spacing.to_hash_key(), + script: unicode_script::Script::Common, + flags, + }; + + let (font_ascent, font_line_gap, font_key, runs) = + crate::context::with_thread_local_font_context(layout_context, |font_context| { + let font_group = font_context.font_group(font_style); + let font = font_group + .borrow_mut() + .first(font_context) + .expect("could not find font"); + let mut font = font.borrow_mut(); + + let (runs, _break_at_start) = gfx::text::text_run::TextRun::break_and_shape( + &mut font, + &self.text, + &shaping_options, + &mut None, + ); + + ( + font.metrics.ascent, + font.metrics.line_gap, + font.font_key, + runs, + ) + }); + + let font_size = self.parent_style.get_font().font_size.size.0; + let mut runs = runs.iter(); + loop { + let mut glyphs = vec![]; + let mut advance_width = Length::zero(); + let mut last_break_opportunity = None; + loop { + let next = runs.next(); + if next + .as_ref() + .map_or(true, |run| run.glyph_store.is_whitespace()) + { + if advance_width > ifc.containing_block.inline_size - ifc.inline_position { + if let Some((len, width, iter)) = last_break_opportunity.take() { + glyphs.truncate(len); + advance_width = width; + runs = iter; + } + break; + } + } + if let Some(run) = next { + if run.glyph_store.is_whitespace() { + last_break_opportunity = Some((glyphs.len(), advance_width, runs.clone())); + } + glyphs.push(run.glyph_store.clone()); + advance_width += Length::from(run.glyph_store.total_advance()); + } else { + break; + } + } + let line_height = match self.parent_style.get_inherited_text().line_height { + LineHeight::Normal => font_line_gap.into(), + LineHeight::Number(n) => font_size * n.0, + LineHeight::Length(l) => l.0, + }; + let content_rect = Rect { + start_corner: Vec2 { + block: Length::zero(), + inline: ifc.inline_position - ifc.current_nesting_level.inline_start, + }, + size: Vec2 { + block: line_height, + inline: advance_width, + }, + }; + ifc.inline_position += advance_width; + ifc.current_nesting_level + .max_block_size_of_fragments_so_far + .max_assign(line_height); + ifc.current_nesting_level + .fragments_so_far + .push(Fragment::Text(TextFragment { + parent_style: self.parent_style.clone(), + content_rect, + ascent: font_ascent.into(), + font_key, + glyphs, + })); + if runs.is_empty() { + break; + } else { + // New line + ifc.current_nesting_level.inline_start = Length::zero(); + let mut nesting_level = &mut ifc.current_nesting_level; + for partial in ifc.partial_inline_boxes_stack.iter_mut().rev() { + partial.finish_layout(nesting_level, &mut ifc.inline_position, true); + partial.start_corner.inline = Length::zero(); + partial.padding.inline_start = Length::zero(); + partial.border.inline_start = Length::zero(); + partial.margin.inline_start = Length::zero(); + partial.parent_nesting_level.inline_start = Length::zero(); + nesting_level = &mut partial.parent_nesting_level; + } + ifc.line_boxes + .finish_line(nesting_level, ifc.containing_block); + ifc.inline_position = Length::zero(); + } + } } } diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 2395380c5eb..b690e447cd7 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -4,6 +4,7 @@ //! Flow layout, also known as block-and-inline layout. +use crate::context::LayoutContext; use crate::flow::float::{FloatBox, FloatContext}; use crate::flow::inline::InlineFormattingContext; use crate::fragments::{ @@ -67,6 +68,7 @@ struct CollapsibleWithParentStartMargin(bool); impl BlockFormattingContext { pub(super) fn layout<'a>( &'a self, + layout_context: &LayoutContext, containing_block: &ContainingBlock, tree_rank: usize, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, @@ -79,6 +81,7 @@ impl BlockFormattingContext { None }; let mut flow_children = self.contents.layout( + layout_context, containing_block, tree_rank, absolutely_positioned_fragments, @@ -97,6 +100,7 @@ impl BlockFormattingContext { impl BlockContainer { fn layout<'a>( &'a self, + layout_context: &LayoutContext, containing_block: &ContainingBlock, tree_rank: usize, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, @@ -105,6 +109,7 @@ impl BlockContainer { ) -> FlowChildren { match self { BlockContainer::BlockLevelBoxes(child_boxes) => layout_block_level_children( + layout_context, child_boxes, containing_block, tree_rank, @@ -112,14 +117,18 @@ impl BlockContainer { float_context, collapsible_with_parent_start_margin, ), - BlockContainer::InlineFormattingContext(ifc) => { - ifc.layout(containing_block, tree_rank, absolutely_positioned_fragments) - }, + BlockContainer::InlineFormattingContext(ifc) => ifc.layout( + layout_context, + containing_block, + tree_rank, + absolutely_positioned_fragments, + ), } } } fn layout_block_level_children<'a>( + layout_context: &LayoutContext, child_boxes: &'a [Arc<BlockLevelBox>], containing_block: &ContainingBlock, tree_rank: usize, @@ -201,6 +210,7 @@ fn layout_block_level_children<'a>( .enumerate() .map(|(tree_rank, box_)| { let mut fragment = box_.layout( + layout_context, containing_block, tree_rank, absolutely_positioned_fragments, @@ -218,6 +228,7 @@ fn layout_block_level_children<'a>( absolutely_positioned_fragments, |abspos_fragments, (tree_rank, box_)| { box_.layout( + layout_context, containing_block, tree_rank, abspos_fragments, @@ -255,6 +266,7 @@ fn layout_block_level_children<'a>( impl BlockLevelBox { fn layout<'a>( &'a self, + layout_context: &LayoutContext, containing_block: &ContainingBlock, tree_rank: usize, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, @@ -263,12 +275,14 @@ impl BlockLevelBox { match self { BlockLevelBox::SameFormattingContextBlock { style, contents } => { Fragment::Box(layout_in_flow_non_replaced_block_level( + layout_context, containing_block, absolutely_positioned_fragments, style, BlockLevelKind::SameFormattingContextBlock, |containing_block, nested_abspos, collapsible_with_parent_start_margin| { contents.layout( + layout_context, containing_block, tree_rank, nested_abspos, @@ -284,12 +298,13 @@ impl BlockLevelBox { match *replaced {} }, Err(contents) => Fragment::Box(layout_in_flow_non_replaced_block_level( + layout_context, containing_block, absolutely_positioned_fragments, style, BlockLevelKind::EstablishesAnIndependentFormattingContext, |containing_block, nested_abspos, _| { - contents.layout(containing_block, tree_rank, nested_abspos) + contents.layout(layout_context, containing_block, tree_rank, nested_abspos) }, )), }, @@ -314,6 +329,7 @@ enum BlockLevelKind { /// https://drafts.csswg.org/css2/visudet.html#blockwidth /// https://drafts.csswg.org/css2/visudet.html#normal-block fn layout_in_flow_non_replaced_block_level<'a>( + layout_context: &LayoutContext, containing_block: &ContainingBlock, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, style: &Arc<ComputedValues>, @@ -433,6 +449,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( }; if style.get_box().position == Position::Relative { AbsolutelyPositionedFragment::in_positioned_containing_block( + layout_context, &nested_abspos, &mut flow_children.fragments, &content_rect.size, diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 54cc1eef07f..a1831c6433a 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -2,6 +2,7 @@ * 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::context::LayoutContext; use crate::display_list::IsContentful; use crate::dom_traversal::{Contents, NodeExt}; use crate::flow::construct::ContainsFloats; @@ -98,7 +99,11 @@ fn construct_for_root_element<'dom>( } impl BoxTreeRoot { - pub fn layout(&self, viewport: geom::Size<CSSPixel>) -> FragmentTreeRoot { + pub fn layout( + &self, + layout_context: &LayoutContext, + viewport: geom::Size<CSSPixel>, + ) -> FragmentTreeRoot { let initial_containing_block_size = Vec2 { inline: Length::new(viewport.width), block: Length::new(viewport.height), @@ -114,6 +119,7 @@ impl BoxTreeRoot { let dummy_tree_rank = 0; let mut absolutely_positioned_fragments = vec![]; let mut flow_children = self.0.layout( + layout_context, &initial_containing_block, dummy_tree_rank, &mut absolutely_positioned_fragments, @@ -126,7 +132,7 @@ impl BoxTreeRoot { flow_children.fragments.par_extend( absolutely_positioned_fragments .par_iter() - .map(|a| a.layout(&initial_containing_block)), + .map(|a| a.layout(layout_context, &initial_containing_block)), ); FragmentTreeRoot(flow_children.fragments) } diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index ceb2fdf7971..a0ea097abb6 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -4,11 +4,13 @@ use crate::geom::flow_relative::{Rect, Sides}; use crate::style_ext::{Direction, WritingMode}; -// use crate::text::ShapedSegment; -use servo_arc::Arc; +use gfx::text::glyph::GlyphStore; +use servo_arc::Arc as ServoArc; +use std::sync::Arc; use style::properties::ComputedValues; use style::values::computed::Length; use style::Zero; +use webrender_api::FontInstanceKey; pub(crate) enum Fragment { Box(BoxFragment), @@ -17,7 +19,7 @@ pub(crate) enum Fragment { } pub(crate) struct BoxFragment { - pub style: Arc<ComputedValues>, + pub style: ServoArc<ComputedValues>, pub children: Vec<Fragment>, /// From the containing block’s start corner…? @@ -52,9 +54,11 @@ pub(crate) struct AnonymousFragment { } pub(crate) struct TextFragment { - pub parent_style: Arc<ComputedValues>, + pub parent_style: ServoArc<ComputedValues>, pub content_rect: Rect<Length>, - // pub text: ShapedSegment, + pub ascent: Length, + pub font_key: FontInstanceKey, + pub glyphs: Vec<Arc<GlyphStore>>, } impl AnonymousFragment { diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index 052cb4b0540..c0892553f35 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -7,6 +7,7 @@ #![allow(unused_imports)] #![allow(unused_variables)] #![deny(unsafe_code)] +#![feature(exact_size_is_empty)] #[macro_use] extern crate serde; @@ -33,6 +34,7 @@ pub mod wrapper; pub use flow::{BoxTreeRoot, FragmentTreeRoot}; +use crate::context::LayoutContext; use crate::dom_traversal::{Contents, NodeExt}; use crate::flow::{BlockFormattingContext, FlowChildren}; use crate::geom::flow_relative::Vec2; @@ -87,13 +89,19 @@ impl IndependentFormattingContext { fn layout<'a>( &'a self, + layout_context: &LayoutContext, containing_block: &ContainingBlock, tree_rank: usize, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, ) -> FlowChildren { match self.as_replaced() { Ok(replaced) => match *replaced {}, - Err(ifc) => ifc.layout(containing_block, tree_rank, absolutely_positioned_fragments), + Err(ifc) => ifc.layout( + layout_context, + containing_block, + tree_rank, + absolutely_positioned_fragments, + ), } } } @@ -101,14 +109,18 @@ impl IndependentFormattingContext { impl<'a> NonReplacedIFC<'a> { fn layout( &self, + layout_context: &LayoutContext, containing_block: &ContainingBlock, tree_rank: usize, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, ) -> FlowChildren { match self { - NonReplacedIFC::Flow(bfc) => { - bfc.layout(containing_block, tree_rank, absolutely_positioned_fragments) - }, + NonReplacedIFC::Flow(bfc) => bfc.layout( + layout_context, + containing_block, + tree_rank, + absolutely_positioned_fragments, + ), } } } diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 55888fb8842..b37a5ed4a70 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -2,6 +2,7 @@ * 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::context::LayoutContext; use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment}; use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::style_ext::{ComputedValuesExt, Direction, WritingMode}; @@ -94,6 +95,7 @@ impl AbsolutelyPositionedBox { impl<'a> AbsolutelyPositionedFragment<'a> { pub(crate) fn in_positioned_containing_block( + layout_context: &LayoutContext, absolute: &[Self], fragments: &mut Vec<Fragment>, content_rect_size: &Vec2<Length>, @@ -116,14 +118,18 @@ impl<'a> AbsolutelyPositionedFragment<'a> { fragments.push(Fragment::Anonymous(AnonymousFragment { children: absolute .par_iter() - .map(|a| a.layout(&containing_block)) + .map(|a| a.layout(layout_context, &containing_block)) .collect(), rect: padding_rect, mode, })) } - pub(crate) fn layout(&self, containing_block: &DefiniteContainingBlock) -> Fragment { + pub(crate) fn layout( + &self, + layout_context: &LayoutContext, + containing_block: &DefiniteContainingBlock, + ) -> Fragment { let style = &self.absolutely_positioned_box.style; let cbis = containing_block.size.inline; let cbbs = containing_block.size.block; @@ -269,6 +275,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { let dummy_tree_rank = 0; let mut absolutely_positioned_fragments = vec![]; let mut flow_children = self.absolutely_positioned_box.contents.layout( + layout_context, &containing_block_for_children, dummy_tree_rank, &mut absolutely_positioned_fragments, @@ -297,6 +304,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { }; AbsolutelyPositionedFragment::in_positioned_containing_block( + layout_context, &absolutely_positioned_fragments, &mut flow_children.fragments, &content_rect.size, diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index bf18c584231..e8fdb1cfccd 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -88,7 +88,7 @@ use style::context::{SharedStyleContext, ThreadLocalStyleContextCreationInfo}; use style::dom::{TDocument, TElement, TNode}; use style::driver; use style::error_reporting::RustLogReporter; -use style::global_style_data::GLOBAL_STYLE_DATA; +use style::global_style_data::{GLOBAL_STYLE_DATA, STYLE_THREAD_POOL}; use style::invalidation::element::restyle_hints::RestyleHint; use style::media_queries::{Device, MediaList, MediaType}; use style::properties::PropertyId; @@ -1087,16 +1087,29 @@ impl LayoutThread { RecalcStyle::pre_traverse(element, shared) }; - if token.should_traverse() { + let rayon_pool = STYLE_THREAD_POOL.pool(); + let rayon_pool = rayon_pool.as_ref().unwrap(); + + let box_tree = if token.should_traverse() { driver::traverse_dom(&traversal, token, None); let shared = DomTraversal::<ServoLayoutElement>::shared_context(&traversal); - let box_tree = - BoxTreeRoot::construct(shared, document.root_element().unwrap().as_node()); - let fragment_tree = box_tree.layout(Size2D::new( + let root_node = document.root_element().unwrap().as_node(); + let box_tree = rayon_pool.install(|| BoxTreeRoot::construct(shared, root_node)); + Some(box_tree) + } else { + None + }; + + layout_context = traversal.destroy(); + + if let Some(box_tree) = box_tree { + let viewport_size = Size2D::new( self.viewport_size.width.to_f32_px(), self.viewport_size.height.to_f32_px(), - )); + ); + let fragment_tree = + rayon_pool.install(|| box_tree.layout(&layout_context, viewport_size)); *self.box_tree_root.borrow_mut() = Some(box_tree); *self.fragment_tree_root.borrow_mut() = Some(fragment_tree); } @@ -1105,8 +1118,6 @@ impl LayoutThread { unsafe { element.unset_snapshot_flags() } } - layout_context = traversal.destroy(); - // GC the rule tree if some heuristics are met. unsafe { layout_context.style_context.stylist.rule_tree().maybe_gc(); diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index a68b179c4c0..b8b6cbc8c34 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -63,6 +63,7 @@ ${helpers.predefined_type( "Float", "computed::Float::None", engines="gecko servo-2013 servo-2020", + servo_2020_pref="layout.2020.unimplemented", initial_specified_value="specified::Float::None", spec="https://drafts.csswg.org/css-box/#propdef-float", animation_value_type="discrete", diff --git a/components/style/properties/longhands/font.mako.rs b/components/style/properties/longhands/font.mako.rs index b4b2ab0598c..7e0bff6fbbe 100644 --- a/components/style/properties/longhands/font.mako.rs +++ b/components/style/properties/longhands/font.mako.rs @@ -11,7 +11,6 @@ ${helpers.predefined_type( "font-family", "FontFamily", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", initial_value="computed::FontFamily::serif()", animation_value_type="discrete", spec="https://drafts.csswg.org/css-fonts/#propdef-font-family", @@ -22,7 +21,6 @@ ${helpers.predefined_type( "font-style", "FontStyle", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", initial_value="computed::FontStyle::normal()", initial_specified_value="specified::FontStyle::normal()", animation_value_type="FontStyle", @@ -40,7 +38,6 @@ ${helpers.single_keyword_system( "font-variant-caps", "normal small-caps", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", extra_gecko_values="all-small-caps petite-caps all-petite-caps unicase titling-caps", gecko_constant_prefix="NS_FONT_VARIANT_CAPS", gecko_ffi_name="mFont.variantCaps", @@ -54,7 +51,6 @@ ${helpers.predefined_type( "font-weight", "FontWeight", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", initial_value="computed::FontWeight::normal()", initial_specified_value="specified::FontWeight::normal()", animation_value_type="Number", @@ -97,7 +93,6 @@ ${helpers.predefined_type( "font-stretch", "FontStretch", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", initial_value="computed::FontStretch::hundred()", initial_specified_value="specified::FontStretch::normal()", animation_value_type="Percentage", diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index 18f5c466d1a..428b40a101f 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -21,7 +21,6 @@ ${helpers.predefined_type( "LineHeight", "computed::LineHeight::normal()", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", animation_value_type="LineHeight", spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height", servo_restyle_damage="reflow" @@ -167,7 +166,7 @@ ${helpers.predefined_type( "letter-spacing", "LetterSpacing", "computed::LetterSpacing::normal()", - engines="gecko servo-2013", + engines="gecko servo-2013 servo-2020", animation_value_type="ComputedValue", spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing", servo_restyle_damage="rebuild_and_reflow", @@ -177,7 +176,7 @@ ${helpers.predefined_type( "word-spacing", "WordSpacing", "computed::WordSpacing::zero()", - engines="gecko servo-2013", + engines="gecko servo-2013 servo-2020", animation_value_type="ComputedValue", spec="https://drafts.csswg.org/css-text/#propdef-word-spacing", servo_restyle_damage="rebuild_and_reflow", @@ -360,7 +359,7 @@ ${helpers.single_keyword( ${helpers.single_keyword( "text-rendering", "auto optimizespeed optimizelegibility geometricprecision", - engines="gecko servo-2013", + engines="gecko servo-2013 servo-2020", gecko_enum_prefix="StyleTextRendering", animation_value_type="discrete", spec="https://www.w3.org/TR/SVG11/painting.html#TextRenderingProperty", diff --git a/components/style/properties/shorthands/font.mako.rs b/components/style/properties/shorthands/font.mako.rs index e3b44d86a36..1feed113875 100644 --- a/components/style/properties/shorthands/font.mako.rs +++ b/components/style/properties/shorthands/font.mako.rs @@ -8,7 +8,6 @@ <%helpers:shorthand name="font" engines="gecko servo-2013 servo-2020" - servo_2020_pref="layout.2020.unimplemented" sub_properties=" font-style font-variant-caps |