mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
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:
commit
55fc48e4c4
19 changed files with 241 additions and 231 deletions
|
@ -21,15 +21,22 @@ use euclid::approxeq::ApproxEq;
|
|||
use euclid::num::Zero;
|
||||
use euclid::rect::TypedRect;
|
||||
use euclid::{Matrix2D, Matrix4, Point2D, Rect, SideOffsets2D, Size2D};
|
||||
use fnv::FnvHasher;
|
||||
use gfx_traits::{LayerId, ScrollPolicy};
|
||||
use heapsize::HeapSizeOf;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::image::base::Image;
|
||||
use paint_context::PaintContext;
|
||||
use range::Range;
|
||||
use serde::de::{self, Deserialize, Deserializer, MapVisitor, Visitor};
|
||||
use serde::ser::impls::MapIteratorVisitor;
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::hash::{BuildHasherDefault, Hash};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::Arc;
|
||||
use style::computed_values::{border_style, cursor, filter, image_rendering, mix_blend_mode};
|
||||
use style::computed_values::{pointer_events};
|
||||
|
@ -141,10 +148,75 @@ pub struct StackingContextOffsets {
|
|||
pub outlines: u32,
|
||||
}
|
||||
|
||||
/// A FNV-based hash map. This is not serializable by `serde` by default, so we provide an
|
||||
/// implementation ourselves.
|
||||
pub struct FnvHashMap<K, V>(pub HashMap<K, V, BuildHasherDefault<FnvHasher>>);
|
||||
|
||||
impl<K, V> Deref for FnvHashMap<K, V> {
|
||||
type Target = HashMap<K, V, BuildHasherDefault<FnvHasher>>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> DerefMut for FnvHashMap<K, V> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> Serialize for FnvHashMap<K, V> where K: Eq + Hash + Serialize, V: Serialize {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
|
||||
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> Deserialize for FnvHashMap<K, V> where K: Eq + Hash + Deserialize, V: Deserialize {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
|
||||
deserializer.visit_map(FnvHashMapVisitor::new())
|
||||
}
|
||||
}
|
||||
/// A visitor that produces a map.
|
||||
pub struct FnvHashMapVisitor<K, V> {
|
||||
marker: PhantomData<FnvHashMap<K, V>>,
|
||||
}
|
||||
|
||||
impl<K, V> FnvHashMapVisitor<K, V> {
|
||||
/// Construct a `FnvHashMapVisitor<T>`.
|
||||
pub fn new() -> Self {
|
||||
FnvHashMapVisitor {
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> Visitor for FnvHashMapVisitor<K, V> where K: Eq + Hash + Deserialize, V: Deserialize {
|
||||
type Value = FnvHashMap<K, V>;
|
||||
|
||||
#[inline]
|
||||
fn visit_unit<E>(&mut self) -> Result<FnvHashMap<K, V>, E> where E: de::Error {
|
||||
Ok(FnvHashMap(HashMap::with_hasher(Default::default())))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_map<Visitor>(&mut self, mut visitor: Visitor)
|
||||
-> Result<FnvHashMap<K, V>, Visitor::Error>
|
||||
where Visitor: MapVisitor {
|
||||
let mut values = FnvHashMap(HashMap::with_hasher(Default::default()));
|
||||
while let Some((key, value)) = try!(visitor.visit()) {
|
||||
HashMap::insert(&mut values, key, value);
|
||||
}
|
||||
try!(visitor.end());
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(HeapSizeOf, Deserialize, Serialize)]
|
||||
pub struct DisplayList {
|
||||
pub list: Vec<DisplayListEntry>,
|
||||
pub offsets: HashMap<StackingContextId, StackingContextOffsets>,
|
||||
pub offsets: FnvHashMap<StackingContextId, StackingContextOffsets>,
|
||||
pub root_stacking_context: StackingContext,
|
||||
}
|
||||
|
||||
|
@ -157,7 +229,7 @@ impl DisplayList {
|
|||
None => panic!("Tried to create empty display list."),
|
||||
};
|
||||
|
||||
let mut offsets = HashMap::new();
|
||||
let mut offsets = FnvHashMap(HashMap::with_hasher(Default::default()));
|
||||
DisplayList::sort_and_count_stacking_contexts(&mut root_stacking_context, &mut offsets, 0);
|
||||
|
||||
let mut display_list = DisplayList {
|
||||
|
@ -201,7 +273,9 @@ impl DisplayList {
|
|||
|
||||
fn sort_and_count_stacking_contexts(
|
||||
stacking_context: &mut StackingContext,
|
||||
offsets: &mut HashMap<StackingContextId, StackingContextOffsets>,
|
||||
offsets: &mut HashMap<StackingContextId,
|
||||
StackingContextOffsets,
|
||||
BuildHasherDefault<FnvHasher>>,
|
||||
mut current_offset: u32)
|
||||
-> u32 {
|
||||
stacking_context.children.sort();
|
||||
|
@ -508,7 +582,7 @@ pub struct StackingContext {
|
|||
pub layer_info: Option<LayerInfo>,
|
||||
|
||||
/// Children of this StackingContext.
|
||||
pub children: Vec<StackingContext>,
|
||||
pub children: Vec<Box<StackingContext>>,
|
||||
}
|
||||
|
||||
impl StackingContext {
|
||||
|
@ -761,16 +835,13 @@ impl ClippingRegion {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the intersection of this clipping region and the given rectangle.
|
||||
/// Mutates this clipping region to intersect with the given rectangle.
|
||||
///
|
||||
/// TODO(pcwalton): This could more eagerly eliminate complex clipping regions, at the cost of
|
||||
/// complexity.
|
||||
#[inline]
|
||||
pub fn intersect_rect(self, rect: &Rect<Au>) -> ClippingRegion {
|
||||
ClippingRegion {
|
||||
main: self.main.intersection(rect).unwrap_or(Rect::zero()),
|
||||
complex: self.complex,
|
||||
}
|
||||
pub fn intersect_rect(&mut self, rect: &Rect<Au>) {
|
||||
self.main = self.main.intersection(rect).unwrap_or(Rect::zero())
|
||||
}
|
||||
|
||||
/// Returns true if this clipping region might be nonempty. This can return false positives,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,9 +163,6 @@ pub struct Opts {
|
|||
/// Emits notifications when there is a relayout.
|
||||
pub relayout_event: bool,
|
||||
|
||||
/// Whether to show an error when display list geometry escapes flow overflow regions.
|
||||
pub validate_display_list_geometry: bool,
|
||||
|
||||
/// Whether Style Sharing Cache is used
|
||||
pub disable_share_style_cache: bool,
|
||||
|
||||
|
@ -254,9 +251,6 @@ pub struct DebugOptions {
|
|||
/// Write layout trace to an external file for debugging.
|
||||
pub trace_layout: bool,
|
||||
|
||||
/// Display an error when display list geometry escapes overflow region.
|
||||
pub validate_display_list_geometry: bool,
|
||||
|
||||
/// Disable the style sharing cache.
|
||||
pub disable_share_style_cache: bool,
|
||||
|
||||
|
@ -308,7 +302,6 @@ impl DebugOptions {
|
|||
"show-parallel-layout" => debug_options.show_parallel_layout = true,
|
||||
"paint-flashing" => debug_options.paint_flashing = true,
|
||||
"trace-layout" => debug_options.trace_layout = true,
|
||||
"validate-display-list-geometry" => debug_options.validate_display_list_geometry = true,
|
||||
"disable-share-style-cache" => debug_options.disable_share_style_cache = true,
|
||||
"convert-mouse-to-touch" => debug_options.convert_mouse_to_touch = true,
|
||||
"replace-surrogates" => debug_options.replace_surrogates = true,
|
||||
|
@ -351,8 +344,6 @@ pub fn print_debug_usage(app: &str) -> ! {
|
|||
print_option("show-parallel-layout", "Mark which thread laid each flow out with colors.");
|
||||
print_option("paint-flashing", "Overlay repainted areas with a random color.");
|
||||
print_option("trace-layout", "Write layout trace to an external file for debugging.");
|
||||
print_option("validate-display-list-geometry",
|
||||
"Display an error when display list geometry escapes overflow region.");
|
||||
print_option("disable-share-style-cache",
|
||||
"Disable the style sharing cache.");
|
||||
print_option("parallel-display-list-building", "Build display lists in parallel.");
|
||||
|
@ -486,7 +477,6 @@ pub fn default_opts() -> Opts {
|
|||
dump_display_list_optimized: false,
|
||||
dump_layer_tree: false,
|
||||
relayout_event: false,
|
||||
validate_display_list_geometry: false,
|
||||
profile_script_events: false,
|
||||
profile_heartbeats: false,
|
||||
disable_share_style_cache: false,
|
||||
|
@ -727,7 +717,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
dump_display_list_optimized: debug_options.dump_display_list_optimized,
|
||||
dump_layer_tree: debug_options.dump_layer_tree,
|
||||
relayout_event: debug_options.relayout_event,
|
||||
validate_display_list_geometry: debug_options.validate_display_list_geometry,
|
||||
disable_share_style_cache: debug_options.disable_share_style_cache,
|
||||
convert_mouse_to_touch: debug_options.convert_mouse_to_touch,
|
||||
exit_after_load: opt_match.opt_present("x"),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue