mirror of
https://github.com/servo/servo.git
synced 2025-08-14 18:05:36 +01:00
layout: Use FastTransform for hit testing (#38554)
`FastTransform` provides faster matrix operations when the involved transforms are just translations. Testing: Not needed (no change in behavior) Signed-off-by: Oriol Brufau <obrufau@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
0d40547bec
commit
4ff1e8dbd9
8 changed files with 58 additions and 71 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
@ -6222,7 +6222,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "peek-poke"
|
name = "peek-poke"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074"
|
source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"peek-poke-derive",
|
"peek-poke-derive",
|
||||||
|
@ -6231,7 +6231,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "peek-poke-derive"
|
name = "peek-poke-derive"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074"
|
source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -7666,6 +7666,7 @@ dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"malloc_size_of_derive",
|
"malloc_size_of_derive",
|
||||||
"servo_malloc_size_of",
|
"servo_malloc_size_of",
|
||||||
|
"webrender",
|
||||||
"webrender_api",
|
"webrender_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -9656,7 +9657,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webrender"
|
name = "webrender"
|
||||||
version = "0.66.0"
|
version = "0.66.0"
|
||||||
source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074"
|
source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
"bincode",
|
"bincode",
|
||||||
|
@ -9691,7 +9692,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webrender_api"
|
name = "webrender_api"
|
||||||
version = "0.66.0"
|
version = "0.66.0"
|
||||||
source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074"
|
source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units",
|
"app_units",
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
|
@ -9712,7 +9713,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webrender_build"
|
name = "webrender_build"
|
||||||
version = "0.0.2"
|
version = "0.0.2"
|
||||||
source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074"
|
source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -10424,7 +10425,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wr_glyph_rasterizer"
|
name = "wr_glyph_rasterizer"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074"
|
source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation 0.9.4",
|
"core-foundation 0.9.4",
|
||||||
"core-graphics",
|
"core-graphics",
|
||||||
|
@ -10449,7 +10450,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wr_malloc_size_of"
|
name = "wr_malloc_size_of"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074"
|
source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units",
|
"app_units",
|
||||||
"euclid",
|
"euclid",
|
||||||
|
|
|
@ -16,4 +16,5 @@ app_units = { workspace = true }
|
||||||
euclid = { workspace = true }
|
euclid = { workspace = true }
|
||||||
malloc_size_of = { workspace = true }
|
malloc_size_of = { workspace = true }
|
||||||
malloc_size_of_derive = { workspace = true }
|
malloc_size_of_derive = { workspace = true }
|
||||||
|
webrender = { workspace = true }
|
||||||
webrender_api = { workspace = true }
|
webrender_api = { workspace = true }
|
||||||
|
|
|
@ -8,9 +8,10 @@ use app_units::{Au, MAX_AU, MIN_AU};
|
||||||
use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D};
|
use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D};
|
||||||
use euclid::{Box2D, Length, Point2D, Scale, SideOffsets2D, Size2D, Vector2D};
|
use euclid::{Box2D, Length, Point2D, Scale, SideOffsets2D, Size2D, Vector2D};
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
|
use webrender::FastTransform;
|
||||||
use webrender_api::units::{
|
use webrender_api::units::{
|
||||||
DeviceIntRect, DeviceIntSize, DevicePixel, FramebufferPixel, LayoutPoint, LayoutRect,
|
DeviceIntRect, DeviceIntSize, DevicePixel, FramebufferPixel, LayoutPixel, LayoutPoint,
|
||||||
LayoutSize,
|
LayoutRect, LayoutSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Units for use with euclid::length and euclid::scale_factor.
|
// Units for use with euclid::length and euclid::scale_factor.
|
||||||
|
@ -46,6 +47,8 @@ pub type DeviceIndependentPoint = Point2D<f32, DeviceIndependentPixel>;
|
||||||
pub type DeviceIndependentVector2D = Vector2D<f32, DeviceIndependentPixel>;
|
pub type DeviceIndependentVector2D = Vector2D<f32, DeviceIndependentPixel>;
|
||||||
pub type DeviceIndependentSize = Size2D<f32, DeviceIndependentPixel>;
|
pub type DeviceIndependentSize = Size2D<f32, DeviceIndependentPixel>;
|
||||||
|
|
||||||
|
pub type FastLayoutTransform = FastTransform<LayoutPixel, LayoutPixel>;
|
||||||
|
|
||||||
// An Au is an "App Unit" and represents 1/60th of a CSS pixel. It was
|
// An Au is an "App Unit" and represents 1/60th of a CSS pixel. It was
|
||||||
// originally proposed in 2002 as a standard unit of measure in Gecko.
|
// originally proposed in 2002 as a standard unit of measure in Gecko.
|
||||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info.
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info.
|
||||||
|
|
|
@ -7,16 +7,17 @@ use std::collections::HashMap;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use base::id::ScrollTreeNodeId;
|
use base::id::ScrollTreeNodeId;
|
||||||
use embedder_traits::Cursor;
|
use embedder_traits::Cursor;
|
||||||
use euclid::{Box2D, Point2D, Point3D, Vector2D};
|
use euclid::{Box2D, Vector2D};
|
||||||
use kurbo::{Ellipse, Shape};
|
use kurbo::{Ellipse, Shape};
|
||||||
use layout_api::{ElementsFromPointFlags, ElementsFromPointResult};
|
use layout_api::{ElementsFromPointFlags, ElementsFromPointResult};
|
||||||
|
use servo_geometry::FastLayoutTransform;
|
||||||
use style::computed_values::backface_visibility::T as BackfaceVisibility;
|
use style::computed_values::backface_visibility::T as BackfaceVisibility;
|
||||||
use style::computed_values::pointer_events::T as PointerEvents;
|
use style::computed_values::pointer_events::T as PointerEvents;
|
||||||
use style::computed_values::visibility::T as Visibility;
|
use style::computed_values::visibility::T as Visibility;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::ui::CursorKind;
|
use style::values::computed::ui::CursorKind;
|
||||||
use webrender_api::BorderRadius;
|
use webrender_api::BorderRadius;
|
||||||
use webrender_api::units::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, RectExt};
|
use webrender_api::units::{LayoutPoint, LayoutRect, LayoutSize, RectExt};
|
||||||
|
|
||||||
use crate::display_list::clip::{Clip, ClipId};
|
use crate::display_list::clip::{Clip, ClipId};
|
||||||
use crate::display_list::stacking_context::StackingContextSection;
|
use crate::display_list::stacking_context::StackingContextSection;
|
||||||
|
@ -33,7 +34,7 @@ pub(crate) struct HitTest<'a> {
|
||||||
point_to_test: LayoutPoint,
|
point_to_test: LayoutPoint,
|
||||||
/// A cached version of [`Self::point_to_test`] projected to a spatial node, to avoid
|
/// A cached version of [`Self::point_to_test`] projected to a spatial node, to avoid
|
||||||
/// doing a lot of matrix math over and over.
|
/// doing a lot of matrix math over and over.
|
||||||
projected_point_to_test: Option<(ScrollTreeNodeId, LayoutPoint, LayoutTransform)>,
|
projected_point_to_test: Option<(ScrollTreeNodeId, LayoutPoint, FastLayoutTransform)>,
|
||||||
/// The stacking context tree against which to perform the hit test.
|
/// The stacking context tree against which to perform the hit test.
|
||||||
stacking_context_tree: &'a StackingContextTree,
|
stacking_context_tree: &'a StackingContextTree,
|
||||||
/// The resulting [`HitTestResultItems`] for this hit test.
|
/// The resulting [`HitTestResultItems`] for this hit test.
|
||||||
|
@ -89,7 +90,7 @@ impl<'a> HitTest<'a> {
|
||||||
fn location_in_spatial_node(
|
fn location_in_spatial_node(
|
||||||
&mut self,
|
&mut self,
|
||||||
scroll_tree_node_id: ScrollTreeNodeId,
|
scroll_tree_node_id: ScrollTreeNodeId,
|
||||||
) -> Option<(LayoutPoint, LayoutTransform)> {
|
) -> Option<(LayoutPoint, FastLayoutTransform)> {
|
||||||
match self.projected_point_to_test {
|
match self.projected_point_to_test {
|
||||||
Some((cached_scroll_tree_node_id, projected_point, transform))
|
Some((cached_scroll_tree_node_id, projected_point, transform))
|
||||||
if cached_scroll_tree_node_id == scroll_tree_node_id =>
|
if cached_scroll_tree_node_id == scroll_tree_node_id =>
|
||||||
|
@ -105,21 +106,7 @@ impl<'a> HitTest<'a> {
|
||||||
.scroll_tree
|
.scroll_tree
|
||||||
.cumulative_root_to_node_transform(&scroll_tree_node_id)?;
|
.cumulative_root_to_node_transform(&scroll_tree_node_id)?;
|
||||||
|
|
||||||
// This comes from WebRender at `webrender/utils.rs`.
|
let projected_point = transform.project_point2d(self.point_to_test)?;
|
||||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1765204#c3.
|
|
||||||
//
|
|
||||||
// We are going from world coordinate space to spatial node coordinate space.
|
|
||||||
// Normally, that transformation happens in the opposite direction, but for hit
|
|
||||||
// testing everything is reversed. The result of the display transformation comes
|
|
||||||
// with a z-coordinate that we do not have access to here.
|
|
||||||
//
|
|
||||||
// We must solve for a value of z here that transforms to 0 (the value of z for our
|
|
||||||
// point).
|
|
||||||
let point = self.point_to_test;
|
|
||||||
let z =
|
|
||||||
-(point.x * transform.m13 + point.y * transform.m23 + transform.m43) / transform.m33;
|
|
||||||
let projected_point = transform.transform_point3d(Point3D::new(point.x, point.y, z))?;
|
|
||||||
let projected_point = Point2D::new(projected_point.x, projected_point.y);
|
|
||||||
|
|
||||||
self.projected_point_to_test = Some((scroll_tree_node_id, projected_point, transform));
|
self.projected_point_to_test = Some((scroll_tree_node_id, projected_point, transform));
|
||||||
Some((projected_point, transform))
|
Some((projected_point, transform))
|
||||||
|
|
|
@ -272,7 +272,7 @@ impl DisplayListBuilder<'_> {
|
||||||
info.origin,
|
info.origin,
|
||||||
*parent_spatial_node_id,
|
*parent_spatial_node_id,
|
||||||
info.transform_style,
|
info.transform_style,
|
||||||
PropertyBinding::Value(info.transform),
|
PropertyBinding::Value(*info.transform.to_transform()),
|
||||||
info.kind,
|
info.kind,
|
||||||
spatial_tree_item_key,
|
spatial_tree_item_key,
|
||||||
);
|
);
|
||||||
|
|
|
@ -234,7 +234,7 @@ impl StackingContextTree {
|
||||||
origin,
|
origin,
|
||||||
frame_origin_for_query,
|
frame_origin_for_query,
|
||||||
transform_style,
|
transform_style,
|
||||||
transform,
|
transform: transform.into(),
|
||||||
kind,
|
kind,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,7 +14,7 @@ use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafe
|
||||||
use layout_api::{LayoutElementType, LayoutNodeType, OffsetParentResponse};
|
use layout_api::{LayoutElementType, LayoutNodeType, OffsetParentResponse};
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoLayoutNode;
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use servo_geometry::{au_rect_to_f32_rect, f32_rect_to_au_rect};
|
use servo_geometry::{FastLayoutTransform, au_rect_to_f32_rect, f32_rect_to_au_rect};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use style::computed_values::display::T as Display;
|
use style::computed_values::display::T as Display;
|
||||||
use style::computed_values::position::T as Position;
|
use style::computed_values::position::T as Position;
|
||||||
|
@ -39,7 +39,6 @@ use style::values::specified::GenericGridTemplateComponent;
|
||||||
use style::values::specified::box_::DisplayInside;
|
use style::values::specified::box_::DisplayInside;
|
||||||
use style::values::specified::text::TextTransformCase;
|
use style::values::specified::text::TextTransformCase;
|
||||||
use style_traits::{ParsingMode, ToCss};
|
use style_traits::{ParsingMode, ToCss};
|
||||||
use webrender_api::units::LayoutTransform;
|
|
||||||
|
|
||||||
use crate::ArcRefCell;
|
use crate::ArcRefCell;
|
||||||
use crate::display_list::StackingContextTree;
|
use crate::display_list::StackingContextTree;
|
||||||
|
@ -55,7 +54,7 @@ use crate::taffy::SpecificTaffyGridInfo;
|
||||||
fn root_transform_for_layout_node(
|
fn root_transform_for_layout_node(
|
||||||
scroll_tree: &ScrollTree,
|
scroll_tree: &ScrollTree,
|
||||||
node: ServoLayoutNode<'_>,
|
node: ServoLayoutNode<'_>,
|
||||||
) -> Option<LayoutTransform> {
|
) -> Option<FastLayoutTransform> {
|
||||||
let fragments = node.fragments_for_pseudo(None);
|
let fragments = node.fragments_for_pseudo(None);
|
||||||
let box_fragment = fragments
|
let box_fragment = fragments
|
||||||
.first()
|
.first()
|
||||||
|
@ -90,7 +89,7 @@ pub(crate) fn process_content_box_request(
|
||||||
return Some(rect_union);
|
return Some(rect_union);
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(transform_au_rectangle(rect_union, transform))
|
transform_au_rectangle(rect_union, transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn process_content_boxes_request(
|
pub(crate) fn process_content_boxes_request(
|
||||||
|
@ -110,7 +109,7 @@ pub(crate) fn process_content_boxes_request(
|
||||||
};
|
};
|
||||||
|
|
||||||
content_boxes
|
content_boxes
|
||||||
.map(|rect| transform_au_rectangle(rect, transform))
|
.filter_map(|rect| transform_au_rectangle(rect, transform))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,9 +1149,17 @@ where
|
||||||
Some(computed_values.clone_font())
|
Some(computed_values.clone_font())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform_au_rectangle(rect_to_transform: Rect<Au>, transform: LayoutTransform) -> Rect<Au> {
|
fn transform_au_rectangle(
|
||||||
transform
|
rect_to_transform: Rect<Au>,
|
||||||
.outer_transformed_rect(&au_rect_to_f32_rect(rect_to_transform).cast_unit())
|
transform: FastLayoutTransform,
|
||||||
|
) -> Option<Rect<Au>> {
|
||||||
|
let rect_to_transform = &au_rect_to_f32_rect(rect_to_transform).cast_unit();
|
||||||
|
let outer_transformed_rect = match transform {
|
||||||
|
FastLayoutTransform::Offset(offset) => Some(rect_to_transform.translate(offset)),
|
||||||
|
FastLayoutTransform::Transform { transform, .. } => {
|
||||||
|
transform.outer_transformed_rect(rect_to_transform)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
outer_transformed_rect
|
||||||
.map(|transformed_rect| f32_rect_to_au_rect(transformed_rect.to_untyped()))
|
.map(|transformed_rect| f32_rect_to_au_rect(transformed_rect.to_untyped()))
|
||||||
.unwrap_or(rect_to_transform)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,12 @@ use base::id::ScrollTreeNodeId;
|
||||||
use base::print_tree::PrintTree;
|
use base::print_tree::PrintTree;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use embedder_traits::ViewportDetails;
|
use embedder_traits::ViewportDetails;
|
||||||
use euclid::{SideOffsets2D, Transform3D};
|
use euclid::SideOffsets2D;
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use servo_geometry::FastLayoutTransform;
|
||||||
use style::values::specified::Overflow;
|
use style::values::specified::Overflow;
|
||||||
use webrender_api::units::{
|
use webrender_api::units::{LayoutPixel, LayoutPoint, LayoutRect, LayoutSize, LayoutVector2D};
|
||||||
LayoutPixel, LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D,
|
|
||||||
};
|
|
||||||
use webrender_api::{
|
use webrender_api::{
|
||||||
Epoch, ExternalScrollId, PipelineId, ReferenceFrameKind, ScrollLocation, SpatialId,
|
Epoch, ExternalScrollId, PipelineId, ReferenceFrameKind, ScrollLocation, SpatialId,
|
||||||
StickyOffsetBounds, TransformStyle,
|
StickyOffsetBounds, TransformStyle,
|
||||||
|
@ -167,7 +166,7 @@ pub struct ReferenceFrameNodeInfo {
|
||||||
/// Origin of this frame relative to the document for bounding box queries.
|
/// Origin of this frame relative to the document for bounding box queries.
|
||||||
pub frame_origin_for_query: LayoutPoint,
|
pub frame_origin_for_query: LayoutPoint,
|
||||||
pub transform_style: TransformStyle,
|
pub transform_style: TransformStyle,
|
||||||
pub transform: LayoutTransform,
|
pub transform: FastLayoutTransform,
|
||||||
pub kind: ReferenceFrameKind,
|
pub kind: ReferenceFrameKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,8 +280,8 @@ impl ScrollableNodeInfo {
|
||||||
/// multiplication when transforms are not involved.
|
/// multiplication when transforms are not involved.
|
||||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
|
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
|
||||||
pub struct ScrollTreeNodeTransformationCache {
|
pub struct ScrollTreeNodeTransformationCache {
|
||||||
node_to_root_transform: LayoutTransform,
|
node_to_root_transform: FastLayoutTransform,
|
||||||
root_to_node_transform: Option<LayoutTransform>,
|
root_to_node_transform: Option<FastLayoutTransform>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -604,7 +603,10 @@ impl ScrollTree {
|
||||||
|
|
||||||
/// Find a transformation that can convert a point in the node coordinate system to a
|
/// Find a transformation that can convert a point in the node coordinate system to a
|
||||||
/// point in the root coordinate system.
|
/// point in the root coordinate system.
|
||||||
pub fn cumulative_node_to_root_transform(&self, node_id: &ScrollTreeNodeId) -> LayoutTransform {
|
pub fn cumulative_node_to_root_transform(
|
||||||
|
&self,
|
||||||
|
node_id: &ScrollTreeNodeId,
|
||||||
|
) -> FastLayoutTransform {
|
||||||
let node = self.get_node(node_id);
|
let node = self.get_node(node_id);
|
||||||
if let Some(cached_transforms) = node.transformation_cache.get() {
|
if let Some(cached_transforms) = node.transformation_cache.get() {
|
||||||
return cached_transforms.node_to_root_transform;
|
return cached_transforms.node_to_root_transform;
|
||||||
|
@ -621,7 +623,7 @@ impl ScrollTree {
|
||||||
pub fn cumulative_root_to_node_transform(
|
pub fn cumulative_root_to_node_transform(
|
||||||
&self,
|
&self,
|
||||||
node_id: &ScrollTreeNodeId,
|
node_id: &ScrollTreeNodeId,
|
||||||
) -> Option<LayoutTransform> {
|
) -> Option<FastLayoutTransform> {
|
||||||
let node = self.get_node(node_id);
|
let node = self.get_node(node_id);
|
||||||
if let Some(cached_transforms) = node.transformation_cache.get() {
|
if let Some(cached_transforms) = node.transformation_cache.get() {
|
||||||
return cached_transforms.root_to_node_transform;
|
return cached_transforms.root_to_node_transform;
|
||||||
|
@ -642,25 +644,16 @@ impl ScrollTree {
|
||||||
None => (Default::default(), Default::default()),
|
None => (Default::default(), Default::default()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let change_basis =
|
|
||||||
|transform: &Transform3D<f32, LayoutPixel, LayoutPixel>, x: f32, y: f32| {
|
|
||||||
let pre_translation = Transform3D::translation(x, y, 0.0);
|
|
||||||
let post_translation = Transform3D::translation(-x, -y, 0.0);
|
|
||||||
post_translation.then(transform).then(&pre_translation)
|
|
||||||
};
|
|
||||||
|
|
||||||
let (node_to_parent_transform, parent_to_node_transform) = match &node.info {
|
let (node_to_parent_transform, parent_to_node_transform) = match &node.info {
|
||||||
SpatialTreeNodeInfo::ReferenceFrame(info) => {
|
SpatialTreeNodeInfo::ReferenceFrame(info) => {
|
||||||
// To apply a transformation we need to make sure the rectangle's
|
// To apply a transformation we need to make sure the rectangle's
|
||||||
// coordinate space is the same as reference frame's coordinate space.
|
// coordinate space is the same as reference frame's coordinate space.
|
||||||
let node_to_parent_transform = change_basis(
|
let offset = info.frame_origin_for_query.to_vector();
|
||||||
&info.transform,
|
let node_to_parent_transform =
|
||||||
info.frame_origin_for_query.x,
|
info.transform.pre_translate(-offset).then_translate(offset);
|
||||||
info.frame_origin_for_query.y,
|
|
||||||
);
|
|
||||||
|
|
||||||
let parent_to_node_transform =
|
let parent_to_node_transform =
|
||||||
Transform3D::translation(-info.origin.x, -info.origin.y, 0.0);
|
FastLayoutTransform::Offset(-info.origin.to_vector());
|
||||||
let parent_to_node_transform = info
|
let parent_to_node_transform = info
|
||||||
.transform
|
.transform
|
||||||
.inverse()
|
.inverse()
|
||||||
|
@ -675,20 +668,15 @@ impl ScrollTree {
|
||||||
SpatialTreeNodeInfo::Scroll(info) => {
|
SpatialTreeNodeInfo::Scroll(info) => {
|
||||||
sticky_info.nearest_scrolling_ancestor_viewport = info.clip_rect;
|
sticky_info.nearest_scrolling_ancestor_viewport = info.clip_rect;
|
||||||
sticky_info.nearest_scrolling_ancestor_offset = -info.offset;
|
sticky_info.nearest_scrolling_ancestor_offset = -info.offset;
|
||||||
|
let offset_transform = FastLayoutTransform::Offset(-info.offset);
|
||||||
(
|
(offset_transform, offset_transform.inverse())
|
||||||
Transform3D::translation(-info.offset.x, -info.offset.y, 0.0),
|
|
||||||
Some(Transform3D::translation(info.offset.x, info.offset.y, 0.0)),
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
SpatialTreeNodeInfo::Sticky(info) => {
|
SpatialTreeNodeInfo::Sticky(info) => {
|
||||||
let offset = info.calculate_sticky_offset(&sticky_info);
|
let offset = info.calculate_sticky_offset(&sticky_info);
|
||||||
sticky_info.nearest_scrolling_ancestor_offset += offset;
|
sticky_info.nearest_scrolling_ancestor_offset += offset;
|
||||||
(
|
let offset_transform = FastLayoutTransform::Offset(offset);
|
||||||
Transform3D::translation(offset.x, offset.y, 0.0),
|
(offset_transform, offset_transform.inverse())
|
||||||
Some(Transform3D::translation(-offset.x, -offset.y, 0.0)),
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -845,7 +833,7 @@ impl CompositorDisplayListInfo {
|
||||||
origin: Default::default(),
|
origin: Default::default(),
|
||||||
frame_origin_for_query: Default::default(),
|
frame_origin_for_query: Default::default(),
|
||||||
transform_style: TransformStyle::Flat,
|
transform_style: TransformStyle::Flat,
|
||||||
transform: LayoutTransform::identity(),
|
transform: FastLayoutTransform::identity(),
|
||||||
kind: ReferenceFrameKind::default(),
|
kind: ReferenceFrameKind::default(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue