mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Combine DOM-related concepts in Layout 2020 into dom.rs
This commit is contained in:
parent
ab4bd2a133
commit
72b5fcd0b6
24 changed files with 257 additions and 344 deletions
|
@ -5,7 +5,6 @@
|
||||||
//! Data needed by the layout thread.
|
//! Data needed by the layout thread.
|
||||||
|
|
||||||
use crate::display_list::items::{OpaqueNode, WebRenderImageInfo};
|
use crate::display_list::items::{OpaqueNode, WebRenderImageInfo};
|
||||||
use crate::opaque_node::OpaqueNodeMethods;
|
|
||||||
use fnv::FnvHasher;
|
use fnv::FnvHasher;
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use gfx::font_context::FontContext;
|
use gfx::font_context::FontContext;
|
||||||
|
@ -121,7 +120,7 @@ impl<'a> LayoutContext<'a> {
|
||||||
ImageCacheResult::Pending(id) => {
|
ImageCacheResult::Pending(id) => {
|
||||||
let image = PendingImage {
|
let image = PendingImage {
|
||||||
state: PendingImageState::PendingResponse,
|
state: PendingImageState::PendingResponse,
|
||||||
node: node.to_untrusted_node_address(),
|
node: node.into(),
|
||||||
id,
|
id,
|
||||||
origin: self.origin.clone(),
|
origin: self.origin.clone(),
|
||||||
};
|
};
|
||||||
|
@ -132,7 +131,7 @@ impl<'a> LayoutContext<'a> {
|
||||||
ImageCacheResult::ReadyForRequest(id) => {
|
ImageCacheResult::ReadyForRequest(id) => {
|
||||||
let image = PendingImage {
|
let image = PendingImage {
|
||||||
state: PendingImageState::Unrequested(url),
|
state: PendingImageState::Unrequested(url),
|
||||||
node: node.to_untrusted_node_address(),
|
node: node.into(),
|
||||||
id,
|
id,
|
||||||
origin: self.origin.clone(),
|
origin: self.origin.clone(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,7 +38,6 @@ mod linked_list;
|
||||||
mod list_item;
|
mod list_item;
|
||||||
mod model;
|
mod model;
|
||||||
mod multicol;
|
mod multicol;
|
||||||
pub mod opaque_node;
|
|
||||||
pub mod parallel;
|
pub mod parallel;
|
||||||
mod persistent_list;
|
mod persistent_list;
|
||||||
pub mod query;
|
pub mod query;
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
/* 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 {
|
|
||||||
/// Converts this node to an `UntrustedNodeAddress`. An `UntrustedNodeAddress` is just the type
|
|
||||||
/// of node that script expects to receive in a hit test.
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,7 +11,6 @@ use crate::display_list::IndexableText;
|
||||||
use crate::flow::{Flow, GetBaseFlow};
|
use crate::flow::{Flow, GetBaseFlow};
|
||||||
use crate::fragment::{Fragment, FragmentBorderBoxIterator, FragmentFlags, SpecificFragmentInfo};
|
use crate::fragment::{Fragment, FragmentBorderBoxIterator, FragmentFlags, SpecificFragmentInfo};
|
||||||
use crate::inline::InlineFragmentNodeFlags;
|
use crate::inline::InlineFragmentNodeFlags;
|
||||||
use crate::opaque_node::OpaqueNodeMethods;
|
|
||||||
use crate::sequential;
|
use crate::sequential;
|
||||||
use crate::wrapper::LayoutNodeLayoutData;
|
use crate::wrapper::LayoutNodeLayoutData;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
@ -1099,7 +1098,7 @@ pub fn process_offset_parent_query(
|
||||||
let origin = node_offset_box.offset - parent_info.origin.to_vector();
|
let origin = node_offset_box.offset - parent_info.origin.to_vector();
|
||||||
let size = node_offset_box.rectangle.size;
|
let size = node_offset_box.rectangle.size;
|
||||||
OffsetParentResponse {
|
OffsetParentResponse {
|
||||||
node_address: Some(parent_info.node_address.to_untrusted_node_address()),
|
node_address: Some(parent_info.node_address.into()),
|
||||||
rect: Rect::new(origin, size),
|
rect: Rect::new(origin, size),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
* 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::WebRenderImageInfo;
|
use crate::display_list::WebRenderImageInfo;
|
||||||
use crate::opaque_node::OpaqueNodeMethods;
|
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use gfx::font_context::FontContext;
|
use gfx::font_context::FontContext;
|
||||||
|
@ -75,7 +74,7 @@ impl<'a> LayoutContext<'a> {
|
||||||
ImageCacheResult::Pending(id) => {
|
ImageCacheResult::Pending(id) => {
|
||||||
let image = PendingImage {
|
let image = PendingImage {
|
||||||
state: PendingImageState::PendingResponse,
|
state: PendingImageState::PendingResponse,
|
||||||
node: node.to_untrusted_node_address(),
|
node: node.into(),
|
||||||
id,
|
id,
|
||||||
origin: self.origin.clone(),
|
origin: self.origin.clone(),
|
||||||
};
|
};
|
||||||
|
@ -86,7 +85,7 @@ impl<'a> LayoutContext<'a> {
|
||||||
ImageCacheResult::ReadyForRequest(id) => {
|
ImageCacheResult::ReadyForRequest(id) => {
|
||||||
let image = PendingImage {
|
let image = PendingImage {
|
||||||
state: PendingImageState::Unrequested(url),
|
state: PendingImageState::Unrequested(url),
|
||||||
node: node.to_untrusted_node_address(),
|
node: node.into(),
|
||||||
id,
|
id,
|
||||||
origin: self.origin.clone(),
|
origin: self.origin.clone(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
/* 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::element_data::LayoutDataForElement;
|
|
||||||
use atomic_refcell::AtomicRefCell;
|
|
||||||
use script_layout_interface::StyleData;
|
|
||||||
|
|
||||||
pub struct StyleAndLayoutData<'dom> {
|
|
||||||
pub style_data: &'dom StyleData,
|
|
||||||
pub(super) layout_data: &'dom AtomicRefCell<LayoutDataForElement>,
|
|
||||||
}
|
|
203
components/layout_2020/dom.rs
Normal file
203
components/layout_2020/dom.rs
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
/* 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::cell::ArcRefCell;
|
||||||
|
use crate::context::LayoutContext;
|
||||||
|
use crate::dom_traversal::WhichPseudoElement;
|
||||||
|
use crate::flexbox::FlexLevelBox;
|
||||||
|
use crate::flow::inline::InlineLevelBox;
|
||||||
|
use crate::flow::BlockLevelBox;
|
||||||
|
use crate::geom::PhysicalSize;
|
||||||
|
use crate::replaced::{CanvasInfo, CanvasSource};
|
||||||
|
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
|
||||||
|
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||||
|
use net_traits::image::base::Image as NetImage;
|
||||||
|
use script_layout_interface::wrapper_traits::{LayoutDataTrait, LayoutNode, ThreadSafeLayoutNode};
|
||||||
|
use script_layout_interface::{HTMLCanvasDataSource, StyleData};
|
||||||
|
use servo_arc::Arc as ServoArc;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use style::properties::ComputedValues;
|
||||||
|
|
||||||
|
/// The data that is stored in each DOM node that is used by layout.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DOMLayoutData {
|
||||||
|
pub(super) self_box: ArcRefCell<Option<LayoutBox>>,
|
||||||
|
pub(super) pseudo_before_box: ArcRefCell<Option<LayoutBox>>,
|
||||||
|
pub(super) pseudo_after_box: ArcRefCell<Option<LayoutBox>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A box that is stored in one of the `DOMLayoutData` slots.
|
||||||
|
pub(super) enum LayoutBox {
|
||||||
|
DisplayContents,
|
||||||
|
BlockLevel(ArcRefCell<BlockLevelBox>),
|
||||||
|
InlineLevel(ArcRefCell<InlineLevelBox>),
|
||||||
|
FlexLevel(ArcRefCell<FlexLevelBox>),
|
||||||
|
}
|
||||||
|
|
||||||
|
// The implementation of this trait allows the data to be stored in the DOM.
|
||||||
|
impl LayoutDataTrait for DOMLayoutData {}
|
||||||
|
|
||||||
|
pub struct StyleAndLayoutData<'dom> {
|
||||||
|
pub style_data: &'dom StyleData,
|
||||||
|
pub(super) layout_data: &'dom AtomicRefCell<DOMLayoutData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BoxSlot<'dom> {
|
||||||
|
pub(crate) slot: Option<ArcRefCell<Option<LayoutBox>>>,
|
||||||
|
pub(crate) marker: PhantomData<&'dom ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A mutable reference to a `LayoutBox` stored in a DOM element.
|
||||||
|
impl BoxSlot<'_> {
|
||||||
|
pub(crate) fn new(slot: ArcRefCell<Option<LayoutBox>>) -> Self {
|
||||||
|
*slot.borrow_mut() = None;
|
||||||
|
let slot = Some(slot);
|
||||||
|
Self {
|
||||||
|
slot,
|
||||||
|
marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn dummy() -> Self {
|
||||||
|
let slot = None;
|
||||||
|
Self {
|
||||||
|
slot,
|
||||||
|
marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set(mut self, box_: LayoutBox) {
|
||||||
|
if let Some(slot) = &mut self.slot {
|
||||||
|
*slot.borrow_mut() = Some(box_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for BoxSlot<'_> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if !std::thread::panicking() {
|
||||||
|
if let Some(slot) = &mut self.slot {
|
||||||
|
assert!(slot.borrow().is_some(), "failed to set a layout box");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait NodeExt<'dom>: 'dom + LayoutNode<'dom> {
|
||||||
|
/// Returns the image if it’s loaded, and its size in image pixels
|
||||||
|
/// adjusted for `image_density`.
|
||||||
|
fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)>;
|
||||||
|
fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)>;
|
||||||
|
fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)>;
|
||||||
|
fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues>;
|
||||||
|
|
||||||
|
fn get_style_and_layout_data(self) -> Option<StyleAndLayoutData<'dom>>;
|
||||||
|
fn layout_data_mut(self) -> AtomicRefMut<'dom, DOMLayoutData>;
|
||||||
|
fn element_box_slot(&self) -> BoxSlot<'dom>;
|
||||||
|
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>;
|
||||||
|
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
||||||
|
|
||||||
|
/// Remove boxes for the element itself, and its `:before` and `:after` if any.
|
||||||
|
fn unset_all_boxes(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'dom, LayoutNodeType> NodeExt<'dom> for LayoutNodeType
|
||||||
|
where
|
||||||
|
LayoutNodeType: 'dom + LayoutNode<'dom>,
|
||||||
|
{
|
||||||
|
fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)> {
|
||||||
|
let node = self.to_threadsafe();
|
||||||
|
let (resource, metadata) = node.image_data()?;
|
||||||
|
let (width, height) = resource
|
||||||
|
.as_ref()
|
||||||
|
.map(|image| (image.width, image.height))
|
||||||
|
.or_else(|| metadata.map(|metadata| (metadata.width, metadata.height)))
|
||||||
|
.unwrap_or((0, 0));
|
||||||
|
let (mut width, mut height) = (width as f64, height as f64);
|
||||||
|
if let Some(density) = node.image_density().filter(|density| *density != 1.) {
|
||||||
|
width = width / density;
|
||||||
|
height = height / density;
|
||||||
|
}
|
||||||
|
Some((resource, PhysicalSize::new(width, height)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)> {
|
||||||
|
let node = self.to_threadsafe();
|
||||||
|
let canvas_data = node.canvas_data()?;
|
||||||
|
let source = match canvas_data.source {
|
||||||
|
HTMLCanvasDataSource::WebGL(texture_id) => CanvasSource::WebGL(texture_id),
|
||||||
|
HTMLCanvasDataSource::Image(ipc_sender) => {
|
||||||
|
CanvasSource::Image(ipc_sender.map(|renderer| Arc::new(Mutex::new(renderer))))
|
||||||
|
},
|
||||||
|
HTMLCanvasDataSource::WebGPU(image_key) => CanvasSource::WebGPU(image_key),
|
||||||
|
};
|
||||||
|
Some((
|
||||||
|
CanvasInfo {
|
||||||
|
source,
|
||||||
|
canvas_id: canvas_data.canvas_id,
|
||||||
|
},
|
||||||
|
PhysicalSize::new(canvas_data.width.into(), canvas_data.height.into()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)> {
|
||||||
|
let node = self.to_threadsafe();
|
||||||
|
match (node.iframe_pipeline_id(), node.iframe_browsing_context_id()) {
|
||||||
|
(Some(pipeline_id), Some(browsing_context_id)) => {
|
||||||
|
Some((pipeline_id, browsing_context_id))
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues> {
|
||||||
|
self.to_threadsafe().style(context.shared_context())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout_data_mut(self) -> AtomicRefMut<'dom, DOMLayoutData> {
|
||||||
|
self.get_style_and_layout_data()
|
||||||
|
.map(|d| d.layout_data.borrow_mut())
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn element_box_slot(&self) -> BoxSlot<'dom> {
|
||||||
|
BoxSlot::new(self.layout_data_mut().self_box.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom> {
|
||||||
|
let data = self.layout_data_mut();
|
||||||
|
let cell = match which {
|
||||||
|
WhichPseudoElement::Before => &data.pseudo_before_box,
|
||||||
|
WhichPseudoElement::After => &data.pseudo_after_box,
|
||||||
|
};
|
||||||
|
BoxSlot::new(cell.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unset_pseudo_element_box(self, which: WhichPseudoElement) {
|
||||||
|
let data = self.layout_data_mut();
|
||||||
|
let cell = match which {
|
||||||
|
WhichPseudoElement::Before => &data.pseudo_before_box,
|
||||||
|
WhichPseudoElement::After => &data.pseudo_after_box,
|
||||||
|
};
|
||||||
|
*cell.borrow_mut() = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unset_all_boxes(self) {
|
||||||
|
let data = self.layout_data_mut();
|
||||||
|
*data.self_box.borrow_mut() = None;
|
||||||
|
*data.pseudo_before_box.borrow_mut() = None;
|
||||||
|
*data.pseudo_after_box.borrow_mut() = None;
|
||||||
|
// Stylo already takes care of removing all layout data
|
||||||
|
// for DOM descendants of elements with `display: none`.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_style_and_layout_data(self) -> Option<StyleAndLayoutData<'dom>> {
|
||||||
|
self.get_style_and_opaque_layout_data()
|
||||||
|
.map(|data| StyleAndLayoutData {
|
||||||
|
style_data: &data.style_data,
|
||||||
|
layout_data: data.generic_data.downcast_ref().unwrap(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,27 +2,15 @@
|
||||||
* 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::cell::ArcRefCell;
|
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::element_data::{LayoutBox, LayoutDataForElement};
|
use crate::dom::{BoxSlot, LayoutBox, NodeExt};
|
||||||
use crate::fragment_tree::{BaseFragmentInfo, FragmentFlags, Tag};
|
use crate::fragment_tree::{BaseFragmentInfo, FragmentFlags, Tag};
|
||||||
use crate::geom::PhysicalSize;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::replaced::{CanvasInfo, CanvasSource, ReplacedContent};
|
|
||||||
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside};
|
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside};
|
||||||
use crate::wrapper::GetStyleAndLayoutData;
|
|
||||||
use atomic_refcell::AtomicRefMut;
|
|
||||||
use html5ever::LocalName;
|
use html5ever::LocalName;
|
||||||
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
||||||
use net_traits::image::base::Image as NetImage;
|
|
||||||
use script_layout_interface::wrapper_traits::{
|
|
||||||
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
|
||||||
};
|
|
||||||
use script_layout_interface::HTMLCanvasDataSource;
|
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::marker::PhantomData as marker;
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use style::dom::{OpaqueNode, TNode};
|
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::selector_parser::PseudoElement;
|
use style::selector_parser::PseudoElement;
|
||||||
use style::values::generics::counters::Content;
|
use style::values::generics::counters::Content;
|
||||||
|
@ -149,9 +137,9 @@ fn traverse_children_of<'dom, Node>(
|
||||||
traverse_pseudo_element(WhichPseudoElement::Before, parent_element, context, handler);
|
traverse_pseudo_element(WhichPseudoElement::Before, parent_element, context, handler);
|
||||||
|
|
||||||
for child in iter_child_nodes(parent_element) {
|
for child in iter_child_nodes(parent_element) {
|
||||||
if let Some(contents) = child.as_text() {
|
if child.is_text_node() {
|
||||||
let info = NodeAndStyleInfo::new(child, child.style(context));
|
let info = NodeAndStyleInfo::new(child, child.style(context));
|
||||||
handler.handle_text(&info, contents);
|
handler.handle_text(&info, child.to_threadsafe().node_text_content());
|
||||||
} else if child.is_element() {
|
} else if child.is_element() {
|
||||||
traverse_element(child, context, handler);
|
traverse_element(child, context, handler);
|
||||||
}
|
}
|
||||||
|
@ -381,184 +369,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BoxSlot<'dom> {
|
|
||||||
slot: Option<ArcRefCell<Option<LayoutBox>>>,
|
|
||||||
marker: marker<&'dom ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BoxSlot<'_> {
|
|
||||||
pub(crate) fn new(slot: ArcRefCell<Option<LayoutBox>>) -> Self {
|
|
||||||
*slot.borrow_mut() = None;
|
|
||||||
let slot = Some(slot);
|
|
||||||
Self { slot, marker }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn dummy() -> Self {
|
|
||||||
let slot = None;
|
|
||||||
Self { slot, marker }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn set(mut self, box_: LayoutBox) {
|
|
||||||
if let Some(slot) = &mut self.slot {
|
|
||||||
*slot.borrow_mut() = Some(box_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for BoxSlot<'_> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if !std::thread::panicking() {
|
|
||||||
if let Some(slot) = &mut self.slot {
|
|
||||||
assert!(slot.borrow().is_some(), "failed to set a layout box");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode<'dom> + Send + Sync {
|
|
||||||
fn is_element(self) -> bool;
|
|
||||||
fn as_text(self) -> Option<Cow<'dom, str>>;
|
|
||||||
|
|
||||||
/// Returns the image if it’s loaded, and its size in image pixels
|
|
||||||
/// adjusted for `image_density`.
|
|
||||||
fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)>;
|
|
||||||
fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)>;
|
|
||||||
fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)>;
|
|
||||||
fn first_child(self) -> Option<Self>;
|
|
||||||
fn next_sibling(self) -> Option<Self>;
|
|
||||||
fn parent_node(self) -> Option<Self>;
|
|
||||||
fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues>;
|
|
||||||
|
|
||||||
fn as_opaque(self) -> OpaqueNode;
|
|
||||||
fn layout_data_mut(self) -> AtomicRefMut<'dom, LayoutDataForElement>;
|
|
||||||
fn element_box_slot(&self) -> BoxSlot<'dom>;
|
|
||||||
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>;
|
|
||||||
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
|
||||||
|
|
||||||
/// Remove boxes for the element itself, and its `:before` and `:after` if any.
|
|
||||||
fn unset_all_boxes(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'dom, T> NodeExt<'dom> for T
|
|
||||||
where
|
|
||||||
T: 'dom + Copy + LayoutNode<'dom> + Send + Sync,
|
|
||||||
{
|
|
||||||
fn is_element(self) -> bool {
|
|
||||||
self.to_threadsafe().as_element().is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_text(self) -> Option<Cow<'dom, str>> {
|
|
||||||
if self.is_text_node() {
|
|
||||||
Some(self.to_threadsafe().node_text_content())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)> {
|
|
||||||
let node = self.to_threadsafe();
|
|
||||||
let (resource, metadata) = node.image_data()?;
|
|
||||||
let (width, height) = resource
|
|
||||||
.as_ref()
|
|
||||||
.map(|image| (image.width, image.height))
|
|
||||||
.or_else(|| metadata.map(|metadata| (metadata.width, metadata.height)))
|
|
||||||
.unwrap_or((0, 0));
|
|
||||||
let (mut width, mut height) = (width as f64, height as f64);
|
|
||||||
if let Some(density) = node.image_density().filter(|density| *density != 1.) {
|
|
||||||
width = width / density;
|
|
||||||
height = height / density;
|
|
||||||
}
|
|
||||||
Some((resource, PhysicalSize::new(width, height)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)> {
|
|
||||||
let node = self.to_threadsafe();
|
|
||||||
let canvas_data = node.canvas_data()?;
|
|
||||||
let source = match canvas_data.source {
|
|
||||||
HTMLCanvasDataSource::WebGL(texture_id) => CanvasSource::WebGL(texture_id),
|
|
||||||
HTMLCanvasDataSource::Image(ipc_sender) => {
|
|
||||||
CanvasSource::Image(ipc_sender.map(|renderer| Arc::new(Mutex::new(renderer))))
|
|
||||||
},
|
|
||||||
HTMLCanvasDataSource::WebGPU(image_key) => CanvasSource::WebGPU(image_key),
|
|
||||||
};
|
|
||||||
Some((
|
|
||||||
CanvasInfo {
|
|
||||||
source,
|
|
||||||
canvas_id: canvas_data.canvas_id,
|
|
||||||
},
|
|
||||||
PhysicalSize::new(canvas_data.width.into(), canvas_data.height.into()),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)> {
|
|
||||||
let node = self.to_threadsafe();
|
|
||||||
match (node.iframe_pipeline_id(), node.iframe_browsing_context_id()) {
|
|
||||||
(Some(pipeline_id), Some(browsing_context_id)) => {
|
|
||||||
Some((pipeline_id, browsing_context_id))
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn first_child(self) -> Option<Self> {
|
|
||||||
TNode::first_child(&self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_sibling(self) -> Option<Self> {
|
|
||||||
TNode::next_sibling(&self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parent_node(self) -> Option<Self> {
|
|
||||||
TNode::parent_node(&self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues> {
|
|
||||||
self.to_threadsafe().style(context.shared_context())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_opaque(self) -> OpaqueNode {
|
|
||||||
self.opaque()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn layout_data_mut(self) -> AtomicRefMut<'dom, LayoutDataForElement> {
|
|
||||||
self.get_style_and_layout_data()
|
|
||||||
.map(|d| d.layout_data.borrow_mut())
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn element_box_slot(&self) -> BoxSlot<'dom> {
|
|
||||||
BoxSlot::new(self.layout_data_mut().self_box.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom> {
|
|
||||||
let data = self.layout_data_mut();
|
|
||||||
let cell = match which {
|
|
||||||
WhichPseudoElement::Before => &data.pseudo_before_box,
|
|
||||||
WhichPseudoElement::After => &data.pseudo_after_box,
|
|
||||||
};
|
|
||||||
BoxSlot::new(cell.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unset_pseudo_element_box(self, which: WhichPseudoElement) {
|
|
||||||
let data = self.layout_data_mut();
|
|
||||||
let cell = match which {
|
|
||||||
WhichPseudoElement::Before => &data.pseudo_before_box,
|
|
||||||
WhichPseudoElement::After => &data.pseudo_after_box,
|
|
||||||
};
|
|
||||||
*cell.borrow_mut() = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unset_all_boxes(self) {
|
|
||||||
let data = self.layout_data_mut();
|
|
||||||
*data.self_box.borrow_mut() = None;
|
|
||||||
*data.pseudo_before_box.borrow_mut() = None;
|
|
||||||
*data.pseudo_after_box.borrow_mut() = None;
|
|
||||||
// Stylo already takes care of removing all layout data
|
|
||||||
// for DOM descendants of elements with `display: none`.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn iter_child_nodes<'dom, Node>(parent: Node) -> impl Iterator<Item = Node>
|
pub(crate) fn iter_child_nodes<'dom, Node>(parent: Node) -> impl Iterator<Item = Node>
|
||||||
where
|
where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/* 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::cell::ArcRefCell;
|
|
||||||
use crate::flexbox::FlexLevelBox;
|
|
||||||
use crate::flow::inline::InlineLevelBox;
|
|
||||||
use crate::flow::BlockLevelBox;
|
|
||||||
use script_layout_interface::wrapper_traits::LayoutDataTrait;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct LayoutDataForElement {
|
|
||||||
pub(super) self_box: ArcRefCell<Option<LayoutBox>>,
|
|
||||||
pub(super) pseudo_before_box: ArcRefCell<Option<LayoutBox>>,
|
|
||||||
pub(super) pseudo_after_box: ArcRefCell<Option<LayoutBox>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) enum LayoutBox {
|
|
||||||
DisplayContents,
|
|
||||||
BlockLevel(ArcRefCell<BlockLevelBox>),
|
|
||||||
InlineLevel(ArcRefCell<InlineLevelBox>),
|
|
||||||
FlexLevel(ArcRefCell<FlexLevelBox>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LayoutDataTrait for LayoutDataForElement {}
|
|
|
@ -5,10 +5,8 @@
|
||||||
use super::{FlexContainer, FlexLevelBox};
|
use super::{FlexContainer, FlexLevelBox};
|
||||||
use crate::cell::ArcRefCell;
|
use crate::cell::ArcRefCell;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::{
|
use crate::dom::{BoxSlot, LayoutBox, NodeExt};
|
||||||
BoxSlot, Contents, NodeAndStyleInfo, NodeExt, NonReplacedContents, TraversalHandler,
|
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler};
|
||||||
};
|
|
||||||
use crate::element_data::LayoutBox;
|
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::positioned::AbsolutelyPositionedBox;
|
use crate::positioned::AbsolutelyPositionedBox;
|
||||||
use crate::style_ext::DisplayGeneratingBox;
|
use crate::style_ext::DisplayGeneratingBox;
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
|
|
||||||
use crate::cell::ArcRefCell;
|
use crate::cell::ArcRefCell;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::{
|
use crate::dom::{BoxSlot, LayoutBox, NodeExt};
|
||||||
BoxSlot, Contents, NodeAndStyleInfo, NodeExt, NonReplacedContents, TraversalHandler,
|
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler};
|
||||||
};
|
|
||||||
use crate::element_data::LayoutBox;
|
|
||||||
use crate::flow::float::FloatBox;
|
use crate::flow::float::FloatBox;
|
||||||
use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, TextRun};
|
use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, TextRun};
|
||||||
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
|
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
//! See CSS 2.1 § 9.5.1: https://www.w3.org/TR/CSS2/visuren.html#float-position
|
//! See CSS 2.1 § 9.5.1: https://www.w3.org/TR/CSS2/visuren.html#float-position
|
||||||
|
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt};
|
use crate::dom::NodeExt;
|
||||||
|
use crate::dom_traversal::{Contents, NodeAndStyleInfo};
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::geom::flow_relative::{Rect, Vec2};
|
use crate::geom::flow_relative::{Rect, Vec2};
|
||||||
use crate::style_ext::DisplayInside;
|
use crate::style_ext::DisplayInside;
|
||||||
|
|
|
@ -7,8 +7,8 @@ use crate::context::LayoutContext;
|
||||||
use crate::display_list::stacking_context::{
|
use crate::display_list::stacking_context::{
|
||||||
ContainingBlock, ContainingBlockInfo, StackingContext, StackingContextBuildMode,
|
ContainingBlock, ContainingBlockInfo, StackingContext, StackingContextBuildMode,
|
||||||
};
|
};
|
||||||
use crate::dom_traversal::{iter_child_nodes, Contents, NodeAndStyleInfo, NodeExt};
|
use crate::dom::{LayoutBox, NodeExt};
|
||||||
use crate::element_data::LayoutBox;
|
use crate::dom_traversal::{iter_child_nodes, Contents, NodeAndStyleInfo};
|
||||||
use crate::flexbox::FlexLevelBox;
|
use crate::flexbox::FlexLevelBox;
|
||||||
use crate::flow::construct::ContainsFloats;
|
use crate::flow::construct::ContainsFloats;
|
||||||
use crate::flow::float::FloatBox;
|
use crate::flow::float::FloatBox;
|
||||||
|
@ -24,7 +24,6 @@ use crate::positioned::PositioningContext;
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::style_ext::ComputedValuesExt;
|
use crate::style_ext::ComputedValuesExt;
|
||||||
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
|
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
|
||||||
use crate::wrapper::GetStyleAndLayoutData;
|
|
||||||
use crate::DefiniteContainingBlock;
|
use crate::DefiniteContainingBlock;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use atomic_refcell::AtomicRef;
|
use atomic_refcell::AtomicRef;
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
* 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::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt};
|
use crate::dom::NodeExt;
|
||||||
|
use crate::dom_traversal::{Contents, NodeAndStyleInfo};
|
||||||
use crate::flexbox::FlexContainer;
|
use crate::flexbox::FlexContainer;
|
||||||
use crate::flow::BlockFormattingContext;
|
use crate::flow::BlockFormattingContext;
|
||||||
use crate::fragment_tree::BaseFragmentInfo;
|
use crate::fragment_tree::BaseFragmentInfo;
|
||||||
|
|
|
@ -11,10 +11,9 @@ extern crate serde;
|
||||||
|
|
||||||
mod cell;
|
mod cell;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod data;
|
|
||||||
pub mod display_list;
|
pub mod display_list;
|
||||||
|
pub mod dom;
|
||||||
mod dom_traversal;
|
mod dom_traversal;
|
||||||
pub mod element_data;
|
|
||||||
mod flexbox;
|
mod flexbox;
|
||||||
pub mod flow;
|
pub mod flow;
|
||||||
mod formatting_contexts;
|
mod formatting_contexts;
|
||||||
|
@ -24,14 +23,12 @@ pub mod geom;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod layout_debug;
|
pub mod layout_debug;
|
||||||
mod lists;
|
mod lists;
|
||||||
mod opaque_node;
|
|
||||||
mod positioned;
|
mod positioned;
|
||||||
pub mod query;
|
pub mod query;
|
||||||
mod replaced;
|
mod replaced;
|
||||||
mod sizing;
|
mod sizing;
|
||||||
mod style_ext;
|
mod style_ext;
|
||||||
pub mod traversal;
|
pub mod traversal;
|
||||||
pub mod wrapper;
|
|
||||||
|
|
||||||
pub use flow::{BoxTree, FragmentTree};
|
pub use flow::{BoxTree, FragmentTree};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
* 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::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::{NodeAndStyleInfo, NodeExt, PseudoElementContentItem};
|
use crate::dom::NodeExt;
|
||||||
|
use crate::dom_traversal::{NodeAndStyleInfo, PseudoElementContentItem};
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use style::properties::longhands::list_style_type::computed_value::T as ListStyleType;
|
use style::properties::longhands::list_style_type::computed_value::T as ListStyleType;
|
||||||
use style::properties::style_structs;
|
use style::properties::style_structs;
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
/* 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 libc::c_void;
|
|
||||||
use script_traits::UntrustedNodeAddress;
|
|
||||||
use style::dom::OpaqueNode;
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,7 +4,8 @@
|
||||||
|
|
||||||
use crate::cell::ArcRefCell;
|
use crate::cell::ArcRefCell;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt};
|
use crate::dom::NodeExt;
|
||||||
|
use crate::dom_traversal::{Contents, NodeAndStyleInfo};
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::fragments::{BoxFragment, CollapsedBlockMargins, Fragment};
|
use crate::fragments::{BoxFragment, CollapsedBlockMargins, Fragment};
|
||||||
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* 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::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::NodeExt;
|
use crate::dom::NodeExt;
|
||||||
use crate::fragment_tree::BaseFragmentInfo;
|
use crate::fragment_tree::BaseFragmentInfo;
|
||||||
use crate::fragments::{Fragment, IFrameFragment, ImageFragment};
|
use crate::fragments::{Fragment, IFrameFragment, ImageFragment};
|
||||||
use crate::geom::flow_relative::{Rect, Vec2};
|
use crate::geom::flow_relative::{Rect, Vec2};
|
||||||
|
@ -142,7 +142,7 @@ impl ReplacedContent {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let base_fragment_info = BaseFragmentInfo::new_for_node(element.as_opaque());
|
let base_fragment_info = BaseFragmentInfo::new_for_node(element.opaque());
|
||||||
return Some(Self {
|
return Some(Self {
|
||||||
kind,
|
kind,
|
||||||
intrinsic,
|
intrinsic,
|
||||||
|
@ -157,7 +157,7 @@ impl ReplacedContent {
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
if let ComputedUrl::Valid(image_url) = image_url {
|
if let ComputedUrl::Valid(image_url) = image_url {
|
||||||
let (image, width, height) = match context.get_or_request_image_or_meta(
|
let (image, width, height) = match context.get_or_request_image_or_meta(
|
||||||
element.as_opaque(),
|
element.opaque(),
|
||||||
image_url.clone(),
|
image_url.clone(),
|
||||||
UsePlaceholder::No,
|
UsePlaceholder::No,
|
||||||
) {
|
) {
|
||||||
|
@ -178,7 +178,7 @@ impl ReplacedContent {
|
||||||
// FIXME https://github.com/w3c/csswg-drafts/issues/4572
|
// FIXME https://github.com/w3c/csswg-drafts/issues/4572
|
||||||
ratio: Some(width / height),
|
ratio: Some(width / height),
|
||||||
},
|
},
|
||||||
base_fragment_info: BaseFragmentInfo::new_for_node(element.as_opaque()),
|
base_fragment_info: BaseFragmentInfo::new_for_node(element.opaque()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* 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::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::wrapper::GetStyleAndLayoutData;
|
use crate::dom::NodeExt;
|
||||||
use script_layout_interface::wrapper_traits::LayoutNode;
|
use script_layout_interface::wrapper_traits::LayoutNode;
|
||||||
use style::context::{SharedStyleContext, StyleContext};
|
use style::context::{SharedStyleContext, StyleContext};
|
||||||
use style::data::ElementData;
|
use style::data::ElementData;
|
||||||
|
@ -33,7 +33,7 @@ impl<'a> RecalcStyle<'a> {
|
||||||
impl<'a, 'dom, E> DomTraversal<E> for RecalcStyle<'a>
|
impl<'a, 'dom, E> DomTraversal<E> for RecalcStyle<'a>
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
E::ConcreteNode: LayoutNode<'dom>,
|
E::ConcreteNode: 'dom + LayoutNode<'dom>,
|
||||||
{
|
{
|
||||||
fn process_preorder<F>(
|
fn process_preorder<F>(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/* 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::GetStyleAndOpaqueLayoutData;
|
|
||||||
|
|
||||||
pub trait GetStyleAndLayoutData<'dom> {
|
|
||||||
fn get_style_and_layout_data(self) -> Option<StyleAndLayoutData<'dom>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'dom, T> GetStyleAndLayoutData<'dom> for T
|
|
||||||
where
|
|
||||||
T: GetStyleAndOpaqueLayoutData<'dom>,
|
|
||||||
{
|
|
||||||
fn get_style_and_layout_data(self) -> Option<StyleAndLayoutData<'dom>> {
|
|
||||||
self.get_style_and_opaque_layout_data()
|
|
||||||
.map(|data| StyleAndLayoutData {
|
|
||||||
style_data: &data.style_data,
|
|
||||||
layout_data: data.generic_data.downcast_ref().unwrap(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -30,7 +30,7 @@ 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, WebRenderImageInfo};
|
use layout::display_list::{DisplayListBuilder, WebRenderImageInfo};
|
||||||
use layout::element_data::LayoutDataForElement;
|
use layout::dom::DOMLayoutData;
|
||||||
use layout::layout_debug;
|
use layout::layout_debug;
|
||||||
use layout::query::{
|
use layout::query::{
|
||||||
process_content_box_request, process_content_boxes_request, process_resolved_font_style_query,
|
process_content_box_request, process_content_boxes_request, process_resolved_font_style_query,
|
||||||
|
@ -801,7 +801,7 @@ impl LayoutThread {
|
||||||
data: &mut ScriptReflowResult,
|
data: &mut ScriptReflowResult,
|
||||||
possibly_locked_rw_data: &mut RwData<'a, 'b>,
|
possibly_locked_rw_data: &mut RwData<'a, 'b>,
|
||||||
) {
|
) {
|
||||||
let document = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&data.document) };
|
let document = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&data.document) };
|
||||||
let document = document.as_document().unwrap();
|
let document = document.as_document().unwrap();
|
||||||
|
|
||||||
let mut rw_data = possibly_locked_rw_data.lock();
|
let mut rw_data = possibly_locked_rw_data.lock();
|
||||||
|
@ -957,7 +957,7 @@ impl LayoutThread {
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|r| r.1.snapshot.is_some())
|
.filter(|r| r.1.snapshot.is_some())
|
||||||
.map(|r| unsafe {
|
.map(|r| unsafe {
|
||||||
ServoLayoutNode::<LayoutDataForElement>::new(&r.0)
|
ServoLayoutNode::<DOMLayoutData>::new(&r.0)
|
||||||
.as_element()
|
.as_element()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
})
|
})
|
||||||
|
@ -965,7 +965,7 @@ impl LayoutThread {
|
||||||
|
|
||||||
for (el, restyle) in restyles {
|
for (el, restyle) in restyles {
|
||||||
let el = unsafe {
|
let el = unsafe {
|
||||||
ServoLayoutNode::<LayoutDataForElement>::new(&el)
|
ServoLayoutNode::<DOMLayoutData>::new(&el)
|
||||||
.as_element()
|
.as_element()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
@ -1004,16 +1004,15 @@ impl LayoutThread {
|
||||||
);
|
);
|
||||||
|
|
||||||
let dirty_root = unsafe {
|
let dirty_root = unsafe {
|
||||||
ServoLayoutNode::<LayoutDataForElement>::new(&data.dirty_root.unwrap())
|
ServoLayoutNode::<DOMLayoutData>::new(&data.dirty_root.unwrap())
|
||||||
.as_element()
|
.as_element()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let traversal = RecalcStyle::new(layout_context);
|
let traversal = RecalcStyle::new(layout_context);
|
||||||
let token = {
|
let token = {
|
||||||
let shared = DomTraversal::<ServoLayoutElement<LayoutDataForElement>>::shared_context(
|
let shared =
|
||||||
&traversal,
|
DomTraversal::<ServoLayoutElement<DOMLayoutData>>::shared_context(&traversal);
|
||||||
);
|
|
||||||
RecalcStyle::pre_traverse(dirty_root, shared)
|
RecalcStyle::pre_traverse(dirty_root, shared)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1021,7 +1020,7 @@ impl LayoutThread {
|
||||||
let rayon_pool = rayon_pool.as_ref();
|
let rayon_pool = rayon_pool.as_ref();
|
||||||
|
|
||||||
if token.should_traverse() {
|
if token.should_traverse() {
|
||||||
let dirty_root: ServoLayoutNode<LayoutDataForElement> =
|
let dirty_root: ServoLayoutNode<DOMLayoutData> =
|
||||||
driver::traverse_dom(&traversal, token, rayon_pool).as_node();
|
driver::traverse_dom(&traversal, token, rayon_pool).as_node();
|
||||||
|
|
||||||
let root_node = root_element.as_node();
|
let root_node = root_element.as_node();
|
||||||
|
@ -1134,12 +1133,12 @@ impl LayoutThread {
|
||||||
process_node_scroll_area_request(node, self.fragment_tree.borrow().clone());
|
process_node_scroll_area_request(node, self.fragment_tree.borrow().clone());
|
||||||
},
|
},
|
||||||
&QueryMsg::NodeScrollIdQuery(node) => {
|
&QueryMsg::NodeScrollIdQuery(node) => {
|
||||||
let node = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&node) };
|
let node = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&node) };
|
||||||
rw_data.scroll_id_response =
|
rw_data.scroll_id_response =
|
||||||
Some(process_node_scroll_id_request(self.id, node));
|
Some(process_node_scroll_id_request(self.id, node));
|
||||||
},
|
},
|
||||||
&QueryMsg::ResolvedStyleQuery(node, ref pseudo, ref property) => {
|
&QueryMsg::ResolvedStyleQuery(node, ref pseudo, ref property) => {
|
||||||
let node = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&node) };
|
let node = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&node) };
|
||||||
let fragment_tree = self.fragment_tree.borrow().clone();
|
let fragment_tree = self.fragment_tree.borrow().clone();
|
||||||
rw_data.resolved_style_response = process_resolved_style_request(
|
rw_data.resolved_style_response = process_resolved_style_request(
|
||||||
context,
|
context,
|
||||||
|
@ -1150,7 +1149,7 @@ impl LayoutThread {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
&QueryMsg::ResolvedFontStyleQuery(node, ref property, ref value) => {
|
&QueryMsg::ResolvedFontStyleQuery(node, ref property, ref value) => {
|
||||||
let node = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&node) };
|
let node = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&node) };
|
||||||
rw_data.resolved_font_style_response =
|
rw_data.resolved_font_style_response =
|
||||||
process_resolved_font_style_query(node, property, value);
|
process_resolved_font_style_query(node, property, value);
|
||||||
},
|
},
|
||||||
|
@ -1180,7 +1179,7 @@ impl LayoutThread {
|
||||||
results.iter().map(|result| result.node).collect()
|
results.iter().map(|result| result.node).collect()
|
||||||
},
|
},
|
||||||
&QueryMsg::ElementInnerTextQuery(node) => {
|
&QueryMsg::ElementInnerTextQuery(node) => {
|
||||||
let node = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&node) };
|
let node = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&node) };
|
||||||
rw_data.element_inner_text_response = process_element_inner_text_query(node);
|
rw_data.element_inner_text_response = process_element_inner_text_query(node);
|
||||||
},
|
},
|
||||||
&QueryMsg::InnerWindowDimensionsQuery(_browsing_context_id) => {
|
&QueryMsg::InnerWindowDimensionsQuery(_browsing_context_id) => {
|
||||||
|
@ -1240,7 +1239,7 @@ impl LayoutThread {
|
||||||
&self,
|
&self,
|
||||||
fragment_tree: Arc<FragmentTree>,
|
fragment_tree: Arc<FragmentTree>,
|
||||||
reflow_goal: &ReflowGoal,
|
reflow_goal: &ReflowGoal,
|
||||||
document: Option<&ServoLayoutDocument<LayoutDataForElement>>,
|
document: Option<&ServoLayoutDocument<DOMLayoutData>>,
|
||||||
context: &mut LayoutContext,
|
context: &mut LayoutContext,
|
||||||
) {
|
) {
|
||||||
Self::cancel_animations_for_nodes_not_in_fragment_tree(
|
Self::cancel_animations_for_nodes_not_in_fragment_tree(
|
||||||
|
|
|
@ -488,7 +488,8 @@ pub struct ServoThreadSafeLayoutNodeChildrenIterator<'dom, LayoutDataType: Layou
|
||||||
parent_node: ServoThreadSafeLayoutNode<'dom, LayoutDataType>,
|
parent_node: ServoThreadSafeLayoutNode<'dom, LayoutDataType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, LayoutDataType: LayoutDataTrait> ServoThreadSafeLayoutNodeChildrenIterator<'dom, LayoutDataType>
|
impl<'dom, LayoutDataType: LayoutDataTrait>
|
||||||
|
ServoThreadSafeLayoutNodeChildrenIterator<'dom, LayoutDataType>
|
||||||
{
|
{
|
||||||
pub fn new(parent: ServoThreadSafeLayoutNode<'dom, LayoutDataType>) -> Self {
|
pub fn new(parent: ServoThreadSafeLayoutNode<'dom, LayoutDataType>) -> Self {
|
||||||
let first_child = match parent.get_pseudo_element_type() {
|
let first_child = match parent.get_pseudo_element_type() {
|
||||||
|
@ -508,7 +509,8 @@ impl<'dom, LayoutDataType: LayoutDataTrait> ServoThreadSafeLayoutNodeChildrenIte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, LayoutDataType: LayoutDataTrait> Iterator for ServoThreadSafeLayoutNodeChildrenIterator<'dom, LayoutDataType>
|
impl<'dom, LayoutDataType: LayoutDataTrait> Iterator
|
||||||
|
for ServoThreadSafeLayoutNodeChildrenIterator<'dom, LayoutDataType>
|
||||||
{
|
{
|
||||||
type Item = ServoThreadSafeLayoutNode<'dom, LayoutDataType>;
|
type Item = ServoThreadSafeLayoutNode<'dom, LayoutDataType>;
|
||||||
fn next(&mut self) -> Option<ServoThreadSafeLayoutNode<'dom, LayoutDataType>> {
|
fn next(&mut self) -> Option<ServoThreadSafeLayoutNode<'dom, LayoutDataType>> {
|
||||||
|
|
|
@ -86,7 +86,12 @@ pub trait GetStyleAndOpaqueLayoutData<'dom> {
|
||||||
|
|
||||||
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
|
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
|
||||||
/// only ever see these and must never see instances of `LayoutDom`.
|
/// only ever see these and must never see instances of `LayoutDom`.
|
||||||
pub trait LayoutNode<'dom>: Debug + GetStyleAndOpaqueLayoutData<'dom> + TNode {
|
/// FIXME(mrobinson): `Send + Sync` is required here for Layout 2020, but eventually it
|
||||||
|
/// should stop sending LayoutNodes to other threads and rely on ThreadSafeLayoutNode
|
||||||
|
/// or some other mechanism to ensure thread safety.
|
||||||
|
pub trait LayoutNode<'dom>:
|
||||||
|
Copy + Debug + GetStyleAndOpaqueLayoutData<'dom> + TNode + Send + Sync
|
||||||
|
{
|
||||||
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<'dom>;
|
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<'dom>;
|
||||||
fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode;
|
fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue