mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
layout: Implement node geometry queries against BoxTree
's Fragment
(#36663)
This is a followup to #36629, continuing to implement script-based layout queries using the `Fragment`s attached to the `BoxTree`. In this change, geometry queris (apart from parent offset) are calculated using `Fragment`s hanging of the `BoxTree`. In order to make this work, all `Fragment`s for inlines split by blocks, need to be accessible in the `BoxTree`. This required some changes to the way that box tree items were stored in DOM `BoxSlot`s. Now every inline level item can have more than a single `BoxTree` item. These are carefully collected by the `InlineFormattingContextBuilder` -- currently a bit fragile, but with more documentation. Testing: There are tests for these changes. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
cc91395397
commit
b63a1818c4
13 changed files with 197 additions and 170 deletions
|
@ -7,6 +7,7 @@ use std::sync::Arc;
|
|||
use app_units::Au;
|
||||
use base::id::PipelineId;
|
||||
use base::print_tree::PrintTree;
|
||||
use euclid::{Point2D, Rect, Size2D, UnknownUnit};
|
||||
use fonts::{ByteIndex, FontMetrics, GlyphStore};
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use range::Range as ServoRange;
|
||||
|
@ -21,7 +22,7 @@ use super::{
|
|||
Tag,
|
||||
};
|
||||
use crate::cell::ArcRefCell;
|
||||
use crate::geom::{LogicalSides, PhysicalRect};
|
||||
use crate::geom::{LogicalSides, PhysicalPoint, PhysicalRect};
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
|
||||
#[derive(Clone, MallocSizeOf)]
|
||||
|
@ -190,6 +191,56 @@ impl Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn cumulative_content_box_rect(&self) -> Option<PhysicalRect<Au>> {
|
||||
match self {
|
||||
Fragment::Box(fragment) | Fragment::Float(fragment) => {
|
||||
let fragment = fragment.borrow();
|
||||
Some(fragment.offset_by_containing_block(&fragment.border_rect()))
|
||||
},
|
||||
Fragment::Positioning(_) |
|
||||
Fragment::Text(_) |
|
||||
Fragment::AbsoluteOrFixedPositioned(_) |
|
||||
Fragment::Image(_) |
|
||||
Fragment::IFrame(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn client_rect(&self) -> Rect<i32, UnknownUnit> {
|
||||
let rect = match self {
|
||||
Fragment::Box(fragment) | Fragment::Float(fragment) => {
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-clienttop
|
||||
// " If the element has no associated CSS layout box or if the
|
||||
// CSS layout box is inline, return zero." For this check we
|
||||
// also explicitly ignore the list item portion of the display
|
||||
// style.
|
||||
let fragment = fragment.borrow();
|
||||
if fragment.is_inline_box() {
|
||||
return Rect::zero();
|
||||
}
|
||||
|
||||
if fragment.is_table_wrapper() {
|
||||
// For tables the border actually belongs to the table grid box,
|
||||
// so we need to include it in the dimension of the table wrapper box.
|
||||
let mut rect = fragment.border_rect();
|
||||
rect.origin = PhysicalPoint::zero();
|
||||
rect
|
||||
} else {
|
||||
let mut rect = fragment.padding_rect();
|
||||
rect.origin = PhysicalPoint::new(fragment.border.left, fragment.border.top);
|
||||
rect
|
||||
}
|
||||
},
|
||||
_ => return Rect::zero(),
|
||||
}
|
||||
.to_untyped();
|
||||
|
||||
let rect = Rect::new(
|
||||
Point2D::new(rect.origin.x.to_f32_px(), rect.origin.y.to_f32_px()),
|
||||
Size2D::new(rect.size.width.to_f32_px(), rect.size.height.to_f32_px()),
|
||||
);
|
||||
rect.round().to_i32()
|
||||
}
|
||||
|
||||
pub(crate) fn find<T>(
|
||||
&self,
|
||||
manager: &ContainingBlockManager<PhysicalRect<Au>>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue