aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-11-25 08:07:02 -0500
committerGitHub <noreply@github.com>2019-11-25 08:07:02 -0500
commita562808ebb0a7b30a570a0302c1f7e69e00a3b4a (patch)
tree4e1ccd3bd391b75e4c9840b7eeb40a6252f9a852
parentea3249550467bd9f5a1de8271ed4fcaa70a7cdda (diff)
parent85b2a4dc6466cc2136f0caa5867803dcee253c8a (diff)
downloadservo-a562808ebb0a7b30a570a0302c1f7e69e00a3b4a.tar.gz
servo-a562808ebb0a7b30a570a0302c1f7e69e00a3b4a.zip
Auto merge of #24822 - servo:fontcontext, r=SimonSapin
Start implementing text in layout 2020
-rw-r--r--Cargo.lock4
-rw-r--r--components/gfx/text/glyph.rs5
-rw-r--r--components/layout_2020/Cargo.toml4
-rw-r--r--components/layout_2020/context.rs17
-rw-r--r--components/layout_2020/display_list.rs55
-rw-r--r--components/layout_2020/flow/inline.rs146
-rw-r--r--components/layout_2020/flow/mod.rs25
-rw-r--r--components/layout_2020/flow/root.rs10
-rw-r--r--components/layout_2020/fragments.rs14
-rw-r--r--components/layout_2020/lib.rs20
-rw-r--r--components/layout_2020/positioned.rs12
-rw-r--r--components/layout_thread_2020/lib.rs27
-rw-r--r--components/style/properties/longhands/box.mako.rs1
-rw-r--r--components/style/properties/longhands/font.mako.rs5
-rw-r--r--components/style/properties/longhands/inherited_text.mako.rs7
-rw-r--r--components/style/properties/shorthands/font.mako.rs1
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