2020: paint background-color

This commit is contained in:
Simon Sapin 2019-10-15 17:52:51 +02:00
parent 4e8eeda976
commit cfc3ffcd54
8 changed files with 143 additions and 24 deletions

1
Cargo.lock generated
View file

@ -2477,6 +2477,7 @@ version = "0.0.1"
dependencies = [ dependencies = [
"app_units", "app_units",
"atomic_refcell", "atomic_refcell",
"cssparser",
"euclid", "euclid",
"gfx", "gfx",
"ipc-channel", "ipc-channel",

View file

@ -15,6 +15,7 @@ doctest = false
[dependencies] [dependencies]
app_units = "0.7" app_units = "0.7"
atomic_refcell = "0.1" atomic_refcell = "0.1"
cssparser = "0.27"
euclid = "0.20" euclid = "0.20"
gfx = {path = "../gfx"} gfx = {path = "../gfx"}
ipc-channel = "0.12" ipc-channel = "0.12"

View file

@ -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(),
)
}

View file

@ -2,11 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * 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::dom_traversal::{Contents, NodeExt};
use crate::flow::construct::ContainsFloats; use crate::flow::construct::ContainsFloats;
use crate::flow::float::FloatBox; use crate::flow::float::FloatBox;
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
use crate::fragments::{Fragment, IsContentful}; use crate::fragments::Fragment;
use crate::geom; use crate::geom;
use crate::geom::flow_relative::Vec2; use crate::geom::flow_relative::Vec2;
use crate::positioned::AbsolutelyPositionedBox; use crate::positioned::AbsolutelyPositionedBox;
@ -20,8 +21,8 @@ use servo_arc::Arc;
use style::context::SharedStyleContext; use style::context::SharedStyleContext;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::{Length, LengthOrAuto}; use style::values::computed::{Length, LengthOrAuto};
use style::Zero;
use style_traits::CSSPixel; use style_traits::CSSPixel;
use webrender_api::DisplayListBuilder;
pub struct BoxTreeRoot(BlockFormattingContext); pub struct BoxTreeRoot(BlockFormattingContext);
pub struct FragmentTreeRoot(Vec<Fragment>); pub struct FragmentTreeRoot(Vec<Fragment>);
@ -132,10 +133,25 @@ impl BoxTreeRoot {
} }
impl FragmentTreeRoot { 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); let mut is_contentful = IsContentful(false);
for fragment in &self.0 { 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 is_contentful
} }

View file

@ -9,7 +9,6 @@ use servo_arc::Arc;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::Length; use style::values::computed::Length;
use style::Zero; use style::Zero;
use webrender_api::DisplayListBuilder;
pub(crate) enum Fragment { pub(crate) enum Fragment {
Box(BoxFragment), Box(BoxFragment),
@ -124,18 +123,3 @@ impl CollapsedMargin {
self.max_positive + self.min_negative 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,
) {
}
}

View file

@ -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()),
}
}
}

View file

@ -17,6 +17,7 @@ use style::Zero;
pub mod context; pub mod context;
pub mod data; pub mod data;
pub mod display_list;
mod dom_traversal; mod dom_traversal;
mod element_data; mod element_data;
mod flow; mod flow;

View file

@ -35,6 +35,7 @@ use gfx_traits::{node_id_from_scroll_id, Epoch};
use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::display_list::DisplayListBuilder;
use layout::query::{ use layout::query::{
process_content_box_request, process_content_boxes_request, LayoutRPCImpl, LayoutThreadData, 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.width.to_f32_px(),
self.viewport_size.height.to_f32_px(), self.viewport_size.height.to_f32_px(),
)); ));
let mut display_list = let mut display_list = DisplayListBuilder::new(self.id.to_webrender(), viewport_size);
webrender_api::DisplayListBuilder::new(self.id.to_webrender(), viewport_size); let is_contentful =
let is_contentful = fragment_tree.build_display_list(&mut display_list); fragment_tree.build_display_list(&mut display_list, self.id, viewport_size);
debug!("Layout done!"); debug!("Layout done!");
@ -1292,7 +1293,7 @@ impl LayoutThread {
webrender_api::Epoch(epoch.0), webrender_api::Epoch(epoch.0),
None, None,
viewport_size, viewport_size,
display_list.finalize(), display_list.wr.finalize(),
true, true,
); );
txn.generate_frame(); txn.generate_frame();