diff options
author | Simon Sapin <simon.sapin@exyr.org> | 2019-10-15 17:52:51 +0200 |
---|---|---|
committer | Simon Sapin <simon.sapin@exyr.org> | 2019-10-24 10:44:31 +0200 |
commit | cfc3ffcd545a18806674cf3bb1e3ddcffff3d89e (patch) | |
tree | 139b37dc348c1a4c4231210611164d9039929e22 | |
parent | 4e8eeda976f1475b11b1630854a01046d51e3c44 (diff) | |
download | servo-cfc3ffcd545a18806674cf3bb1e3ddcffff3d89e.tar.gz servo-cfc3ffcd545a18806674cf3bb1e3ddcffff3d89e.zip |
2020: paint background-color
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | components/layout_2020/Cargo.toml | 1 | ||||
-rw-r--r-- | components/layout_2020/display_list.rs | 106 | ||||
-rw-r--r-- | components/layout_2020/flow/root.rs | 24 | ||||
-rw-r--r-- | components/layout_2020/fragments.rs | 16 | ||||
-rw-r--r-- | components/layout_2020/geom.rs | 9 | ||||
-rw-r--r-- | components/layout_2020/lib.rs | 1 | ||||
-rw-r--r-- | components/layout_thread_2020/lib.rs | 9 |
8 files changed, 143 insertions, 24 deletions
diff --git a/Cargo.lock b/Cargo.lock index f6c6c03ddf0..da1e5f81bb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2477,6 +2477,7 @@ version = "0.0.1" dependencies = [ "app_units", "atomic_refcell", + "cssparser", "euclid", "gfx", "ipc-channel", diff --git a/components/layout_2020/Cargo.toml b/components/layout_2020/Cargo.toml index cacece15eb5..69b0bea014e 100644 --- a/components/layout_2020/Cargo.toml +++ b/components/layout_2020/Cargo.toml @@ -15,6 +15,7 @@ doctest = false [dependencies] app_units = "0.7" atomic_refcell = "0.1" +cssparser = "0.27" euclid = "0.20" gfx = {path = "../gfx"} ipc-channel = "0.12" diff --git a/components/layout_2020/display_list.rs b/components/layout_2020/display_list.rs new file mode 100644 index 00000000000..cd3d3b103db --- /dev/null +++ b/components/layout_2020/display_list.rs @@ -0,0 +1,106 @@ +/* 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/. */ + +use crate::fragments::{BoxFragment, Fragment}; +use crate::geom::physical::{Rect, Vec2}; +use crate::style_ext::ComputedValuesExt; +use app_units::Au; +use style::values::computed::Length; +use webrender_api::CommonItemProperties; + +pub struct DisplayListBuilder { + pipeline_id: webrender_api::PipelineId, + pub wr: webrender_api::DisplayListBuilder, + pub is_contentful: bool, +} + +impl DisplayListBuilder { + pub fn new( + pipeline_id: webrender_api::PipelineId, + viewport_size: webrender_api::units::LayoutSize, + ) -> Self { + Self { + pipeline_id, + is_contentful: false, + wr: webrender_api::DisplayListBuilder::new(pipeline_id, viewport_size), + } + } +} + +/// Contentful paint, for the purpose of +/// https://w3c.github.io/paint-timing/#first-contentful-paint +/// (i.e. the display list contains items of type text, +/// image, non-white canvas or SVG). Used by metrics. +pub struct IsContentful(pub bool); + +impl Fragment { + pub(crate) fn build_display_list( + &self, + builder: &mut DisplayListBuilder, + is_contentful: &mut IsContentful, + containing_block: &Rect<Length>, + ) { + match self { + Fragment::Box(b) => b.build_display_list(builder, is_contentful, containing_block), + Fragment::Anonymous(a) => { + let rect = a + .rect + .to_physical(a.mode, containing_block) + .translate(&containing_block.top_left); + for child in &a.children { + child.build_display_list(builder, is_contentful, &rect) + } + }, + Fragment::Text(_) => { + is_contentful.0 = true; + // FIXME + }, + } + } +} + +impl BoxFragment { + fn build_display_list( + &self, + builder: &mut DisplayListBuilder, + is_contentful: &mut IsContentful, + containing_block: &Rect<Length>, + ) { + let background_color = self + .style + .resolve_color(self.style.clone_background_color()); + if background_color.alpha > 0 { + let clip_rect = self + .border_rect() + .to_physical(self.style.writing_mode(), containing_block) + .translate(&containing_block.top_left) + .into(); + let common = CommonItemProperties { + clip_rect, + clip_id: webrender_api::ClipId::root(builder.pipeline_id), + spatial_id: webrender_api::SpatialId::root_scroll_node(builder.pipeline_id), + hit_info: None, + // TODO(gw): Make use of the WR backface visibility functionality. + is_backface_visible: true, + }; + builder.wr.push_rect(&common, rgba(background_color)) + } + let content_rect = self + .content_rect + .to_physical(self.style.writing_mode(), containing_block) + .translate(&containing_block.top_left); + for child in &self.children { + child.build_display_list(builder, is_contentful, &content_rect) + } + } +} + +fn rgba(rgba: cssparser::RGBA) -> webrender_api::ColorF { + webrender_api::ColorF::new( + rgba.red_f32(), + rgba.green_f32(), + rgba.blue_f32(), + rgba.alpha_f32(), + ) +} diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index ba473abc410..54cc1eef07f 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.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::display_list::IsContentful; use crate::dom_traversal::{Contents, NodeExt}; use crate::flow::construct::ContainsFloats; use crate::flow::float::FloatBox; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; -use crate::fragments::{Fragment, IsContentful}; +use crate::fragments::Fragment; use crate::geom; use crate::geom::flow_relative::Vec2; use crate::positioned::AbsolutelyPositionedBox; @@ -20,8 +21,8 @@ use servo_arc::Arc; use style::context::SharedStyleContext; use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto}; +use style::Zero; use style_traits::CSSPixel; -use webrender_api::DisplayListBuilder; pub struct BoxTreeRoot(BlockFormattingContext); pub struct FragmentTreeRoot(Vec<Fragment>); @@ -132,10 +133,25 @@ impl BoxTreeRoot { } impl FragmentTreeRoot { - pub fn build_display_list(&self, builder: &mut DisplayListBuilder) -> IsContentful { + pub fn build_display_list( + &self, + builder: &mut crate::display_list::DisplayListBuilder, + pipeline_id: msg::constellation_msg::PipelineId, + viewport_size: webrender_api::units::LayoutSize, + ) -> IsContentful { + let containing_block = geom::physical::Rect { + top_left: geom::physical::Vec2 { + x: Length::zero(), + y: Length::zero(), + }, + size: geom::physical::Vec2 { + x: Length::new(viewport_size.width), + y: Length::new(viewport_size.height), + }, + }; let mut is_contentful = IsContentful(false); for fragment in &self.0 { - fragment.build_display_list(builder, &mut is_contentful) + fragment.build_display_list(builder, &mut is_contentful, &containing_block) } is_contentful } diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index ad1ebd41359..ceb2fdf7971 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -9,7 +9,6 @@ use servo_arc::Arc; use style::properties::ComputedValues; use style::values::computed::Length; use style::Zero; -use webrender_api::DisplayListBuilder; pub(crate) enum Fragment { Box(BoxFragment), @@ -124,18 +123,3 @@ impl CollapsedMargin { self.max_positive + self.min_negative } } - -/// Contentful paint, for the purpose of -/// https://w3c.github.io/paint-timing/#first-contentful-paint -/// (i.e. the display list contains items of type text, -/// image, non-white canvas or SVG). Used by metrics. -pub struct IsContentful(pub bool); - -impl Fragment { - pub(crate) fn build_display_list( - &self, - builder: &mut DisplayListBuilder, - is_contentful: &mut IsContentful, - ) { - } -} diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index af8d37393b5..a56ee5c7613 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -332,3 +332,12 @@ impl From<physical::Rect<Length>> for Rect<CSSPixel> { } } } + +impl From<physical::Rect<Length>> for webrender_api::units::LayoutRect { + fn from(r: physical::Rect<Length>) -> Self { + Rect { + origin: Point::new(r.top_left.x.px(), r.top_left.y.px()), + size: Size::new(r.size.x.px(), r.size.y.px()), + } + } +} diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index b7578713f5d..5c046feecd7 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -17,6 +17,7 @@ use style::Zero; pub mod context; pub mod data; +pub mod display_list; mod dom_traversal; mod element_data; mod flow; diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index 1c0ee67a268..13cf35975ee 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -35,6 +35,7 @@ use gfx_traits::{node_id_from_scroll_id, Epoch}; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; use layout::context::LayoutContext; +use layout::display_list::DisplayListBuilder; use layout::query::{ process_content_box_request, process_content_boxes_request, LayoutRPCImpl, LayoutThreadData, }; @@ -1271,9 +1272,9 @@ impl LayoutThread { self.viewport_size.width.to_f32_px(), self.viewport_size.height.to_f32_px(), )); - let mut display_list = - webrender_api::DisplayListBuilder::new(self.id.to_webrender(), viewport_size); - let is_contentful = fragment_tree.build_display_list(&mut display_list); + let mut display_list = DisplayListBuilder::new(self.id.to_webrender(), viewport_size); + let is_contentful = + fragment_tree.build_display_list(&mut display_list, self.id, viewport_size); debug!("Layout done!"); @@ -1292,7 +1293,7 @@ impl LayoutThread { webrender_api::Epoch(epoch.0), None, viewport_size, - display_list.finalize(), + display_list.wr.finalize(), true, ); txn.generate_frame(); |