aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2019-10-15 17:52:51 +0200
committerSimon Sapin <simon.sapin@exyr.org>2019-10-24 10:44:31 +0200
commitcfc3ffcd545a18806674cf3bb1e3ddcffff3d89e (patch)
tree139b37dc348c1a4c4231210611164d9039929e22
parent4e8eeda976f1475b11b1630854a01046d51e3c44 (diff)
downloadservo-cfc3ffcd545a18806674cf3bb1e3ddcffff3d89e.tar.gz
servo-cfc3ffcd545a18806674cf3bb1e3ddcffff3d89e.zip
2020: paint background-color
-rw-r--r--Cargo.lock1
-rw-r--r--components/layout_2020/Cargo.toml1
-rw-r--r--components/layout_2020/display_list.rs106
-rw-r--r--components/layout_2020/flow/root.rs24
-rw-r--r--components/layout_2020/fragments.rs16
-rw-r--r--components/layout_2020/geom.rs9
-rw-r--r--components/layout_2020/lib.rs1
-rw-r--r--components/layout_thread_2020/lib.rs9
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();