mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Separate computing a WR reference frame from adding it to the display list
This commit is contained in:
parent
3e8623332b
commit
c7acfc37ed
1 changed files with 36 additions and 27 deletions
|
@ -364,6 +364,12 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ReferenceFrameData {
|
||||||
|
origin: crate::geom::PhysicalPoint<Length>,
|
||||||
|
transform: LayoutTransform,
|
||||||
|
kind: wr::ReferenceFrameKind,
|
||||||
|
}
|
||||||
|
|
||||||
impl BoxFragment {
|
impl BoxFragment {
|
||||||
fn get_stacking_context_type(&self) -> Option<StackingContextType> {
|
fn get_stacking_context_type(&self) -> Option<StackingContextType> {
|
||||||
if self.style.establishes_stacking_context() {
|
if self.style.establishes_stacking_context() {
|
||||||
|
@ -464,22 +470,24 @@ impl BoxFragment {
|
||||||
) {
|
) {
|
||||||
// If we are creating a stacking context, we may also need to create a reference
|
// If we are creating a stacking context, we may also need to create a reference
|
||||||
// frame first.
|
// frame first.
|
||||||
let relative_border_rect = self
|
let reference_frame_data = self.reference_frame_data_if_necessary(containing_block_info);
|
||||||
.border_rect()
|
|
||||||
.to_physical(self.style.writing_mode, &containing_block_info.rect);
|
|
||||||
let border_rect =
|
|
||||||
relative_border_rect.translate(containing_block_info.rect.origin.to_vector());
|
|
||||||
let established_reference_frame =
|
|
||||||
self.build_reference_frame_if_necessary(builder, &border_rect);
|
|
||||||
|
|
||||||
// WebRender reference frames establish a new coordinate system at their origin
|
// WebRender reference frames establish a new coordinate system at their origin
|
||||||
// (the border box of the fragment). We need to ensure that any coordinates we
|
// (the border box of the fragment). We need to ensure that any coordinates we
|
||||||
// give to WebRender in this reference frame are relative to the fragment border
|
// give to WebRender in this reference frame are relative to the fragment border
|
||||||
// box. We do this by adjusting the containing block origin.
|
// box. We do this by adjusting the containing block origin.
|
||||||
let mut new_containing_block_info = containing_block_info.clone();
|
let mut new_containing_block_info = containing_block_info.clone();
|
||||||
if established_reference_frame {
|
|
||||||
new_containing_block_info.rect.origin =
|
if let Some(reference_frame_data) = &reference_frame_data {
|
||||||
(-relative_border_rect.origin.to_vector()).to_point();
|
new_containing_block_info.rect.origin -= reference_frame_data.origin.to_vector();
|
||||||
|
builder.current_space_and_clip.spatial_id = builder.wr.push_reference_frame(
|
||||||
|
reference_frame_data.origin.to_webrender(),
|
||||||
|
builder.current_space_and_clip.spatial_id,
|
||||||
|
self.style.get_box().transform_style.to_webrender(),
|
||||||
|
wr::PropertyBinding::Value(reference_frame_data.transform),
|
||||||
|
reference_frame_data.kind,
|
||||||
|
);
|
||||||
|
builder.nearest_reference_frame = builder.current_space_and_clip.spatial_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut child_stacking_context = StackingContext::new(
|
let mut child_stacking_context = StackingContext::new(
|
||||||
|
@ -510,7 +518,7 @@ impl BoxFragment {
|
||||||
.stacking_contexts
|
.stacking_contexts
|
||||||
.append(&mut stolen_children);
|
.append(&mut stolen_children);
|
||||||
|
|
||||||
if established_reference_frame {
|
if reference_frame_data.is_some() {
|
||||||
builder.wr.pop_reference_frame();
|
builder.wr.pop_reference_frame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,17 +619,22 @@ impl BoxFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a reference frame for this fragment if it is necessary. Returns `true` if
|
/// Optionally returns the data for building a reference frame, without yet building it.
|
||||||
/// a reference was built and `false` otherwise.
|
fn reference_frame_data_if_necessary(
|
||||||
fn build_reference_frame_if_necessary(
|
|
||||||
&self,
|
&self,
|
||||||
builder: &mut StackingContextBuilder,
|
containing_block_info: &ContainingBlockInfo,
|
||||||
border_rect: &PhysicalRect<Length>,
|
) -> Option<ReferenceFrameData> {
|
||||||
) -> bool {
|
|
||||||
if !self.style.has_transform_or_perspective() {
|
if !self.style.has_transform_or_perspective() {
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let relative_border_rect = self
|
||||||
|
.border_rect()
|
||||||
|
.to_physical(self.style.writing_mode, &containing_block_info.rect);
|
||||||
|
let border_rect = relative_border_rect
|
||||||
|
.translate(containing_block_info.rect.origin.to_vector());
|
||||||
let untyped_border_rect = border_rect.to_untyped();
|
let untyped_border_rect = border_rect.to_untyped();
|
||||||
|
|
||||||
let transform = self.calculate_transform_matrix(&untyped_border_rect);
|
let transform = self.calculate_transform_matrix(&untyped_border_rect);
|
||||||
let perspective = self.calculate_perspective_matrix(&untyped_border_rect);
|
let perspective = self.calculate_perspective_matrix(&untyped_border_rect);
|
||||||
let (reference_frame_transform, reference_frame_kind) = match (transform, perspective) {
|
let (reference_frame_transform, reference_frame_kind) = match (transform, perspective) {
|
||||||
|
@ -641,15 +654,11 @@ impl BoxFragment {
|
||||||
(None, None) => unreachable!(),
|
(None, None) => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
builder.current_space_and_clip.spatial_id = builder.wr.push_reference_frame(
|
Some(ReferenceFrameData {
|
||||||
border_rect.origin.to_webrender(),
|
origin: border_rect.origin,
|
||||||
builder.current_space_and_clip.spatial_id,
|
transform: reference_frame_transform,
|
||||||
self.style.get_box().transform_style.to_webrender(),
|
kind: reference_frame_kind,
|
||||||
wr::PropertyBinding::Value(reference_frame_transform),
|
})
|
||||||
reference_frame_kind,
|
|
||||||
);
|
|
||||||
builder.nearest_reference_frame = builder.current_space_and_clip.spatial_id;
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the 4D matrix representing this fragment's transform.
|
/// Returns the 4D matrix representing this fragment's transform.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue