mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #26037 - mrobinson:arcrefcell-fragment-tree, r=SimonSapin
layout_2020: Use ArcRefCell in the fragment tree This will allow mutability which is useful for things like animations. <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #___ (GitHub issue number if applicable) <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because they should not change behavior. <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
commit
4dbe3b30cd
4 changed files with 133 additions and 114 deletions
|
@ -2,6 +2,7 @@
|
||||||
* 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::display_list::conversions::ToWebRender;
|
use crate::display_list::conversions::ToWebRender;
|
||||||
use crate::display_list::DisplayListBuilder;
|
use crate::display_list::DisplayListBuilder;
|
||||||
use crate::fragments::{
|
use crate::fragments::{
|
||||||
|
@ -13,12 +14,14 @@ use crate::style_ext::ComputedValuesExt;
|
||||||
use euclid::default::Rect;
|
use euclid::default::Rect;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
|
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
|
||||||
|
use servo_arc::Arc as ServoArc;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use style::computed_values::float::T as ComputedFloat;
|
use style::computed_values::float::T as ComputedFloat;
|
||||||
use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode;
|
use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode;
|
||||||
use style::computed_values::overflow_x::T as ComputedOverflow;
|
use style::computed_values::overflow_x::T as ComputedOverflow;
|
||||||
use style::computed_values::position::T as ComputedPosition;
|
use style::computed_values::position::T as ComputedPosition;
|
||||||
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::Length;
|
use style::values::computed::Length;
|
||||||
use style::values::generics::box_::Perspective;
|
use style::values::generics::box_::Perspective;
|
||||||
use style::values::generics::transform;
|
use style::values::generics::transform;
|
||||||
|
@ -27,7 +30,7 @@ use webrender_api as wr;
|
||||||
use webrender_api::units::{LayoutPoint, LayoutTransform, LayoutVector2D};
|
use webrender_api::units::{LayoutPoint, LayoutTransform, LayoutVector2D};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct ContainingBlock<'a> {
|
pub(crate) struct ContainingBlock {
|
||||||
/// The SpaceAndClipInfo that contains the children of the fragment that
|
/// The SpaceAndClipInfo that contains the children of the fragment that
|
||||||
/// established this containing block.
|
/// established this containing block.
|
||||||
space_and_clip: wr::SpaceAndClipInfo,
|
space_and_clip: wr::SpaceAndClipInfo,
|
||||||
|
@ -38,19 +41,19 @@ pub(crate) struct ContainingBlock<'a> {
|
||||||
/// Fragments for positioned descendants (including direct children) that were
|
/// Fragments for positioned descendants (including direct children) that were
|
||||||
/// hoisted into this containing block. They have hashed based on the
|
/// hoisted into this containing block. They have hashed based on the
|
||||||
/// HoistedFragmentId that is generated during hoisting.
|
/// HoistedFragmentId that is generated during hoisting.
|
||||||
hoisted_children: FnvHashMap<HoistedFragmentId, &'a Fragment>,
|
hoisted_children: FnvHashMap<HoistedFragmentId, ArcRefCell<Fragment>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ContainingBlock<'a> {
|
impl ContainingBlock {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
rect: &PhysicalRect<Length>,
|
rect: &PhysicalRect<Length>,
|
||||||
space_and_clip: wr::SpaceAndClipInfo,
|
space_and_clip: wr::SpaceAndClipInfo,
|
||||||
children: &'a Vec<Fragment>,
|
children: &[ArcRefCell<Fragment>],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut hoisted_children = FnvHashMap::default();
|
let mut hoisted_children = FnvHashMap::default();
|
||||||
for child in children {
|
for child in children {
|
||||||
if let Some(hoisted_fragment_id) = child.hoisted_fragment_id() {
|
if let Some(hoisted_fragment_id) = child.borrow().hoisted_fragment_id() {
|
||||||
hoisted_children.insert(*hoisted_fragment_id, child);
|
hoisted_children.insert(*hoisted_fragment_id, child.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,19 +66,19 @@ impl<'a> ContainingBlock<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct ContainingBlockInfo<'a> {
|
pub(crate) struct ContainingBlockInfo {
|
||||||
/// The positioning rectangle established by the parent. This is sometimes
|
/// The positioning rectangle established by the parent. This is sometimes
|
||||||
/// called the "containing block" in layout_2020.
|
/// called the "containing block" in layout_2020.
|
||||||
pub rect: PhysicalRect<Length>,
|
pub rect: PhysicalRect<Length>,
|
||||||
|
|
||||||
/// The nearest real containing block at this point in the construction of
|
/// The nearest real containing block at this point in the construction of
|
||||||
/// the stacking context tree.
|
/// the stacking context tree.
|
||||||
pub nearest_containing_block: Option<ContainingBlock<'a>>,
|
pub nearest_containing_block: Option<ContainingBlock>,
|
||||||
|
|
||||||
/// The nearest containing block for all descendants at this point in the
|
/// The nearest containing block for all descendants at this point in the
|
||||||
/// stacking context tree. This containing blocks contains fixed position
|
/// stacking context tree. This containing blocks contains fixed position
|
||||||
/// elements.
|
/// elements.
|
||||||
pub containing_block_for_all_descendants: ContainingBlock<'a>,
|
pub containing_block_for_all_descendants: ContainingBlock,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct StackingContextBuilder<'a> {
|
pub(crate) struct StackingContextBuilder<'a> {
|
||||||
|
@ -117,17 +120,18 @@ pub(crate) enum StackingContextSection {
|
||||||
Content,
|
Content,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct StackingContextFragment<'a> {
|
pub(crate) struct StackingContextFragment {
|
||||||
space_and_clip: wr::SpaceAndClipInfo,
|
space_and_clip: wr::SpaceAndClipInfo,
|
||||||
section: StackingContextSection,
|
section: StackingContextSection,
|
||||||
containing_block: PhysicalRect<Length>,
|
containing_block: PhysicalRect<Length>,
|
||||||
fragment: &'a Fragment,
|
fragment: ArcRefCell<Fragment>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StackingContextFragment<'a> {
|
impl StackingContextFragment {
|
||||||
fn build_display_list(&self, builder: &mut DisplayListBuilder) {
|
fn build_display_list(&self, builder: &mut DisplayListBuilder) {
|
||||||
builder.current_space_and_clip = self.space_and_clip;
|
builder.current_space_and_clip = self.space_and_clip;
|
||||||
self.fragment
|
self.fragment
|
||||||
|
.borrow()
|
||||||
.build_display_list(builder, &self.containing_block);
|
.build_display_list(builder, &self.containing_block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,31 +144,31 @@ pub(crate) enum StackingContextType {
|
||||||
PseudoAtomicInline,
|
PseudoAtomicInline,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct StackingContext<'a> {
|
pub(crate) struct StackingContext {
|
||||||
/// The fragment that established this stacking context.
|
/// The fragment that established this stacking context.
|
||||||
initializing_fragment: Option<&'a BoxFragment>,
|
initializing_fragment_style: Option<ServoArc<ComputedValues>>,
|
||||||
|
|
||||||
/// The type of this StackingContext. Used for collecting and sorting.
|
/// The type of this StackingContext. Used for collecting and sorting.
|
||||||
context_type: StackingContextType,
|
context_type: StackingContextType,
|
||||||
|
|
||||||
/// Fragments that make up the content of this stacking context.
|
/// Fragments that make up the content of this stacking context.
|
||||||
fragments: Vec<StackingContextFragment<'a>>,
|
fragments: Vec<StackingContextFragment>,
|
||||||
|
|
||||||
/// All non-float stacking context and pseudo stacking context children
|
/// All non-float stacking context and pseudo stacking context children
|
||||||
/// of this stacking context.
|
/// of this stacking context.
|
||||||
stacking_contexts: Vec<StackingContext<'a>>,
|
stacking_contexts: Vec<StackingContext>,
|
||||||
|
|
||||||
/// All float pseudo stacking context children of this stacking context.
|
/// All float pseudo stacking context children of this stacking context.
|
||||||
float_stacking_contexts: Vec<StackingContext<'a>>,
|
float_stacking_contexts: Vec<StackingContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StackingContext<'a> {
|
impl StackingContext {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
initializing_fragment: &'a BoxFragment,
|
initializing_fragment_style: ServoArc<ComputedValues>,
|
||||||
context_type: StackingContextType,
|
context_type: StackingContextType,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
initializing_fragment: Some(initializing_fragment),
|
initializing_fragment_style: Some(initializing_fragment_style),
|
||||||
context_type,
|
context_type,
|
||||||
fragments: vec![],
|
fragments: vec![],
|
||||||
stacking_contexts: vec![],
|
stacking_contexts: vec![],
|
||||||
|
@ -174,7 +178,7 @@ impl<'a> StackingContext<'a> {
|
||||||
|
|
||||||
pub(crate) fn create_root() -> Self {
|
pub(crate) fn create_root() -> Self {
|
||||||
Self {
|
Self {
|
||||||
initializing_fragment: None,
|
initializing_fragment_style: None,
|
||||||
context_type: StackingContextType::Real,
|
context_type: StackingContextType::Real,
|
||||||
fragments: vec![],
|
fragments: vec![],
|
||||||
stacking_contexts: vec![],
|
stacking_contexts: vec![],
|
||||||
|
@ -183,10 +187,9 @@ impl<'a> StackingContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn z_index(&self) -> i32 {
|
fn z_index(&self) -> i32 {
|
||||||
match self.initializing_fragment {
|
self.initializing_fragment_style
|
||||||
Some(fragment) => fragment.style.effective_z_index(),
|
.as_ref()
|
||||||
None => 0,
|
.map_or(0, |style| style.effective_z_index())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn sort(&mut self) {
|
pub(crate) fn sort(&mut self) {
|
||||||
|
@ -210,18 +213,17 @@ impl<'a> StackingContext<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_webrender_stacking_context_if_necessary(
|
fn push_webrender_stacking_context_if_necessary<'a>(
|
||||||
&self,
|
&self,
|
||||||
builder: &'a mut DisplayListBuilder,
|
builder: &'a mut DisplayListBuilder,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let fragment = match self.initializing_fragment {
|
let effects = match self.initializing_fragment_style.as_ref() {
|
||||||
Some(fragment) => fragment,
|
Some(style) => style.get_effects(),
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// WebRender only uses the stacking context to apply certain effects. If we don't
|
// WebRender only uses the stacking context to apply certain effects. If we don't
|
||||||
// actually need to create a stacking context, just avoid creating one.
|
// actually need to create a stacking context, just avoid creating one.
|
||||||
let effects = fragment.style.get_effects();
|
|
||||||
if effects.filter.0.is_empty() &&
|
if effects.filter.0.is_empty() &&
|
||||||
effects.opacity == 1.0 &&
|
effects.opacity == 1.0 &&
|
||||||
effects.mix_blend_mode == ComputedMixBlendMode::Normal
|
effects.mix_blend_mode == ComputedMixBlendMode::Normal
|
||||||
|
@ -261,7 +263,7 @@ impl<'a> StackingContext<'a> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build_display_list(&'a self, builder: &'a mut DisplayListBuilder) {
|
pub(crate) fn build_display_list<'a>(&self, builder: &'a mut DisplayListBuilder) {
|
||||||
let pushed_context = self.push_webrender_stacking_context_if_necessary(builder);
|
let pushed_context = self.push_webrender_stacking_context_if_necessary(builder);
|
||||||
|
|
||||||
// Properly order display items that make up a stacking context. "Steps" here
|
// Properly order display items that make up a stacking context. "Steps" here
|
||||||
|
@ -323,11 +325,12 @@ pub(crate) enum StackingContextBuildMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fragment {
|
impl Fragment {
|
||||||
pub(crate) fn build_stacking_context_tree<'a>(
|
pub(crate) fn build_stacking_context_tree(
|
||||||
&'a self,
|
&self,
|
||||||
|
fragment_ref: &ArcRefCell<Fragment>,
|
||||||
builder: &mut StackingContextBuilder,
|
builder: &mut StackingContextBuilder,
|
||||||
containing_block_info: &ContainingBlockInfo<'a>,
|
containing_block_info: &ContainingBlockInfo,
|
||||||
stacking_context: &mut StackingContext<'a>,
|
stacking_context: &mut StackingContext,
|
||||||
mode: StackingContextBuildMode,
|
mode: StackingContextBuildMode,
|
||||||
) {
|
) {
|
||||||
if mode == StackingContextBuildMode::SkipHoisted && self.is_hoisted() {
|
if mode == StackingContextBuildMode::SkipHoisted && self.is_hoisted() {
|
||||||
|
@ -337,7 +340,7 @@ impl Fragment {
|
||||||
match self {
|
match self {
|
||||||
Fragment::Box(fragment) => {
|
Fragment::Box(fragment) => {
|
||||||
fragment.build_stacking_context_tree(
|
fragment.build_stacking_context_tree(
|
||||||
self,
|
fragment_ref,
|
||||||
builder,
|
builder,
|
||||||
containing_block_info,
|
containing_block_info,
|
||||||
stacking_context,
|
stacking_context,
|
||||||
|
@ -362,7 +365,7 @@ impl Fragment {
|
||||||
section: StackingContextSection::Content,
|
section: StackingContextSection::Content,
|
||||||
space_and_clip: builder.current_space_and_clip,
|
space_and_clip: builder.current_space_and_clip,
|
||||||
containing_block: containing_block_info.rect,
|
containing_block: containing_block_info.rect,
|
||||||
fragment: self,
|
fragment: fragment_ref.clone(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -407,7 +410,7 @@ impl BoxFragment {
|
||||||
&'a self,
|
&'a self,
|
||||||
builder: &mut StackingContextBuilder,
|
builder: &mut StackingContextBuilder,
|
||||||
padding_rect: &PhysicalRect<Length>,
|
padding_rect: &PhysicalRect<Length>,
|
||||||
containing_block_info: &mut ContainingBlockInfo<'a>,
|
containing_block_info: &mut ContainingBlockInfo,
|
||||||
) {
|
) {
|
||||||
if !self.style.establishes_containing_block() {
|
if !self.style.establishes_containing_block() {
|
||||||
return;
|
return;
|
||||||
|
@ -427,12 +430,12 @@ impl BoxFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_stacking_context_tree<'a>(
|
fn build_stacking_context_tree(
|
||||||
&'a self,
|
&self,
|
||||||
fragment: &'a Fragment,
|
fragment: &ArcRefCell<Fragment>,
|
||||||
builder: &mut StackingContextBuilder,
|
builder: &mut StackingContextBuilder,
|
||||||
containing_block_info: &ContainingBlockInfo<'a>,
|
containing_block_info: &ContainingBlockInfo,
|
||||||
stacking_context: &mut StackingContext<'a>,
|
stacking_context: &mut StackingContext,
|
||||||
) {
|
) {
|
||||||
builder.clipping_and_scrolling_scope(|builder| {
|
builder.clipping_and_scrolling_scope(|builder| {
|
||||||
self.adjust_spatial_id_for_positioning(builder);
|
self.adjust_spatial_id_for_positioning(builder);
|
||||||
|
@ -450,7 +453,7 @@ impl BoxFragment {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut child_stacking_context = StackingContext::new(self, context_type);
|
let mut child_stacking_context = StackingContext::new(self.style.clone(), context_type);
|
||||||
self.build_stacking_context_tree_for_children(
|
self.build_stacking_context_tree_for_children(
|
||||||
fragment,
|
fragment,
|
||||||
builder,
|
builder,
|
||||||
|
@ -478,10 +481,10 @@ impl BoxFragment {
|
||||||
|
|
||||||
fn build_stacking_context_tree_for_children<'a>(
|
fn build_stacking_context_tree_for_children<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
fragment: &'a Fragment,
|
fragment: &ArcRefCell<Fragment>,
|
||||||
builder: &mut StackingContextBuilder,
|
builder: &mut StackingContextBuilder,
|
||||||
containing_block_info: &ContainingBlockInfo<'a>,
|
containing_block_info: &ContainingBlockInfo,
|
||||||
stacking_context: &mut StackingContext<'a>,
|
stacking_context: &mut StackingContext,
|
||||||
) {
|
) {
|
||||||
let relative_border_rect = self
|
let relative_border_rect = self
|
||||||
.border_rect()
|
.border_rect()
|
||||||
|
@ -506,7 +509,7 @@ impl BoxFragment {
|
||||||
space_and_clip: builder.current_space_and_clip,
|
space_and_clip: builder.current_space_and_clip,
|
||||||
section: self.get_stacking_context_section(),
|
section: self.get_stacking_context_section(),
|
||||||
containing_block: new_containing_block_info.rect,
|
containing_block: new_containing_block_info.rect,
|
||||||
fragment,
|
fragment: fragment.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// We want to build the scroll frame after the background and border, because
|
// We want to build the scroll frame after the background and border, because
|
||||||
|
@ -528,7 +531,8 @@ impl BoxFragment {
|
||||||
self.build_containing_block(builder, &padding_rect, &mut new_containing_block_info);
|
self.build_containing_block(builder, &padding_rect, &mut new_containing_block_info);
|
||||||
|
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
child.build_stacking_context_tree(
|
child.borrow().build_stacking_context_tree(
|
||||||
|
child,
|
||||||
builder,
|
builder,
|
||||||
&new_containing_block_info,
|
&new_containing_block_info,
|
||||||
stacking_context,
|
stacking_context,
|
||||||
|
@ -551,7 +555,7 @@ impl BoxFragment {
|
||||||
fn build_scroll_frame_if_necessary<'a>(
|
fn build_scroll_frame_if_necessary<'a>(
|
||||||
&self,
|
&self,
|
||||||
builder: &mut StackingContextBuilder,
|
builder: &mut StackingContextBuilder,
|
||||||
containing_block_info: &ContainingBlockInfo<'a>,
|
containing_block_info: &ContainingBlockInfo,
|
||||||
) {
|
) {
|
||||||
let overflow_x = self.style.get_box().overflow_x;
|
let overflow_x = self.style.get_box().overflow_x;
|
||||||
let overflow_y = self.style.get_box().overflow_y;
|
let overflow_y = self.style.get_box().overflow_y;
|
||||||
|
@ -716,11 +720,11 @@ impl BoxFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnonymousFragment {
|
impl AnonymousFragment {
|
||||||
fn build_stacking_context_tree<'a>(
|
fn build_stacking_context_tree(
|
||||||
&'a self,
|
&self,
|
||||||
builder: &mut StackingContextBuilder,
|
builder: &mut StackingContextBuilder,
|
||||||
containing_block_info: &ContainingBlockInfo<'a>,
|
containing_block_info: &ContainingBlockInfo,
|
||||||
stacking_context: &mut StackingContext<'a>,
|
stacking_context: &mut StackingContext,
|
||||||
) {
|
) {
|
||||||
let mut new_containing_block_info = containing_block_info.clone();
|
let mut new_containing_block_info = containing_block_info.clone();
|
||||||
new_containing_block_info.rect = self
|
new_containing_block_info.rect = self
|
||||||
|
@ -728,7 +732,8 @@ impl AnonymousFragment {
|
||||||
.to_physical(self.mode, &containing_block_info.rect)
|
.to_physical(self.mode, &containing_block_info.rect)
|
||||||
.translate(containing_block_info.rect.origin.to_vector());
|
.translate(containing_block_info.rect.origin.to_vector());
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
child.build_stacking_context_tree(
|
child.borrow().build_stacking_context_tree(
|
||||||
|
child,
|
||||||
builder,
|
builder,
|
||||||
&new_containing_block_info,
|
&new_containing_block_info,
|
||||||
stacking_context,
|
stacking_context,
|
||||||
|
@ -739,13 +744,13 @@ impl AnonymousFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbsoluteOrFixedPositionedFragment {
|
impl AbsoluteOrFixedPositionedFragment {
|
||||||
fn build_stacking_context_tree<'a>(
|
fn build_stacking_context_tree(
|
||||||
&'a self,
|
&self,
|
||||||
builder: &mut StackingContextBuilder,
|
builder: &mut StackingContextBuilder,
|
||||||
containing_block_info: &ContainingBlockInfo<'a>,
|
containing_block_info: &ContainingBlockInfo,
|
||||||
stacking_context: &mut StackingContext<'a>,
|
stacking_context: &mut StackingContext,
|
||||||
) {
|
) {
|
||||||
let mut build_for_containing_block = |containing_block: &ContainingBlock<'a>| {
|
let mut build_for_containing_block = |containing_block: &ContainingBlock| {
|
||||||
let hoisted_child = match containing_block.hoisted_children.get(&self.0) {
|
let hoisted_child = match containing_block.hoisted_children.get(&self.0) {
|
||||||
Some(hoisted_child) => hoisted_child,
|
Some(hoisted_child) => hoisted_child,
|
||||||
None => return false,
|
None => return false,
|
||||||
|
@ -755,7 +760,8 @@ impl AbsoluteOrFixedPositionedFragment {
|
||||||
let mut new_containing_block_info = containing_block_info.clone();
|
let mut new_containing_block_info = containing_block_info.clone();
|
||||||
new_containing_block_info.rect = containing_block.rect;
|
new_containing_block_info.rect = containing_block.rect;
|
||||||
builder.current_space_and_clip = containing_block.space_and_clip;
|
builder.current_space_and_clip = containing_block.space_and_clip;
|
||||||
hoisted_child.build_stacking_context_tree(
|
hoisted_child.borrow().build_stacking_context_tree(
|
||||||
|
hoisted_child,
|
||||||
builder,
|
builder,
|
||||||
&new_containing_block_info,
|
&new_containing_block_info,
|
||||||
stacking_context,
|
stacking_context,
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub struct BoxTreeRoot(BlockFormattingContext);
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct FragmentTreeRoot {
|
pub struct FragmentTreeRoot {
|
||||||
/// The children of the root of the fragment tree.
|
/// The children of the root of the fragment tree.
|
||||||
children: Vec<Fragment>,
|
children: Vec<ArcRefCell<Fragment>>,
|
||||||
|
|
||||||
/// The scrollable overflow of the root of the fragment tree.
|
/// The scrollable overflow of the root of the fragment tree.
|
||||||
scrollable_overflow: PhysicalRect<Length>,
|
scrollable_overflow: PhysicalRect<Length>,
|
||||||
|
@ -184,7 +184,11 @@ impl BoxTreeRoot {
|
||||||
});
|
});
|
||||||
|
|
||||||
FragmentTreeRoot {
|
FragmentTreeRoot {
|
||||||
children: independent_layout.fragments,
|
children: independent_layout
|
||||||
|
.fragments
|
||||||
|
.into_iter()
|
||||||
|
.map(|fragment| ArcRefCell::new(fragment))
|
||||||
|
.collect(),
|
||||||
scrollable_overflow,
|
scrollable_overflow,
|
||||||
initial_containing_block: physical_containing_block,
|
initial_containing_block: physical_containing_block,
|
||||||
}
|
}
|
||||||
|
@ -207,7 +211,8 @@ impl FragmentTreeRoot {
|
||||||
};
|
};
|
||||||
|
|
||||||
for fragment in &self.children {
|
for fragment in &self.children {
|
||||||
fragment.build_stacking_context_tree(
|
fragment.borrow().build_stacking_context_tree(
|
||||||
|
fragment,
|
||||||
&mut stacking_context_builder,
|
&mut stacking_context_builder,
|
||||||
&containing_block_info,
|
&containing_block_info,
|
||||||
&mut stacking_context,
|
&mut stacking_context,
|
||||||
|
@ -223,7 +228,7 @@ impl FragmentTreeRoot {
|
||||||
pub fn print(&self) {
|
pub fn print(&self) {
|
||||||
let mut print_tree = PrintTree::new("Fragment Tree".to_string());
|
let mut print_tree = PrintTree::new("Fragment Tree".to_string());
|
||||||
for fragment in &self.children {
|
for fragment in &self.children {
|
||||||
fragment.print(&mut print_tree);
|
fragment.borrow().print(&mut print_tree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,49 +243,11 @@ impl FragmentTreeRoot {
|
||||||
&self,
|
&self,
|
||||||
mut process_func: impl FnMut(&Fragment, &PhysicalRect<Length>) -> Option<T>,
|
mut process_func: impl FnMut(&Fragment, &PhysicalRect<Length>) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
fn recur<T>(
|
self.children.iter().find_map(|child| {
|
||||||
fragments: &[Fragment],
|
child
|
||||||
containing_block: &PhysicalRect<Length>,
|
.borrow()
|
||||||
process_func: &mut impl FnMut(&Fragment, &PhysicalRect<Length>) -> Option<T>,
|
.find(&self.initial_containing_block, &mut process_func)
|
||||||
) -> Option<T> {
|
})
|
||||||
for fragment in fragments {
|
|
||||||
if let Some(result) = process_func(fragment, containing_block) {
|
|
||||||
return Some(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
match fragment {
|
|
||||||
Fragment::Box(fragment) => {
|
|
||||||
let new_containing_block = fragment
|
|
||||||
.content_rect
|
|
||||||
.to_physical(fragment.style.writing_mode, containing_block)
|
|
||||||
.translate(containing_block.origin.to_vector());
|
|
||||||
if let Some(result) =
|
|
||||||
recur(&fragment.children, &new_containing_block, process_func)
|
|
||||||
{
|
|
||||||
return Some(result);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Fragment::Anonymous(fragment) => {
|
|
||||||
let new_containing_block = fragment
|
|
||||||
.rect
|
|
||||||
.to_physical(fragment.mode, containing_block)
|
|
||||||
.translate(containing_block.origin.to_vector());
|
|
||||||
if let Some(result) =
|
|
||||||
recur(&fragment.children, &new_containing_block, process_func)
|
|
||||||
{
|
|
||||||
return Some(result);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
recur(
|
|
||||||
&self.children,
|
|
||||||
&self.initial_containing_block,
|
|
||||||
&mut process_func,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_content_box_for_node(&self, requested_node: OpaqueNode) -> Rect<Au> {
|
pub fn get_content_box_for_node(&self, requested_node: OpaqueNode) -> Rect<Au> {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* 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::geom::flow_relative::{Rect, Sides};
|
use crate::geom::flow_relative::{Rect, Sides};
|
||||||
use crate::geom::{PhysicalPoint, PhysicalRect};
|
use crate::geom::{PhysicalPoint, PhysicalRect};
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
|
@ -41,7 +42,7 @@ pub(crate) struct BoxFragment {
|
||||||
pub debug_id: DebugId,
|
pub debug_id: DebugId,
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
pub style: ServoArc<ComputedValues>,
|
pub style: ServoArc<ComputedValues>,
|
||||||
pub children: Vec<Fragment>,
|
pub children: Vec<ArcRefCell<Fragment>>,
|
||||||
|
|
||||||
/// From the containing block’s start corner…?
|
/// From the containing block’s start corner…?
|
||||||
/// This might be broken when the containing block is in a different writing mode:
|
/// This might be broken when the containing block is in a different writing mode:
|
||||||
|
@ -81,7 +82,7 @@ pub(crate) struct CollapsedMargin {
|
||||||
pub(crate) struct AnonymousFragment {
|
pub(crate) struct AnonymousFragment {
|
||||||
pub debug_id: DebugId,
|
pub debug_id: DebugId,
|
||||||
pub rect: Rect<Length>,
|
pub rect: Rect<Length>,
|
||||||
pub children: Vec<Fragment>,
|
pub children: Vec<ArcRefCell<Fragment>>,
|
||||||
pub mode: WritingMode,
|
pub mode: WritingMode,
|
||||||
|
|
||||||
/// The scrollable overflow of this anonymous fragment's children.
|
/// The scrollable overflow of this anonymous fragment's children.
|
||||||
|
@ -189,6 +190,40 @@ impl Fragment {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn find<T>(
|
||||||
|
&self,
|
||||||
|
containing_block: &PhysicalRect<Length>,
|
||||||
|
process_func: &mut impl FnMut(&Fragment, &PhysicalRect<Length>) -> Option<T>,
|
||||||
|
) -> Option<T> {
|
||||||
|
if let Some(result) = process_func(self, containing_block) {
|
||||||
|
return Some(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Fragment::Box(fragment) => {
|
||||||
|
let new_containing_block = fragment
|
||||||
|
.content_rect
|
||||||
|
.to_physical(fragment.style.writing_mode, containing_block)
|
||||||
|
.translate(containing_block.origin.to_vector());
|
||||||
|
fragment
|
||||||
|
.children
|
||||||
|
.iter()
|
||||||
|
.find_map(|child| child.borrow().find(&new_containing_block, process_func))
|
||||||
|
},
|
||||||
|
Fragment::Anonymous(fragment) => {
|
||||||
|
let new_containing_block = fragment
|
||||||
|
.rect
|
||||||
|
.to_physical(fragment.mode, containing_block)
|
||||||
|
.translate(containing_block.origin.to_vector());
|
||||||
|
fragment
|
||||||
|
.children
|
||||||
|
.iter()
|
||||||
|
.find_map(|child| child.borrow().find(&new_containing_block, process_func))
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbsoluteOrFixedPositionedFragment {
|
impl AbsoluteOrFixedPositionedFragment {
|
||||||
|
@ -223,7 +258,10 @@ impl AnonymousFragment {
|
||||||
AnonymousFragment {
|
AnonymousFragment {
|
||||||
debug_id: DebugId::new(),
|
debug_id: DebugId::new(),
|
||||||
rect,
|
rect,
|
||||||
children,
|
children: children
|
||||||
|
.into_iter()
|
||||||
|
.map(|fragment| ArcRefCell::new(fragment))
|
||||||
|
.collect(),
|
||||||
mode,
|
mode,
|
||||||
scrollable_overflow,
|
scrollable_overflow,
|
||||||
}
|
}
|
||||||
|
@ -238,7 +276,7 @@ impl AnonymousFragment {
|
||||||
));
|
));
|
||||||
|
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
child.print(tree);
|
child.borrow().print(tree);
|
||||||
}
|
}
|
||||||
tree.end_level();
|
tree.end_level();
|
||||||
}
|
}
|
||||||
|
@ -267,7 +305,10 @@ impl BoxFragment {
|
||||||
tag,
|
tag,
|
||||||
debug_id: DebugId::new(),
|
debug_id: DebugId::new(),
|
||||||
style,
|
style,
|
||||||
children,
|
children: children
|
||||||
|
.into_iter()
|
||||||
|
.map(|fragment| ArcRefCell::new(fragment))
|
||||||
|
.collect(),
|
||||||
content_rect,
|
content_rect,
|
||||||
padding,
|
padding,
|
||||||
border,
|
border,
|
||||||
|
@ -326,7 +367,7 @@ impl BoxFragment {
|
||||||
));
|
));
|
||||||
|
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
child.print(tree);
|
child.borrow().print(tree);
|
||||||
}
|
}
|
||||||
tree.end_level();
|
tree.end_level();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* 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::dom_traversal::{Contents, NodeExt};
|
use crate::dom_traversal::{Contents, NodeExt};
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
|
@ -285,7 +286,11 @@ impl PositioningContext {
|
||||||
hoisted_boxes = take_hoisted_boxes_pending_layout(self);
|
hoisted_boxes = take_hoisted_boxes_pending_layout(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_fragment.children.extend(laid_out_child_fragments);
|
new_fragment.children.extend(
|
||||||
|
laid_out_child_fragments
|
||||||
|
.into_iter()
|
||||||
|
.map(|fragment| ArcRefCell::new(fragment)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn push(&mut self, box_: HoistedAbsolutelyPositionedBox) {
|
pub(crate) fn push(&mut self, box_: HoistedAbsolutelyPositionedBox) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue