mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
layout: Paint stacking contexts' overflow areas properly.
This was making `box-shadow` not show up in many cases, in particular, but the effects were not limited to that.
This commit is contained in:
parent
ba8cf6b0e6
commit
5ea2c6dcfd
30 changed files with 357 additions and 179 deletions
|
@ -41,7 +41,7 @@ use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
|
|||
use flow::{IS_ABSOLUTELY_POSITIONED};
|
||||
use flow::{CLEARS_LEFT, CLEARS_RIGHT};
|
||||
use flow;
|
||||
use fragment::{Fragment, FragmentBoundsIterator, SpecificFragmentInfo};
|
||||
use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo};
|
||||
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||
use layout_debug;
|
||||
use model::{IntrinsicISizes, MarginCollapseInfo};
|
||||
|
@ -49,7 +49,7 @@ use model::{MaybeAuto, CollapsibleMargins, specified, specified_or_none};
|
|||
use table::ColumnComputedInlineSize;
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use geom::Size2D;
|
||||
use geom::{Rect, Size2D};
|
||||
use gfx::display_list::{ClippingRegion, DisplayList};
|
||||
use serialize::{Encoder, Encodable};
|
||||
use servo_msg::compositor_msg::LayerId;
|
||||
|
@ -1797,13 +1797,6 @@ impl Flow for BlockFlow {
|
|||
self.flags.insert(IS_ROOT)
|
||||
}
|
||||
|
||||
/// Return true if store overflow is delayed for this flow.
|
||||
///
|
||||
/// Currently happens only for absolutely positioned flows.
|
||||
fn is_store_overflow_delayed(&mut self) -> bool {
|
||||
self.base.flags.contains(IS_ABSOLUTELY_POSITIONED)
|
||||
}
|
||||
|
||||
fn is_root(&self) -> bool {
|
||||
self.flags.contains(IS_ROOT)
|
||||
}
|
||||
|
@ -1864,12 +1857,13 @@ impl Flow for BlockFlow {
|
|||
self.fragment.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
self.fragment.compute_overflow()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
||||
if iterator.should_process(&self.fragment) {
|
||||
let fragment_origin =
|
||||
self.base.stacking_relative_position_of_child_fragment(&self.fragment);
|
||||
iterator.process(&self.fragment,
|
||||
self.fragment.stacking_relative_bounds(&fragment_origin));
|
||||
iterator.process(&self.fragment, self.fragment.compute_overflow());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2455,11 +2449,14 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
|
|||
MaybeAuto::Specified(fragment.content_inline_size())
|
||||
}
|
||||
|
||||
fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au {
|
||||
fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext)
|
||||
-> Au {
|
||||
block.containing_block_size(ctx.shared.screen_size).inline
|
||||
}
|
||||
|
||||
fn set_flow_x_coord_if_necessary(&self, block: &mut BlockFlow, solution: ISizeConstraintSolution) {
|
||||
fn set_flow_x_coord_if_necessary(&self,
|
||||
block: &mut BlockFlow,
|
||||
solution: ISizeConstraintSolution) {
|
||||
// Set the x-coordinate of the absolute flow wrt to its containing block.
|
||||
block.base.position.start.i = solution.inline_start;
|
||||
}
|
||||
|
|
|
@ -1103,7 +1103,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
background_border_level);
|
||||
|
||||
self.base.display_list_building_result = if self.fragment.establishes_stacking_context() {
|
||||
DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, None))
|
||||
DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list,
|
||||
None))
|
||||
} else {
|
||||
DisplayListBuildingResult::Normal(display_list)
|
||||
}
|
||||
|
@ -1120,7 +1121,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
!self.base.flags.contains(NEEDS_LAYER) {
|
||||
// We didn't need a layer.
|
||||
self.base.display_list_building_result =
|
||||
DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, None));
|
||||
DisplayListBuildingResult::StackingContext(self.create_stacking_context(
|
||||
display_list,
|
||||
None));
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1137,7 +1140,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
Some(Arc::new(PaintLayer::new(self.layer_id(0),
|
||||
transparent,
|
||||
scroll_policy))));
|
||||
self.base.display_list_building_result = DisplayListBuildingResult::StackingContext(stacking_context)
|
||||
self.base.display_list_building_result =
|
||||
DisplayListBuildingResult::StackingContext(stacking_context)
|
||||
}
|
||||
|
||||
fn build_display_list_for_floating_block(&mut self,
|
||||
|
@ -1149,7 +1153,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
display_list.form_float_pseudo_stacking_context();
|
||||
|
||||
self.base.display_list_building_result = if self.fragment.establishes_stacking_context() {
|
||||
DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, None))
|
||||
DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list,
|
||||
None))
|
||||
} else {
|
||||
DisplayListBuildingResult::Normal(display_list)
|
||||
}
|
||||
|
@ -1165,7 +1170,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
} else if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
||||
self.build_display_list_for_absolutely_positioned_block(display_list, layout_context)
|
||||
} else {
|
||||
self.build_display_list_for_static_block(display_list, layout_context, BackgroundAndBorderLevel::Block)
|
||||
self.build_display_list_for_static_block(display_list,
|
||||
layout_context,
|
||||
BackgroundAndBorderLevel::Block)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1173,11 +1180,16 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
display_list: Box<DisplayList>,
|
||||
layer: Option<Arc<PaintLayer>>)
|
||||
-> Arc<StackingContext> {
|
||||
let bounds = Rect(self.base.stacking_relative_position,
|
||||
self.base.overflow.size.to_physical(self.base.writing_mode));
|
||||
let size = self.base.position.size.to_physical(self.base.writing_mode);
|
||||
let bounds = Rect(self.base.stacking_relative_position, size);
|
||||
let z_index = self.fragment.style().get_box().z_index.number_or_zero();
|
||||
let opacity = self.fragment.style().get_effects().opacity as f32;
|
||||
Arc::new(StackingContext::new(display_list, bounds, z_index, opacity, layer))
|
||||
Arc::new(StackingContext::new(display_list,
|
||||
&bounds,
|
||||
&self.base.overflow,
|
||||
z_index,
|
||||
opacity,
|
||||
layer))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ use display_list_builder::DisplayListBuildingResult;
|
|||
use floats::Floats;
|
||||
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
||||
use flow_ref::FlowRef;
|
||||
use fragment::{Fragment, FragmentBoundsIterator, SpecificFragmentInfo};
|
||||
use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo};
|
||||
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
||||
use inline::InlineFlow;
|
||||
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
||||
|
@ -50,7 +50,7 @@ use geom::{Point2D, Rect, Size2D};
|
|||
use gfx::display_list::ClippingRegion;
|
||||
use serialize::{Encoder, Encodable};
|
||||
use servo_msg::compositor_msg::LayerId;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::geometry::{Au, ZERO_RECT};
|
||||
use servo_util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
|
||||
use std::mem;
|
||||
use std::fmt;
|
||||
|
@ -220,8 +220,11 @@ pub trait Flow: fmt::Show + ToString + Sync {
|
|||
/// Phase 5 of reflow: builds display lists.
|
||||
fn build_display_list(&mut self, layout_context: &LayoutContext);
|
||||
|
||||
/// Perform an iteration of fragment bounds on this flow.
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator);
|
||||
/// Returns the union of all overflow rects of all of this flow's fragments.
|
||||
fn compute_overflow(&self) -> Rect<Au>;
|
||||
|
||||
/// Iterates through overflow rects of all of this flow's fragments.
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator);
|
||||
|
||||
fn compute_collapsible_block_start_margin(&mut self,
|
||||
_layout_context: &mut LayoutContext,
|
||||
|
@ -718,7 +721,7 @@ pub struct BaseFlow {
|
|||
|
||||
/// The amount of overflow of this flow, relative to the containing block. Must include all the
|
||||
/// pixels of all the display list items for correct invalidation.
|
||||
pub overflow: LogicalRect<Au>,
|
||||
pub overflow: Rect<Au>,
|
||||
|
||||
/// Data used during parallel traversals.
|
||||
///
|
||||
|
@ -894,7 +897,7 @@ impl BaseFlow {
|
|||
children: FlowList::new(),
|
||||
intrinsic_inline_sizes: IntrinsicISizes::new(),
|
||||
position: LogicalRect::zero(writing_mode),
|
||||
overflow: LogicalRect::zero(writing_mode),
|
||||
overflow: ZERO_RECT,
|
||||
parallel: FlowParallelInfo::new(),
|
||||
floats: Floats::new(writing_mode),
|
||||
collapsible_margins: CollapsibleMargins::new(),
|
||||
|
@ -929,10 +932,12 @@ impl BaseFlow {
|
|||
/// Ensures that all display list items generated by this flow are within the flow's overflow
|
||||
/// rect. This should only be used for debugging.
|
||||
pub fn validate_display_list_geometry(&self) {
|
||||
let position_with_overflow = self.position.union(&self.overflow);
|
||||
let bounds = Rect(self.stacking_relative_position,
|
||||
Size2D(position_with_overflow.size.inline,
|
||||
position_with_overflow.size.block));
|
||||
// FIXME(pcwalton, #2795): Get the real container size.
|
||||
let container_size = Size2D::zero();
|
||||
let position_with_overflow = self.position
|
||||
.to_physical(self.writing_mode, container_size)
|
||||
.union(&self.overflow);
|
||||
let bounds = Rect(self.stacking_relative_position, position_with_overflow.size);
|
||||
|
||||
let all_items = match self.display_list_building_result {
|
||||
DisplayListBuildingResult::None => Vec::new(),
|
||||
|
@ -1175,40 +1180,29 @@ impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
|
|||
/// already been set.
|
||||
/// Assumption: Absolute descendants have had their overflow calculated.
|
||||
fn store_overflow(self, _: &LayoutContext) {
|
||||
let my_position = mut_base(self).position;
|
||||
|
||||
// FIXME(pcwalton): We should calculate overflow on a per-fragment basis, because their
|
||||
// styles can affect overflow regions. Consider `box-shadow`, `outline`, etc.--anything
|
||||
// that can draw outside the border box. For now we assume overflow is the border box, but
|
||||
// that is wrong.
|
||||
let mut overflow = my_position;
|
||||
|
||||
// Calculate overflow on a per-fragment basis.
|
||||
let mut overflow = self.compute_overflow();
|
||||
if self.is_block_container() {
|
||||
let writing_mode = base(self).writing_mode;
|
||||
// FIXME(#2795): Get the real container size
|
||||
// FIXME(#2795): Get the real container size.
|
||||
let container_size = Size2D::zero();
|
||||
for kid in child_iter(self) {
|
||||
if kid.is_store_overflow_delayed() {
|
||||
// Absolute flows will be handled by their CB. If we are
|
||||
// their CB, they will show up in `abs_descendants`.
|
||||
continue;
|
||||
if base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
||||
continue
|
||||
}
|
||||
let kid_base = base(kid);
|
||||
let mut kid_overflow = kid_base.overflow.convert(
|
||||
kid_base.writing_mode, writing_mode, container_size);
|
||||
kid_overflow = kid_overflow.translate(&my_position.start);
|
||||
overflow = overflow.union(&kid_overflow)
|
||||
let kid_overflow = base(kid).overflow;
|
||||
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
|
||||
container_size);
|
||||
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
|
||||
}
|
||||
|
||||
// FIXME(#2004, pcwalton): This is wrong for `position: fixed`.
|
||||
for descendant_link in mut_base(self).abs_descendants.iter() {
|
||||
let kid_base = base(descendant_link);
|
||||
let mut kid_overflow = kid_base.overflow.convert(
|
||||
kid_base.writing_mode, writing_mode, container_size);
|
||||
kid_overflow = kid_overflow.translate(&my_position.start);
|
||||
overflow = overflow.union(&kid_overflow)
|
||||
for kid in mut_base(self).abs_descendants.iter() {
|
||||
let kid_overflow = base(kid).overflow;
|
||||
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
|
||||
container_size);
|
||||
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
|
||||
}
|
||||
}
|
||||
|
||||
mut_base(self).overflow = overflow;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ use util::OpaqueNodeMethods;
|
|||
use wrapper::{TLayoutNode, ThreadSafeLayoutNode};
|
||||
|
||||
use geom::{Point2D, Rect, Size2D};
|
||||
use gfx::display_list::OpaqueNode;
|
||||
use gfx::display_list::{BOX_SHADOW_INFLATION_FACTOR, OpaqueNode};
|
||||
use gfx::text::glyph::CharIndex;
|
||||
use gfx::text::text_run::{TextRun, TextRunSlice};
|
||||
use script_traits::UntrustedNodeAddress;
|
||||
|
@ -531,8 +531,9 @@ impl Fragment {
|
|||
// Foo
|
||||
// </div>
|
||||
//
|
||||
// Anonymous table fragments, SpecificFragmentInfo::TableRow and SpecificFragmentInfo::TableCell, are generated around
|
||||
// `Foo`, but they shouldn't inherit the border.
|
||||
// Anonymous table fragments, SpecificFragmentInfo::TableRow and
|
||||
// SpecificFragmentInfo::TableCell, are generated around `Foo`, but they shouldn't inherit
|
||||
// the border.
|
||||
|
||||
let node_style = cascade_anonymous(&**node.style());
|
||||
let writing_mode = node_style.writing_mode;
|
||||
|
@ -647,7 +648,10 @@ impl Fragment {
|
|||
fn quantities_included_in_intrinsic_inline_size(&self)
|
||||
-> QuantitiesIncludedInIntrinsicInlineSizes {
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::InlineBlock(_) => {
|
||||
SpecificFragmentInfo::Generic |
|
||||
SpecificFragmentInfo::Iframe(_) |
|
||||
SpecificFragmentInfo::Image(_) |
|
||||
SpecificFragmentInfo::InlineBlock(_) => {
|
||||
QuantitiesIncludedInIntrinsicInlineSizes::all()
|
||||
}
|
||||
SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell => {
|
||||
|
@ -836,9 +840,7 @@ impl Fragment {
|
|||
}
|
||||
|
||||
// Return offset from original position because of `position: relative`.
|
||||
pub fn relative_position(&self,
|
||||
containing_block_size: &LogicalSize<Au>)
|
||||
-> LogicalSize<Au> {
|
||||
pub fn relative_position(&self, containing_block_size: &LogicalSize<Au>) -> LogicalSize<Au> {
|
||||
fn from_style(style: &ComputedValues, container_size: &LogicalSize<Au>)
|
||||
-> LogicalSize<Au> {
|
||||
let offsets = style.logical_position();
|
||||
|
@ -1567,6 +1569,41 @@ impl Fragment {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the overflow rect of this fragment relative to the start of the flow.
|
||||
pub fn compute_overflow(&self) -> Rect<Au> {
|
||||
// FIXME(pcwalton, #2795): Get the real container size.
|
||||
let container_size = Size2D::zero();
|
||||
let mut border_box = self.border_box.to_physical(self.style.writing_mode, container_size);
|
||||
|
||||
// Relative position can cause us to draw outside our border box.
|
||||
//
|
||||
// FIXME(pcwalton): I'm not a fan of the way this makes us crawl though so many styles all
|
||||
// the time. Can't we handle relative positioning by just adjusting `border_box`?
|
||||
let relative_position =
|
||||
self.relative_position(&LogicalSize::zero(self.style.writing_mode));
|
||||
border_box =
|
||||
border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode));
|
||||
let mut overflow = border_box;
|
||||
|
||||
// Box shadows cause us to draw outside our border box.
|
||||
for box_shadow in self.style().get_effects().box_shadow.iter() {
|
||||
let offset = Point2D(box_shadow.offset_x, box_shadow.offset_y);
|
||||
let inflation = box_shadow.spread_radius +
|
||||
box_shadow.blur_radius * BOX_SHADOW_INFLATION_FACTOR;
|
||||
overflow = overflow.union(&border_box.translate(&offset).inflate(inflation, inflation))
|
||||
}
|
||||
|
||||
// Outlines cause us to draw outside our border box.
|
||||
let outline_width = self.style.get_outline().outline_width;
|
||||
if outline_width != Au(0) {
|
||||
overflow = overflow.union(&border_box.inflate(outline_width, outline_width))
|
||||
}
|
||||
|
||||
// FIXME(pcwalton): Sometimes excessively fancy glyphs can make us draw outside our border
|
||||
// box too.
|
||||
overflow
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for Fragment {
|
||||
|
@ -1600,10 +1637,10 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
/// A top-down fragment bounds iteration handler.
|
||||
pub trait FragmentBoundsIterator {
|
||||
/// A top-down fragment overflow region iteration handler.
|
||||
pub trait FragmentOverflowIterator {
|
||||
/// The operation to perform.
|
||||
fn process(&mut self, fragment: &Fragment, bounds: 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,
|
||||
/// we skip the operation for this fragment, but continue processing siblings.
|
||||
|
|
|
@ -12,7 +12,7 @@ use flow::{BaseFlow, FlowClass, Flow, MutableFlowUtils, ForceNonfloatedFlag};
|
|||
use flow::{IS_ABSOLUTELY_POSITIONED};
|
||||
use flow;
|
||||
use fragment::{Fragment, SpecificFragmentInfo};
|
||||
use fragment::{FragmentBoundsIterator, ScannedTextFragmentInfo};
|
||||
use fragment::{FragmentOverflowIterator, ScannedTextFragmentInfo};
|
||||
use fragment::SplitInfo;
|
||||
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||
use layout_debug;
|
||||
|
@ -20,12 +20,12 @@ use model::IntrinsicISizesContribution;
|
|||
use text;
|
||||
|
||||
use collections::{RingBuf};
|
||||
use geom::Size2D;
|
||||
use geom::{Rect, Size2D};
|
||||
use gfx::display_list::DisplayList;
|
||||
use gfx::font::FontMetrics;
|
||||
use gfx::font_context::FontContext;
|
||||
use gfx::text::glyph::CharIndex;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::geometry::{Au, ZERO_RECT};
|
||||
use servo_util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
|
||||
use servo_util::opts;
|
||||
use servo_util::range::{Range, RangeIndex};
|
||||
|
@ -1271,7 +1271,15 @@ impl Flow for InlineFlow {
|
|||
|
||||
fn repair_style(&mut self, _: &Arc<ComputedValues>) {}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
let mut overflow = ZERO_RECT;
|
||||
for fragment in self.fragments.fragments.iter() {
|
||||
overflow = overflow.union(&fragment.compute_overflow())
|
||||
}
|
||||
overflow
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
||||
for fragment in self.fragments.fragments.iter() {
|
||||
if iterator.should_process(fragment) {
|
||||
let fragment_origin =
|
||||
|
|
|
@ -10,7 +10,7 @@ use construct::ConstructionResult;
|
|||
use context::SharedLayoutContext;
|
||||
use flow::{mod, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
||||
use flow_ref::FlowRef;
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use fragment::{Fragment, FragmentOverflowIterator};
|
||||
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT};
|
||||
use layout_debug;
|
||||
use parallel::{mod, UnsafeFlow};
|
||||
|
@ -604,7 +604,7 @@ impl LayoutTask {
|
|||
// FIXME(pcwalton): This has not been updated to handle the stacking context relative
|
||||
// stuff. So the position is wrong in most cases.
|
||||
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||
let mut iterator = UnioningFragmentBoundsIterator::new(requested_node);
|
||||
let mut iterator = UnioningFragmentOverflowIterator::new(requested_node);
|
||||
sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator);
|
||||
rw_data.content_box_response = iterator.rect;
|
||||
}
|
||||
|
@ -616,7 +616,7 @@ impl LayoutTask {
|
|||
// FIXME(pcwalton): This has not been updated to handle the stacking context relative
|
||||
// stuff. So the position is wrong in most cases.
|
||||
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||
let mut iterator = CollectingFragmentBoundsIterator::new(requested_node);
|
||||
let mut iterator = CollectingFragmentOverflowIterator::new(requested_node);
|
||||
sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator);
|
||||
rw_data.content_boxes_response = iterator.rects;
|
||||
}
|
||||
|
@ -689,11 +689,12 @@ impl LayoutTask {
|
|||
flow::mut_base(layout_root.deref_mut()).display_list_building_result
|
||||
.add_to(&mut *display_list);
|
||||
let paint_layer = Arc::new(PaintLayer::new(layout_root.layer_id(0),
|
||||
color,
|
||||
Scrollable));
|
||||
color,
|
||||
Scrollable));
|
||||
let origin = Rect(Point2D(Au(0), Au(0)), root_size);
|
||||
let stacking_context = Arc::new(StackingContext::new(display_list,
|
||||
origin,
|
||||
&origin,
|
||||
&origin,
|
||||
0,
|
||||
1.0,
|
||||
Some(paint_layer)));
|
||||
|
@ -1016,21 +1017,21 @@ impl LayoutRPC for LayoutRPCImpl {
|
|||
}
|
||||
}
|
||||
|
||||
struct UnioningFragmentBoundsIterator {
|
||||
struct UnioningFragmentOverflowIterator {
|
||||
node_address: OpaqueNode,
|
||||
rect: Rect<Au>,
|
||||
}
|
||||
|
||||
impl UnioningFragmentBoundsIterator {
|
||||
fn new(node_address: OpaqueNode) -> UnioningFragmentBoundsIterator {
|
||||
UnioningFragmentBoundsIterator {
|
||||
impl UnioningFragmentOverflowIterator {
|
||||
fn new(node_address: OpaqueNode) -> UnioningFragmentOverflowIterator {
|
||||
UnioningFragmentOverflowIterator {
|
||||
node_address: node_address,
|
||||
rect: Rect::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FragmentBoundsIterator for UnioningFragmentBoundsIterator {
|
||||
impl FragmentOverflowIterator for UnioningFragmentOverflowIterator {
|
||||
fn process(&mut self, _: &Fragment, bounds: Rect<Au>) {
|
||||
if self.rect.is_empty() {
|
||||
self.rect = bounds;
|
||||
|
@ -1044,21 +1045,21 @@ impl FragmentBoundsIterator for UnioningFragmentBoundsIterator {
|
|||
}
|
||||
}
|
||||
|
||||
struct CollectingFragmentBoundsIterator {
|
||||
struct CollectingFragmentOverflowIterator {
|
||||
node_address: OpaqueNode,
|
||||
rects: Vec<Rect<Au>>,
|
||||
}
|
||||
|
||||
impl CollectingFragmentBoundsIterator {
|
||||
fn new(node_address: OpaqueNode) -> CollectingFragmentBoundsIterator {
|
||||
CollectingFragmentBoundsIterator {
|
||||
impl CollectingFragmentOverflowIterator {
|
||||
fn new(node_address: OpaqueNode) -> CollectingFragmentOverflowIterator {
|
||||
CollectingFragmentOverflowIterator {
|
||||
node_address: node_address,
|
||||
rects: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FragmentBoundsIterator for CollectingFragmentBoundsIterator {
|
||||
impl FragmentOverflowIterator for CollectingFragmentOverflowIterator {
|
||||
fn process(&mut self, _: &Fragment, bounds: Rect<Au>) {
|
||||
self.rects.push(bounds);
|
||||
}
|
||||
|
|
|
@ -12,9 +12,10 @@ use construct::FlowConstructor;
|
|||
use context::LayoutContext;
|
||||
use display_list_builder::ListItemFlowDisplayListBuilding;
|
||||
use flow::{Flow, FlowClass};
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use fragment::{Fragment, FragmentOverflowIterator};
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use geom::Rect;
|
||||
use gfx::display_list::DisplayList;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::opts;
|
||||
|
@ -111,8 +112,12 @@ impl Flow for ListItemFlow {
|
|||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use context::{LayoutContext, SharedLayoutContext};
|
|||
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
|
||||
use flow;
|
||||
use flow_ref::FlowRef;
|
||||
use fragment::FragmentBoundsIterator;
|
||||
use fragment::FragmentOverflowIterator;
|
||||
use servo_util::opts;
|
||||
use traversal::{BubbleISizes, RecalcStyleForNode, ConstructFlows};
|
||||
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
|
||||
|
@ -95,9 +95,9 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
|||
}
|
||||
|
||||
pub fn iterate_through_flow_tree_fragment_bounds(root: &mut FlowRef,
|
||||
iterator: &mut FragmentBoundsIterator) {
|
||||
fn doit(flow: &mut Flow, iterator: &mut FragmentBoundsIterator) {
|
||||
flow.iterate_through_fragment_bounds(iterator);
|
||||
iterator: &mut FragmentOverflowIterator) {
|
||||
fn doit(flow: &mut Flow, iterator: &mut FragmentOverflowIterator) {
|
||||
flow.iterate_through_fragment_overflow(iterator);
|
||||
|
||||
for kid in flow::mut_base(flow).child_iter() {
|
||||
doit(kid, iterator);
|
||||
|
|
|
@ -13,13 +13,14 @@ use context::LayoutContext;
|
|||
use floats::FloatKind;
|
||||
use flow::{mod, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
|
||||
use flow::ImmutableFlowUtils;
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use fragment::{Fragment, FragmentOverflowIterator};
|
||||
use layout_debug;
|
||||
use model::{IntrinsicISizes, IntrinsicISizesContribution};
|
||||
use table_row::CellIntrinsicInlineSize;
|
||||
use table_wrapper::TableLayout;
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use geom::Rect;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::logical_geometry::LogicalRect;
|
||||
use std::cmp::max;
|
||||
|
@ -384,8 +385,12 @@ impl Flow for TableFlow {
|
|||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,10 @@ use block::BlockFlow;
|
|||
use construct::FlowConstructor;
|
||||
use context::LayoutContext;
|
||||
use flow::{FlowClass, Flow};
|
||||
use fragment::FragmentBoundsIterator;
|
||||
use fragment::FragmentOverflowIterator;
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use geom::Rect;
|
||||
use servo_util::geometry::Au;
|
||||
use std::fmt;
|
||||
use style::ComputedValues;
|
||||
|
@ -81,8 +82,12 @@ impl Flow for TableCaptionFlow {
|
|||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,13 @@
|
|||
use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
|
||||
use context::LayoutContext;
|
||||
use flow::{Flow, FlowClass};
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use fragment::{Fragment, FragmentOverflowIterator};
|
||||
use model::{MaybeAuto};
|
||||
use layout_debug;
|
||||
use table::InternalTable;
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use geom::Rect;
|
||||
use servo_util::geometry::Au;
|
||||
use std::fmt;
|
||||
use style::{UnsignedIntegerAttribute, ComputedValues};
|
||||
|
@ -162,8 +163,12 @@ impl Flow for TableCellFlow {
|
|||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
use context::LayoutContext;
|
||||
use css::node_style::StyledNode;
|
||||
use flow::{BaseFlow, FlowClass, Flow, ForceNonfloatedFlag};
|
||||
use fragment::{Fragment, FragmentBoundsIterator, SpecificFragmentInfo};
|
||||
use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo};
|
||||
use layout_debug;
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use servo_util::geometry::Au;
|
||||
use geom::Rect;
|
||||
use servo_util::geometry::{Au, ZERO_RECT};
|
||||
use std::cmp::max;
|
||||
use std::fmt;
|
||||
use style::computed_values::LengthOrPercentageOrAuto;
|
||||
|
@ -96,7 +97,11 @@ impl Flow for TableColGroupFlow {
|
|||
|
||||
fn repair_style(&mut self, _: &Arc<ComputedValues>) {}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, _: &mut FragmentBoundsIterator) {
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
ZERO_RECT
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, _: &mut FragmentOverflowIterator) {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,12 +12,13 @@ use construct::FlowConstructor;
|
|||
use context::LayoutContext;
|
||||
use flow::{FlowClass, Flow, ImmutableFlowUtils};
|
||||
use flow;
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use fragment::{Fragment, FragmentOverflowIterator};
|
||||
use layout_debug;
|
||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable};
|
||||
use model::MaybeAuto;
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use geom::Rect;
|
||||
use servo_util::geometry::Au;
|
||||
use std::cmp::max;
|
||||
use std::fmt;
|
||||
|
@ -315,8 +316,12 @@ impl Flow for TableRowFlow {
|
|||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,12 @@ use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
|
|||
use construct::FlowConstructor;
|
||||
use context::LayoutContext;
|
||||
use flow::{FlowClass, Flow};
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use fragment::{Fragment, FragmentOverflowIterator};
|
||||
use layout_debug;
|
||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable};
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use geom::Rect;
|
||||
use servo_util::geometry::Au;
|
||||
use std::fmt;
|
||||
use style::ComputedValues;
|
||||
|
@ -150,8 +151,12 @@ impl Flow for TableRowGroupFlow {
|
|||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,10 +19,11 @@ use context::LayoutContext;
|
|||
use floats::FloatKind;
|
||||
use flow::{FlowClass, Flow, ImmutableFlowUtils};
|
||||
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
|
||||
use fragment::{Fragment, FragmentBoundsIterator};
|
||||
use fragment::{Fragment, FragmentOverflowIterator};
|
||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use geom::Rect;
|
||||
use servo_util::geometry::Au;
|
||||
use std::cmp::{max, min};
|
||||
use std::fmt;
|
||||
|
@ -358,8 +359,12 @@ impl Flow for TableWrapperFlow {
|
|||
self.block_flow.repair_style(new_style)
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) {
|
||||
self.block_flow.iterate_through_fragment_bounds(iterator);
|
||||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) {
|
||||
self.block_flow.iterate_through_fragment_overflow(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -332,12 +332,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {
|
|||
}
|
||||
|
||||
flow.assign_block_size(self.layout_context);
|
||||
|
||||
// Skip store-overflow for absolutely positioned flows. That will be
|
||||
// done in a separate traversal.
|
||||
if !flow.is_store_overflow_delayed() {
|
||||
flow.store_overflow(self.layout_context);
|
||||
}
|
||||
flow.store_overflow(self.layout_context);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue