mirror of
https://github.com/servo/servo.git
synced 2025-06-22 08:08:59 +01:00
Multiple display list support
This commit is contained in:
parent
7e3075522d
commit
0892fada74
7 changed files with 172 additions and 103 deletions
|
@ -27,11 +27,62 @@ use std::cast::transmute_region;
|
||||||
use std::vec::VecIterator;
|
use std::vec::VecIterator;
|
||||||
use style::computed_values::border_style;
|
use style::computed_values::border_style;
|
||||||
|
|
||||||
|
pub struct DisplayListCollection<E> {
|
||||||
|
lists: ~[DisplayList<E>]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> DisplayListCollection<E> {
|
||||||
|
pub fn new() -> DisplayListCollection<E> {
|
||||||
|
DisplayListCollection {
|
||||||
|
lists: ~[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter<'a>(&'a self) -> DisplayListIterator<'a,E> {
|
||||||
|
ParentDisplayListIterator(self.lists.iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_list(&mut self, list: DisplayList<E>) {
|
||||||
|
self.lists.push(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_lists_into_context(&self, render_context: &mut RenderContext) {
|
||||||
|
for list in self.lists.iter() {
|
||||||
|
list.draw_into_context(render_context);
|
||||||
|
}
|
||||||
|
debug!("{:?}", self.dump());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump(&self) {
|
||||||
|
let mut index = 0;
|
||||||
|
for list in self.lists.iter() {
|
||||||
|
debug!("dumping display list {:d}:", index);
|
||||||
|
list.dump();
|
||||||
|
index = index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A list of rendering operations to be performed.
|
/// A list of rendering operations to be performed.
|
||||||
pub struct DisplayList<E> {
|
pub struct DisplayList<E> {
|
||||||
list: ~[DisplayItem<E>]
|
list: ~[DisplayItem<E>]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum DisplayListIterator<'a,E> {
|
||||||
|
EmptyDisplayListIterator,
|
||||||
|
ParentDisplayListIterator(VecIterator<'a,DisplayList<E>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a,E> Iterator<&'a DisplayList<E>> for DisplayListIterator<'a,E> {
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<&'a DisplayList<E>> {
|
||||||
|
match *self {
|
||||||
|
EmptyDisplayListIterator => None,
|
||||||
|
ParentDisplayListIterator(ref mut subiterator) => subiterator.next(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E> DisplayList<E> {
|
impl<E> DisplayList<E> {
|
||||||
/// Creates a new display list.
|
/// Creates a new display list.
|
||||||
pub fn new() -> DisplayList<E> {
|
pub fn new() -> DisplayList<E> {
|
||||||
|
@ -62,7 +113,6 @@ impl<E> DisplayList<E> {
|
||||||
item.draw_into_context(render_context)
|
item.draw_into_context(render_context)
|
||||||
}
|
}
|
||||||
debug!("Ending display list.");
|
debug!("Ending display list.");
|
||||||
debug!("{:?}", self.dump());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a preorder iterator over the given display list.
|
/// Returns a preorder iterator over the given display list.
|
||||||
|
|
|
@ -24,13 +24,14 @@ use std::comm::{Chan, Port, SharedChan};
|
||||||
use extra::arc::Arc;
|
use extra::arc::Arc;
|
||||||
|
|
||||||
use buffer_map::BufferMap;
|
use buffer_map::BufferMap;
|
||||||
use display_list::DisplayList;
|
use font_context::{FontContext, FontContextInfo};
|
||||||
|
use display_list::DisplayListCollection;
|
||||||
use font_context::{FontContext, FontContextInfo};
|
use font_context::{FontContext, FontContextInfo};
|
||||||
use opts::Opts;
|
use opts::Opts;
|
||||||
use render_context::RenderContext;
|
use render_context::RenderContext;
|
||||||
|
|
||||||
pub struct RenderLayer<T> {
|
pub struct RenderLayer<T> {
|
||||||
display_list: Arc<DisplayList<T>>,
|
display_list_collection: Arc<DisplayListCollection<T>>,
|
||||||
size: Size2D<uint>,
|
size: Size2D<uint>,
|
||||||
color: Color
|
color: Color
|
||||||
}
|
}
|
||||||
|
@ -305,7 +306,7 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
|
||||||
|
|
||||||
// Draw the display list.
|
// Draw the display list.
|
||||||
profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
|
profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
|
||||||
render_layer.display_list.get().draw_into_context(&mut ctx);
|
render_layer.display_list_collection.get().draw_lists_into_context(&mut ctx);
|
||||||
ctx.draw_target.flush();
|
ctx.draw_target.flush();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use layout::float_context::{FloatContext, PlacementInfo, Invalid, FloatType};
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use geom::{Point2D, Rect, SideOffsets2D};
|
use geom::{Point2D, Rect, SideOffsets2D};
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::{DisplayList, DisplayListCollection};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use servo_util::geometry;
|
use servo_util::geometry;
|
||||||
|
|
||||||
|
@ -496,22 +496,31 @@ impl BlockFlow {
|
||||||
&mut self,
|
&mut self,
|
||||||
builder: &DisplayListBuilder,
|
builder: &DisplayListBuilder,
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
list: &RefCell<DisplayList<E>>)
|
mut index: uint,
|
||||||
-> bool {
|
lists: &RefCell<DisplayListCollection<E>>)
|
||||||
|
-> uint {
|
||||||
if self.is_float() {
|
if self.is_float() {
|
||||||
return self.build_display_list_float(builder, dirty, list);
|
self.build_display_list_float(builder, dirty, index, lists);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.is_fixed {
|
||||||
|
lists.with_mut(|lists| {
|
||||||
|
index = lists.lists.len();
|
||||||
|
lists.add_list(DisplayList::<E>::new());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
|
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
|
||||||
if !abs_rect.intersects(dirty) {
|
if !abs_rect.intersects(dirty) {
|
||||||
return true;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("build_display_list_block: adding display element");
|
debug!("build_display_list_block: adding display element");
|
||||||
|
|
||||||
// add box that starts block context
|
// add box that starts block context
|
||||||
for box_ in self.box_.iter() {
|
for box_ in self.box_.iter() {
|
||||||
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list)
|
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, index, lists);
|
||||||
}
|
}
|
||||||
// TODO: handle any out-of-flow elements
|
// TODO: handle any out-of-flow elements
|
||||||
let this_position = self.base.abs_position;
|
let this_position = self.base.abs_position;
|
||||||
|
@ -521,24 +530,26 @@ impl BlockFlow {
|
||||||
child_base.abs_position = this_position + child_base.position.origin;
|
child_base.abs_position = this_position + child_base.position.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_display_list_float<E:ExtraDisplayListData>(
|
pub fn build_display_list_float<E:ExtraDisplayListData>(
|
||||||
&mut self,
|
&mut self,
|
||||||
builder: &DisplayListBuilder,
|
builder: &DisplayListBuilder,
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
list: &RefCell<DisplayList<E>>)
|
index: uint,
|
||||||
|
lists: &RefCell<DisplayListCollection<E>>)
|
||||||
-> bool {
|
-> bool {
|
||||||
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
|
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
|
||||||
if !abs_rect.intersects(dirty) {
|
if !abs_rect.intersects(dirty) {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let offset = self.base.abs_position + self.float.get_ref().rel_pos;
|
let offset = self.base.abs_position + self.float.get_ref().rel_pos;
|
||||||
// add box that starts block context
|
// add box that starts block context
|
||||||
for box_ in self.box_.iter() {
|
for box_ in self.box_.iter() {
|
||||||
box_.build_display_list(builder, dirty, offset, (&*self) as &Flow, list)
|
box_.build_display_list(builder, dirty, offset, (&*self) as &Flow, index, lists);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,10 @@ use extra::arc::{MutexArc, Arc};
|
||||||
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
|
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
|
||||||
use gfx::color::rgb;
|
use gfx::color::rgb;
|
||||||
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
||||||
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass};
|
use gfx::display_list::{ImageDisplayItem, ImageDisplayItemClass};
|
||||||
use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, TextDisplayItem};
|
use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, TextDisplayItem};
|
||||||
use gfx::display_list::{TextDisplayItemClass, TextDisplayItemFlags, ClipDisplayItem};
|
use gfx::display_list::{TextDisplayItemClass, TextDisplayItemFlags, ClipDisplayItem};
|
||||||
use gfx::display_list::{ClipDisplayItemClass};
|
use gfx::display_list::{ClipDisplayItemClass, DisplayListCollection};
|
||||||
use gfx::font::FontStyle;
|
use gfx::font::FontStyle;
|
||||||
|
|
||||||
use gfx::text::text_run::TextRun;
|
use gfx::text::text_run::TextRun;
|
||||||
|
@ -784,7 +784,8 @@ impl Box {
|
||||||
|
|
||||||
pub fn paint_inline_background_border_if_applicable<E:ExtraDisplayListData>(
|
pub fn paint_inline_background_border_if_applicable<E:ExtraDisplayListData>(
|
||||||
&self,
|
&self,
|
||||||
list: &RefCell<DisplayList<E>>,
|
index: uint,
|
||||||
|
lists: &RefCell<DisplayListCollection<E>>,
|
||||||
absolute_bounds: &Rect<Au>,
|
absolute_bounds: &Rect<Au>,
|
||||||
offset: &Point2D<Au>) {
|
offset: &Point2D<Au>) {
|
||||||
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
||||||
|
@ -803,7 +804,7 @@ impl Box {
|
||||||
info.style.get().Background.background_color);
|
info.style.get().Background.background_color);
|
||||||
|
|
||||||
if !background_color.alpha.approx_eq(&0.0) {
|
if !background_color.alpha.approx_eq(&0.0) {
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let solid_color_display_item = ~SolidColorDisplayItem {
|
let solid_color_display_item = ~SolidColorDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: bg_rect.clone(),
|
bounds: bg_rect.clone(),
|
||||||
|
@ -812,7 +813,7 @@ impl Box {
|
||||||
color: background_color.to_gfx_color(),
|
color: background_color.to_gfx_color(),
|
||||||
};
|
};
|
||||||
|
|
||||||
list.append_item(SolidColorDisplayItemClass(solid_color_display_item))
|
lists.lists[index].append_item(SolidColorDisplayItemClass(solid_color_display_item))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let border = &info.border;
|
let border = &info.border;
|
||||||
|
@ -834,7 +835,7 @@ impl Box {
|
||||||
let left_style = style.Border.border_left_style;
|
let left_style = style.Border.border_left_style;
|
||||||
|
|
||||||
|
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let border_display_item = ~BorderDisplayItem {
|
let border_display_item = ~BorderDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: bg_rect,
|
bounds: bg_rect,
|
||||||
|
@ -851,7 +852,7 @@ impl Box {
|
||||||
left_style)
|
left_style)
|
||||||
};
|
};
|
||||||
|
|
||||||
list.append_item(BorderDisplayItemClass(border_display_item))
|
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item))
|
||||||
});
|
});
|
||||||
|
|
||||||
bg_rect.origin.x = bg_rect.origin.x + border.left;
|
bg_rect.origin.x = bg_rect.origin.x + border.left;
|
||||||
|
@ -865,7 +866,8 @@ impl Box {
|
||||||
/// necessary.
|
/// necessary.
|
||||||
pub fn paint_background_if_applicable<E:ExtraDisplayListData>(
|
pub fn paint_background_if_applicable<E:ExtraDisplayListData>(
|
||||||
&self,
|
&self,
|
||||||
list: &RefCell<DisplayList<E>>,
|
index: uint,
|
||||||
|
lists: &RefCell<DisplayListCollection<E>>,
|
||||||
absolute_bounds: &Rect<Au>) {
|
absolute_bounds: &Rect<Au>) {
|
||||||
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
||||||
// needed. We could use display list optimization to clean this up, but it still seems
|
// needed. We could use display list optimization to clean this up, but it still seems
|
||||||
|
@ -874,7 +876,7 @@ impl Box {
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
let background_color = style.resolve_color(style.Background.background_color);
|
let background_color = style.resolve_color(style.Background.background_color);
|
||||||
if !background_color.alpha.approx_eq(&0.0) {
|
if !background_color.alpha.approx_eq(&0.0) {
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let solid_color_display_item = ~SolidColorDisplayItem {
|
let solid_color_display_item = ~SolidColorDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: *absolute_bounds,
|
bounds: *absolute_bounds,
|
||||||
|
@ -883,8 +885,8 @@ impl Box {
|
||||||
color: background_color.to_gfx_color(),
|
color: background_color.to_gfx_color(),
|
||||||
};
|
};
|
||||||
|
|
||||||
list.append_item(SolidColorDisplayItemClass(solid_color_display_item))
|
lists.lists[index].append_item(SolidColorDisplayItemClass(solid_color_display_item))
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,7 +894,8 @@ impl Box {
|
||||||
/// necessary.
|
/// necessary.
|
||||||
pub fn paint_borders_if_applicable<E:ExtraDisplayListData>(
|
pub fn paint_borders_if_applicable<E:ExtraDisplayListData>(
|
||||||
&self,
|
&self,
|
||||||
list: &RefCell<DisplayList<E>>,
|
index: uint,
|
||||||
|
lists: &RefCell<DisplayListCollection<E>>,
|
||||||
abs_bounds: &Rect<Au>) {
|
abs_bounds: &Rect<Au>) {
|
||||||
// Fast path.
|
// Fast path.
|
||||||
let border = self.border.get();
|
let border = self.border.get();
|
||||||
|
@ -916,7 +919,7 @@ impl Box {
|
||||||
- self.noncontent_inline_right();
|
- self.noncontent_inline_right();
|
||||||
|
|
||||||
// Append the border to the display list.
|
// Append the border to the display list.
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let border_display_item = ~BorderDisplayItem {
|
let border_display_item = ~BorderDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: abs_bounds,
|
bounds: abs_bounds,
|
||||||
|
@ -933,7 +936,7 @@ impl Box {
|
||||||
left_style)
|
left_style)
|
||||||
};
|
};
|
||||||
|
|
||||||
list.append_item(BorderDisplayItemClass(border_display_item))
|
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,7 +960,8 @@ impl Box {
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
offset: Point2D<Au>,
|
offset: Point2D<Au>,
|
||||||
flow: &Flow,
|
flow: &Flow,
|
||||||
list: &RefCell<DisplayList<E>>) {
|
index: uint,
|
||||||
|
lists: &RefCell<DisplayListCollection<E>>) {
|
||||||
let box_bounds = self.position.get();
|
let box_bounds = self.position.get();
|
||||||
let absolute_box_bounds = box_bounds.translate(&offset);
|
let absolute_box_bounds = box_bounds.translate(&offset);
|
||||||
debug!("Box::build_display_list at rel={}, abs={}: {:s}",
|
debug!("Box::build_display_list at rel={}, abs={}: {:s}",
|
||||||
|
@ -975,14 +979,14 @@ impl Box {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.paint_inline_background_border_if_applicable(list, &absolute_box_bounds, &offset);
|
self.paint_inline_background_border_if_applicable(index, lists, &absolute_box_bounds, &offset);
|
||||||
// Add the background to the list, if applicable.
|
// Add the background to the list, if applicable.
|
||||||
self.paint_background_if_applicable(list, &absolute_box_bounds);
|
self.paint_background_if_applicable(index, lists, &absolute_box_bounds);
|
||||||
|
|
||||||
match self.specific {
|
match self.specific {
|
||||||
UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."),
|
UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."),
|
||||||
ScannedTextBox(ref text_box) => {
|
ScannedTextBox(ref text_box) => {
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let item = ~ClipDisplayItem {
|
let item = ~ClipDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: absolute_box_bounds,
|
bounds: absolute_box_bounds,
|
||||||
|
@ -991,7 +995,7 @@ impl Box {
|
||||||
child_list: ~[],
|
child_list: ~[],
|
||||||
need_clip: false
|
need_clip: false
|
||||||
};
|
};
|
||||||
list.append_item(ClipDisplayItemClass(item));
|
lists.lists[index].append_item(ClipDisplayItemClass(item));
|
||||||
});
|
});
|
||||||
|
|
||||||
let text_color = self.style().Color.color.to_gfx_color();
|
let text_color = self.style().Color.color.to_gfx_color();
|
||||||
|
@ -1022,7 +1026,7 @@ impl Box {
|
||||||
- self.noncontent_inline_right();
|
- self.noncontent_inline_right();
|
||||||
|
|
||||||
// Create the text box.
|
// Create the text box.
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let text_display_item = ~TextDisplayItem {
|
let text_display_item = ~TextDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: bounds,
|
bounds: bounds,
|
||||||
|
@ -1037,7 +1041,7 @@ impl Box {
|
||||||
flags: text_flags,
|
flags: text_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
list.append_item(TextDisplayItemClass(text_display_item))
|
lists.lists[index].append_item(TextDisplayItemClass(text_display_item));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Draw debug frames for text bounds.
|
// Draw debug frames for text bounds.
|
||||||
|
@ -1048,7 +1052,7 @@ impl Box {
|
||||||
// Compute the text box bounds and draw a border surrounding them.
|
// Compute the text box bounds and draw a border surrounding them.
|
||||||
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
||||||
|
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let border_display_item = ~BorderDisplayItem {
|
let border_display_item = ~BorderDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: absolute_box_bounds,
|
bounds: absolute_box_bounds,
|
||||||
|
@ -1059,7 +1063,7 @@ impl Box {
|
||||||
style: SideOffsets2D::new_all_same(border_style::solid)
|
style: SideOffsets2D::new_all_same(border_style::solid)
|
||||||
|
|
||||||
};
|
};
|
||||||
list.append_item(BorderDisplayItemClass(border_display_item))
|
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Draw a rectangle representing the baselines.
|
// Draw a rectangle representing the baselines.
|
||||||
|
@ -1070,7 +1074,7 @@ impl Box {
|
||||||
let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent),
|
let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent),
|
||||||
Size2D(absolute_box_bounds.size.width, Au(0)));
|
Size2D(absolute_box_bounds.size.width, Au(0)));
|
||||||
|
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let border_display_item = ~BorderDisplayItem {
|
let border_display_item = ~BorderDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: baseline,
|
bounds: baseline,
|
||||||
|
@ -1081,12 +1085,12 @@ impl Box {
|
||||||
style: SideOffsets2D::new_all_same(border_style::dashed)
|
style: SideOffsets2D::new_all_same(border_style::dashed)
|
||||||
|
|
||||||
};
|
};
|
||||||
list.append_item(BorderDisplayItemClass(border_display_item))
|
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
GenericBox | IframeBox(..) => {
|
GenericBox | IframeBox(..) => {
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let item = ~ClipDisplayItem {
|
let item = ~ClipDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: absolute_box_bounds,
|
bounds: absolute_box_bounds,
|
||||||
|
@ -1095,7 +1099,7 @@ impl Box {
|
||||||
child_list: ~[],
|
child_list: ~[],
|
||||||
need_clip: self.needs_clip()
|
need_clip: self.needs_clip()
|
||||||
};
|
};
|
||||||
list.append_item(ClipDisplayItemClass(item));
|
lists.lists[index].append_item(ClipDisplayItemClass(item));
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
||||||
|
@ -1103,7 +1107,7 @@ impl Box {
|
||||||
debug!("{:?}", {
|
debug!("{:?}", {
|
||||||
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
||||||
|
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let border_display_item = ~BorderDisplayItem {
|
let border_display_item = ~BorderDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: absolute_box_bounds,
|
bounds: absolute_box_bounds,
|
||||||
|
@ -1114,12 +1118,12 @@ impl Box {
|
||||||
style: SideOffsets2D::new_all_same(border_style::solid)
|
style: SideOffsets2D::new_all_same(border_style::solid)
|
||||||
|
|
||||||
};
|
};
|
||||||
list.append_item(BorderDisplayItemClass(border_display_item))
|
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
ImageBox(ref image_box) => {
|
ImageBox(ref image_box) => {
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let item = ~ClipDisplayItem {
|
let item = ~ClipDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: absolute_box_bounds,
|
bounds: absolute_box_bounds,
|
||||||
|
@ -1128,7 +1132,7 @@ impl Box {
|
||||||
child_list: ~[],
|
child_list: ~[],
|
||||||
need_clip: false
|
need_clip: false
|
||||||
};
|
};
|
||||||
list.append_item(ClipDisplayItemClass(item));
|
lists.lists[index].append_item(ClipDisplayItemClass(item));
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut image_ref = image_box.image.borrow_mut();
|
let mut image_ref = image_box.image.borrow_mut();
|
||||||
|
@ -1146,7 +1150,7 @@ impl Box {
|
||||||
debug!("(building display list) building image box");
|
debug!("(building display list) building image box");
|
||||||
|
|
||||||
// Place the image into the display list.
|
// Place the image into the display list.
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let image_display_item = ~ImageDisplayItem {
|
let image_display_item = ~ImageDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: bounds,
|
bounds: bounds,
|
||||||
|
@ -1154,7 +1158,7 @@ impl Box {
|
||||||
},
|
},
|
||||||
image: image.clone(),
|
image: image.clone(),
|
||||||
};
|
};
|
||||||
list.append_item(ImageDisplayItemClass(image_display_item));
|
lists.lists[index].append_item(ImageDisplayItemClass(image_display_item));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -1169,7 +1173,7 @@ impl Box {
|
||||||
debug!("{:?}", {
|
debug!("{:?}", {
|
||||||
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
||||||
|
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let border_display_item = ~BorderDisplayItem {
|
let border_display_item = ~BorderDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: absolute_box_bounds,
|
bounds: absolute_box_bounds,
|
||||||
|
@ -1180,7 +1184,7 @@ impl Box {
|
||||||
style: SideOffsets2D::new_all_same(border_style::solid)
|
style: SideOffsets2D::new_all_same(border_style::solid)
|
||||||
|
|
||||||
};
|
};
|
||||||
list.append_item(BorderDisplayItemClass(border_display_item))
|
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item))
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1207,7 +1211,8 @@ impl Box {
|
||||||
// Add a border, if applicable.
|
// Add a border, if applicable.
|
||||||
//
|
//
|
||||||
// TODO: Outlines.
|
// TODO: Outlines.
|
||||||
self.paint_borders_if_applicable(list, &absolute_box_bounds);
|
self.paint_borders_if_applicable(index, lists, &absolute_box_bounds);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the *minimum width* and *preferred width* of this box as defined by CSS 2.1.
|
/// Returns the *minimum width* and *preferred width* of this box as defined by CSS 2.1.
|
||||||
|
|
|
@ -41,7 +41,7 @@ use extra::dlist::{DList, DListIterator, MutDListIterator};
|
||||||
use extra::container::Deque;
|
use extra::container::Deque;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::display_list::{ClipDisplayItemClass, DisplayList};
|
use gfx::display_list::{ClipDisplayItemClass, DisplayListCollection, DisplayList};
|
||||||
use layout::display_list_builder::ToGfxColor;
|
use layout::display_list_builder::ToGfxColor;
|
||||||
use gfx::color::Color;
|
use gfx::color::Color;
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
|
@ -206,12 +206,13 @@ pub trait MutableFlowUtils {
|
||||||
/// Computes the overflow region for this flow.
|
/// Computes the overflow region for this flow.
|
||||||
fn store_overflow(self, _: &mut LayoutContext);
|
fn store_overflow(self, _: &mut LayoutContext);
|
||||||
|
|
||||||
/// Builds a display list for this flow and its children.
|
/// builds the display lists
|
||||||
fn build_display_list<E:ExtraDisplayListData>(
|
fn build_display_lists<E:ExtraDisplayListData>(
|
||||||
self,
|
self,
|
||||||
builder: &DisplayListBuilder,
|
builder: &DisplayListBuilder,
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
list: &RefCell<DisplayList<E>>)
|
index: uint,
|
||||||
|
mut list: &RefCell<DisplayListCollection<E>>)
|
||||||
-> bool;
|
-> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,33 +700,37 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
||||||
mut_base(self).overflow = overflow
|
mut_base(self).overflow = overflow
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list<E:ExtraDisplayListData>(
|
fn build_display_lists<E:ExtraDisplayListData>(
|
||||||
self,
|
self,
|
||||||
builder: &DisplayListBuilder,
|
builder: &DisplayListBuilder,
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
list: &RefCell<DisplayList<E>>)
|
mut index: uint,
|
||||||
|
lists: &RefCell<DisplayListCollection<E>>)
|
||||||
-> bool {
|
-> bool {
|
||||||
debug!("Flow: building display list for f{}", base(self).id);
|
debug!("Flow: building display list for f{}", base(self).id);
|
||||||
match self.class() {
|
index = match self.class() {
|
||||||
BlockFlowClass => self.as_block().build_display_list_block(builder, dirty, list),
|
BlockFlowClass => self.as_block().build_display_list_block(builder, dirty, index, lists),
|
||||||
InlineFlowClass => self.as_inline().build_display_list_inline(builder, dirty, list),
|
InlineFlowClass => self.as_inline().build_display_list_inline(builder, dirty, index, lists),
|
||||||
};
|
};
|
||||||
|
|
||||||
if list.with_mut(|list| list.list.len() == 0) {
|
if lists.with_mut(|lists| lists.lists[index].list.len() == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let child_list = ~RefCell::new(DisplayList::new());
|
let mut child_lists = DisplayListCollection::new();
|
||||||
|
child_lists.add_list(DisplayList::new());
|
||||||
|
let child_lists = RefCell::new(child_lists);
|
||||||
for kid in child_iter(self) {
|
for kid in child_iter(self) {
|
||||||
kid.build_display_list(builder,dirty,child_list);
|
kid.build_display_lists(builder, dirty, 0u, &child_lists);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut child_list = Some(child_list.unwrap());
|
let mut child_lists = Some(child_lists.unwrap());
|
||||||
list.with_mut(|list| {
|
lists.with_mut(|lists| {
|
||||||
let result = list.list.mut_rev_iter().position(|item| {
|
let mut child_lists = child_lists.take_unwrap();
|
||||||
|
let result = lists.lists[index].list.mut_rev_iter().position(|item| {
|
||||||
match *item {
|
match *item {
|
||||||
ClipDisplayItemClass(ref mut item) => {
|
ClipDisplayItemClass(ref mut item) => {
|
||||||
item.child_list.push_all_move(child_list.take_unwrap().list);
|
item.child_list.push_all_move(child_lists.lists.shift().list);
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -736,6 +741,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
||||||
fail!("fail to find parent item");
|
fail!("fail to find parent item");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lists.lists.push_all_move(child_lists.lists);
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ use layout::float_context::{PlacementInfo, FloatLeft};
|
||||||
use extra::container::Deque;
|
use extra::container::Deque;
|
||||||
use extra::ringbuf::RingBuf;
|
use extra::ringbuf::RingBuf;
|
||||||
use geom::{Point2D, Rect, Size2D};
|
use geom::{Point2D, Rect, Size2D};
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayListCollection;
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -495,11 +495,12 @@ impl InlineFlow {
|
||||||
&self,
|
&self,
|
||||||
builder: &DisplayListBuilder,
|
builder: &DisplayListBuilder,
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
list: &RefCell<DisplayList<E>>)
|
index: uint,
|
||||||
-> bool {
|
lists: &RefCell<DisplayListCollection<E>>)
|
||||||
|
-> uint {
|
||||||
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
|
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
|
||||||
if !abs_rect.intersects(dirty) {
|
if !abs_rect.intersects(dirty) {
|
||||||
return true;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and
|
// TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and
|
||||||
|
@ -509,14 +510,14 @@ impl InlineFlow {
|
||||||
self.boxes.len());
|
self.boxes.len());
|
||||||
|
|
||||||
for box_ in self.boxes.iter() {
|
for box_ in self.boxes.iter() {
|
||||||
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list)
|
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, index, lists);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
|
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
|
||||||
// should the flow be nested inside the box somehow?
|
// should the flow be nested inside the box somehow?
|
||||||
|
|
||||||
// For now, don't traverse the subtree rooted here
|
// For now, don't traverse the subtree rooted here
|
||||||
true
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the relative offset from the baseline for this box, taking into account the value
|
/// Returns the relative offset from the baseline for this box, taking into account the value
|
||||||
|
|
|
@ -25,7 +25,8 @@ use layout::wrapper::LayoutNode;
|
||||||
use extra::arc::{Arc, MutexArc};
|
use extra::arc::{Arc, MutexArc};
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::display_list::{ClipDisplayItemClass, DisplayItem, DisplayItemIterator, DisplayList};
|
use gfx::display_list::{ClipDisplayItemClass, DisplayItem, DisplayItemIterator};
|
||||||
|
use gfx::display_list::{DisplayList, DisplayListCollection};
|
||||||
use gfx::font_context::FontContextInfo;
|
use gfx::font_context::FontContextInfo;
|
||||||
use gfx::opts::Opts;
|
use gfx::opts::Opts;
|
||||||
use gfx::render_task::{RenderMsg, RenderChan, RenderLayer};
|
use gfx::render_task::{RenderMsg, RenderChan, RenderLayer};
|
||||||
|
@ -89,7 +90,7 @@ pub struct LayoutTask {
|
||||||
screen_size: Size2D<Au>,
|
screen_size: Size2D<Au>,
|
||||||
|
|
||||||
/// A cached display list.
|
/// A cached display list.
|
||||||
display_list: Option<Arc<DisplayList<OpaqueNode>>>,
|
display_list_collection: Option<Arc<DisplayListCollection<OpaqueNode>>>,
|
||||||
|
|
||||||
stylist: ~Stylist,
|
stylist: ~Stylist,
|
||||||
|
|
||||||
|
@ -273,7 +274,7 @@ impl LayoutTask {
|
||||||
screen_size: screen_size,
|
screen_size: screen_size,
|
||||||
leaf_set: MutexArc::new(LeafSet::new()),
|
leaf_set: MutexArc::new(LeafSet::new()),
|
||||||
|
|
||||||
display_list: None,
|
display_list_collection: None,
|
||||||
stylist: ~new_stylist(),
|
stylist: ~new_stylist(),
|
||||||
parallel_traversal: parallel_traversal,
|
parallel_traversal: parallel_traversal,
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
|
@ -575,14 +576,16 @@ impl LayoutTask {
|
||||||
if data.goal == ReflowForDisplay {
|
if data.goal == ReflowForDisplay {
|
||||||
profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone(), || {
|
profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone(), || {
|
||||||
let root_size = flow::base(layout_root).position.size;
|
let root_size = flow::base(layout_root).position.size;
|
||||||
let display_list = ~RefCell::new(DisplayList::<OpaqueNode>::new());
|
let mut display_list_collection = DisplayListCollection::new();
|
||||||
|
display_list_collection.add_list(DisplayList::<OpaqueNode>::new());
|
||||||
|
let display_list_collection = ~RefCell::new(display_list_collection);
|
||||||
let dirty = flow::base(layout_root).position.clone();
|
let dirty = flow::base(layout_root).position.clone();
|
||||||
let display_list_builder = DisplayListBuilder {
|
let display_list_builder = DisplayListBuilder {
|
||||||
ctx: &layout_ctx,
|
ctx: &layout_ctx,
|
||||||
};
|
};
|
||||||
layout_root.build_display_list(&display_list_builder, &dirty, display_list);
|
layout_root.build_display_lists(&display_list_builder, &dirty, 0u, display_list_collection);
|
||||||
|
|
||||||
let display_list = Arc::new(display_list.unwrap());
|
let display_list_collection = Arc::new(display_list_collection.unwrap());
|
||||||
|
|
||||||
let mut color = color::rgba(255.0, 255.0, 255.0, 255.0);
|
let mut color = color::rgba(255.0, 255.0, 255.0, 255.0);
|
||||||
|
|
||||||
|
@ -607,13 +610,13 @@ impl LayoutTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_layer = RenderLayer {
|
let render_layer = RenderLayer {
|
||||||
display_list: display_list.clone(),
|
display_list_collection: display_list_collection.clone(),
|
||||||
size: Size2D(root_size.width.to_nearest_px() as uint,
|
size: Size2D(root_size.width.to_nearest_px() as uint,
|
||||||
root_size.height.to_nearest_px() as uint),
|
root_size.height.to_nearest_px() as uint),
|
||||||
color: color
|
color: color
|
||||||
};
|
};
|
||||||
|
|
||||||
self.display_list = Some(display_list.clone());
|
self.display_list_collection = Some(display_list_collection.clone());
|
||||||
|
|
||||||
debug!("Layout done!");
|
debug!("Layout done!");
|
||||||
|
|
||||||
|
@ -656,8 +659,9 @@ impl LayoutTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rect = None;
|
let mut rect = None;
|
||||||
let display_list = self.display_list.as_ref().unwrap().get();
|
for display_list in self.display_list_collection.as_ref().unwrap().get().iter() {
|
||||||
union_boxes_for_node(&mut rect, display_list.iter(), node);
|
union_boxes_for_node(&mut rect, display_list.iter(), node);
|
||||||
|
}
|
||||||
reply_chan.send(ContentBoxResponse(rect.unwrap_or(Au::zero_rect())))
|
reply_chan.send(ContentBoxResponse(rect.unwrap_or(Au::zero_rect())))
|
||||||
}
|
}
|
||||||
ContentBoxesQuery(node, reply_chan) => {
|
ContentBoxesQuery(node, reply_chan) => {
|
||||||
|
@ -676,8 +680,9 @@ impl LayoutTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut boxes = ~[];
|
let mut boxes = ~[];
|
||||||
let display_list = self.display_list.as_ref().unwrap().get();
|
for display_list in self.display_list_collection.as_ref().unwrap().get().iter() {
|
||||||
add_boxes_for_node(&mut boxes, display_list.iter(), node);
|
add_boxes_for_node(&mut boxes, display_list.iter(), node);
|
||||||
|
}
|
||||||
reply_chan.send(ContentBoxesResponse(boxes))
|
reply_chan.send(ContentBoxesResponse(boxes))
|
||||||
}
|
}
|
||||||
HitTestQuery(_, point, reply_chan) => {
|
HitTestQuery(_, point, reply_chan) => {
|
||||||
|
@ -717,27 +722,17 @@ impl LayoutTask {
|
||||||
let ret: Option<HitTestResponse> = None;
|
let ret: Option<HitTestResponse> = None;
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
let response = {
|
for display_list in self.display_list_collection.as_ref().unwrap().get().lists.rev_iter() {
|
||||||
match self.display_list {
|
|
||||||
Some(ref list) => {
|
|
||||||
let display_list = list.get();
|
|
||||||
let (x, y) = (Au::from_frac_px(point.x as f64),
|
let (x, y) = (Au::from_frac_px(point.x as f64),
|
||||||
Au::from_frac_px(point.y as f64));
|
Au::from_frac_px(point.y as f64));
|
||||||
let resp = hit_test(x,y,display_list.list);
|
let resp = hit_test(x,y,display_list.list);
|
||||||
if resp.is_none() {
|
if resp.is_some() {
|
||||||
Err(())
|
reply_chan.send(Ok(resp.unwrap()));
|
||||||
} else {
|
return
|
||||||
Ok(resp.unwrap())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
reply_chan.send(Err(()));
|
||||||
error!("Can't hit test: no display list");
|
|
||||||
Err(())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
reply_chan.send(response)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue