mirror of
https://github.com/servo/servo.git
synced 2025-08-10 07:55:33 +01:00
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:
commit
021cabd3e6
4 changed files with 150 additions and 137 deletions
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) => {}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue