mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
layout: Consider transform for bounding box queries (#37871)
The recent changes that cached the Scroll Tree present an opportunity to calculate the queries that consider transform and scroll (dubbed as post composite queries) accurately. This PR propose a solution for this calculation by noting the lowest scroll tree nodes that would affect a fragment. To do this, each fragment would store a new attribute `spatial_tree_node` -- scroll tree node id that we could use for the query. This referencing is considered because the scroll tree node construction is managed by the fragment itself. Therefore it would ease the managing the possibly stale reference and future query cache invalidation considering the development of incremental layout. The bounding box query then could transform the bounding content rect of a fragment using the computed current transformation matrix. Fixes: https://github.com/servo/servo/issues/35768 Testing: Existing and new WPT --------- Signed-off-by: stevennovaryo <steven.novaryo@gmail.com> Signed-off-by: Jo Steven Novaryo <jo.steven.novaryo@huawei.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
37ac4ffeb4
commit
900dd8d191
31 changed files with 304 additions and 146 deletions
|
@ -10,7 +10,7 @@ use base::id::ScrollTreeNodeId;
|
|||
use base::print_tree::PrintTree;
|
||||
use bitflags::bitflags;
|
||||
use embedder_traits::{Cursor, ViewportDetails};
|
||||
use euclid::SideOffsets2D;
|
||||
use euclid::{SideOffsets2D, Transform3D};
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use style::values::specified::Overflow;
|
||||
|
@ -88,6 +88,8 @@ pub struct StickyNodeInfo {
|
|||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct ReferenceFrameNodeInfo {
|
||||
pub origin: LayoutPoint,
|
||||
/// Origin of this frame relative to the document for bounding box queries.
|
||||
pub frame_origin_for_query: LayoutPoint,
|
||||
pub transform_style: TransformStyle,
|
||||
pub transform: LayoutTransform,
|
||||
pub kind: ReferenceFrameKind,
|
||||
|
@ -422,6 +424,53 @@ impl ScrollTree {
|
|||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Traverse a scroll node to its root to calculate the transform.
|
||||
///
|
||||
/// TODO(stevennovaryo): Add caching mechanism for this.
|
||||
pub fn cumulative_node_transform(&self, node_id: &ScrollTreeNodeId) -> LayoutTransform {
|
||||
let current_node = self.get_node(node_id);
|
||||
|
||||
let change_basis =
|
||||
|transform: &Transform3D<f32, LayoutPixel, LayoutPixel>, x: f32, y: f32, z: f32| {
|
||||
let pre_translation = Transform3D::translation(x, y, z);
|
||||
let post_translation = Transform3D::translation(-x, -y, -z);
|
||||
post_translation.then(transform).then(&pre_translation)
|
||||
};
|
||||
|
||||
// FIXME(stevennovaryo): Ideally we should optimize the computation of simpler
|
||||
// transformation like translate as it could be done
|
||||
// in smaller amount of operation compared to a normal
|
||||
// matrix multiplication.
|
||||
let node_transform = match ¤t_node.info {
|
||||
// To apply a transformation we need to make sure the rectangle's
|
||||
// coordinate space is the same as reference frame's coordinate space.
|
||||
// TODO(stevennovaryo): contrary to how Firefox are handling the coordinate space,
|
||||
// we are ignoring zoom in transforming the coordinate
|
||||
// space, and we might need to consider zoom here if it was
|
||||
// implemented completely.
|
||||
SpatialTreeNodeInfo::ReferenceFrame(info) => change_basis(
|
||||
&info.transform,
|
||||
info.frame_origin_for_query.x,
|
||||
info.frame_origin_for_query.y,
|
||||
0.0,
|
||||
),
|
||||
SpatialTreeNodeInfo::Scroll(info) => {
|
||||
Transform3D::translation(-info.offset.x, -info.offset.y, 0.0)
|
||||
},
|
||||
// TODO(stevennovaryo): Need to consider sticky frame accurately.
|
||||
SpatialTreeNodeInfo::Sticky(_) => Default::default(),
|
||||
};
|
||||
|
||||
match current_node.parent {
|
||||
// If a node is not a root, accumulate the transforms.
|
||||
Some(parent_id) => {
|
||||
let ancestors_transform = self.cumulative_node_transform(&parent_id);
|
||||
node_transform.then(&ancestors_transform)
|
||||
},
|
||||
None => node_transform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// In order to pretty print the [ScrollTree] structure, we are converting
|
||||
|
@ -539,6 +588,7 @@ impl CompositorDisplayListInfo {
|
|||
None,
|
||||
SpatialTreeNodeInfo::ReferenceFrame(ReferenceFrameNodeInfo {
|
||||
origin: Default::default(),
|
||||
frame_origin_for_query: Default::default(),
|
||||
transform_style: TransformStyle::Flat,
|
||||
transform: LayoutTransform::identity(),
|
||||
kind: ReferenceFrameKind::default(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue