mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
layout: Explicitly thread border box dimensions and relative offsets
through display list building. The old `flow_origin` concept was ill-defined (sometimes the border box plus the flow origin, sometimes including horizontal margins and sometimes not, sometimes including relative position and sometimes not), leading to brittleness and test failures. This commit reworks the logic to always pass border box origins in during display list building.
This commit is contained in:
parent
5ea2c6dcfd
commit
bf540d590a
20 changed files with 591 additions and 456 deletions
|
@ -609,6 +609,20 @@ impl ClippingRegion {
|
||||||
});
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Translates this clipping region by the given vector.
|
||||||
|
#[inline]
|
||||||
|
pub fn translate(&self, delta: &Point2D<Au>) -> ClippingRegion {
|
||||||
|
ClippingRegion {
|
||||||
|
main: self.main.translate(delta),
|
||||||
|
complex: self.complex.iter().map(|complex| {
|
||||||
|
ComplexClippingRegion {
|
||||||
|
rect: complex.rect.translate(delta),
|
||||||
|
radii: complex.radii,
|
||||||
|
}
|
||||||
|
}).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata attached to each display item. This is useful for performing auxiliary tasks with
|
/// Metadata attached to each display item. This is useful for performing auxiliary tasks with
|
||||||
|
|
|
@ -32,7 +32,7 @@ use context::LayoutContext;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use display_list_builder::{BlockFlowDisplayListBuilding, FragmentDisplayListBuilding};
|
use display_list_builder::{BlockFlowDisplayListBuilding, FragmentDisplayListBuilding};
|
||||||
use floats::{ClearType, FloatKind, Floats, PlacementInfo};
|
use floats::{ClearType, FloatKind, Floats, PlacementInfo};
|
||||||
use flow::{AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow};
|
use flow::{mod, AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow};
|
||||||
use flow::{ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTraversal};
|
use flow::{ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTraversal};
|
||||||
use flow::{PostorderFlowTraversal, mut_base};
|
use flow::{PostorderFlowTraversal, mut_base};
|
||||||
use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
|
use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
|
||||||
|
@ -40,8 +40,7 @@ use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
|
||||||
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
|
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
|
||||||
use flow::{IS_ABSOLUTELY_POSITIONED};
|
use flow::{IS_ABSOLUTELY_POSITIONED};
|
||||||
use flow::{CLEARS_LEFT, CLEARS_RIGHT};
|
use flow::{CLEARS_LEFT, CLEARS_RIGHT};
|
||||||
use flow;
|
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
|
||||||
use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo};
|
|
||||||
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
|
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use model::{IntrinsicISizes, MarginCollapseInfo};
|
use model::{IntrinsicISizes, MarginCollapseInfo};
|
||||||
|
@ -49,11 +48,11 @@ use model::{MaybeAuto, CollapsibleMargins, specified, specified_or_none};
|
||||||
use table::ColumnComputedInlineSize;
|
use table::ColumnComputedInlineSize;
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use geom::{Rect, Size2D};
|
use geom::{Point2D, Rect, Size2D};
|
||||||
use gfx::display_list::{ClippingRegion, DisplayList};
|
use gfx::display_list::{ClippingRegion, DisplayList};
|
||||||
use serialize::{Encoder, Encodable};
|
use serialize::{Encoder, Encodable};
|
||||||
use servo_msg::compositor_msg::LayerId;
|
use servo_msg::compositor_msg::LayerId;
|
||||||
use servo_util::geometry::{Au, MAX_AU, ZERO_POINT};
|
use servo_util::geometry::{Au, MAX_AU};
|
||||||
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
|
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
|
||||||
use servo_util::opts;
|
use servo_util::opts;
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
|
@ -1769,23 +1768,40 @@ impl Flow for BlockFlow {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compute the origin and clipping rectangle for children.
|
// Compute the origin and clipping rectangle for children.
|
||||||
let origin_for_children = if self.fragment.establishes_stacking_context() {
|
let relative_offset = relative_offset.to_physical(self.base.writing_mode);
|
||||||
ZERO_POINT
|
let origin_for_children;
|
||||||
|
let clip_in_child_coordinate_system;
|
||||||
|
if self.fragment.establishes_stacking_context() {
|
||||||
|
// We establish a stacking context, so the position of our children is vertically
|
||||||
|
// correct, but has to be adjusted to accommodate horizontal margins. (Note the
|
||||||
|
// calculation involving `position` below and recall that inline-direction flow
|
||||||
|
// positions are relative to the edges of the margin box.)
|
||||||
|
//
|
||||||
|
// FIXME(pcwalton): Is this vertical-writing-direction-safe?
|
||||||
|
let margin = self.fragment.margin.to_physical(self.base.writing_mode);
|
||||||
|
origin_for_children = Point2D(-margin.left, Au(0)) + relative_offset;
|
||||||
|
clip_in_child_coordinate_system =
|
||||||
|
self.base.clip.translate(&-self.base.stacking_relative_position)
|
||||||
} else {
|
} else {
|
||||||
self.base.stacking_relative_position
|
origin_for_children = self.base.stacking_relative_position + relative_offset;
|
||||||
};
|
clip_in_child_coordinate_system = self.base.clip.clone()
|
||||||
let clip = self.fragment.clipping_region_for_children(&self.base.clip,
|
}
|
||||||
&origin_for_children);
|
let stacking_relative_border_box =
|
||||||
|
self.fragment
|
||||||
|
.stacking_relative_border_box(&self.base.stacking_relative_position,
|
||||||
|
&self.base
|
||||||
|
.absolute_position_info
|
||||||
|
.relative_containing_block_size,
|
||||||
|
CoordinateSystem::Self);
|
||||||
|
let clip = self.fragment.clipping_region_for_children(&clip_in_child_coordinate_system,
|
||||||
|
&stacking_relative_border_box);
|
||||||
|
|
||||||
// Process children.
|
// Process children.
|
||||||
let writing_mode = self.base.writing_mode;
|
|
||||||
for kid in self.base.child_iter() {
|
for kid in self.base.child_iter() {
|
||||||
if !flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
if !flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
||||||
let kid_base = flow::mut_base(kid);
|
let kid_base = flow::mut_base(kid);
|
||||||
kid_base.stacking_relative_position =
|
kid_base.stacking_relative_position = origin_for_children +
|
||||||
origin_for_children
|
kid_base.position.start.to_physical(kid_base.writing_mode, container_size);
|
||||||
+ kid_base.position.start.to_physical(kid_base.writing_mode, container_size)
|
|
||||||
+ relative_offset.to_physical(writing_mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
flow::mut_base(kid).absolute_position_info = absolute_position_info_for_children;
|
flow::mut_base(kid).absolute_position_info = absolute_position_info_for_children;
|
||||||
|
@ -1832,16 +1848,20 @@ impl Flow for BlockFlow {
|
||||||
|
|
||||||
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
|
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
|
||||||
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
|
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
|
||||||
self.fragment.style().logical_position().inline_start == LengthOrPercentageOrAuto::Auto &&
|
self.fragment.style().logical_position().inline_start ==
|
||||||
self.fragment.style().logical_position().inline_end == LengthOrPercentageOrAuto::Auto {
|
LengthOrPercentageOrAuto::Auto &&
|
||||||
|
self.fragment.style().logical_position().inline_end ==
|
||||||
|
LengthOrPercentageOrAuto::Auto {
|
||||||
self.base.position.start.i = inline_position
|
self.base.position.start.i = inline_position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) {
|
fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) {
|
||||||
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
|
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
|
||||||
self.fragment.style().logical_position().block_start == LengthOrPercentageOrAuto::Auto &&
|
self.fragment.style().logical_position().block_start ==
|
||||||
self.fragment.style().logical_position().block_end == LengthOrPercentageOrAuto::Auto {
|
LengthOrPercentageOrAuto::Auto &&
|
||||||
|
self.fragment.style().logical_position().block_end ==
|
||||||
|
LengthOrPercentageOrAuto::Auto {
|
||||||
self.base.position.start.b = block_position
|
self.base.position.start.b = block_position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1861,16 +1881,32 @@ impl Flow for BlockFlow {
|
||||||
self.fragment.compute_overflow()
|
self.fragment.compute_overflow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
if iterator.should_process(&self.fragment) {
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
iterator.process(&self.fragment, self.fragment.compute_overflow());
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
if !iterator.should_process(&self.fragment) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iterator.process(&self.fragment,
|
||||||
|
&self.fragment
|
||||||
|
.stacking_relative_border_box(&self.base.stacking_relative_position,
|
||||||
|
&self.base
|
||||||
|
.absolute_position_info
|
||||||
|
.relative_containing_block_size,
|
||||||
|
CoordinateSystem::Parent)
|
||||||
|
.translate(stacking_context_position));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for BlockFlow {
|
impl fmt::Show for BlockFlow {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{} - {:x}: frag={} ({})", self.class(), self.base.debug_id(), self.fragment, self.base)
|
write!(f,
|
||||||
|
"{} - {:x}: frag={} ({})",
|
||||||
|
self.class(),
|
||||||
|
self.base.debug_id(),
|
||||||
|
self.fragment,
|
||||||
|
self.base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,9 +52,9 @@ use servo_util::opts;
|
||||||
use std::collections::DList;
|
use std::collections::DList;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::atomic::Relaxed;
|
use std::sync::atomic::Relaxed;
|
||||||
use style::ComputedValues;
|
|
||||||
use style::computed_values::{caption_side, display, empty_cells, float, list_style_position};
|
use style::computed_values::{caption_side, display, empty_cells, float, list_style_position};
|
||||||
use style::computed_values::{position};
|
use style::computed_values::{position};
|
||||||
|
use style::{mod, ComputedValues};
|
||||||
use sync::Arc;
|
use sync::Arc;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -681,7 +681,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
/// doesn't render its children, so this just nukes a child's fragments and creates a
|
/// doesn't render its children, so this just nukes a child's fragments and creates a
|
||||||
/// `Fragment`.
|
/// `Fragment`.
|
||||||
fn build_fragments_for_replaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
fn build_fragments_for_replaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
kid.set_flow_construction_result(ConstructionResult::None)
|
kid.set_flow_construction_result(ConstructionResult::None)
|
||||||
}
|
}
|
||||||
|
@ -697,24 +697,42 @@ impl<'a> FlowConstructor<'a> {
|
||||||
node.restyle_damage()))
|
node.restyle_damage()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the value of `display` property is not `inline`, then we have a situation like
|
||||||
|
// `<div style="position:absolute">foo bar baz</div>`. The fragments for `foo`, `bar`, and
|
||||||
|
// `baz` had better not be absolutely positioned!
|
||||||
|
let mut style = (*node.style()).clone();
|
||||||
|
if style.get_box().display != display::inline {
|
||||||
|
style = Arc::new(style::make_inline(&*style))
|
||||||
|
}
|
||||||
|
|
||||||
// If this is generated content, then we need to initialize the accumulator with the
|
// If this is generated content, then we need to initialize the accumulator with the
|
||||||
// fragment corresponding to that content. Otherwise, just initialize with the ordinary
|
// fragment corresponding to that content. Otherwise, just initialize with the ordinary
|
||||||
// fragment that needs to be generated for this inline node.
|
// fragment that needs to be generated for this inline node.
|
||||||
let fragment = if node.get_pseudo_element_type() != PseudoElementType::Normal {
|
let fragment = if node.get_pseudo_element_type() != PseudoElementType::Normal {
|
||||||
let fragment_info = SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::new(node));
|
let fragment_info =
|
||||||
Fragment::new_from_specific_info(node, fragment_info)
|
SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::new(node));
|
||||||
|
Fragment::from_opaque_node_and_style(
|
||||||
|
OpaqueNodeMethods::from_thread_safe_layout_node(node),
|
||||||
|
style,
|
||||||
|
node.restyle_damage(),
|
||||||
|
fragment_info)
|
||||||
} else {
|
} else {
|
||||||
Fragment::new(self, node)
|
Fragment::from_opaque_node_and_style(
|
||||||
|
OpaqueNodeMethods::from_thread_safe_layout_node(node),
|
||||||
|
style,
|
||||||
|
node.restyle_damage(),
|
||||||
|
self.build_specific_fragment_info_for_node(node))
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut fragments = DList::new();
|
let mut fragments = DList::new();
|
||||||
fragments.push_back(fragment);
|
fragments.push_back(fragment);
|
||||||
|
|
||||||
let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
let construction_item =
|
||||||
splits: DList::new(),
|
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
||||||
fragments: fragments,
|
splits: DList::new(),
|
||||||
abs_descendants: Descendants::new(),
|
fragments: fragments,
|
||||||
});
|
abs_descendants: Descendants::new(),
|
||||||
|
});
|
||||||
ConstructionResult::ConstructionItem(construction_item)
|
ConstructionResult::ConstructionItem(construction_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,17 +744,19 @@ impl<'a> FlowConstructor<'a> {
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(block_flow));
|
let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(
|
||||||
|
block_flow));
|
||||||
let fragment = Fragment::new_from_specific_info(node, fragment_info);
|
let fragment = Fragment::new_from_specific_info(node, fragment_info);
|
||||||
|
|
||||||
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
|
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
|
||||||
fragment_accumulator.fragments.push_back(fragment);
|
fragment_accumulator.fragments.push_back(fragment);
|
||||||
|
|
||||||
let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
let construction_item =
|
||||||
splits: DList::new(),
|
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
||||||
fragments: fragment_accumulator.to_dlist(),
|
splits: DList::new(),
|
||||||
abs_descendants: abs_descendants,
|
fragments: fragment_accumulator.to_dlist(),
|
||||||
});
|
abs_descendants: abs_descendants,
|
||||||
|
});
|
||||||
ConstructionResult::ConstructionItem(construction_item)
|
ConstructionResult::ConstructionItem(construction_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,11 +777,12 @@ impl<'a> FlowConstructor<'a> {
|
||||||
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
|
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
|
||||||
fragment_accumulator.fragments.push_back(fragment);
|
fragment_accumulator.fragments.push_back(fragment);
|
||||||
|
|
||||||
let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
let construction_item =
|
||||||
splits: DList::new(),
|
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
||||||
fragments: fragment_accumulator.to_dlist(),
|
splits: DList::new(),
|
||||||
abs_descendants: abs_descendants,
|
fragments: fragment_accumulator.to_dlist(),
|
||||||
});
|
abs_descendants: abs_descendants,
|
||||||
|
});
|
||||||
ConstructionResult::ConstructionItem(construction_item)
|
ConstructionResult::ConstructionItem(construction_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,9 @@
|
||||||
use block::BlockFlow;
|
use block::BlockFlow;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use flow::{mod, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER};
|
use flow::{mod, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER};
|
||||||
use fragment::{Fragment, SpecificFragmentInfo, IframeFragmentInfo, ImageFragmentInfo};
|
use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo};
|
||||||
use fragment::ScannedTextFragmentInfo;
|
use fragment::{ScannedTextFragmentInfo, SpecificFragmentInfo};
|
||||||
|
use inline::InlineFlow;
|
||||||
use list_item::ListItemFlow;
|
use list_item::ListItemFlow;
|
||||||
use model;
|
use model;
|
||||||
use util::{OpaqueNodeMethods, ToGfxColor};
|
use util::{OpaqueNodeMethods, ToGfxColor};
|
||||||
|
@ -36,8 +37,8 @@ use servo_msg::constellation_msg::Msg as ConstellationMsg;
|
||||||
use servo_msg::constellation_msg::ConstellationChan;
|
use servo_msg::constellation_msg::ConstellationChan;
|
||||||
use servo_net::image::holder::ImageHolder;
|
use servo_net::image::holder::ImageHolder;
|
||||||
use servo_util::cursor::{DefaultCursor, TextCursor, VerticalTextCursor};
|
use servo_util::cursor::{DefaultCursor, TextCursor, VerticalTextCursor};
|
||||||
use servo_util::geometry::{mod, Au, ZERO_POINT};
|
use servo_util::geometry::{mod, Au};
|
||||||
use servo_util::logical_geometry::{LogicalRect, WritingMode};
|
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
|
||||||
use servo_util::opts;
|
use servo_util::opts;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::num::FloatMath;
|
use std::num::FloatMath;
|
||||||
|
@ -133,16 +134,19 @@ pub trait FragmentDisplayListBuilding {
|
||||||
absolute_bounds: &Rect<Au>,
|
absolute_bounds: &Rect<Au>,
|
||||||
clip: &ClippingRegion);
|
clip: &ClippingRegion);
|
||||||
|
|
||||||
|
/// Adds display items necessary to draw debug boxes around a scanned text fragment.
|
||||||
fn build_debug_borders_around_text_fragments(&self,
|
fn build_debug_borders_around_text_fragments(&self,
|
||||||
style: &ComputedValues,
|
style: &ComputedValues,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
flow_origin: Point2D<Au>,
|
stacking_relative_border_box: &Rect<Au>,
|
||||||
|
stacking_relative_content_box: &Rect<Au>,
|
||||||
text_fragment: &ScannedTextFragmentInfo,
|
text_fragment: &ScannedTextFragmentInfo,
|
||||||
clip: &ClippingRegion);
|
clip: &ClippingRegion);
|
||||||
|
|
||||||
|
/// Adds display items necessary to draw debug boxes around this fragment.
|
||||||
fn build_debug_borders_around_fragment(&self,
|
fn build_debug_borders_around_fragment(&self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
flow_origin: Point2D<Au>,
|
stacking_relative_border_box: &Rect<Au>,
|
||||||
clip: &ClippingRegion);
|
clip: &ClippingRegion);
|
||||||
|
|
||||||
/// Adds the display items for this fragment to the given display list.
|
/// Adds the display items for this fragment to the given display list.
|
||||||
|
@ -152,12 +156,16 @@ pub trait FragmentDisplayListBuilding {
|
||||||
/// * `display_list`: The display list to add display items to.
|
/// * `display_list`: The display list to add display items to.
|
||||||
/// * `layout_context`: The layout context.
|
/// * `layout_context`: The layout context.
|
||||||
/// * `dirty`: The dirty rectangle in the coordinate system of the owning flow.
|
/// * `dirty`: The dirty rectangle in the coordinate system of the owning flow.
|
||||||
/// * `flow_origin`: Position of the origin of the owning flow wrt the display list root flow.
|
/// * `stacking_relative_flow_origin`: Position of the origin of the owning flow with respect
|
||||||
|
/// to its nearest ancestor stacking context.
|
||||||
|
/// * `relative_containing_block_size`: The size of the containing block that
|
||||||
|
/// `position: relative` makes use of.
|
||||||
/// * `clip`: The region to clip the display items to.
|
/// * `clip`: The region to clip the display items to.
|
||||||
fn build_display_list(&mut self,
|
fn build_display_list(&mut self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
flow_origin: Point2D<Au>,
|
stacking_relative_flow_origin: &Point2D<Au>,
|
||||||
|
relative_containing_block_size: &LogicalSize<Au>,
|
||||||
background_and_border_level: BackgroundAndBorderLevel,
|
background_and_border_level: BackgroundAndBorderLevel,
|
||||||
clip: &ClippingRegion);
|
clip: &ClippingRegion);
|
||||||
|
|
||||||
|
@ -168,12 +176,17 @@ pub trait FragmentDisplayListBuilding {
|
||||||
offset: Point2D<Au>,
|
offset: Point2D<Au>,
|
||||||
layout_context: &LayoutContext);
|
layout_context: &LayoutContext);
|
||||||
|
|
||||||
fn clipping_region_for_children(&self, current_clip: &ClippingRegion, flow_origin: &Point2D<Au>)
|
/// Returns the appropriate clipping region for descendants of this flow.
|
||||||
|
fn clipping_region_for_children(&self,
|
||||||
|
current_clip: &ClippingRegion,
|
||||||
|
stacking_relative_border_box: &Rect<Au>)
|
||||||
-> ClippingRegion;
|
-> ClippingRegion;
|
||||||
|
|
||||||
/// Calculates the clipping rectangle for a fragment, taking the `clip` property into account
|
/// Calculates the clipping rectangle for a fragment, taking the `clip` property into account
|
||||||
/// per CSS 2.1 § 11.1.2.
|
/// per CSS 2.1 § 11.1.2.
|
||||||
fn calculate_style_specified_clip(&self, parent_clip: &ClippingRegion, origin: &Point2D<Au>)
|
fn calculate_style_specified_clip(&self,
|
||||||
|
parent_clip: &ClippingRegion,
|
||||||
|
stacking_relative_border_box: &Rect<Au>)
|
||||||
-> ClippingRegion;
|
-> ClippingRegion;
|
||||||
|
|
||||||
/// Creates the text display item for one text fragment.
|
/// Creates the text display item for one text fragment.
|
||||||
|
@ -181,23 +194,20 @@ pub trait FragmentDisplayListBuilding {
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
text_fragment: &ScannedTextFragmentInfo,
|
text_fragment: &ScannedTextFragmentInfo,
|
||||||
text_color: RGBA,
|
text_color: RGBA,
|
||||||
offset: &Point2D<Au>,
|
stacking_relative_content_box: &Rect<Au>,
|
||||||
flow_origin: &Point2D<Au>,
|
|
||||||
clip: &ClippingRegion);
|
clip: &ClippingRegion);
|
||||||
|
|
||||||
/// Creates the display item for a text decoration: underline, overline, or line-through.
|
/// Creates the display item for a text decoration: underline, overline, or line-through.
|
||||||
fn build_display_list_for_text_decoration(&self,
|
fn build_display_list_for_text_decoration(&self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
color: RGBA,
|
color: &RGBA,
|
||||||
flow_origin: &Point2D<Au>,
|
stacking_relative_box: &LogicalRect<Au>,
|
||||||
clip: &ClippingRegion,
|
clip: &ClippingRegion);
|
||||||
logical_bounds: &LogicalRect<Au>,
|
|
||||||
offset: &Point2D<Au>);
|
|
||||||
|
|
||||||
/// A helper method that `build_display_list` calls to create per-fragment-type display items.
|
/// A helper method that `build_display_list` calls to create per-fragment-type display items.
|
||||||
fn build_fragment_type_specific_display_items(&mut self,
|
fn build_fragment_type_specific_display_items(&mut self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
flow_origin: Point2D<Au>,
|
stacking_relative_border_box: &Rect<Au>,
|
||||||
clip: &ClippingRegion);
|
clip: &ClippingRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,20 +590,16 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
fn build_debug_borders_around_text_fragments(&self,
|
fn build_debug_borders_around_text_fragments(&self,
|
||||||
style: &ComputedValues,
|
style: &ComputedValues,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
flow_origin: Point2D<Au>,
|
stacking_relative_border_box: &Rect<Au>,
|
||||||
|
stacking_relative_content_box: &Rect<Au>,
|
||||||
text_fragment: &ScannedTextFragmentInfo,
|
text_fragment: &ScannedTextFragmentInfo,
|
||||||
clip: &ClippingRegion) {
|
clip: &ClippingRegion) {
|
||||||
// FIXME(#2795): Get the real container size
|
// FIXME(pcwalton, #2795): Get the real container size.
|
||||||
let container_size = Size2D::zero();
|
let container_size = Size2D::zero();
|
||||||
// Fragment position wrt to the owning flow.
|
|
||||||
let fragment_bounds = self.border_box.to_physical(self.style.writing_mode, container_size);
|
|
||||||
let absolute_fragment_bounds = Rect(
|
|
||||||
fragment_bounds.origin + flow_origin,
|
|
||||||
fragment_bounds.size);
|
|
||||||
|
|
||||||
// Compute the text fragment bounds and draw a border surrounding them.
|
// Compute the text fragment bounds and draw a border surrounding them.
|
||||||
display_list.content.push_back(DisplayItem::BorderClass(box BorderDisplayItem {
|
display_list.content.push_back(DisplayItem::BorderClass(box BorderDisplayItem {
|
||||||
base: BaseDisplayItem::new(absolute_fragment_bounds,
|
base: BaseDisplayItem::new(*stacking_relative_border_box,
|
||||||
DisplayItemMetadata::new(self.node, style, DefaultCursor),
|
DisplayItemMetadata::new(self.node, style, DefaultCursor),
|
||||||
(*clip).clone()),
|
(*clip).clone()),
|
||||||
border_widths: SideOffsets2D::new_all_same(Au::from_px(1)),
|
border_widths: SideOffsets2D::new_all_same(Au::from_px(1)),
|
||||||
|
@ -603,12 +609,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Draw a rectangle representing the baselines.
|
// Draw a rectangle representing the baselines.
|
||||||
let ascent = text_fragment.run.ascent();
|
let mut baseline = LogicalRect::from_physical(self.style.writing_mode,
|
||||||
let mut baseline = self.border_box.clone();
|
*stacking_relative_content_box,
|
||||||
baseline.start.b = baseline.start.b + ascent;
|
container_size);
|
||||||
|
baseline.start.b = baseline.start.b + text_fragment.run.ascent();
|
||||||
baseline.size.block = Au(0);
|
baseline.size.block = Au(0);
|
||||||
let mut baseline = baseline.to_physical(self.style.writing_mode, container_size);
|
let baseline = baseline.to_physical(self.style.writing_mode, container_size);
|
||||||
baseline.origin = baseline.origin + flow_origin;
|
|
||||||
|
|
||||||
let line_display_item = box LineDisplayItem {
|
let line_display_item = box LineDisplayItem {
|
||||||
base: BaseDisplayItem::new(baseline,
|
base: BaseDisplayItem::new(baseline,
|
||||||
|
@ -622,19 +628,11 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
|
|
||||||
fn build_debug_borders_around_fragment(&self,
|
fn build_debug_borders_around_fragment(&self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
flow_origin: Point2D<Au>,
|
stacking_relative_border_box: &Rect<Au>,
|
||||||
clip: &ClippingRegion) {
|
clip: &ClippingRegion) {
|
||||||
// FIXME(#2795): Get the real container size
|
|
||||||
let container_size = Size2D::zero();
|
|
||||||
// Fragment position wrt to the owning flow.
|
|
||||||
let fragment_bounds = self.border_box.to_physical(self.style.writing_mode, container_size);
|
|
||||||
let absolute_fragment_bounds = Rect(
|
|
||||||
fragment_bounds.origin + flow_origin,
|
|
||||||
fragment_bounds.size);
|
|
||||||
|
|
||||||
// This prints a debug border around the border of this fragment.
|
// This prints a debug border around the border of this fragment.
|
||||||
display_list.content.push_back(DisplayItem::BorderClass(box BorderDisplayItem {
|
display_list.content.push_back(DisplayItem::BorderClass(box BorderDisplayItem {
|
||||||
base: BaseDisplayItem::new(absolute_fragment_bounds,
|
base: BaseDisplayItem::new(*stacking_relative_border_box,
|
||||||
DisplayItemMetadata::new(self.node,
|
DisplayItemMetadata::new(self.node,
|
||||||
&*self.style,
|
&*self.style,
|
||||||
DefaultCursor),
|
DefaultCursor),
|
||||||
|
@ -646,7 +644,9 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_style_specified_clip(&self, parent_clip: &ClippingRegion, origin: &Point2D<Au>)
|
fn calculate_style_specified_clip(&self,
|
||||||
|
parent_clip: &ClippingRegion,
|
||||||
|
stacking_relative_border_box: &Rect<Au>)
|
||||||
-> ClippingRegion {
|
-> ClippingRegion {
|
||||||
// Account for `clip` per CSS 2.1 § 11.1.2.
|
// Account for `clip` per CSS 2.1 § 11.1.2.
|
||||||
let style_clip_rect = match (self.style().get_box().position,
|
let style_clip_rect = match (self.style().get_box().position,
|
||||||
|
@ -656,54 +656,49 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME(pcwalton, #2795): Get the real container size.
|
// FIXME(pcwalton, #2795): Get the real container size.
|
||||||
let border_box = self.border_box.to_physical(self.style.writing_mode, Size2D::zero());
|
let clip_origin = Point2D(stacking_relative_border_box.origin.x + style_clip_rect.left,
|
||||||
let clip_origin = Point2D(border_box.origin.x + style_clip_rect.left,
|
stacking_relative_border_box.origin.y + style_clip_rect.top);
|
||||||
border_box.origin.y + style_clip_rect.top);
|
let right = style_clip_rect.right.unwrap_or(stacking_relative_border_box.size.width);
|
||||||
let new_clip_rect =
|
let bottom = style_clip_rect.bottom.unwrap_or(stacking_relative_border_box.size.height);
|
||||||
Rect(clip_origin + *origin,
|
let clip_size = Size2D(right - clip_origin.x, bottom - clip_origin.y);
|
||||||
Size2D(style_clip_rect.right.unwrap_or(border_box.size.width) - clip_origin.x,
|
(*parent_clip).clone().intersect_rect(&Rect(clip_origin, clip_size))
|
||||||
style_clip_rect.bottom.unwrap_or(border_box.size.height) - clip_origin.y));
|
|
||||||
(*parent_clip).clone().intersect_rect(&new_clip_rect)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list(&mut self,
|
fn build_display_list(&mut self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
flow_origin: Point2D<Au>,
|
stacking_relative_flow_origin: &Point2D<Au>,
|
||||||
|
relative_containing_block_size: &LogicalSize<Au>,
|
||||||
background_and_border_level: BackgroundAndBorderLevel,
|
background_and_border_level: BackgroundAndBorderLevel,
|
||||||
clip: &ClippingRegion) {
|
clip: &ClippingRegion) {
|
||||||
// Compute the fragment position relative to the parent stacking context. If the fragment
|
// Compute the fragment position relative to the parent stacking context. If the fragment
|
||||||
// itself establishes a stacking context, then the origin of its position will be (0, 0)
|
// itself establishes a stacking context, then the origin of its position will be (0, 0)
|
||||||
// for the purposes of this computation.
|
// for the purposes of this computation.
|
||||||
let stacking_relative_flow_origin = if self.establishes_stacking_context() {
|
let stacking_relative_border_box =
|
||||||
ZERO_POINT
|
self.stacking_relative_border_box(stacking_relative_flow_origin,
|
||||||
} else {
|
relative_containing_block_size,
|
||||||
flow_origin
|
CoordinateSystem::Self);
|
||||||
};
|
|
||||||
let absolute_fragment_bounds =
|
|
||||||
self.stacking_relative_bounds(&stacking_relative_flow_origin);
|
|
||||||
|
|
||||||
debug!("Fragment::build_display_list at rel={}, abs={}: {}",
|
debug!("Fragment::build_display_list at rel={}, abs={}, dirty={}, flow origin={}: {}",
|
||||||
self.border_box,
|
self.border_box,
|
||||||
absolute_fragment_bounds,
|
stacking_relative_border_box,
|
||||||
self);
|
|
||||||
debug!("Fragment::build_display_list: dirty={}, flow_origin={}",
|
|
||||||
layout_context.shared.dirty,
|
layout_context.shared.dirty,
|
||||||
flow_origin);
|
stacking_relative_flow_origin,
|
||||||
|
self);
|
||||||
|
|
||||||
if self.style().get_inheritedbox().visibility != visibility::visible {
|
if self.style().get_inheritedbox().visibility != visibility::visible {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !absolute_fragment_bounds.intersects(&layout_context.shared.dirty) {
|
if !stacking_relative_border_box.intersects(&layout_context.shared.dirty) {
|
||||||
debug!("Fragment::build_display_list: Did not intersect...");
|
debug!("Fragment::build_display_list: Did not intersect...");
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the clip rect. If there's nothing to render at all, don't even construct
|
// Calculate the clip rect. If there's nothing to render at all, don't even construct
|
||||||
// display list items.
|
// display list items.
|
||||||
let clip = self.calculate_style_specified_clip(clip, &absolute_fragment_bounds.origin);
|
let clip = self.calculate_style_specified_clip(clip, &stacking_relative_border_box);
|
||||||
if !clip.might_intersect_rect(&absolute_fragment_bounds) {
|
if !clip.might_intersect_rect(&stacking_relative_border_box) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,15 +708,34 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let level =
|
let level =
|
||||||
StackingLevel::from_background_and_border_level(background_and_border_level);
|
StackingLevel::from_background_and_border_level(background_and_border_level);
|
||||||
|
|
||||||
// Add a shadow to the list, if applicable.
|
// Add shadows, background, borders, and outlines, if applicable.
|
||||||
if let Some(ref inline_context) = self.inline_context {
|
if let Some(ref inline_context) = self.inline_context {
|
||||||
for style in inline_context.styles.iter().rev() {
|
for style in inline_context.styles.iter().rev() {
|
||||||
self.build_display_list_for_box_shadow_if_applicable(&**style,
|
self.build_display_list_for_box_shadow_if_applicable(
|
||||||
display_list,
|
&**style,
|
||||||
layout_context,
|
display_list,
|
||||||
level,
|
layout_context,
|
||||||
&absolute_fragment_bounds,
|
level,
|
||||||
&clip);
|
&stacking_relative_border_box,
|
||||||
|
&clip);
|
||||||
|
self.build_display_list_for_background_if_applicable(
|
||||||
|
&**style,
|
||||||
|
display_list,
|
||||||
|
layout_context,
|
||||||
|
level,
|
||||||
|
&stacking_relative_border_box,
|
||||||
|
&clip);
|
||||||
|
self.build_display_list_for_borders_if_applicable(
|
||||||
|
&**style,
|
||||||
|
display_list,
|
||||||
|
&stacking_relative_border_box,
|
||||||
|
level,
|
||||||
|
&clip);
|
||||||
|
self.build_display_list_for_outline_if_applicable(
|
||||||
|
&**style,
|
||||||
|
display_list,
|
||||||
|
&stacking_relative_border_box,
|
||||||
|
&clip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !self.is_scanned_text_fragment() {
|
if !self.is_scanned_text_fragment() {
|
||||||
|
@ -729,62 +743,35 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
display_list,
|
display_list,
|
||||||
layout_context,
|
layout_context,
|
||||||
level,
|
level,
|
||||||
&absolute_fragment_bounds,
|
&stacking_relative_border_box,
|
||||||
&clip);
|
&clip);
|
||||||
}
|
|
||||||
|
|
||||||
// Add the background to the list, if applicable.
|
|
||||||
if let Some(ref inline_context) = self.inline_context {
|
|
||||||
for style in inline_context.styles.iter().rev() {
|
|
||||||
self.build_display_list_for_background_if_applicable(&**style,
|
|
||||||
display_list,
|
|
||||||
layout_context,
|
|
||||||
level,
|
|
||||||
&absolute_fragment_bounds,
|
|
||||||
&clip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !self.is_scanned_text_fragment() {
|
|
||||||
self.build_display_list_for_background_if_applicable(&*self.style,
|
self.build_display_list_for_background_if_applicable(&*self.style,
|
||||||
display_list,
|
display_list,
|
||||||
layout_context,
|
layout_context,
|
||||||
level,
|
level,
|
||||||
&absolute_fragment_bounds,
|
&stacking_relative_border_box,
|
||||||
&clip);
|
&clip);
|
||||||
}
|
|
||||||
|
|
||||||
// Add a border and outlines, if applicable.
|
|
||||||
if let Some(ref inline_context) = self.inline_context {
|
|
||||||
for style in inline_context.styles.iter().rev() {
|
|
||||||
self.build_display_list_for_borders_if_applicable(&**style,
|
|
||||||
display_list,
|
|
||||||
&absolute_fragment_bounds,
|
|
||||||
level,
|
|
||||||
&clip);
|
|
||||||
self.build_display_list_for_outline_if_applicable(&**style,
|
|
||||||
display_list,
|
|
||||||
&absolute_fragment_bounds,
|
|
||||||
&clip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !self.is_scanned_text_fragment() {
|
|
||||||
self.build_display_list_for_borders_if_applicable(&*self.style,
|
self.build_display_list_for_borders_if_applicable(&*self.style,
|
||||||
display_list,
|
display_list,
|
||||||
&absolute_fragment_bounds,
|
&stacking_relative_border_box,
|
||||||
level,
|
level,
|
||||||
&clip);
|
&clip);
|
||||||
self.build_display_list_for_outline_if_applicable(&*self.style,
|
self.build_display_list_for_outline_if_applicable(&*self.style,
|
||||||
display_list,
|
display_list,
|
||||||
&absolute_fragment_bounds,
|
&stacking_relative_border_box,
|
||||||
&clip);
|
&clip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create special per-fragment-type display items.
|
// Create special per-fragment-type display items.
|
||||||
self.build_fragment_type_specific_display_items(display_list, flow_origin, &clip);
|
self.build_fragment_type_specific_display_items(display_list,
|
||||||
|
&stacking_relative_border_box,
|
||||||
|
&clip);
|
||||||
|
|
||||||
if opts::get().show_debug_fragment_borders {
|
if opts::get().show_debug_fragment_borders {
|
||||||
self.build_debug_borders_around_fragment(display_list, flow_origin, &clip)
|
self.build_debug_borders_around_fragment(display_list,
|
||||||
|
&stacking_relative_border_box,
|
||||||
|
&clip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is an iframe, then send its position and size up to the constellation.
|
// If this is an iframe, then send its position and size up to the constellation.
|
||||||
|
@ -799,31 +786,18 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
// the iframe is actually going to be displayed.
|
// the iframe is actually going to be displayed.
|
||||||
if let SpecificFragmentInfo::Iframe(ref iframe_fragment) = self.specific {
|
if let SpecificFragmentInfo::Iframe(ref iframe_fragment) = self.specific {
|
||||||
self.finalize_position_and_size_of_iframe(&**iframe_fragment,
|
self.finalize_position_and_size_of_iframe(&**iframe_fragment,
|
||||||
absolute_fragment_bounds.origin,
|
stacking_relative_border_box.origin,
|
||||||
layout_context)
|
layout_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_fragment_type_specific_display_items(&mut self,
|
fn build_fragment_type_specific_display_items(&mut self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
flow_origin: Point2D<Au>,
|
stacking_relative_border_box: &Rect<Au>,
|
||||||
clip: &ClippingRegion) {
|
clip: &ClippingRegion) {
|
||||||
// Compute the fragment position relative to the parent stacking context. If the fragment
|
// Compute the context box position relative to the parent stacking context.
|
||||||
// itself establishes a stacking context, then the origin of its position will be (0, 0)
|
let stacking_relative_content_box =
|
||||||
// for the purposes of this computation.
|
self.stacking_relative_content_box(stacking_relative_border_box);
|
||||||
let stacking_relative_flow_origin = if self.establishes_stacking_context() {
|
|
||||||
ZERO_POINT
|
|
||||||
} else {
|
|
||||||
flow_origin
|
|
||||||
};
|
|
||||||
|
|
||||||
// FIXME(#2795): Get the real container size.
|
|
||||||
let content_box = self.content_box();
|
|
||||||
let container_size = Size2D::zero();
|
|
||||||
let rect_to_absolute = |writing_mode: WritingMode, logical_rect: LogicalRect<Au>| {
|
|
||||||
let physical_rect = logical_rect.to_physical(writing_mode, container_size);
|
|
||||||
Rect(physical_rect.origin + stacking_relative_flow_origin, physical_rect.size)
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.specific {
|
match self.specific {
|
||||||
SpecificFragmentInfo::UnscannedText(_) => {
|
SpecificFragmentInfo::UnscannedText(_) => {
|
||||||
|
@ -838,16 +812,16 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
self.build_display_list_for_text_fragment(display_list,
|
self.build_display_list_for_text_fragment(display_list,
|
||||||
&**text_fragment,
|
&**text_fragment,
|
||||||
text_color,
|
text_color,
|
||||||
&flow_origin,
|
&stacking_relative_content_box,
|
||||||
&Point2D(Au(0), Au(0)),
|
|
||||||
clip);
|
clip);
|
||||||
|
|
||||||
if opts::get().show_debug_fragment_borders {
|
if opts::get().show_debug_fragment_borders {
|
||||||
self.build_debug_borders_around_text_fragments(self.style(),
|
self.build_debug_borders_around_text_fragments(self.style(),
|
||||||
display_list,
|
display_list,
|
||||||
flow_origin,
|
stacking_relative_border_box,
|
||||||
|
&stacking_relative_content_box,
|
||||||
&**text_fragment,
|
&**text_fragment,
|
||||||
clip);
|
clip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::Generic |
|
SpecificFragmentInfo::Generic |
|
||||||
|
@ -859,25 +833,25 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
SpecificFragmentInfo::InlineBlock(_) |
|
SpecificFragmentInfo::InlineBlock(_) |
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {
|
||||||
if opts::get().show_debug_fragment_borders {
|
if opts::get().show_debug_fragment_borders {
|
||||||
self.build_debug_borders_around_fragment(display_list, flow_origin, clip);
|
self.build_debug_borders_around_fragment(display_list,
|
||||||
|
stacking_relative_border_box,
|
||||||
|
clip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::Image(ref mut image_fragment) => {
|
SpecificFragmentInfo::Image(ref mut image_fragment) => {
|
||||||
let image_ref = &mut image_fragment.image;
|
let image_ref = &mut image_fragment.image;
|
||||||
if let Some(image) = image_ref.get_image(self.node.to_untrusted_node_address()) {
|
if let Some(image) = image_ref.get_image(self.node.to_untrusted_node_address()) {
|
||||||
debug!("(building display list) building image fragment");
|
debug!("(building display list) building image fragment");
|
||||||
let absolute_content_box = rect_to_absolute(self.style.writing_mode,
|
|
||||||
content_box);
|
|
||||||
|
|
||||||
// Place the image into the display list.
|
// Place the image into the display list.
|
||||||
display_list.content.push_back(DisplayItem::ImageClass(box ImageDisplayItem {
|
display_list.content.push_back(DisplayItem::ImageClass(box ImageDisplayItem {
|
||||||
base: BaseDisplayItem::new(absolute_content_box,
|
base: BaseDisplayItem::new(stacking_relative_content_box,
|
||||||
DisplayItemMetadata::new(self.node,
|
DisplayItemMetadata::new(self.node,
|
||||||
&*self.style,
|
&*self.style,
|
||||||
DefaultCursor),
|
DefaultCursor),
|
||||||
(*clip).clone()),
|
(*clip).clone()),
|
||||||
image: image.clone(),
|
image: image.clone(),
|
||||||
stretch_size: absolute_content_box.size,
|
stretch_size: stacking_relative_content_box.size,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
// No image data at all? Do nothing.
|
// No image data at all? Do nothing.
|
||||||
|
@ -910,7 +884,9 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
iframe_rect));
|
iframe_rect));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clipping_region_for_children(&self, current_clip: &ClippingRegion, flow_origin: &Point2D<Au>)
|
fn clipping_region_for_children(&self,
|
||||||
|
current_clip: &ClippingRegion,
|
||||||
|
stacking_relative_border_box: &Rect<Au>)
|
||||||
-> ClippingRegion {
|
-> ClippingRegion {
|
||||||
// Don't clip if we're text.
|
// Don't clip if we're text.
|
||||||
if self.is_scanned_text_fragment() {
|
if self.is_scanned_text_fragment() {
|
||||||
|
@ -918,27 +894,24 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account for style-specified `clip`.
|
// Account for style-specified `clip`.
|
||||||
let current_clip = self.calculate_style_specified_clip(current_clip, flow_origin);
|
let current_clip = self.calculate_style_specified_clip(current_clip,
|
||||||
|
stacking_relative_border_box);
|
||||||
|
|
||||||
// Only clip if `overflow` tells us to.
|
// Only clip if `overflow` tells us to.
|
||||||
match self.style.get_box().overflow {
|
match self.style.get_box().overflow {
|
||||||
overflow::hidden | overflow::auto | overflow::scroll => {}
|
overflow::hidden | overflow::auto | overflow::scroll => {
|
||||||
_ => return current_clip,
|
// Create a new clip rect.
|
||||||
|
current_clip.intersect_rect(stacking_relative_border_box)
|
||||||
|
}
|
||||||
|
_ => current_clip,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new clip rect.
|
|
||||||
//
|
|
||||||
// FIXME(#2795): Get the real container size.
|
|
||||||
let physical_rect = self.border_box.to_physical(self.style.writing_mode, Size2D::zero());
|
|
||||||
current_clip.intersect_rect(&Rect(physical_rect.origin + *flow_origin, physical_rect.size))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list_for_text_fragment(&self,
|
fn build_display_list_for_text_fragment(&self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
text_fragment: &ScannedTextFragmentInfo,
|
text_fragment: &ScannedTextFragmentInfo,
|
||||||
text_color: RGBA,
|
text_color: RGBA,
|
||||||
flow_origin: &Point2D<Au>,
|
stacking_relative_content_box: &Rect<Au>,
|
||||||
offset: &Point2D<Au>,
|
|
||||||
clip: &ClippingRegion) {
|
clip: &ClippingRegion) {
|
||||||
// Determine the orientation and cursor to use.
|
// Determine the orientation and cursor to use.
|
||||||
let (orientation, cursor) = if self.style.writing_mode.is_vertical() {
|
let (orientation, cursor) = if self.style.writing_mode.is_vertical() {
|
||||||
|
@ -955,29 +928,16 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): Get the real container size.
|
// FIXME(pcwalton): Get the real container size.
|
||||||
let container_size = Size2D::zero();
|
let container_size = Size2D::zero();
|
||||||
let content_box = self.content_box();
|
|
||||||
let metrics = &text_fragment.run.font_metrics;
|
let metrics = &text_fragment.run.font_metrics;
|
||||||
let baseline_origin = {
|
let baseline_origin = stacking_relative_content_box.origin +
|
||||||
let mut content_box_start = content_box.start;
|
LogicalPoint::new(self.style.writing_mode,
|
||||||
content_box_start.b = content_box_start.b + metrics.ascent;
|
Au(0),
|
||||||
content_box_start.to_physical(self.style.writing_mode, container_size) + *flow_origin +
|
metrics.ascent).to_physical(self.style.writing_mode,
|
||||||
*offset
|
container_size);
|
||||||
};
|
|
||||||
let stacking_relative_flow_origin = if self.establishes_stacking_context() {
|
|
||||||
ZERO_POINT
|
|
||||||
} else {
|
|
||||||
*flow_origin
|
|
||||||
};
|
|
||||||
let rect_to_absolute = |writing_mode: WritingMode, logical_rect: LogicalRect<Au>| {
|
|
||||||
let physical_rect = logical_rect.to_physical(writing_mode, container_size);
|
|
||||||
Rect(physical_rect.origin + stacking_relative_flow_origin, physical_rect.size)
|
|
||||||
};
|
|
||||||
let content_rect = rect_to_absolute(self.style.writing_mode,
|
|
||||||
content_box).translate(offset);
|
|
||||||
|
|
||||||
// Create the text display item.
|
// Create the text display item.
|
||||||
display_list.content.push_back(DisplayItem::TextClass(box TextDisplayItem {
|
display_list.content.push_back(DisplayItem::TextClass(box TextDisplayItem {
|
||||||
base: BaseDisplayItem::new(content_rect,
|
base: BaseDisplayItem::new(*stacking_relative_content_box,
|
||||||
DisplayItemMetadata::new(self.node, self.style(), cursor),
|
DisplayItemMetadata::new(self.node, self.style(), cursor),
|
||||||
(*clip).clone()),
|
(*clip).clone()),
|
||||||
text_run: text_fragment.run.clone(),
|
text_run: text_fragment.run.clone(),
|
||||||
|
@ -989,63 +949,55 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
|
|
||||||
// Create display items for text decorations.
|
// Create display items for text decorations.
|
||||||
let text_decorations = self.style().get_inheritedtext()._servo_text_decorations_in_effect;
|
let text_decorations = self.style().get_inheritedtext()._servo_text_decorations_in_effect;
|
||||||
if let Some(underline_color) = text_decorations.underline {
|
let stacking_relative_content_box =
|
||||||
let mut rect = content_box.clone();
|
LogicalRect::from_physical(self.style.writing_mode,
|
||||||
rect.start.b = rect.start.b + metrics.ascent - metrics.underline_offset;
|
*stacking_relative_content_box,
|
||||||
rect.size.block = metrics.underline_size;
|
container_size);
|
||||||
|
if let Some(ref underline_color) = text_decorations.underline {
|
||||||
|
let mut stacking_relative_box = stacking_relative_content_box;
|
||||||
|
stacking_relative_box.start.b = stacking_relative_content_box.start.b +
|
||||||
|
metrics.ascent - metrics.underline_offset;
|
||||||
|
stacking_relative_box.size.block = metrics.underline_size;
|
||||||
self.build_display_list_for_text_decoration(display_list,
|
self.build_display_list_for_text_decoration(display_list,
|
||||||
underline_color,
|
underline_color,
|
||||||
flow_origin,
|
&stacking_relative_box,
|
||||||
clip,
|
clip)
|
||||||
&rect,
|
|
||||||
offset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(overline_color) = text_decorations.overline {
|
if let Some(ref overline_color) = text_decorations.overline {
|
||||||
let mut rect = content_box.clone();
|
let mut stacking_relative_box = stacking_relative_content_box;
|
||||||
rect.size.block = metrics.underline_size;
|
stacking_relative_box.size.block = metrics.underline_size;
|
||||||
self.build_display_list_for_text_decoration(display_list,
|
self.build_display_list_for_text_decoration(display_list,
|
||||||
overline_color,
|
overline_color,
|
||||||
flow_origin,
|
&stacking_relative_box,
|
||||||
clip,
|
clip)
|
||||||
&rect,
|
|
||||||
offset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(line_through_color) = text_decorations.line_through {
|
if let Some(ref line_through_color) = text_decorations.line_through {
|
||||||
let mut rect = content_box.clone();
|
let mut stacking_relative_box = stacking_relative_content_box;
|
||||||
rect.start.b = rect.start.b + metrics.ascent - metrics.strikeout_offset;
|
stacking_relative_box.start.b = stacking_relative_box.start.b + metrics.ascent -
|
||||||
rect.size.block = metrics.strikeout_size;
|
metrics.strikeout_offset;
|
||||||
|
stacking_relative_box.size.block = metrics.strikeout_size;
|
||||||
self.build_display_list_for_text_decoration(display_list,
|
self.build_display_list_for_text_decoration(display_list,
|
||||||
line_through_color,
|
line_through_color,
|
||||||
flow_origin,
|
&stacking_relative_box,
|
||||||
clip,
|
clip)
|
||||||
&rect,
|
|
||||||
offset)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list_for_text_decoration(&self,
|
fn build_display_list_for_text_decoration(&self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
color: RGBA,
|
color: &RGBA,
|
||||||
flow_origin: &Point2D<Au>,
|
stacking_relative_box: &LogicalRect<Au>,
|
||||||
clip: &ClippingRegion,
|
clip: &ClippingRegion) {
|
||||||
logical_bounds: &LogicalRect<Au>,
|
// FIXME(pcwalton, #2795): Get the real container size.
|
||||||
offset: &Point2D<Au>) {
|
|
||||||
// FIXME(pcwalton): Get the real container size.
|
|
||||||
let container_size = Size2D::zero();
|
let container_size = Size2D::zero();
|
||||||
let stacking_relative_flow_origin = if self.establishes_stacking_context() {
|
let stacking_relative_box = stacking_relative_box.to_physical(self.style.writing_mode,
|
||||||
ZERO_POINT
|
container_size);
|
||||||
} else {
|
|
||||||
*flow_origin
|
|
||||||
};
|
|
||||||
let physical_rect = logical_bounds.to_physical(self.style.writing_mode, container_size);
|
|
||||||
|
|
||||||
let bounds = Rect(physical_rect.origin + stacking_relative_flow_origin,
|
|
||||||
physical_rect.size).translate(offset);
|
|
||||||
let metadata = DisplayItemMetadata::new(self.node, &*self.style, DefaultCursor);
|
let metadata = DisplayItemMetadata::new(self.node, &*self.style, DefaultCursor);
|
||||||
display_list.content.push_back(DisplayItem::SolidColorClass(box SolidColorDisplayItem {
|
display_list.content.push_back(DisplayItem::SolidColorClass(box SolidColorDisplayItem {
|
||||||
base: BaseDisplayItem::new(bounds, metadata, (*clip).clone()),
|
base: BaseDisplayItem::new(stacking_relative_box, metadata, (*clip).clone()),
|
||||||
color: color.to_gfx_color(),
|
color: color.to_gfx_color(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -1081,14 +1033,16 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
background_border_level: BackgroundAndBorderLevel) {
|
background_border_level: BackgroundAndBorderLevel) {
|
||||||
// Add the box that starts the block context.
|
// Add the box that starts the block context.
|
||||||
let stacking_relative_fragment_origin =
|
|
||||||
self.base.stacking_relative_position_of_child_fragment(&self.fragment);
|
|
||||||
self.fragment.build_display_list(display_list,
|
self.fragment.build_display_list(display_list,
|
||||||
layout_context,
|
layout_context,
|
||||||
stacking_relative_fragment_origin,
|
&self.base.stacking_relative_position,
|
||||||
|
&self.base
|
||||||
|
.absolute_position_info
|
||||||
|
.relative_containing_block_size,
|
||||||
background_border_level,
|
background_border_level,
|
||||||
&self.base.clip);
|
&self.base.clip);
|
||||||
|
|
||||||
|
// Add children.
|
||||||
for kid in self.base.children.iter_mut() {
|
for kid in self.base.children.iter_mut() {
|
||||||
flow::mut_base(kid).display_list_building_result.add_to(display_list);
|
flow::mut_base(kid).display_list_building_result.add_to(display_list);
|
||||||
}
|
}
|
||||||
|
@ -1180,19 +1134,70 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
display_list: Box<DisplayList>,
|
display_list: Box<DisplayList>,
|
||||||
layer: Option<Arc<PaintLayer>>)
|
layer: Option<Arc<PaintLayer>>)
|
||||||
-> Arc<StackingContext> {
|
-> Arc<StackingContext> {
|
||||||
let size = self.base.position.size.to_physical(self.base.writing_mode);
|
debug_assert!(self.fragment.establishes_stacking_context());
|
||||||
let bounds = Rect(self.base.stacking_relative_position, size);
|
let border_box = self.fragment
|
||||||
let z_index = self.fragment.style().get_box().z_index.number_or_zero();
|
.stacking_relative_border_box(&self.base.stacking_relative_position,
|
||||||
let opacity = self.fragment.style().get_effects().opacity as f32;
|
&self.base
|
||||||
|
.absolute_position_info
|
||||||
|
.relative_containing_block_size,
|
||||||
|
CoordinateSystem::Parent);
|
||||||
|
|
||||||
|
// FIXME(pcwalton): Is this vertical-writing-direction-safe?
|
||||||
|
let margin = self.fragment.margin.to_physical(self.base.writing_mode);
|
||||||
|
let overflow = self.base.overflow.translate(&-Point2D(margin.left, Au(0)));
|
||||||
|
|
||||||
Arc::new(StackingContext::new(display_list,
|
Arc::new(StackingContext::new(display_list,
|
||||||
&bounds,
|
&border_box,
|
||||||
&self.base.overflow,
|
&overflow,
|
||||||
z_index,
|
self.fragment.style().get_box().z_index.number_or_zero(),
|
||||||
opacity,
|
self.fragment.style().get_effects().opacity as f32,
|
||||||
layer))
|
layer))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait InlineFlowDisplayListBuilding {
|
||||||
|
fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
|
fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext) {
|
||||||
|
// TODO(#228): Once we form lines and have their cached bounds, we can be smarter and
|
||||||
|
// not recurse on a line if nothing in it can intersect the dirty region.
|
||||||
|
debug!("Flow: building display list for {:u} inline fragments", self.fragments.len());
|
||||||
|
|
||||||
|
let mut display_list = box DisplayList::new();
|
||||||
|
for fragment in self.fragments.fragments.iter_mut() {
|
||||||
|
fragment.build_display_list(&mut *display_list,
|
||||||
|
layout_context,
|
||||||
|
&self.base.stacking_relative_position,
|
||||||
|
&self.base
|
||||||
|
.absolute_position_info
|
||||||
|
.relative_containing_block_size,
|
||||||
|
BackgroundAndBorderLevel::Content,
|
||||||
|
&self.base.clip);
|
||||||
|
match fragment.specific {
|
||||||
|
SpecificFragmentInfo::InlineBlock(ref mut block_flow) => {
|
||||||
|
let block_flow = block_flow.flow_ref.deref_mut();
|
||||||
|
flow::mut_base(block_flow).display_list_building_result
|
||||||
|
.add_to(&mut *display_list)
|
||||||
|
}
|
||||||
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => {
|
||||||
|
let block_flow = block_flow.flow_ref.deref_mut();
|
||||||
|
flow::mut_base(block_flow).display_list_building_result
|
||||||
|
.add_to(&mut *display_list)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.base.display_list_building_result = DisplayListBuildingResult::Normal(display_list);
|
||||||
|
|
||||||
|
if opts::get().validate_display_list_geometry {
|
||||||
|
self.base.validate_display_list_geometry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ListItemFlowDisplayListBuilding {
|
pub trait ListItemFlowDisplayListBuilding {
|
||||||
fn build_display_list_for_list_item(&mut self,
|
fn build_display_list_for_list_item(&mut self,
|
||||||
display_list: Box<DisplayList>,
|
display_list: Box<DisplayList>,
|
||||||
|
@ -1204,17 +1209,16 @@ impl ListItemFlowDisplayListBuilding for ListItemFlow {
|
||||||
mut display_list: Box<DisplayList>,
|
mut display_list: Box<DisplayList>,
|
||||||
layout_context: &LayoutContext) {
|
layout_context: &LayoutContext) {
|
||||||
// Draw the marker, if applicable.
|
// Draw the marker, if applicable.
|
||||||
match self.marker {
|
if let Some(ref mut marker) = self.marker {
|
||||||
None => {}
|
marker.build_display_list(&mut *display_list,
|
||||||
Some(ref mut marker) => {
|
layout_context,
|
||||||
let stacking_relative_fragment_origin =
|
&self.block_flow.base.stacking_relative_position,
|
||||||
self.block_flow.base.stacking_relative_position_of_child_fragment(marker);
|
&self.block_flow
|
||||||
marker.build_display_list(&mut *display_list,
|
.base
|
||||||
layout_context,
|
.absolute_position_info
|
||||||
stacking_relative_fragment_origin,
|
.relative_containing_block_size,
|
||||||
BackgroundAndBorderLevel::Content,
|
BackgroundAndBorderLevel::Content,
|
||||||
&self.block_flow.base.clip);
|
&self.block_flow.base.clip);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the rest of the block.
|
// Draw the rest of the block.
|
||||||
|
@ -1292,3 +1296,4 @@ impl StackingContextConstruction for DisplayList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ use display_list_builder::DisplayListBuildingResult;
|
||||||
use floats::Floats;
|
use floats::Floats;
|
||||||
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo};
|
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
|
||||||
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
||||||
use inline::InlineFlow;
|
use inline::InlineFlow;
|
||||||
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
||||||
|
@ -223,8 +223,10 @@ pub trait Flow: fmt::Show + ToString + Sync {
|
||||||
/// Returns the union of all overflow rects of all of this flow's fragments.
|
/// Returns the union of all overflow rects of all of this flow's fragments.
|
||||||
fn compute_overflow(&self) -> Rect<Au>;
|
fn compute_overflow(&self) -> Rect<Au>;
|
||||||
|
|
||||||
/// Iterates through overflow rects of all of this flow's fragments.
|
/// Iterates through border boxes of all of this flow's fragments.
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator);
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>);
|
||||||
|
|
||||||
fn compute_collapsible_block_start_margin(&mut self,
|
fn compute_collapsible_block_start_margin(&mut self,
|
||||||
_layout_context: &mut LayoutContext,
|
_layout_context: &mut LayoutContext,
|
||||||
|
@ -958,17 +960,6 @@ impl BaseFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the position of the given fragment relative to the start of the nearest ancestor
|
|
||||||
/// stacking context. The fragment must be a child fragment of this flow.
|
|
||||||
pub fn stacking_relative_position_of_child_fragment(&self, fragment: &Fragment)
|
|
||||||
-> Point2D<Au> {
|
|
||||||
let relative_offset =
|
|
||||||
fragment.relative_position(&self
|
|
||||||
.absolute_position_info
|
|
||||||
.relative_containing_block_size);
|
|
||||||
self.stacking_relative_position.add_size(&relative_offset.to_physical(self.writing_mode))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ImmutableFlowUtils for &'a Flow + 'a {
|
impl<'a> ImmutableFlowUtils for &'a Flow + 'a {
|
||||||
|
@ -1065,14 +1056,14 @@ impl<'a> ImmutableFlowUtils for &'a Flow + 'a {
|
||||||
let flow = match self.class() {
|
let flow = match self.class() {
|
||||||
FlowClass::Table | FlowClass::TableRowGroup => {
|
FlowClass::Table | FlowClass::TableRowGroup => {
|
||||||
let fragment =
|
let fragment =
|
||||||
Fragment::new_anonymous_table_fragment(node,
|
Fragment::new_anonymous_from_specific_info(node,
|
||||||
SpecificFragmentInfo::TableRow);
|
SpecificFragmentInfo::TableRow);
|
||||||
box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow>
|
box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow>
|
||||||
},
|
},
|
||||||
FlowClass::TableRow => {
|
FlowClass::TableRow => {
|
||||||
let fragment =
|
let fragment =
|
||||||
Fragment::new_anonymous_table_fragment(node,
|
Fragment::new_anonymous_from_specific_info(node,
|
||||||
SpecificFragmentInfo::TableCell);
|
SpecificFragmentInfo::TableCell);
|
||||||
let hide = node.style().get_inheritedtable().empty_cells == empty_cells::hide;
|
let hide = node.style().get_inheritedtable().empty_cells == empty_cells::hide;
|
||||||
box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide) as
|
box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide) as
|
||||||
Box<Flow>
|
Box<Flow>
|
||||||
|
|
|
@ -31,8 +31,7 @@ use serialize::{Encodable, Encoder};
|
||||||
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
||||||
use servo_net::image::holder::ImageHolder;
|
use servo_net::image::holder::ImageHolder;
|
||||||
use servo_net::local_image_cache::LocalImageCache;
|
use servo_net::local_image_cache::LocalImageCache;
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::{mod, Au, ZERO_POINT};
|
||||||
use servo_util::geometry;
|
|
||||||
use servo_util::logical_geometry::{LogicalRect, LogicalSize, LogicalMargin};
|
use servo_util::logical_geometry::{LogicalRect, LogicalSize, LogicalMargin};
|
||||||
use servo_util::range::*;
|
use servo_util::range::*;
|
||||||
use servo_util::smallvec::SmallVec;
|
use servo_util::smallvec::SmallVec;
|
||||||
|
@ -62,8 +61,8 @@ use url::Url;
|
||||||
/// positioned as if it were a block fragment, but its children are positioned according to
|
/// positioned as if it were a block fragment, but its children are positioned according to
|
||||||
/// inline flow.
|
/// inline flow.
|
||||||
///
|
///
|
||||||
/// A `SpecificFragmentInfo::Generic` is an empty fragment that contributes only borders, margins, padding, and
|
/// A `SpecificFragmentInfo::Generic` is an empty fragment that contributes only borders, margins,
|
||||||
/// backgrounds. It is analogous to a CSS nonreplaced content box.
|
/// padding, and backgrounds. It is analogous to a CSS nonreplaced content box.
|
||||||
///
|
///
|
||||||
/// A fragment's type influences how its styles are interpreted during layout. For example,
|
/// A fragment's type influences how its styles are interpreted during layout. For example,
|
||||||
/// replaced content such as images are resized differently from tables, text, or other content.
|
/// replaced content such as images are resized differently from tables, text, or other content.
|
||||||
|
@ -83,8 +82,10 @@ pub struct Fragment {
|
||||||
/// The CSS style of this fragment.
|
/// The CSS style of this fragment.
|
||||||
pub style: Arc<ComputedValues>,
|
pub style: Arc<ComputedValues>,
|
||||||
|
|
||||||
/// The position of this fragment relative to its owning flow.
|
/// The position of this fragment relative to its owning flow. The size includes padding and
|
||||||
/// The size includes padding and border, but not margin.
|
/// border, but not margin.
|
||||||
|
///
|
||||||
|
/// NB: This does not account for relative positioning.
|
||||||
pub border_box: LogicalRect<Au>,
|
pub border_box: LogicalRect<Au>,
|
||||||
|
|
||||||
/// The sum of border and padding; i.e. the distance from the edge of the border box to the
|
/// The sum of border and padding; i.e. the distance from the edge of the border box to the
|
||||||
|
@ -520,10 +521,28 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a new `Fragment` instance for an anonymous object.
|
||||||
|
pub fn new_anonymous(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode)
|
||||||
|
-> Fragment {
|
||||||
|
let node_style = cascade_anonymous(&**node.style());
|
||||||
|
let writing_mode = node_style.writing_mode;
|
||||||
|
Fragment {
|
||||||
|
node: OpaqueNodeMethods::from_thread_safe_layout_node(node),
|
||||||
|
style: Arc::new(node_style),
|
||||||
|
restyle_damage: node.restyle_damage(),
|
||||||
|
border_box: LogicalRect::zero(writing_mode),
|
||||||
|
border_padding: LogicalMargin::zero(writing_mode),
|
||||||
|
margin: LogicalMargin::zero(writing_mode),
|
||||||
|
specific: constructor.build_specific_fragment_info_for_node(node),
|
||||||
|
inline_context: None,
|
||||||
|
debug_id: layout_debug::generate_unique_debug_id(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructs a new `Fragment` instance for an anonymous table object.
|
/// Constructs a new `Fragment` instance for an anonymous table object.
|
||||||
pub fn new_anonymous_table_fragment(node: &ThreadSafeLayoutNode,
|
pub fn new_anonymous_from_specific_info(node: &ThreadSafeLayoutNode,
|
||||||
specific: SpecificFragmentInfo)
|
specific: SpecificFragmentInfo)
|
||||||
-> Fragment {
|
-> Fragment {
|
||||||
// CSS 2.1 § 17.2.1 This is for non-inherited properties on anonymous table fragments
|
// CSS 2.1 § 17.2.1 This is for non-inherited properties on anonymous table fragments
|
||||||
// example:
|
// example:
|
||||||
//
|
//
|
||||||
|
@ -1508,10 +1527,17 @@ impl Fragment {
|
||||||
/// because the corresponding table flow is the primary fragment.
|
/// because the corresponding table flow is the primary fragment.
|
||||||
pub fn is_primary_fragment(&self) -> bool {
|
pub fn is_primary_fragment(&self) -> bool {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
SpecificFragmentInfo::InlineBlock(_) | SpecificFragmentInfo::InlineAbsoluteHypothetical(_) |
|
SpecificFragmentInfo::InlineBlock(_) |
|
||||||
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) |
|
||||||
SpecificFragmentInfo::TableWrapper => false,
|
SpecificFragmentInfo::TableWrapper => false,
|
||||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) |
|
SpecificFragmentInfo::Generic |
|
||||||
SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableColumn(_) | SpecificFragmentInfo::TableRow |
|
SpecificFragmentInfo::Iframe(_) |
|
||||||
|
SpecificFragmentInfo::Image(_) |
|
||||||
|
SpecificFragmentInfo::ScannedText(_) |
|
||||||
|
SpecificFragmentInfo::Table |
|
||||||
|
SpecificFragmentInfo::TableCell |
|
||||||
|
SpecificFragmentInfo::TableColumn(_) |
|
||||||
|
SpecificFragmentInfo::TableRow |
|
||||||
SpecificFragmentInfo::UnscannedText(_) => true,
|
SpecificFragmentInfo::UnscannedText(_) => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1540,15 +1566,48 @@ impl Fragment {
|
||||||
self.style = (*new_style).clone()
|
self.style = (*new_style).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given the stacking-context-relative position of the containing flow, returns the boundaries
|
/// Given the stacking-context-relative position of the containing flow, returns the border box
|
||||||
/// of this fragment relative to the parent stacking context.
|
/// of this fragment relative to the parent stacking context. This takes `position: relative`
|
||||||
pub fn stacking_relative_bounds(&self, stacking_relative_flow_origin: &Point2D<Au>)
|
/// into account.
|
||||||
-> Rect<Au> {
|
///
|
||||||
// FIXME(#2795): Get the real container size
|
/// If `coordinate_system` is `Parent`, this returns the border box in the parent stacking
|
||||||
|
/// context's coordinate system. Otherwise, if `coordinate_system` is `Self` and this fragment
|
||||||
|
/// establishes a stacking context itself, this returns a border box anchored at (0, 0). (If
|
||||||
|
/// this fragment does not establish a stacking context, then it always belongs to its parent
|
||||||
|
/// stacking context and thus `coordinate_system` is ignored.)
|
||||||
|
///
|
||||||
|
/// This is the method you should use for display list construction as well as
|
||||||
|
/// `getBoundingClientRect()` and so forth.
|
||||||
|
pub fn stacking_relative_border_box(&self,
|
||||||
|
stacking_relative_flow_origin: &Point2D<Au>,
|
||||||
|
relative_containing_block_size: &LogicalSize<Au>,
|
||||||
|
coordinate_system: CoordinateSystem)
|
||||||
|
-> Rect<Au> {
|
||||||
|
// FIXME(pcwalton, #2795): Get the real container size.
|
||||||
let container_size = Size2D::zero();
|
let container_size = Size2D::zero();
|
||||||
self.border_box
|
let border_box = self.border_box.to_physical(self.style.writing_mode, container_size);
|
||||||
.to_physical(self.style.writing_mode, container_size)
|
if coordinate_system == CoordinateSystem::Self && self.establishes_stacking_context() {
|
||||||
.translate(stacking_relative_flow_origin)
|
return Rect(ZERO_POINT, border_box.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(pcwalton): This can double-count relative position sometimes for inlines (e.g.
|
||||||
|
// `<div style="position:relative">x</div>`, because the `position:relative` trickles down
|
||||||
|
// to the inline flow. Possibly we should extend the notion of "primary fragment" to fix
|
||||||
|
// this.
|
||||||
|
let relative_position = self.relative_position(relative_containing_block_size);
|
||||||
|
border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode))
|
||||||
|
.translate(stacking_relative_flow_origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given the stacking-context-relative border box, returns the stacking-context-relative
|
||||||
|
/// content box.
|
||||||
|
pub fn stacking_relative_content_box(&self, stacking_relative_border_box: &Rect<Au>)
|
||||||
|
-> Rect<Au> {
|
||||||
|
let border_padding = self.border_padding.to_physical(self.style.writing_mode);
|
||||||
|
Rect(Point2D(stacking_relative_border_box.origin.x + border_padding.left,
|
||||||
|
stacking_relative_border_box.origin.y + border_padding.top),
|
||||||
|
Size2D(stacking_relative_border_box.size.width - border_padding.horizontal(),
|
||||||
|
stacking_relative_border_box.size.height - border_padding.vertical()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this fragment establishes a new stacking context and false otherwise.
|
/// Returns true if this fragment establishes a new stacking context and false otherwise.
|
||||||
|
@ -1637,13 +1696,23 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A top-down fragment overflow region iteration handler.
|
/// A top-down fragment border box iteration handler.
|
||||||
pub trait FragmentOverflowIterator {
|
pub trait FragmentBorderBoxIterator {
|
||||||
/// The operation to perform.
|
/// The operation to perform.
|
||||||
fn process(&mut self, fragment: &Fragment, overflow: Rect<Au>);
|
fn process(&mut self, fragment: &Fragment, overflow: &Rect<Au>);
|
||||||
|
|
||||||
/// Returns true if this fragment must be processed in-order. If this returns false,
|
/// Returns true if this fragment must be processed in-order. If this returns false,
|
||||||
/// we skip the operation for this fragment, but continue processing siblings.
|
/// we skip the operation for this fragment, but continue processing siblings.
|
||||||
fn should_process(&mut self, fragment: &Fragment) -> bool;
|
fn should_process(&mut self, fragment: &Fragment) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The coordinate system used in `stacking_relative_border_box()`. See the documentation of that
|
||||||
|
/// method for details.
|
||||||
|
#[deriving(Clone, PartialEq, Show)]
|
||||||
|
pub enum CoordinateSystem {
|
||||||
|
/// The border box returned is relative to the fragment's parent stacking context.
|
||||||
|
Parent,
|
||||||
|
/// The border box returned is relative to the fragment's own stacking context, if applicable.
|
||||||
|
Self,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
|
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use display_list_builder::{BackgroundAndBorderLevel, DisplayListBuildingResult, FragmentDisplayListBuilding};
|
use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBuilding};
|
||||||
use floats::{FloatKind, Floats, PlacementInfo};
|
use floats::{FloatKind, Floats, PlacementInfo};
|
||||||
use flow::{BaseFlow, FlowClass, Flow, MutableFlowUtils, ForceNonfloatedFlag};
|
use flow::{BaseFlow, FlowClass, Flow, MutableFlowUtils, ForceNonfloatedFlag};
|
||||||
use flow::{IS_ABSOLUTELY_POSITIONED};
|
use flow::{IS_ABSOLUTELY_POSITIONED};
|
||||||
use flow;
|
use flow;
|
||||||
use fragment::{Fragment, SpecificFragmentInfo};
|
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, ScannedTextFragmentInfo};
|
||||||
use fragment::{FragmentOverflowIterator, ScannedTextFragmentInfo};
|
use fragment::{SpecificFragmentInfo};
|
||||||
use fragment::SplitInfo;
|
use fragment::SplitInfo;
|
||||||
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
|
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
|
@ -20,16 +20,14 @@ use model::IntrinsicISizesContribution;
|
||||||
use text;
|
use text;
|
||||||
|
|
||||||
use collections::{RingBuf};
|
use collections::{RingBuf};
|
||||||
use geom::{Rect, Size2D};
|
use geom::{Point2D, Rect};
|
||||||
use gfx::display_list::DisplayList;
|
|
||||||
use gfx::font::FontMetrics;
|
use gfx::font::FontMetrics;
|
||||||
use gfx::font_context::FontContext;
|
use gfx::font_context::FontContext;
|
||||||
use gfx::text::glyph::CharIndex;
|
use gfx::text::glyph::CharIndex;
|
||||||
|
use servo_util::arc_ptr_eq;
|
||||||
use servo_util::geometry::{Au, ZERO_RECT};
|
use servo_util::geometry::{Au, ZERO_RECT};
|
||||||
use servo_util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
|
use servo_util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
|
||||||
use servo_util::opts;
|
|
||||||
use servo_util::range::{Range, RangeIndex};
|
use servo_util::range::{Range, RangeIndex};
|
||||||
use servo_util::arc_ptr_eq;
|
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -1186,44 +1184,29 @@ impl Flow for InlineFlow {
|
||||||
|
|
||||||
fn compute_absolute_position(&mut self) {
|
fn compute_absolute_position(&mut self) {
|
||||||
for fragment in self.fragments.fragments.iter_mut() {
|
for fragment in self.fragments.fragments.iter_mut() {
|
||||||
let stacking_relative_position = match fragment.specific {
|
let stacking_relative_border_box =
|
||||||
SpecificFragmentInfo::InlineBlock(ref mut info) => {
|
fragment.stacking_relative_border_box(&self.base.stacking_relative_position,
|
||||||
let block_flow = info.flow_ref.as_block();
|
&self.base
|
||||||
block_flow.base.absolute_position_info = self.base.absolute_position_info;
|
.absolute_position_info
|
||||||
|
.relative_containing_block_size,
|
||||||
// FIXME(#2795): Get the real container size
|
CoordinateSystem::Self);
|
||||||
let container_size = Size2D::zero();
|
|
||||||
block_flow.base.stacking_relative_position =
|
|
||||||
self.base.stacking_relative_position +
|
|
||||||
fragment.border_box.start.to_physical(self.base.writing_mode,
|
|
||||||
container_size);
|
|
||||||
block_flow.base.stacking_relative_position
|
|
||||||
}
|
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
|
|
||||||
let block_flow = info.flow_ref.as_block();
|
|
||||||
block_flow.base.absolute_position_info = self.base.absolute_position_info;
|
|
||||||
|
|
||||||
// FIXME(#2795): Get the real container size
|
|
||||||
let container_size = Size2D::zero();
|
|
||||||
block_flow.base.stacking_relative_position =
|
|
||||||
self.base.stacking_relative_position +
|
|
||||||
fragment.border_box.start.to_physical(self.base.writing_mode,
|
|
||||||
container_size);
|
|
||||||
block_flow.base.stacking_relative_position
|
|
||||||
|
|
||||||
}
|
|
||||||
_ => continue,
|
|
||||||
};
|
|
||||||
|
|
||||||
let clip = fragment.clipping_region_for_children(&self.base.clip,
|
let clip = fragment.clipping_region_for_children(&self.base.clip,
|
||||||
&stacking_relative_position);
|
&stacking_relative_border_box);
|
||||||
|
|
||||||
match fragment.specific {
|
match fragment.specific {
|
||||||
SpecificFragmentInfo::InlineBlock(ref mut info) => {
|
SpecificFragmentInfo::InlineBlock(ref mut info) => {
|
||||||
flow::mut_base(info.flow_ref.deref_mut()).clip = clip
|
flow::mut_base(info.flow_ref.deref_mut()).clip = clip;
|
||||||
|
let block_flow = info.flow_ref.as_block();
|
||||||
|
block_flow.base.absolute_position_info = self.base.absolute_position_info;
|
||||||
|
block_flow.base.stacking_relative_position =
|
||||||
|
stacking_relative_border_box.origin;
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
|
||||||
flow::mut_base(info.flow_ref.deref_mut()).clip = clip
|
flow::mut_base(info.flow_ref.deref_mut()).clip = clip;
|
||||||
|
let block_flow = info.flow_ref.as_block();
|
||||||
|
block_flow.base.absolute_position_info = self.base.absolute_position_info;
|
||||||
|
block_flow.base.stacking_relative_position =
|
||||||
|
stacking_relative_border_box.origin
|
||||||
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -1235,38 +1218,7 @@ impl Flow for InlineFlow {
|
||||||
fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {}
|
fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {}
|
||||||
|
|
||||||
fn build_display_list(&mut self, layout_context: &LayoutContext) {
|
fn build_display_list(&mut self, layout_context: &LayoutContext) {
|
||||||
// TODO(#228): Once we form lines and have their cached bounds, we can be smarter and
|
self.build_display_list_for_inline(layout_context)
|
||||||
// not recurse on a line if nothing in it can intersect the dirty region.
|
|
||||||
debug!("Flow: building display list for {} inline fragments", self.fragments.len());
|
|
||||||
|
|
||||||
let mut display_list = box DisplayList::new();
|
|
||||||
for fragment in self.fragments.fragments.iter_mut() {
|
|
||||||
let fragment_origin = self.base.stacking_relative_position_of_child_fragment(fragment);
|
|
||||||
fragment.build_display_list(&mut *display_list,
|
|
||||||
layout_context,
|
|
||||||
fragment_origin,
|
|
||||||
BackgroundAndBorderLevel::Content,
|
|
||||||
&self.base.clip);
|
|
||||||
match fragment.specific {
|
|
||||||
SpecificFragmentInfo::InlineBlock(ref mut block_flow) => {
|
|
||||||
let block_flow = block_flow.flow_ref.deref_mut();
|
|
||||||
flow::mut_base(block_flow).display_list_building_result
|
|
||||||
.add_to(&mut *display_list)
|
|
||||||
}
|
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => {
|
|
||||||
let block_flow = block_flow.flow_ref.deref_mut();
|
|
||||||
flow::mut_base(block_flow).display_list_building_result
|
|
||||||
.add_to(&mut *display_list)
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.base.display_list_building_result = DisplayListBuildingResult::Normal(display_list);
|
|
||||||
|
|
||||||
if opts::get().validate_display_list_geometry {
|
|
||||||
self.base.validate_display_list_geometry();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repair_style(&mut self, _: &Arc<ComputedValues>) {}
|
fn repair_style(&mut self, _: &Arc<ComputedValues>) {}
|
||||||
|
@ -1279,13 +1231,23 @@ impl Flow for InlineFlow {
|
||||||
overflow
|
overflow
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
// FIXME(#2795): Get the real container size.
|
||||||
for fragment in self.fragments.fragments.iter() {
|
for fragment in self.fragments.fragments.iter() {
|
||||||
if iterator.should_process(fragment) {
|
if !iterator.should_process(fragment) {
|
||||||
let fragment_origin =
|
continue
|
||||||
self.base.stacking_relative_position_of_child_fragment(fragment);
|
|
||||||
iterator.process(fragment, fragment.stacking_relative_bounds(&fragment_origin));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let stacking_relative_position = &self.base.stacking_relative_position;
|
||||||
|
let relative_containing_block_size =
|
||||||
|
&self.base.absolute_position_info.relative_containing_block_size;
|
||||||
|
iterator.process(fragment,
|
||||||
|
&fragment.stacking_relative_border_box(stacking_relative_position,
|
||||||
|
relative_containing_block_size,
|
||||||
|
CoordinateSystem::Parent)
|
||||||
|
.translate(stacking_context_position))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use construct::ConstructionResult;
|
||||||
use context::SharedLayoutContext;
|
use context::SharedLayoutContext;
|
||||||
use flow::{mod, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
use flow::{mod, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
use fragment::{Fragment, FragmentOverflowIterator};
|
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||||
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT};
|
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use parallel::{mod, UnsafeFlow};
|
use parallel::{mod, UnsafeFlow};
|
||||||
|
@ -604,8 +604,8 @@ impl LayoutTask {
|
||||||
// FIXME(pcwalton): This has not been updated to handle the stacking context relative
|
// FIXME(pcwalton): This has not been updated to handle the stacking context relative
|
||||||
// stuff. So the position is wrong in most cases.
|
// stuff. So the position is wrong in most cases.
|
||||||
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||||
let mut iterator = UnioningFragmentOverflowIterator::new(requested_node);
|
let mut iterator = UnioningFragmentBorderBoxIterator::new(requested_node);
|
||||||
sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator);
|
sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
|
||||||
rw_data.content_box_response = iterator.rect;
|
rw_data.content_box_response = iterator.rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,8 +616,8 @@ impl LayoutTask {
|
||||||
// FIXME(pcwalton): This has not been updated to handle the stacking context relative
|
// FIXME(pcwalton): This has not been updated to handle the stacking context relative
|
||||||
// stuff. So the position is wrong in most cases.
|
// stuff. So the position is wrong in most cases.
|
||||||
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||||
let mut iterator = CollectingFragmentOverflowIterator::new(requested_node);
|
let mut iterator = CollectingFragmentBorderBoxIterator::new(requested_node);
|
||||||
sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator);
|
sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
|
||||||
rw_data.content_boxes_response = iterator.rects;
|
rw_data.content_boxes_response = iterator.rects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,26 +1017,26 @@ impl LayoutRPC for LayoutRPCImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UnioningFragmentOverflowIterator {
|
struct UnioningFragmentBorderBoxIterator {
|
||||||
node_address: OpaqueNode,
|
node_address: OpaqueNode,
|
||||||
rect: Rect<Au>,
|
rect: Rect<Au>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnioningFragmentOverflowIterator {
|
impl UnioningFragmentBorderBoxIterator {
|
||||||
fn new(node_address: OpaqueNode) -> UnioningFragmentOverflowIterator {
|
fn new(node_address: OpaqueNode) -> UnioningFragmentBorderBoxIterator {
|
||||||
UnioningFragmentOverflowIterator {
|
UnioningFragmentBorderBoxIterator {
|
||||||
node_address: node_address,
|
node_address: node_address,
|
||||||
rect: Rect::zero(),
|
rect: Rect::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FragmentOverflowIterator for UnioningFragmentOverflowIterator {
|
impl FragmentBorderBoxIterator for UnioningFragmentBorderBoxIterator {
|
||||||
fn process(&mut self, _: &Fragment, bounds: Rect<Au>) {
|
fn process(&mut self, _: &Fragment, border_box: &Rect<Au>) {
|
||||||
if self.rect.is_empty() {
|
self.rect = if self.rect.is_empty() {
|
||||||
self.rect = bounds;
|
*border_box
|
||||||
} else {
|
} else {
|
||||||
self.rect = self.rect.union(&bounds);
|
self.rect.union(border_box)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1045,23 +1045,23 @@ impl FragmentOverflowIterator for UnioningFragmentOverflowIterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CollectingFragmentOverflowIterator {
|
struct CollectingFragmentBorderBoxIterator {
|
||||||
node_address: OpaqueNode,
|
node_address: OpaqueNode,
|
||||||
rects: Vec<Rect<Au>>,
|
rects: Vec<Rect<Au>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CollectingFragmentOverflowIterator {
|
impl CollectingFragmentBorderBoxIterator {
|
||||||
fn new(node_address: OpaqueNode) -> CollectingFragmentOverflowIterator {
|
fn new(node_address: OpaqueNode) -> CollectingFragmentBorderBoxIterator {
|
||||||
CollectingFragmentOverflowIterator {
|
CollectingFragmentBorderBoxIterator {
|
||||||
node_address: node_address,
|
node_address: node_address,
|
||||||
rects: Vec::new(),
|
rects: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FragmentOverflowIterator for CollectingFragmentOverflowIterator {
|
impl FragmentBorderBoxIterator for CollectingFragmentBorderBoxIterator {
|
||||||
fn process(&mut self, _: &Fragment, bounds: Rect<Au>) {
|
fn process(&mut self, _: &Fragment, border_box: &Rect<Au>) {
|
||||||
self.rects.push(bounds);
|
self.rects.push(*border_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_process(&mut self, fragment: &Fragment) -> bool {
|
fn should_process(&mut self, fragment: &Fragment) -> bool {
|
||||||
|
|
|
@ -12,10 +12,10 @@ use construct::FlowConstructor;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use display_list_builder::ListItemFlowDisplayListBuilding;
|
use display_list_builder::ListItemFlowDisplayListBuilding;
|
||||||
use flow::{Flow, FlowClass};
|
use flow::{Flow, FlowClass};
|
||||||
use fragment::{Fragment, FragmentOverflowIterator};
|
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use geom::Rect;
|
use geom::{Point2D, Rect};
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use servo_util::opts;
|
use servo_util::opts;
|
||||||
|
@ -116,8 +116,10 @@ impl Flow for ListItemFlow {
|
||||||
self.block_flow.compute_overflow()
|
self.block_flow.compute_overflow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,10 @@
|
||||||
//! Implements sequential traversals over the DOM and flow trees.
|
//! Implements sequential traversals over the DOM and flow trees.
|
||||||
|
|
||||||
use context::{LayoutContext, SharedLayoutContext};
|
use context::{LayoutContext, SharedLayoutContext};
|
||||||
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
|
use flow::{mod, Flow, ImmutableFlowUtils, MutableFlowUtils, PostorderFlowTraversal};
|
||||||
use flow;
|
use flow::{PreorderFlowTraversal};
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
use fragment::FragmentOverflowIterator;
|
use fragment::FragmentBorderBoxIterator;
|
||||||
use servo_util::opts;
|
|
||||||
use traversal::{BubbleISizes, RecalcStyleForNode, ConstructFlows};
|
use traversal::{BubbleISizes, RecalcStyleForNode, ConstructFlows};
|
||||||
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
|
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
|
||||||
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
|
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
|
||||||
|
@ -17,6 +16,10 @@ use wrapper::LayoutNode;
|
||||||
use wrapper::{PostorderNodeMutTraversal};
|
use wrapper::{PostorderNodeMutTraversal};
|
||||||
use wrapper::{PreorderDomTraversal, PostorderDomTraversal};
|
use wrapper::{PreorderDomTraversal, PostorderDomTraversal};
|
||||||
|
|
||||||
|
use geom::point::Point2D;
|
||||||
|
use servo_util::geometry::{Au, ZERO_POINT};
|
||||||
|
use servo_util::opts;
|
||||||
|
|
||||||
pub fn traverse_dom_preorder(root: LayoutNode,
|
pub fn traverse_dom_preorder(root: LayoutNode,
|
||||||
shared_layout_context: &SharedLayoutContext) {
|
shared_layout_context: &SharedLayoutContext) {
|
||||||
fn doit(node: LayoutNode, recalc_style: RecalcStyleForNode, construct_flows: ConstructFlows) {
|
fn doit(node: LayoutNode, recalc_style: RecalcStyleForNode, construct_flows: ConstructFlows) {
|
||||||
|
@ -94,15 +97,25 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
||||||
doit(root.deref_mut(), compute_absolute_positions, build_display_list);
|
doit(root.deref_mut(), compute_absolute_positions, build_display_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterate_through_flow_tree_fragment_bounds(root: &mut FlowRef,
|
pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef,
|
||||||
iterator: &mut FragmentOverflowIterator) {
|
iterator: &mut FragmentBorderBoxIterator) {
|
||||||
fn doit(flow: &mut Flow, iterator: &mut FragmentOverflowIterator) {
|
fn doit(flow: &mut Flow,
|
||||||
flow.iterate_through_fragment_overflow(iterator);
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position);
|
||||||
|
|
||||||
for kid in flow::mut_base(flow).child_iter() {
|
for kid in flow::mut_base(flow).child_iter() {
|
||||||
doit(kid, iterator);
|
let stacking_context_position =
|
||||||
|
if kid.is_block_flow() && kid.as_block().fragment.establishes_stacking_context() {
|
||||||
|
*stacking_context_position + flow::base(kid).stacking_relative_position
|
||||||
|
} else {
|
||||||
|
*stacking_context_position
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME(#2795): Get the real container size.
|
||||||
|
doit(kid, iterator, &stacking_context_position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doit(root.deref_mut(), iterator);
|
doit(root.deref_mut(), iterator, &ZERO_POINT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,14 @@ use context::LayoutContext;
|
||||||
use floats::FloatKind;
|
use floats::FloatKind;
|
||||||
use flow::{mod, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
|
use flow::{mod, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
|
||||||
use flow::ImmutableFlowUtils;
|
use flow::ImmutableFlowUtils;
|
||||||
use fragment::{Fragment, FragmentOverflowIterator};
|
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use model::{IntrinsicISizes, IntrinsicISizesContribution};
|
use model::{IntrinsicISizes, IntrinsicISizesContribution};
|
||||||
use table_row::CellIntrinsicInlineSize;
|
use table_row::CellIntrinsicInlineSize;
|
||||||
use table_wrapper::TableLayout;
|
use table_wrapper::TableLayout;
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use geom::Rect;
|
use geom::{Point2D, Rect};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use servo_util::logical_geometry::LogicalRect;
|
use servo_util::logical_geometry::LogicalRect;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
@ -389,8 +389,10 @@ impl Flow for TableFlow {
|
||||||
self.block_flow.compute_overflow()
|
self.block_flow.compute_overflow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ use block::BlockFlow;
|
||||||
use construct::FlowConstructor;
|
use construct::FlowConstructor;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use flow::{FlowClass, Flow};
|
use flow::{FlowClass, Flow};
|
||||||
use fragment::FragmentOverflowIterator;
|
use fragment::FragmentBorderBoxIterator;
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use geom::Rect;
|
use geom::{Point2D, Rect};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style::ComputedValues;
|
use style::ComputedValues;
|
||||||
|
@ -86,8 +86,10 @@ impl Flow for TableCaptionFlow {
|
||||||
self.block_flow.compute_overflow()
|
self.block_flow.compute_overflow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
|
use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use flow::{Flow, FlowClass};
|
use flow::{Flow, FlowClass};
|
||||||
use fragment::{Fragment, FragmentOverflowIterator};
|
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||||
use model::{MaybeAuto};
|
use model::{MaybeAuto};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use table::InternalTable;
|
use table::InternalTable;
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use geom::Rect;
|
use geom::{Point2D, Rect};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style::{UnsignedIntegerAttribute, ComputedValues};
|
use style::{UnsignedIntegerAttribute, ComputedValues};
|
||||||
|
@ -167,8 +167,10 @@ impl Flow for TableCellFlow {
|
||||||
self.block_flow.compute_overflow()
|
self.block_flow.compute_overflow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use flow::{BaseFlow, FlowClass, Flow, ForceNonfloatedFlag};
|
use flow::{BaseFlow, FlowClass, Flow, ForceNonfloatedFlag};
|
||||||
use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo};
|
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use geom::Rect;
|
use geom::{Point2D, Rect};
|
||||||
use servo_util::geometry::{Au, ZERO_RECT};
|
use servo_util::geometry::{Au, ZERO_RECT};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -101,8 +101,9 @@ impl Flow for TableColGroupFlow {
|
||||||
ZERO_RECT
|
ZERO_RECT
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, _: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
}
|
_: &mut FragmentBorderBoxIterator,
|
||||||
|
_: &Point2D<Au>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for TableColGroupFlow {
|
impl fmt::Show for TableColGroupFlow {
|
||||||
|
|
|
@ -12,13 +12,13 @@ use construct::FlowConstructor;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use flow::{FlowClass, Flow, ImmutableFlowUtils};
|
use flow::{FlowClass, Flow, ImmutableFlowUtils};
|
||||||
use flow;
|
use flow;
|
||||||
use fragment::{Fragment, FragmentOverflowIterator};
|
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable};
|
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable};
|
||||||
use model::MaybeAuto;
|
use model::MaybeAuto;
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use geom::Rect;
|
use geom::{Point2D, Rect};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -320,8 +320,10 @@ impl Flow for TableRowFlow {
|
||||||
self.block_flow.compute_overflow()
|
self.block_flow.compute_overflow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,12 @@ use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
|
||||||
use construct::FlowConstructor;
|
use construct::FlowConstructor;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use flow::{FlowClass, Flow};
|
use flow::{FlowClass, Flow};
|
||||||
use fragment::{Fragment, FragmentOverflowIterator};
|
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable};
|
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable};
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use geom::Rect;
|
use geom::{Point2D, Rect};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style::ComputedValues;
|
use style::ComputedValues;
|
||||||
|
@ -155,8 +155,10 @@ impl Flow for TableRowGroupFlow {
|
||||||
self.block_flow.compute_overflow()
|
self.block_flow.compute_overflow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,11 @@ use context::LayoutContext;
|
||||||
use floats::FloatKind;
|
use floats::FloatKind;
|
||||||
use flow::{FlowClass, Flow, ImmutableFlowUtils};
|
use flow::{FlowClass, Flow, ImmutableFlowUtils};
|
||||||
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
|
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
|
||||||
use fragment::{Fragment, FragmentOverflowIterator};
|
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
|
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
|
||||||
use wrapper::ThreadSafeLayoutNode;
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
use geom::Rect;
|
use geom::{Point2D, Rect};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -363,8 +363,10 @@ impl Flow for TableWrapperFlow {
|
||||||
self.block_flow.compute_overflow()
|
self.block_flow.compute_overflow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
fn iterate_through_fragment_border_boxes(&self,
|
||||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
iterator: &mut FragmentBorderBoxIterator,
|
||||||
|
stacking_context_position: &Point2D<Au>) {
|
||||||
|
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ pub use selector_matching::{matches, matches_simple_selector, common_style_affec
|
||||||
pub use selector_matching::{rare_style_affecting_attributes};
|
pub use selector_matching::{rare_style_affecting_attributes};
|
||||||
pub use selector_matching::{RECOMMENDED_SELECTOR_BLOOM_FILTER_SIZE, SELECTOR_WHITESPACE};
|
pub use selector_matching::{RECOMMENDED_SELECTOR_BLOOM_FILTER_SIZE, SELECTOR_WHITESPACE};
|
||||||
pub use properties::{cascade, cascade_anonymous, computed, longhands_from_shorthand};
|
pub use properties::{cascade, cascade_anonymous, computed, longhands_from_shorthand};
|
||||||
pub use properties::is_supported_property;
|
pub use properties::{is_supported_property, make_inline};
|
||||||
pub use properties::{PropertyDeclaration, ComputedValues, computed_values, style_structs};
|
pub use properties::{PropertyDeclaration, ComputedValues, computed_values, style_structs};
|
||||||
pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes
|
pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes
|
||||||
pub use properties::{CSSFloat, DeclaredValue, PropertyDeclarationParseResult};
|
pub use properties::{CSSFloat, DeclaredValue, PropertyDeclarationParseResult};
|
||||||
|
|
|
@ -3183,6 +3183,15 @@ pub fn cascade_anonymous(parent_style: &ComputedValues) -> ComputedValues {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets `display` to `inline` and `position` to `static`.
|
||||||
|
#[inline]
|
||||||
|
pub fn make_inline(style: &ComputedValues) -> ComputedValues {
|
||||||
|
let mut style = (*style).clone();
|
||||||
|
style.box_.make_unique().display = longhands::display::computed_value::T::inline;
|
||||||
|
style.box_.make_unique().position = longhands::position::computed_value::T::static_;
|
||||||
|
style
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_supported_property(property: &str) -> bool {
|
pub fn is_supported_property(property: &str) -> bool {
|
||||||
match property {
|
match property {
|
||||||
% for property in SHORTHANDS:
|
% for property in SHORTHANDS:
|
||||||
|
|
|
@ -22,7 +22,7 @@ function _pass(s, m) {
|
||||||
|
|
||||||
function _printer(opstr, op) {
|
function _printer(opstr, op) {
|
||||||
return function (a, b, msg) {
|
return function (a, b, msg) {
|
||||||
let f = op(a,b) ? _pass : _fail;
|
var f = op(a,b) ? _pass : _fail;
|
||||||
if (!msg) msg = "";
|
if (!msg) msg = "";
|
||||||
f(a + " " + opstr + " " + b, msg);
|
f(a + " " + opstr + " " + b, msg);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue