Auto merge of #23896 - nox:layout-2020, r=SimonSapin

Remove most of the things in layout 2020

We keep mostly the query system. There is probably more to delete but
that's a good start I think.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23896)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-08-01 08:08:19 -04:00 committed by GitHub
commit 196c511d5e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 4775 additions and 22 deletions

View file

@ -7,9 +7,28 @@ edition = "2018"
publish = false
[lib]
name = "layout"
path = "lib.rs"
test = false
doctest = false
[dependencies]
app_units = "0.7"
euclid = "0.20"
fnv = "1.0"
gfx = {path = "../gfx"}
gfx_traits = {path = "../gfx_traits"}
ipc-channel = "0.11"
libc = "0.2"
malloc_size_of = { path = "../malloc_size_of" }
msg = {path = "../msg"}
range = {path = "../range"}
rayon = "1"
script_layout_interface = {path = "../script_layout_interface"}
script_traits = {path = "../script_traits"}
serde = "1.0"
servo_arc = {path = "../servo_arc"}
servo_url = {path = "../url"}
style = {path = "../style", features = ["servo", "servo-layout-2020"]}
style_traits = {path = "../style_traits"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}

View file

@ -0,0 +1,18 @@
/* 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 msg::constellation_msg::PipelineId;
use style::context::SharedStyleContext;
pub struct LayoutContext<'a> {
pub id: PipelineId,
pub style_context: SharedStyleContext<'a>,
}
impl<'a> LayoutContext<'a> {
#[inline(always)]
pub fn shared_context(&self) -> &SharedStyleContext {
&self.style_context
}
}

View file

@ -0,0 +1,18 @@
/* 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 script_layout_interface::StyleData;
#[repr(C)]
pub struct StyleAndLayoutData {
pub style_data: StyleData,
}
impl StyleAndLayoutData {
pub fn new() -> Self {
Self {
style_data: StyleData::new(),
}
}
}

View file

@ -0,0 +1,53 @@
/* 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/. */
//! Builds display lists from flows and fragments.
//!
//! Other browser engines sometimes call this "painting", but it is more accurately called display
//! list building, as the actual painting does not happen here—only deciding *what* we're going to
//! paint.
use crate::display_list::items::OpaqueNode;
use app_units::Au;
use euclid::default::Point2D;
use fnv::FnvHashMap;
use gfx::text::glyph::ByteIndex;
use gfx::text::TextRun;
use range::Range;
use std::sync::Arc;
pub struct IndexableTextItem {
/// The placement of the text item on the plane.
pub origin: Point2D<Au>,
/// The text run.
pub text_run: Arc<TextRun>,
/// The range of text within the text run.
pub range: Range<ByteIndex>,
/// The position of the start of the baseline of this text.
pub baseline_origin: Point2D<Au>,
}
#[derive(Default)]
pub struct IndexableText {
inner: FnvHashMap<OpaqueNode, Vec<IndexableTextItem>>,
}
impl IndexableText {
pub fn get(&self, node: OpaqueNode) -> Option<&[IndexableTextItem]> {
self.inner.get(&node).map(|x| x.as_slice())
}
// Returns the text index within a node for the point of interest.
pub fn text_index(&self, node: OpaqueNode, point_in_item: Point2D<Au>) -> Option<usize> {
let item = self.inner.get(&node)?;
// TODO(#20020): access all elements
let point = point_in_item + item[0].origin.to_vector();
let offset = point - item[0].baseline_origin;
Some(
item[0]
.text_run
.range_index_of_advance(&item[0].range, offset.x),
)
}
}

View file

@ -0,0 +1,24 @@
/* 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 euclid::Vector2D;
use gfx_traits;
use std::collections::HashMap;
use std::f32;
use webrender_api::units::LayoutPixel;
use webrender_api::ExternalScrollId;
pub use style::dom::OpaqueNode;
#[derive(Serialize)]
pub struct DisplayList {}
impl gfx_traits::DisplayList for DisplayList {
fn is_contentful(&self) -> bool {
false
}
}
/// The type of the scroll offset list. This is only populated if WebRender is in use.
pub type ScrollOffsetMap = HashMap<ExternalScrollId, Vector2D<f32, LayoutPixel>>;

View file

@ -0,0 +1,10 @@
/* 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/. */
pub use self::builder::IndexableText;
pub use self::webrender_helpers::WebRenderDisplayListConverter;
mod builder;
pub mod items;
mod webrender_helpers;

View file

@ -0,0 +1,26 @@
/* 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::display_list::items::DisplayList;
use msg::constellation_msg::PipelineId;
use webrender_api::units::LayoutSize;
use webrender_api::{self, DisplayListBuilder};
pub trait WebRenderDisplayListConverter {
fn convert_to_webrender(&mut self, pipeline_id: PipelineId) -> DisplayListBuilder;
}
impl WebRenderDisplayListConverter for DisplayList {
fn convert_to_webrender(&mut self, pipeline_id: PipelineId) -> DisplayListBuilder {
let webrender_pipeline = pipeline_id.to_webrender();
let builder = DisplayListBuilder::with_capacity(
webrender_pipeline,
LayoutSize::zero(),
1024 * 1024, // 1 MB of space
);
builder
}
}

View file

@ -0,0 +1,38 @@
/* 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 std::fmt;
use style::selector_parser::RestyleDamage;
#[allow(unsafe_code)]
pub unsafe trait HasBaseFlow {}
pub trait GetBaseFlow {
fn base(&self) -> &BaseFlow;
fn mut_base(&mut self) -> &mut BaseFlow;
}
impl<T: HasBaseFlow + ?Sized> GetBaseFlow for T {
#[inline(always)]
#[allow(unsafe_code)]
fn base(&self) -> &BaseFlow {
let ptr: *const Self = self;
let ptr = ptr as *const BaseFlow;
unsafe { &*ptr }
}
#[inline(always)]
#[allow(unsafe_code)]
fn mut_base(&mut self) -> &mut BaseFlow {
let ptr: *mut Self = self;
let ptr = ptr as *mut BaseFlow;
unsafe { &mut *ptr }
}
}
pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {}
pub struct BaseFlow {
pub restyle_damage: RestyleDamage,
}

View file

@ -0,0 +1,30 @@
/* 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::flow::Flow;
use std::ops::Deref;
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct FlowRef(Arc<dyn Flow>);
impl Deref for FlowRef {
type Target = dyn Flow;
fn deref(&self) -> &dyn Flow {
self.0.deref()
}
}
impl FlowRef {
pub fn new(mut r: Arc<dyn Flow>) -> Self {
assert!(Arc::get_mut(&mut r).is_some());
FlowRef(r)
}
#[allow(unsafe_code)]
pub fn deref_mut(this: &mut FlowRef) -> &mut dyn Flow {
let ptr: *const dyn Flow = &*this.0;
unsafe { &mut *(ptr as *mut dyn Flow) }
}
}

View file

@ -0,0 +1,110 @@
/* 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/. */
//! The `Fragment` type, which represents the leaves of the layout tree.
use crate::context::LayoutContext;
use crate::display_list::items::OpaqueNode;
use crate::ServoArc;
use app_units::Au;
use euclid::default::Rect;
use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutNode};
use serde::ser::{Serialize, SerializeStruct, Serializer};
use style::logical_geometry::{LogicalMargin, LogicalRect};
use style::properties::ComputedValues;
use style::selector_parser::RestyleDamage;
use style::servo::restyle_damage::ServoRestyleDamage;
#[derive(Clone)]
pub struct Fragment {
pub node: OpaqueNode,
pub style: ServoArc<ComputedValues>,
pub border_box: LogicalRect<Au>,
pub border_padding: LogicalMargin<Au>,
pub margin: LogicalMargin<Au>,
pub specific: SpecificFragmentInfo,
pub restyle_damage: RestyleDamage,
pub pseudo: PseudoElementType,
}
impl Serialize for Fragment {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut serializer = serializer.serialize_struct("fragment", 3)?;
serializer.serialize_field("border_box", &self.border_box)?;
serializer.serialize_field("margin", &self.margin)?;
serializer.end()
}
}
#[derive(Clone)]
pub enum SpecificFragmentInfo {
Generic,
}
impl SpecificFragmentInfo {
fn restyle_damage(&self) -> RestyleDamage {
RestyleDamage::empty()
}
}
impl Fragment {
/// Constructs a new `Fragment` instance.
pub fn new<N: ThreadSafeLayoutNode>(
node: &N,
specific: SpecificFragmentInfo,
ctx: &LayoutContext,
) -> Fragment {
let shared_context = ctx.shared_context();
let style = node.style(shared_context);
let writing_mode = style.writing_mode;
let mut restyle_damage = RestyleDamage::rebuild_and_reflow();
restyle_damage.remove(ServoRestyleDamage::RECONSTRUCT_FLOW);
Fragment {
node: node.opaque(),
style: style,
restyle_damage: restyle_damage,
border_box: LogicalRect::zero(writing_mode),
border_padding: LogicalMargin::zero(writing_mode),
margin: LogicalMargin::zero(writing_mode),
specific: specific,
pseudo: node.get_pseudo_element_type(),
}
}
pub fn restyle_damage(&self) -> RestyleDamage {
self.restyle_damage | self.specific.restyle_damage()
}
pub fn contains_node(&self, node_address: OpaqueNode) -> bool {
node_address == self.node
}
/// Returns the sum of the inline-sizes of all the borders of this fragment. Note that this
/// can be expensive to compute, so if possible use the `border_padding` field instead.
#[inline]
pub fn border_width(&self) -> LogicalMargin<Au> {
self.style().logical_border_width()
}
#[inline(always)]
pub fn style(&self) -> &ComputedValues {
&*self.style
}
pub fn is_primary_fragment(&self) -> bool {
true
}
}
/// A top-down fragment border box iteration handler.
pub trait FragmentBorderBoxIterator {
/// The operation to perform.
fn process(&mut self, fragment: &Fragment, level: i32, overflow: &Rect<Au>);
/// Returns true if this fragment must be processed in-order. If this returns false,
/// we skip the operation for this fragment, but continue processing siblings.
fn should_process(&mut self, fragment: &Fragment) -> bool;
}

View file

@ -1,3 +1,26 @@
/* 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/. */
#![deny(unsafe_code)]
#[macro_use]
extern crate serde;
pub mod context;
pub mod data;
pub mod display_list;
pub mod flow;
pub mod flow_ref;
mod fragment;
pub mod opaque_node;
pub mod query;
pub mod traversal;
pub mod wrapper;
// For unit tests:
pub use crate::fragment::Fragment;
// We can't use servo_arc for everything in layout, because the Flow stuff uses
// weak references.
use servo_arc::Arc as ServoArc;

View file

@ -0,0 +1,17 @@
/* 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::display_list::items::OpaqueNode;
use libc::c_void;
use script_traits::UntrustedNodeAddress;
pub trait OpaqueNodeMethods {
fn to_untrusted_node_address(&self) -> UntrustedNodeAddress;
}
impl OpaqueNodeMethods for OpaqueNode {
fn to_untrusted_node_address(&self) -> UntrustedNodeAddress {
UntrustedNodeAddress(self.0 as *const c_void)
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,68 @@
/* 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::context::LayoutContext;
use crate::wrapper::GetRawData;
use script_layout_interface::wrapper_traits::LayoutNode;
use style::context::{SharedStyleContext, StyleContext};
use style::data::ElementData;
use style::dom::{NodeInfo, TElement, TNode};
use style::traversal::PerLevelTraversalData;
use style::traversal::{recalc_style_at, DomTraversal};
pub struct RecalcStyleAndConstructFlows<'a> {
context: LayoutContext<'a>,
}
impl<'a> RecalcStyleAndConstructFlows<'a> {
pub fn new(context: LayoutContext<'a>) -> Self {
RecalcStyleAndConstructFlows { context: context }
}
pub fn destroy(self) -> LayoutContext<'a> {
self.context
}
}
#[allow(unsafe_code)]
impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a>
where
E: TElement,
E::ConcreteNode: LayoutNode,
E::FontMetricsProvider: Send,
{
fn process_preorder<F>(
&self,
traversal_data: &PerLevelTraversalData,
context: &mut StyleContext<E>,
node: E::ConcreteNode,
note_child: F,
) where
F: FnMut(E::ConcreteNode),
{
unsafe { node.initialize_data() };
if !node.is_text_node() {
let el = node.as_element().unwrap();
let mut data = el.mutate_data().unwrap();
recalc_style_at(self, traversal_data, context, el, &mut data, note_child);
}
}
fn process_postorder(&self, _style_context: &mut StyleContext<E>, node: E::ConcreteNode) {
if let Some(el) = node.as_element() {
unsafe {
el.unset_dirty_descendants();
}
}
}
fn text_node_needs_traversal(node: E::ConcreteNode, parent_data: &ElementData) -> bool {
node.get_raw_data().is_none() || !parent_data.damage.is_empty()
}
fn shared_context(&self) -> &SharedStyleContext {
&self.context.style_context
}
}

View file

@ -0,0 +1,21 @@
/* 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/. */
#![allow(unsafe_code)]
use crate::data::StyleAndLayoutData;
use script_layout_interface::wrapper_traits::GetLayoutData;
pub trait GetRawData {
fn get_raw_data(&self) -> Option<&StyleAndLayoutData>;
}
impl<T: GetLayoutData> GetRawData for T {
fn get_raw_data(&self) -> Option<&StyleAndLayoutData> {
self.get_style_and_layout_data().map(|opaque| {
let container = opaque.ptr.as_ptr() as *mut StyleAndLayoutData;
unsafe { &*container }
})
}
}

View file

@ -11,18 +11,43 @@ name = "layout_thread"
path = "lib.rs"
[dependencies]
app_units = "0.7"
atomic_refcell = "0.1"
crossbeam-channel = "0.3"
embedder_traits = {path = "../embedder_traits"}
euclid = "0.20"
fnv = "1.0"
fxhash = "0.2"
gfx = {path = "../gfx"}
gfx_traits = {path = "../gfx_traits"}
histogram = "0.6.8"
html5ever = "0.23"
ipc-channel = "0.11"
layout = {path = "../layout_2020", package = "layout_2020"}
layout_traits = {path = "../layout_traits"}
lazy_static = "1"
libc = "0.2"
log = "0.4"
time = "0.1.17"
malloc_size_of = { path = "../malloc_size_of" }
metrics = {path = "../metrics"}
msg = {path = "../msg"}
net_traits = {path = "../net_traits"}
parking_lot = {version = "0.8", features = ["nightly"]}
profile_traits = {path = "../profile_traits"}
range = {path = "../range"}
rayon = "1"
script = {path = "../script"}
script_layout_interface = {path = "../script_layout_interface"}
script_traits = {path = "../script_traits"}
servo_url = {path = "../url"}
selectors = { path = "../selectors" }
serde_json = "1.0"
servo_allocator = {path = "../allocator"}
servo_arc = {path = "../servo_arc"}
servo_atoms = {path = "../atoms"}
servo_config = {path = "../config"}
servo_geometry = {path = "../geometry"}
servo_url = {path = "../url"}
style = {path = "../style"}
style_traits = {path = "../style_traits"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -196,7 +196,7 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-text/#propdef-white-space"
servo_restyle_damage="rebuild_and_reflow"
>
% if engine == "servo-2013":
% if engine in ["servo-2013", "servo-2020"]:
impl SpecifiedValue {
pub fn allow_wrap(&self) -> bool {
match *self {