Auto merge of #14020 - mrobinson:scroll_root_prep, r=pcwalton

Fold some DisplayList methods into DisplayListBuildState

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes do not require tests because they should not change behavior.

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

This makes the API used to build display lists quite a bit simpler and
reduces the amount of auxiliary data structures that need to be passed
around. It is also important preparation work for separating scrolling
areas from stacking contexts.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/14020)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-11-02 13:55:07 -05:00 committed by GitHub
commit 021cabd3e6
4 changed files with 150 additions and 137 deletions

View file

@ -29,7 +29,6 @@ use range::Range;
use std::cmp::{self, Ordering};
use std::collections::HashMap;
use std::fmt;
use std::mem;
use std::sync::Arc;
use style::computed_values::{border_style, filter, image_rendering, mix_blend_mode};
use style_traits::cursor::Cursor;
@ -54,96 +53,6 @@ pub struct DisplayList {
}
impl DisplayList {
pub fn new(root_stacking_context: StackingContext,
all_items: Vec<DisplayItem>)
-> DisplayList {
let mut mapped_items = HashMap::new();
for item in all_items.into_iter() {
let items = mapped_items.entry(item.stacking_context_id()).or_insert(Vec::new());
items.push(item);
}
let mut list = Vec::new();
DisplayList::generate_display_list(&mut list, &mut mapped_items, root_stacking_context);
DisplayList {
list: list,
}
}
fn generate_display_list(list: &mut Vec<DisplayItem>,
mapped_items: &mut HashMap<StackingContextId, Vec<DisplayItem>>,
mut stacking_context: StackingContext) {
let mut child_stacking_contexts =
mem::replace(&mut stacking_context.children, Vec::new());
child_stacking_contexts.sort();
let mut child_stacking_contexts = child_stacking_contexts.into_iter().peekable();
let mut child_items = mapped_items.remove(&stacking_context.id)
.unwrap_or(Vec::new());
child_items.sort_by(|a, b| a.base().section.cmp(&b.base().section));
child_items.reverse();
let stacking_context_id = stacking_context.id;
let real_stacking_context = stacking_context.context_type == StackingContextType::Real;
if real_stacking_context {
list.push(DisplayItem::PushStackingContext(Box::new(PushStackingContextItem {
base: BaseDisplayItem::empty(),
stacking_context: stacking_context,
})));
}
// Properly order display items that make up a stacking context. "Steps" here
// refer to the steps in CSS 2.1 Appendix E.
// Steps 1 and 2: Borders and background for the root.
while child_items.last().map_or(false,
|child| child.section() == DisplayListSection::BackgroundAndBorders) {
list.push(child_items.pop().unwrap());
}
// Step 3: Positioned descendants with negative z-indices.
while child_stacking_contexts.peek().map_or(false, |child| child.z_index < 0) {
let context = child_stacking_contexts.next().unwrap();
DisplayList::generate_display_list(list, mapped_items, context);
}
// Step 4: Block backgrounds and borders.
while child_items.last().map_or(false,
|child| child.section() == DisplayListSection::BlockBackgroundsAndBorders) {
list.push(child_items.pop().unwrap());
}
// Step 5: Floats.
while child_stacking_contexts.peek().map_or(false,
|child| child.context_type == StackingContextType::PseudoFloat) {
let context = child_stacking_contexts.next().unwrap();
DisplayList::generate_display_list(list, mapped_items, context);
}
// Step 6 & 7: Content and inlines that generate stacking contexts.
while child_items.last().map_or(false,
|child| child.section() == DisplayListSection::Content) {
list.push(child_items.pop().unwrap());
}
// Step 8 & 9: Positioned descendants with nonnegative, numeric z-indices.
for child in child_stacking_contexts {
DisplayList::generate_display_list(list, mapped_items, child);
}
// Step 10: Outlines.
list.extend(child_items);
if real_stacking_context {
list.push(DisplayItem::PopStackingContext(Box::new(
PopStackingContextItem {
base: BaseDisplayItem::empty(),
stacking_context_id: stacking_context_id,
}
)));
}
}
// Return all nodes containing the point of interest, bottommost first, and
// respecting the `pointer-events` CSS property.
pub fn hit_test(&self,
@ -424,6 +333,22 @@ impl StackingContext {
}
}
#[inline]
pub fn root() -> StackingContext {
StackingContext::new(StackingContextId::new(0),
StackingContextType::Real,
&Rect::zero(),
&Rect::zero(),
0,
filter::T::new(Vec::new()),
mix_blend_mode::T::normal,
Matrix4D::identity(),
Matrix4D::identity(),
true,
ScrollPolicy::Scrollable,
None)
}
pub fn add_child(&mut self, mut child: StackingContext) {
child.update_overflow_for_all_children();
self.children.push(child);
@ -474,6 +399,27 @@ impl StackingContext {
}
print_tree.end_level();
}
pub fn to_display_list_items(self) -> (DisplayItem, DisplayItem) {
let mut base_item = BaseDisplayItem::empty();
base_item.stacking_context_id = self.id;
let pop_item = DisplayItem::PopStackingContext(Box::new(
PopStackingContextItem {
base: base_item.clone(),
stacking_context_id: self.id,
}
));
let push_item = DisplayItem::PushStackingContext(Box::new(
PushStackingContextItem {
base: base_item,
stacking_context: self,
}
));
(push_item, pop_item)
}
}
impl Ord for StackingContext {

View file

@ -23,11 +23,11 @@ use fragment::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmen
use fragment::SpecificFragmentInfo;
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection, GradientDisplayItem};
use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem};
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayList, DisplayListSection};
use gfx::display_list::{GradientDisplayItem, GradientStop, IframeDisplayItem, ImageDisplayItem};
use gfx::display_list::{LineDisplayItem, OpaqueNode};
use gfx::display_list::{SolidColorDisplayItem, StackingContext, StackingContextType};
use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo};
use gfx::display_list::{TextDisplayItem, TextOrientation, WebGLDisplayItem, WebRenderImageInfo};
use gfx_traits::{ScrollPolicy, ScrollRootId, StackingContextId};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc;
@ -38,7 +38,9 @@ use net_traits::image_cache_thread::UsePlaceholder;
use range::Range;
use script_layout_interface::restyle_damage::REPAINT;
use std::{cmp, f32};
use std::collections::HashMap;
use std::default::Default;
use std::mem;
use std::sync::Arc;
use style::computed_values::{background_attachment, background_clip, background_origin};
use style::computed_values::{background_repeat, background_size, border_style};
@ -76,7 +78,8 @@ fn get_cyclic<T>(arr: &[T], index: usize) -> &T {
pub struct DisplayListBuildState<'a> {
pub shared_layout_context: &'a SharedLayoutContext,
pub items: Vec<DisplayItem>,
pub root_stacking_context: StackingContext,
pub items: HashMap<StackingContextId, Vec<DisplayItem>>,
pub stacking_context_id_stack: Vec<StackingContextId>,
pub scroll_root_id_stack: Vec<ScrollRootId>,
}
@ -87,14 +90,16 @@ impl<'a> DisplayListBuildState<'a> {
-> DisplayListBuildState<'a> {
DisplayListBuildState {
shared_layout_context: shared_layout_context,
items: Vec::new(),
root_stacking_context: StackingContext::root(),
items: HashMap::new(),
stacking_context_id_stack: vec!(stacking_context_id),
scroll_root_id_stack: vec!(ScrollRootId::root()),
}
}
fn add_display_item(&mut self, display_item: DisplayItem) {
self.items.push(display_item);
let items = self.items.entry(display_item.stacking_context_id()).or_insert(Vec::new());
items.push(display_item);
}
pub fn stacking_context_id(&self) -> StackingContextId {
@ -139,6 +144,91 @@ impl<'a> DisplayListBuildState<'a> {
section,
self.stacking_context_id())
}
pub fn to_display_list(mut self) -> DisplayList {
let mut list = Vec::new();
let root_context = mem::replace(&mut self.root_stacking_context, StackingContext::root());
self.to_display_list_for_stacking_context(&mut list, root_context);
DisplayList {
list: list,
}
}
fn to_display_list_for_stacking_context(&mut self,
list: &mut Vec<DisplayItem>,
mut stacking_context: StackingContext) {
let mut child_items = self.items.remove(&stacking_context.id).unwrap_or(Vec::new());
child_items.sort_by(|a, b| a.base().section.cmp(&b.base().section));
child_items.reverse();
let mut child_stacking_contexts =
mem::replace(&mut stacking_context.children, Vec::new());
child_stacking_contexts.sort();
let real_stacking_context = stacking_context.context_type == StackingContextType::Real;
if !real_stacking_context {
self.to_display_list_for_items(list,
child_items,
child_stacking_contexts);
return;
}
let (push_item, pop_item) = stacking_context.to_display_list_items();
list.push(push_item);
self.to_display_list_for_items(list,
child_items,
child_stacking_contexts);
list.push(pop_item);
}
fn to_display_list_for_items(&mut self,
list: &mut Vec<DisplayItem>,
mut child_items: Vec<DisplayItem>,
child_stacking_contexts: Vec<StackingContext>) {
// Properly order display items that make up a stacking context. "Steps" here
// refer to the steps in CSS 2.1 Appendix E.
// Steps 1 and 2: Borders and background for the root.
while child_items.last().map_or(false,
|child| child.section() == DisplayListSection::BackgroundAndBorders) {
list.push(child_items.pop().unwrap());
}
// Step 3: Positioned descendants with negative z-indices.
let mut child_stacking_contexts = child_stacking_contexts.into_iter().peekable();
while child_stacking_contexts.peek().map_or(false, |child| child.z_index < 0) {
let context = child_stacking_contexts.next().unwrap();
self.to_display_list_for_stacking_context(list, context);
}
// Step 4: Block backgrounds and borders.
while child_items.last().map_or(false,
|child| child.section() == DisplayListSection::BlockBackgroundsAndBorders) {
list.push(child_items.pop().unwrap());
}
// Step 5: Floats.
while child_stacking_contexts.peek().map_or(false,
|child| child.context_type == StackingContextType::PseudoFloat) {
let context = child_stacking_contexts.next().unwrap();
self.to_display_list_for_stacking_context(list, context);
}
// Step 6 & 7: Content and inlines that generate stacking contexts.
while child_items.last().map_or(false,
|child| child.section() == DisplayListSection::Content) {
list.push(child_items.pop().unwrap());
}
// Step 8 & 9: Positioned descendants with nonnegative, numeric z-indices.
for child in child_stacking_contexts {
self.to_display_list_for_stacking_context(list, child);
}
// Step 10: Outlines.
list.extend(child_items);
}
}
/// The logical width of an insertion point: at the moment, a one-pixel-wide line.

View file

@ -14,7 +14,6 @@ use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
use flow::IS_ABSOLUTELY_POSITIONED;
use fragment::FragmentBorderBoxIterator;
use generated_content::ResolveGeneratedContent;
use gfx::display_list::{DisplayItem, StackingContext};
use gfx_traits::ScrollRootId;
use script_layout_interface::restyle_damage::{REFLOW, STORE_OVERFLOW};
use style::context::StyleContext;
@ -75,17 +74,16 @@ pub fn traverse_flow_tree_preorder(root: &mut Flow,
doit(root, assign_inline_sizes, assign_block_sizes);
}
pub fn build_display_list_for_subtree(flow_root: &mut Flow,
root_stacking_context: &mut StackingContext,
shared_layout_context: &SharedLayoutContext)
-> Vec<DisplayItem> {
flow_root.collect_stacking_contexts(root_stacking_context, ScrollRootId::root());
let mut build_display_list = BuildDisplayList {
state: DisplayListBuildState::new(shared_layout_context,
flow::base(flow_root).stacking_context_id),
};
pub fn build_display_list_for_subtree<'a>(flow_root: &mut Flow,
shared_layout_context: &'a SharedLayoutContext)
-> DisplayListBuildState<'a> {
let mut state = DisplayListBuildState::new(shared_layout_context,
flow::base(flow_root).stacking_context_id);
flow_root.collect_stacking_contexts(&mut state.root_stacking_context, ScrollRootId::root());
let mut build_display_list = BuildDisplayList { state: state };
build_display_list.traverse(flow_root);
build_display_list.state.items
build_display_list.state
}
pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut Flow,

View file

@ -47,18 +47,16 @@ extern crate webrender_traits;
use app_units::Au;
use azure::azure_hl::Color;
use euclid::Matrix4D;
use euclid::point::Point2D;
use euclid::rect::Rect;
use euclid::scale_factor::ScaleFactor;
use euclid::size::Size2D;
use fnv::FnvHasher;
use gfx::display_list::{ClippingRegion, DisplayList, OpaqueNode};
use gfx::display_list::{StackingContext, StackingContextType, WebRenderImageInfo};
use gfx::display_list::{ClippingRegion, OpaqueNode, WebRenderImageInfo};
use gfx::font;
use gfx::font_cache_thread::FontCacheThread;
use gfx::font_context;
use gfx_traits::{Epoch, FragmentType, ScrollPolicy, ScrollRootId, StackingContextId};
use gfx_traits::{Epoch, FragmentType, ScrollRootId};
use heapsize::HeapSizeOf;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
@ -107,7 +105,6 @@ use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{Receiver, Sender, channel};
use style::animation::Animation;
use style::computed_values::{filter, mix_blend_mode};
use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext};
use style::dom::{TDocument, TElement, TNode};
use style::error_reporting::{ParseErrorReporter, StdoutErrorReporter};
@ -910,24 +907,9 @@ impl LayoutThread {
.unwrap_or(false);
match (data.goal, display_list_needed) {
(ReflowGoal::ForDisplay, _) | (ReflowGoal::ForScriptQuery, true) => {
let mut root_stacking_context =
StackingContext::new(StackingContextId::new(0),
StackingContextType::Real,
&Rect::zero(),
&Rect::zero(),
0,
filter::T::new(Vec::new()),
mix_blend_mode::T::normal,
Matrix4D::identity(),
Matrix4D::identity(),
true,
ScrollPolicy::Scrollable,
None);
let display_list_entries =
sequential::build_display_list_for_subtree(layout_root,
&mut root_stacking_context,
shared_layout_context);
let mut build_state =
sequential::build_display_list_for_subtree(layout_root,
shared_layout_context);
debug!("Done building display list.");
@ -941,12 +923,9 @@ impl LayoutThread {
};
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
root_stacking_context.bounds = origin;
root_stacking_context.overflow = origin;
rw_data.display_list =
Some(Arc::new(DisplayList::new(root_stacking_context,
display_list_entries)))
build_state.root_stacking_context.bounds = origin;
build_state.root_stacking_context.overflow = origin;
rw_data.display_list = Some(Arc::new(build_state.to_display_list()));
}
(ReflowGoal::ForScriptQuery, false) => {}
}