mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
Fold some DisplayList methods into DisplayListBuildState
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.
This commit is contained in:
parent
1192aaa14d
commit
cd1c881830
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