mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
layout: Allow inline elements to be containing blocks for
absolutely-positioned elements. This also implements a little bit of the infrastructure needed to support for fragmentation via support for multiple positioned fragments in one flow. Improves Google.
This commit is contained in:
parent
b3b9deafa7
commit
1f0b5889da
19 changed files with 592 additions and 241 deletions
|
@ -324,19 +324,15 @@ pub trait Flow: fmt::Debug + Sync {
|
|||
self.positioning() == position::T::fixed
|
||||
}
|
||||
|
||||
fn is_positioned(&self) -> bool {
|
||||
self.is_relatively_positioned() || base(self).flags.contains(IS_ABSOLUTELY_POSITIONED)
|
||||
fn contains_positioned_fragments(&self) -> bool {
|
||||
self.contains_relatively_positioned_fragments() ||
|
||||
base(self).flags.contains(IS_ABSOLUTELY_POSITIONED)
|
||||
}
|
||||
|
||||
fn is_relatively_positioned(&self) -> bool {
|
||||
fn contains_relatively_positioned_fragments(&self) -> bool {
|
||||
self.positioning() == position::T::relative
|
||||
}
|
||||
|
||||
/// Return true if this is the root of an absolute flow tree.
|
||||
fn is_root_of_absolute_flow_tree(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns true if this is an absolute containing block.
|
||||
fn is_absolute_containing_block(&self) -> bool {
|
||||
false
|
||||
|
@ -350,14 +346,12 @@ pub trait Flow: fmt::Debug + Sync {
|
|||
/// this is only used for absolutely-positioned inline-blocks.
|
||||
fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au);
|
||||
|
||||
/// Return the dimensions of the containing block generated by this flow for absolutely-
|
||||
/// positioned descendants. For block flows, this is the padding box.
|
||||
/// Return the size of the containing block generated by this flow for the absolutely-
|
||||
/// positioned descendant referenced by `for_flow`. For block flows, this is the padding box.
|
||||
///
|
||||
/// NB: Do not change this `&self` to `&mut self` under any circumstances! It has security
|
||||
/// implications because this can be called on parents concurrently from descendants!
|
||||
fn generated_containing_block_rect(&self) -> LogicalRect<Au> {
|
||||
panic!("generated_containing_block_rect not yet implemented for this flow")
|
||||
}
|
||||
fn generated_containing_block_size(&self, _: OpaqueFlow) -> LogicalSize<Au>;
|
||||
|
||||
/// Returns a layer ID for the given fragment.
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -440,6 +434,9 @@ pub trait ImmutableFlowUtils {
|
|||
/// Generates missing child flow of this flow.
|
||||
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> FlowRef;
|
||||
|
||||
/// Returns true if this flow contains fragments that are roots of an absolute flow tree.
|
||||
fn contains_roots_of_absolute_flow_tree(&self) -> bool;
|
||||
|
||||
/// Returns true if this flow has no children.
|
||||
fn is_leaf(self) -> bool;
|
||||
|
||||
|
@ -471,6 +468,21 @@ pub trait MutableFlowUtils {
|
|||
/// Traverses the tree in postorder.
|
||||
fn traverse_postorder<T:PostorderFlowTraversal>(self, traversal: &T);
|
||||
|
||||
/// Traverse the Absolute flow tree in preorder.
|
||||
///
|
||||
/// Traverse all your direct absolute descendants, who will then traverse
|
||||
/// their direct absolute descendants.
|
||||
///
|
||||
/// Return true if the traversal is to continue or false to stop.
|
||||
fn traverse_preorder_absolute_flows<T>(&mut self, traversal: &mut T)
|
||||
where T: PreorderFlowTraversal;
|
||||
|
||||
/// Traverse the Absolute flow tree in postorder.
|
||||
///
|
||||
/// Return true if the traversal is to continue or false to stop.
|
||||
fn traverse_postorder_absolute_flows<T>(&mut self, traversal: &mut T)
|
||||
where T: PostorderFlowTraversal;
|
||||
|
||||
// Mutators
|
||||
|
||||
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
|
||||
|
@ -1183,6 +1195,11 @@ impl<'a> ImmutableFlowUtils for &'a (Flow + 'a) {
|
|||
FlowRef::new(flow)
|
||||
}
|
||||
|
||||
/// Returns true if this flow contains fragments that are roots of an absolute flow tree.
|
||||
fn contains_roots_of_absolute_flow_tree(&self) -> bool {
|
||||
self.contains_relatively_positioned_fragments() || self.is_root()
|
||||
}
|
||||
|
||||
/// Returns true if this flow has no children.
|
||||
fn is_leaf(self) -> bool {
|
||||
base(self).children.len() == 0
|
||||
|
@ -1276,6 +1293,34 @@ impl<'a> MutableFlowUtils for &'a mut (Flow + 'a) {
|
|||
self.repair_style(style);
|
||||
self.bubble_inline_sizes();
|
||||
}
|
||||
|
||||
/// Traverse the Absolute flow tree in preorder.
|
||||
///
|
||||
/// Traverse all your direct absolute descendants, who will then traverse
|
||||
/// their direct absolute descendants.
|
||||
///
|
||||
/// Return true if the traversal is to continue or false to stop.
|
||||
fn traverse_preorder_absolute_flows<T>(&mut self, traversal: &mut T)
|
||||
where T: PreorderFlowTraversal {
|
||||
traversal.process(*self);
|
||||
|
||||
let descendant_offset_iter = mut_base(*self).abs_descendants.iter();
|
||||
for ref mut descendant_link in descendant_offset_iter {
|
||||
descendant_link.traverse_preorder_absolute_flows(traversal)
|
||||
}
|
||||
}
|
||||
|
||||
/// Traverse the Absolute flow tree in postorder.
|
||||
///
|
||||
/// Return true if the traversal is to continue or false to stop.
|
||||
fn traverse_postorder_absolute_flows<T>(&mut self, traversal: &mut T)
|
||||
where T: PostorderFlowTraversal {
|
||||
for mut descendant_link in mut_base(*self).abs_descendants.iter() {
|
||||
descendant_link.traverse_postorder_absolute_flows(traversal);
|
||||
}
|
||||
|
||||
traversal.process(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MutableOwnedFlowUtils for FlowRef {
|
||||
|
@ -1288,13 +1333,11 @@ impl MutableOwnedFlowUtils for FlowRef {
|
|||
/// construction is allowed to possess.
|
||||
fn set_absolute_descendants(&mut self, abs_descendants: AbsDescendants) {
|
||||
let this = self.clone();
|
||||
|
||||
let block = self.as_block();
|
||||
block.base.abs_descendants = abs_descendants;
|
||||
|
||||
for descendant_link in block.base.abs_descendants.iter() {
|
||||
let base = mut_base(descendant_link);
|
||||
base.absolute_cb.set(this.clone());
|
||||
let base = mut_base(&mut **self);
|
||||
base.abs_descendants = abs_descendants;
|
||||
for descendant_link in base.abs_descendants.iter() {
|
||||
let descendant_base = mut_base(descendant_link);
|
||||
descendant_base.absolute_cb.set(this.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1329,10 +1372,33 @@ impl ContainingBlockLink {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn generated_containing_block_rect(&mut self) -> LogicalRect<Au> {
|
||||
pub fn generated_containing_block_size(&mut self, for_flow: OpaqueFlow) -> LogicalSize<Au> {
|
||||
match self.link {
|
||||
None => panic!("haven't done it"),
|
||||
Some(ref mut link) => link.generated_containing_block_rect(),
|
||||
None => {
|
||||
panic!("Link to containing block not established; perhaps you forgot to call \
|
||||
`set_absolute_descendants`?")
|
||||
}
|
||||
Some(ref mut link) => link.generated_containing_block_size(for_flow),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper for the pointer address of a flow. These pointer addresses may only be compared for
|
||||
/// equality with other such pointer addresses, never dereferenced.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct OpaqueFlow(pub usize);
|
||||
|
||||
impl OpaqueFlow {
|
||||
#[allow(unsafe_code)]
|
||||
pub fn from_flow(flow: &Flow) -> OpaqueFlow {
|
||||
unsafe {
|
||||
let object = mem::transmute::<&Flow,raw::TraitObject>(flow);
|
||||
OpaqueFlow(object.data as usize)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_base_flow(base_flow: &BaseFlow) -> OpaqueFlow {
|
||||
OpaqueFlow(base_flow as *const BaseFlow as usize)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue