Auto merge of #9843 - pcwalton:optimize-flat-display-lists, r=mrobinson

Optimize flat display lists

Flat display lists were a 2x regression on the spheres demo. This patch series fixes that.

See the individual commits for more details.

r? @mrobinson

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9843)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-03-04 02:49:04 +05:30
commit 55fc48e4c4
19 changed files with 241 additions and 231 deletions

View file

@ -64,7 +64,6 @@ use style::properties::ComputedValues;
use style::values::computed::{LengthOrNone, LengthOrPercentageOrNone};
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use util::geometry::MAX_RECT;
use util::opts;
use util::print_tree::PrintTree;
/// Information specific to floated blocks.
@ -1622,14 +1621,18 @@ impl BlockFlow {
}
}
pub fn establishes_pseudo_stacking_context(&self) -> bool {
pub fn block_stacking_context_type(&self) -> BlockStackingContextType {
if self.fragment.establishes_stacking_context() {
return false;
return BlockStackingContextType::StackingContext
}
self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
self.fragment.style.get_box().position != position::T::static_ ||
self.base.flags.is_float()
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
self.fragment.style.get_box().position != position::T::static_ ||
self.base.flags.is_float() {
BlockStackingContextType::PseudoStackingContext
} else {
BlockStackingContextType::NonstackingContext
}
}
pub fn has_scrolling_overflow(&self) -> bool {
@ -1954,8 +1957,10 @@ impl Flow for BlockFlow {
self.base.position.size.to_physical(self.base.writing_mode);
// Compute the origin and clipping rectangle for children.
//
// `clip` is in the child coordinate system.
let mut clip;
let origin_for_children;
let clip_in_child_coordinate_system;
let is_stacking_context = self.fragment.establishes_stacking_context();
if is_stacking_context {
// We establish a stacking context, so the position of our children is vertically
@ -1966,12 +1971,11 @@ impl Flow for BlockFlow {
// FIXME(pcwalton): Is this vertical-writing-direction-safe?
let margin = self.fragment.margin.to_physical(self.base.writing_mode);
origin_for_children = Point2D::new(-margin.left, Au(0));
clip_in_child_coordinate_system =
self.base.clip.translate(&-self.base.stacking_relative_position);
clip = self.base.clip.translate(&-self.base.stacking_relative_position);
} else {
let relative_offset = relative_offset.to_physical(self.base.writing_mode);
origin_for_children = self.base.stacking_relative_position + relative_offset;
clip_in_child_coordinate_system = self.base.clip.clone();
clip = self.base.clip.clone();
}
let stacking_relative_position_of_display_port_for_children =
@ -2003,8 +2007,8 @@ impl Flow for BlockFlow {
.early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Own);
let clip = self.fragment.clipping_region_for_children(
&clip_in_child_coordinate_system,
self.fragment.adjust_clipping_region_for_children(
&mut clip,
&stacking_relative_border_box,
self.base.flags.contains(IS_ABSOLUTELY_POSITIONED));
@ -2109,7 +2113,7 @@ impl Flow for BlockFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.collect_stacking_contexts_for_block(parent_id, contexts)
}
@ -2117,9 +2121,6 @@ impl Flow for BlockFlow {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_block(state, BorderPaintingMode::Separate);
self.fragment.restyle_damage.remove(REPAINT);
if opts::get().validate_display_list_geometry {
self.base.validate_display_list_geometry();
}
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
@ -3036,3 +3037,12 @@ impl ISizeAndMarginsComputer for InlineBlockReplaced {
MaybeAuto::Specified(fragment.content_inline_size())
}
}
/// A stacking context, a pseudo-stacking context, or a non-stacking context.
#[derive(Copy, Clone, PartialEq)]
pub enum BlockStackingContextType {
NonstackingContext,
PseudoStackingContext,
StackingContext,
}

View file

@ -12,13 +12,13 @@
use app_units::{Au, AU_PER_PX};
use azure::azure_hl::Color;
use block::BlockFlow;
use block::{BlockFlow, BlockStackingContextType};
use canvas_traits::{CanvasMsg, CanvasPixelData, CanvasData, FromLayoutMsg};
use context::LayoutContext;
use euclid::num::Zero;
use euclid::{Matrix4, Point2D, Point3D, Rect, SideOffsets2D, Size2D};
use flex::FlexFlow;
use flow::{self, BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref;
use fragment::{CoordinateSystem, Fragment, HAS_LAYER, ImageFragmentInfo, ScannedTextFragmentInfo};
use fragment::{SpecificFragmentInfo};
@ -67,8 +67,7 @@ pub struct DisplayListBuildState<'a> {
}
impl<'a> DisplayListBuildState<'a> {
pub fn new(layout_context: &'a LayoutContext,
stacking_context_id: StackingContextId)
pub fn new(layout_context: &'a LayoutContext, stacking_context_id: StackingContextId)
-> DisplayListBuildState<'a> {
DisplayListBuildState {
layout_context: layout_context,
@ -87,21 +86,15 @@ impl<'a> DisplayListBuildState<'a> {
});
}
fn append_from(&mut self, other_list: &mut Option<Vec<DisplayListEntry>>) {
if let Some(mut other) = other_list.take() {
self.items.append(&mut other);
}
}
fn stacking_context_id(&self) -> StackingContextId {
self.stacking_context_id_stack.last().unwrap().clone()
}
fn push_stacking_context_id(&mut self, stacking_context_id: StackingContextId) {
pub fn push_stacking_context_id(&mut self, stacking_context_id: StackingContextId) {
self.stacking_context_id_stack.push(stacking_context_id);
}
fn pop_stacking_context_id(&mut self) {
pub fn pop_stacking_context_id(&mut self) {
self.stacking_context_id_stack.pop();
assert!(!self.stacking_context_id_stack.is_empty());
}
@ -232,19 +225,17 @@ pub trait FragmentDisplayListBuilding {
clip: &ClippingRegion,
stacking_relative_display_port: &Rect<Au>);
/// Returns the appropriate clipping region for descendants of this fragment.
fn clipping_region_for_children(&self,
current_clip: &ClippingRegion,
stacking_relative_border_box: &Rect<Au>,
is_absolutely_positioned: bool)
-> ClippingRegion;
/// Adjusts the clipping region for descendants of this fragment as appropriate.
fn adjust_clipping_region_for_children(&self,
current_clip: &mut ClippingRegion,
stacking_relative_border_box: &Rect<Au>,
is_absolutely_positioned: bool);
/// Calculates the clipping rectangle for a fragment, taking the `clip` property into account
/// Adjusts the clipping rectangle for a fragment to take the `clip` property into account
/// per CSS 2.1 § 11.1.2.
fn calculate_style_specified_clip(&self,
parent_clip: &ClippingRegion,
stacking_relative_border_box: &Rect<Au>)
-> ClippingRegion;
fn adjust_clip_for_style(&self,
parent_clip: &mut ClippingRegion,
stacking_relative_border_box: &Rect<Au>);
/// Builds the display items necessary to paint the selection and/or caret for this fragment,
/// if any.
@ -287,7 +278,7 @@ pub trait FragmentDisplayListBuilding {
base_flow: &BaseFlow,
scroll_policy: ScrollPolicy,
mode: StackingContextCreationMode)
-> StackingContext;
-> Box<StackingContext>;
}
fn handle_overlapping_radii(size: &Size2D<Au>, radii: &BorderRadii<Au>) -> BorderRadii<Au> {
@ -482,7 +473,8 @@ impl FragmentDisplayListBuilding for Fragment {
// Clip.
//
// TODO: Check the bounds to see if a clip item is actually required.
let clip = clip.clone().intersect_rect(&bounds);
let mut clip = clip.clone();
clip.intersect_rect(&bounds);
// Background image should be positioned on the padding box basis.
let border = style.logical_border_width().to_physical(style.writing_mode);
@ -581,7 +573,8 @@ impl FragmentDisplayListBuilding for Fragment {
clip: &ClippingRegion,
gradient: &LinearGradient,
style: &ComputedValues) {
let clip = clip.clone().intersect_rect(absolute_bounds);
let mut clip = clip.clone();
clip.intersect_rect(absolute_bounds);
// This is the distance between the center and the ending point; i.e. half of the distance
// between the starting point and the ending point.
@ -894,15 +887,14 @@ impl FragmentDisplayListBuilding for Fragment {
}), DisplayListSection::Content);
}
fn calculate_style_specified_clip(&self,
parent_clip: &ClippingRegion,
stacking_relative_border_box: &Rect<Au>)
-> ClippingRegion {
fn adjust_clip_for_style(&self,
parent_clip: &mut ClippingRegion,
stacking_relative_border_box: &Rect<Au>) {
// Account for `clip` per CSS 2.1 § 11.1.2.
let style_clip_rect = match (self.style().get_box().position,
self.style().get_effects().clip.0) {
(position::T::absolute, Some(style_clip_rect)) => style_clip_rect,
_ => return (*parent_clip).clone(),
_ => return,
};
// FIXME(pcwalton, #2795): Get the real container size.
@ -911,7 +903,7 @@ impl FragmentDisplayListBuilding for Fragment {
let right = style_clip_rect.right.unwrap_or(stacking_relative_border_box.size.width);
let bottom = style_clip_rect.bottom.unwrap_or(stacking_relative_border_box.size.height);
let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
(*parent_clip).clone().intersect_rect(&Rect::new(clip_origin, clip_size))
parent_clip.intersect_rect(&Rect::new(clip_origin, clip_size))
}
fn build_display_items_for_selection_if_necessary(&self,
@ -996,7 +988,8 @@ impl FragmentDisplayListBuilding for Fragment {
// Calculate the clip rect. If there's nothing to render at all, don't even construct
// display list items.
let clip = self.calculate_style_specified_clip(clip, &stacking_relative_border_box);
let mut clip = (*clip).clone();
self.adjust_clip_for_style(&mut clip, &stacking_relative_border_box);
if !clip.might_intersect_rect(&stacking_relative_border_box) {
return;
}
@ -1277,7 +1270,7 @@ impl FragmentDisplayListBuilding for Fragment {
base_flow: &BaseFlow,
scroll_policy: ScrollPolicy,
mode: StackingContextCreationMode)
-> StackingContext {
-> Box<StackingContext> {
let border_box = match mode {
StackingContextCreationMode::InnerScrollWrapper => {
Rect::new(Point2D::zero(), base_flow.overflow.scroll.size)
@ -1411,33 +1404,31 @@ impl FragmentDisplayListBuilding for Fragment {
_ => StackingContextType::Real,
};
StackingContext::new(id,
context_type,
&border_box,
&overflow,
self.effective_z_index(),
filters,
self.style().get_effects().mix_blend_mode,
transform,
perspective,
establishes_3d_context,
scrolls_overflow_area,
layer_info)
Box::new(StackingContext::new(id,
context_type,
&border_box,
&overflow,
self.effective_z_index(),
filters,
self.style().get_effects().mix_blend_mode,
transform,
perspective,
establishes_3d_context,
scrolls_overflow_area,
layer_info))
}
fn clipping_region_for_children(&self,
current_clip: &ClippingRegion,
stacking_relative_border_box: &Rect<Au>,
is_absolutely_positioned: bool)
-> ClippingRegion {
fn adjust_clipping_region_for_children(&self,
current_clip: &mut ClippingRegion,
stacking_relative_border_box: &Rect<Au>,
is_absolutely_positioned: bool) {
// Don't clip if we're text.
if self.is_scanned_text_fragment() {
return (*current_clip).clone()
return
}
// Account for style-specified `clip`.
let mut current_clip = self.calculate_style_specified_clip(current_clip,
stacking_relative_border_box);
self.adjust_clip_for_style(current_clip, stacking_relative_border_box);
// Clip according to the values of `overflow-x` and `overflow-y`.
//
@ -1453,7 +1444,7 @@ impl FragmentDisplayListBuilding for Fragment {
let max_x = cmp::min(bounds.max_x(), stacking_relative_border_box.max_x());
bounds.origin.x = cmp::max(bounds.origin.x, stacking_relative_border_box.origin.x);
bounds.size.width = max_x - bounds.origin.x;
current_clip = current_clip.intersect_rect(&bounds)
current_clip.intersect_rect(&bounds)
}
_ => {}
}
@ -1465,12 +1456,10 @@ impl FragmentDisplayListBuilding for Fragment {
let max_y = cmp::min(bounds.max_y(), stacking_relative_border_box.max_y());
bounds.origin.y = cmp::max(bounds.origin.y, stacking_relative_border_box.origin.y);
bounds.size.height = max_y - bounds.origin.y;
current_clip = current_clip.intersect_rect(&bounds)
current_clip.intersect_rect(&bounds)
}
_ => {}
}
current_clip
}
fn build_display_list_for_text_fragment(&self,
@ -1600,7 +1589,7 @@ impl FragmentDisplayListBuilding for Fragment {
pub trait BlockFlowDisplayListBuilding {
fn collect_stacking_contexts_for_block(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId;
fn build_display_list_for_block(&mut self,
state: &mut DisplayListBuildState,
@ -1610,10 +1599,10 @@ pub trait BlockFlowDisplayListBuilding {
impl BlockFlowDisplayListBuilding for BlockFlow {
fn collect_stacking_contexts_for_block(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
if !self.fragment.establishes_stacking_context() &&
!self.establishes_pseudo_stacking_context() {
let block_stacking_context_type = self.block_stacking_context_type();
if block_stacking_context_type == BlockStackingContextType::NonstackingContext {
self.base.stacking_context_id = parent_id;
self.base.collect_stacking_contexts_for_children(parent_id, contexts);
return parent_id;
@ -1625,8 +1614,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
self.base.stacking_context_id = stacking_context_id;
let inner_stacking_context_id = if self.has_scrolling_overflow() {
StackingContextId::new_of_type(self.base.flow_id(),
self.fragment.fragment_type())
StackingContextId::new_of_type(self.base.flow_id(), self.fragment.fragment_type())
} else {
stacking_context_id
};
@ -1635,7 +1623,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
self.base.collect_stacking_contexts_for_children(inner_stacking_context_id,
&mut child_contexts);
if self.establishes_pseudo_stacking_context() {
if block_stacking_context_type == BlockStackingContextType::PseudoStackingContext {
let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
self.fragment.style.get_box().position != position::T::static_ {
StackingContextCreationMode::PseudoPositioned
@ -1644,18 +1632,24 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
StackingContextCreationMode::PseudoFloat
};
let mut stacking_context =
self.fragment.create_stacking_context(stacking_context_id,
&self.base,
ScrollPolicy::Scrollable,
creation_mode);
let (mut floating, mut positioned) = child_contexts.into_iter().partition(|context| {
context.context_type == StackingContextType::PseudoFloat
});
let stacking_context_index = contexts.len();
contexts.push(self.fragment.create_stacking_context(stacking_context_id,
&self.base,
ScrollPolicy::Scrollable,
creation_mode));
stacking_context.children.append(&mut floating);
contexts.push(stacking_context);
contexts.append(&mut positioned);
let mut floating = vec![];
for child_context in child_contexts.into_iter() {
if child_context.context_type == StackingContextType::PseudoFloat {
// Floating.
floating.push(child_context)
} else {
// Positioned.
contexts.push(child_context)
}
}
contexts[stacking_context_index].children = floating;
return stacking_context_id;
}
@ -1671,7 +1665,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base,
scroll_policy,
StackingContextCreationMode::InnerScrollWrapper);
inner_stacking_context.children.append(&mut child_contexts);
inner_stacking_context.children = child_contexts;
let mut outer_stacking_context = self.fragment.create_stacking_context(
stacking_context_id,
@ -1686,7 +1680,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base,
scroll_policy,
StackingContextCreationMode::Normal);
stacking_context.children.append(&mut child_contexts);
stacking_context.children = child_contexts;
stacking_context
};
@ -1697,10 +1691,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
fn build_display_list_for_block(&mut self,
state: &mut DisplayListBuildState,
border_painting_mode: BorderPaintingMode) {
let establishes_stacking_context = self.fragment.establishes_stacking_context();
let background_border_section = if self.base.flags.is_float() {
DisplayListSection::BackgroundAndBorders
} else if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
if self.fragment.establishes_stacking_context() {
if establishes_stacking_context {
DisplayListSection::BackgroundAndBorders
} else {
DisplayListSection::BlockBackgroundsAndBorders
@ -1710,10 +1705,14 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
};
// Add the box that starts the block context.
let clip = if self.fragment.establishes_stacking_context() {
self.base.clip.translate(&-self.base.stacking_relative_position)
let translated_clip = if establishes_stacking_context {
Some(self.base.clip.translate(&-self.base.stacking_relative_position))
} else {
self.base.clip.clone()
None
};
let clip = match translated_clip {
Some(ref translated_clip) => translated_clip,
None => &self.base.clip,
};
self.fragment
@ -1727,14 +1726,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
.relative_containing_block_mode,
border_painting_mode,
background_border_section,
&clip,
clip,
&self.base.stacking_relative_position_of_display_port);
// Add children.
for kid in self.base.children.iter_mut() {
state.append_from(&mut flow::mut_base(kid).display_list_building_result);
}
self.base.build_display_items_for_debugging_tint(state, self.fragment.node);
}
}
@ -1742,7 +1736,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
pub trait InlineFlowDisplayListBuilding {
fn collect_stacking_contexts_for_inline(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId;
fn build_display_list_for_inline_fragment_at_index(&mut self,
state: &mut DisplayListBuildState,
@ -1753,7 +1747,7 @@ pub trait InlineFlowDisplayListBuilding {
impl InlineFlowDisplayListBuilding for InlineFlow {
fn collect_stacking_contexts_for_inline(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.base.stacking_context_id = parent_id;
@ -1799,22 +1793,6 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
DisplayListSection::Content,
&self.base.clip,
&self.base.stacking_relative_position_of_display_port);
match fragment.specific {
SpecificFragmentInfo::InlineBlock(ref mut block_flow) => {
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
state.append_from(&mut flow::mut_base(block_flow).display_list_building_result)
}
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => {
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
state.append_from(&mut flow::mut_base(block_flow).display_list_building_result)
}
SpecificFragmentInfo::InlineAbsolute(ref mut block_flow) => {
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
state.append_from(&mut flow::mut_base(block_flow).display_list_building_result)
}
_ => {}
}
}
fn build_display_list_for_inline(&mut self, state: &mut DisplayListBuildState) {
@ -1847,10 +1825,6 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
self.base.build_display_items_for_debugging_tint(state,
self.fragments.fragments[0].node);
}
if opts::get().validate_display_list_geometry {
self.base.validate_display_list_geometry();
}
}
}

View file

@ -31,7 +31,6 @@ use style::logical_geometry::LogicalSize;
use style::properties::ComputedValues;
use style::properties::style_structs;
use style::values::computed::LengthOrPercentageOrAuto;
use util::opts;
// A mode describes which logical axis a flex axis is parallel with.
// The logical axises are inline and block, the flex axises are main and cross.
@ -422,15 +421,11 @@ impl Flow for FlexFlow {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_flex(state);
if opts::get().validate_display_list_geometry {
self.block_flow.base.validate_display_list_geometry();
}
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}

View file

@ -34,7 +34,7 @@ use floats::Floats;
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
use flow_ref::{self, FlowRef, WeakFlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
use gfx::display_list::{ClippingRegion, DisplayListEntry, StackingContext, StackingContextId};
use gfx::display_list::{ClippingRegion, StackingContext, StackingContextId};
use gfx_traits::{LayerId, LayerType};
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
use inline::InlineFlow;
@ -224,7 +224,7 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
fn collect_stacking_contexts(&mut self,
_parent_id: StackingContextId,
_: &mut Vec<StackingContext>)
_: &mut Vec<Box<StackingContext>>)
-> StackingContextId;
/// If this is a float, places it. The default implementation does nothing.
@ -957,9 +957,6 @@ pub struct BaseFlow {
/// per-stacking-context.
pub stacking_relative_position_of_display_port: Rect<Au>,
/// The results of display list building for this flow.
pub display_list_building_result: Option<Vec<DisplayListEntry>>,
/// The writing mode for this flow.
pub writing_mode: WritingMode,
@ -1129,7 +1126,6 @@ impl BaseFlow {
block_container_writing_mode: writing_mode,
block_container_explicit_block_size: None,
absolute_cb: ContainingBlockLink::new(),
display_list_building_result: None,
early_absolute_position_info: EarlyAbsolutePositionInfo::new(writing_mode),
late_absolute_position_info: LateAbsolutePositionInfo::new(),
clip: ClippingRegion::max(),
@ -1147,8 +1143,6 @@ impl BaseFlow {
children: children,
restyle_damage: self.restyle_damage | REPAINT | REFLOW_OUT_OF_FLOW | REFLOW,
parallel: FlowParallelInfo::new(),
display_list_building_result: None,
floats: self.floats.clone(),
abs_descendants: self.abs_descendants.clone(),
absolute_cb: self.absolute_cb.clone(),
@ -1167,43 +1161,13 @@ impl BaseFlow {
p as usize
}
/// 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) {
// 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.paint);
let bounds = Rect::new(self.stacking_relative_position, position_with_overflow.size);
let items = match self.display_list_building_result {
Some(ref items) => items,
None => return,
};
for item in items.iter() {
let base_item = item.item.base();
let paint_bounds = base_item.clip.clone().intersect_rect(&base_item.bounds);
if !paint_bounds.might_be_nonempty() {
continue;
}
if bounds.union(&paint_bounds.bounding_rect()) != bounds {
error!("DisplayList item {:?} outside of Flow overflow ({:?})",
item.item,
paint_bounds);
}
}
}
pub fn flow_id(&self) -> usize {
return self as *const BaseFlow as usize;
}
pub fn collect_stacking_contexts_for_children(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>) {
contexts: &mut Vec<Box<StackingContext>>) {
for kid in self.children.iter_mut() {
kid.collect_stacking_contexts(parent_id, contexts);
}

View file

@ -1680,9 +1680,10 @@ impl Flow for InlineFlow {
CoordinateSystem::Parent);
let stacking_relative_content_box =
fragment.stacking_relative_content_box(&stacking_relative_border_box);
let clip = fragment.clipping_region_for_children(&self.base.clip,
&stacking_relative_border_box,
false);
let mut clip = self.base.clip.clone();
fragment.adjust_clipping_region_for_children(&mut clip,
&stacking_relative_border_box,
false);
let is_positioned = fragment.is_positioned();
match fragment.specific {
SpecificFragmentInfo::InlineBlock(ref mut info) => {
@ -1750,7 +1751,7 @@ impl Flow for InlineFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.collect_stacking_contexts_for_inline(parent_id, contexts)
}

View file

@ -875,9 +875,10 @@ impl LayoutThread {
false,
None);
sequential::build_display_list_for_subtree(layout_root,
&mut root_stacking_context,
shared_layout_context);
let display_list_entries =
sequential::build_display_list_for_subtree(layout_root,
&mut root_stacking_context,
shared_layout_context);
if data.goal == ReflowGoal::ForDisplay {
debug!("Done building display list.");
@ -900,11 +901,9 @@ impl LayoutThread {
ScrollPolicy::Scrollable,
None,
root_background_color));
let display_list = DisplayList::new(
root_stacking_context,
&mut flow::mut_base(flow_ref::deref_mut(layout_root))
.display_list_building_result);
let display_list = DisplayList::new(root_stacking_context,
&mut Some(display_list_entries));
if opts::get().dump_display_list {
display_list.print();
}

View file

@ -25,7 +25,6 @@ use style::computed_values::{list_style_type, position};
use style::logical_geometry::LogicalSize;
use style::properties::ComputedValues;
use text;
use util::opts;
/// A block with the CSS `display` property equal to `list-item`.
#[derive(Debug)]
@ -144,14 +143,11 @@ impl Flow for ListItemFlow {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_list_item(state);
if opts::get().validate_display_list_geometry {
self.block_flow.base.validate_display_list_geometry();
}
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}

View file

@ -186,7 +186,7 @@ impl Flow for MulticolFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
@ -271,7 +271,7 @@ impl Flow for MulticolColumnFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}

View file

@ -6,13 +6,14 @@
use app_units::Au;
use context::{LayoutContext, SharedLayoutContext};
use display_list_builder::DisplayListBuildState;
use euclid::point::Point2D;
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils};
use flow_ref::{self, FlowRef};
use fragment::FragmentBorderBoxIterator;
use generated_content::ResolveGeneratedContent;
use gfx::display_list::StackingContext;
use gfx::display_list::{DisplayListEntry, StackingContext};
use style::dom::TNode;
use style::traversal::DomTraversalContext;
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
@ -77,13 +78,19 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
pub fn build_display_list_for_subtree(root: &mut FlowRef,
root_stacking_context: &mut StackingContext,
shared_layout_context: &SharedLayoutContext) {
shared_layout_context: &SharedLayoutContext)
-> Vec<DisplayListEntry> {
let flow_root = flow_ref::deref_mut(root);
let layout_context = LayoutContext::new(shared_layout_context);
flow_root.traverse_preorder(&ComputeAbsolutePositions { layout_context: &layout_context });
flow_root.collect_stacking_contexts(root_stacking_context.id,
&mut root_stacking_context.children);
flow_root.traverse_postorder(&BuildDisplayList { layout_context: &layout_context });
let mut build_display_list = BuildDisplayList {
state: DisplayListBuildState::new(&layout_context,
flow::base(&**root).stacking_context_id),
};
build_display_list.traverse(&mut *flow_root);
build_display_list.state.items
}
pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef,

View file

@ -467,7 +467,7 @@ impl Flow for TableFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}

View file

@ -83,7 +83,7 @@ impl Flow for TableCaptionFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}

View file

@ -193,7 +193,7 @@ impl Flow for TableCellFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}

View file

@ -96,7 +96,7 @@ impl Flow for TableColGroupFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
_: &mut Vec<StackingContext>)
_: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
parent_id
}

View file

@ -435,7 +435,7 @@ impl Flow for TableRowFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}

View file

@ -212,7 +212,7 @@ impl Flow for TableRowGroupFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}

View file

@ -451,7 +451,7 @@ impl Flow for TableWrapperFlow {
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
contexts: &mut Vec<Box<StackingContext>>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}

View file

@ -215,23 +215,27 @@ impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
}
}
#[derive(Copy, Clone)]
pub struct BuildDisplayList<'a> {
pub layout_context: &'a LayoutContext<'a>,
pub state: DisplayListBuildState<'a>,
}
impl<'a> PostorderFlowTraversal for BuildDisplayList<'a> {
impl<'a> BuildDisplayList<'a> {
#[inline]
fn process(&self, flow: &mut Flow) {
let mut state = DisplayListBuildState::new(
self.layout_context, flow::base(flow).stacking_context_id);
flow.build_display_list(&mut state);
flow::mut_base(flow).display_list_building_result = Some(state.items);
flow::mut_base(flow).restyle_damage.remove(REPAINT);
pub fn traverse(&mut self, flow: &mut Flow) {
if self.should_process() {
self.state.push_stacking_context_id(flow::base(flow).stacking_context_id);
flow.build_display_list(&mut self.state);
flow::mut_base(flow).restyle_damage.remove(REPAINT);
self.state.pop_stacking_context_id();
}
for kid in flow::child_iter(flow) {
self.traverse(kid);
}
}
#[inline]
fn should_process(&self, _: &mut Flow) -> bool {
self.layout_context.shared_context().goal == ReflowGoal::ForDisplay
fn should_process(&self) -> bool {
self.state.layout_context.shared_context().goal == ReflowGoal::ForDisplay
}
}