mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Add flows if requested to the display list info.
This will be used for hit testing.
This commit is contained in:
parent
e2bcd3648e
commit
2e4cecc718
8 changed files with 112 additions and 72 deletions
|
@ -26,20 +26,20 @@ use std::arc::ARC;
|
|||
use std::arc;
|
||||
|
||||
/// A list of rendering operations to be performed.
|
||||
pub struct DisplayList {
|
||||
priv list: ~[DisplayItem]
|
||||
pub struct DisplayList<E> {
|
||||
priv list: ~[DisplayItem<E>]
|
||||
}
|
||||
|
||||
impl DisplayList {
|
||||
impl<E> DisplayList<E> {
|
||||
/// Creates a new display list.
|
||||
pub fn new() -> DisplayList {
|
||||
pub fn new() -> DisplayList<E> {
|
||||
DisplayList {
|
||||
list: ~[]
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends the given item to the display list.
|
||||
pub fn append_item(&mut self, item: DisplayItem) {
|
||||
pub fn append_item(&mut self, item: DisplayItem<E>) {
|
||||
// FIXME(Issue #150): crashes
|
||||
//debug!("Adding display item %u: %?", self.len(), item);
|
||||
self.list.push(item)
|
||||
|
@ -58,51 +58,54 @@ impl DisplayList {
|
|||
}
|
||||
|
||||
/// One drawing command in the list.
|
||||
pub enum DisplayItem {
|
||||
SolidColorDisplayItemClass(~SolidColorDisplayItem),
|
||||
TextDisplayItemClass(~TextDisplayItem),
|
||||
ImageDisplayItemClass(~ImageDisplayItem),
|
||||
BorderDisplayItemClass(~BorderDisplayItem),
|
||||
pub enum DisplayItem<E> {
|
||||
SolidColorDisplayItemClass(~SolidColorDisplayItem<E>),
|
||||
TextDisplayItemClass(~TextDisplayItem<E>),
|
||||
ImageDisplayItemClass(~ImageDisplayItem<E>),
|
||||
BorderDisplayItemClass(~BorderDisplayItem<E>),
|
||||
}
|
||||
|
||||
/// Information common to all display items.
|
||||
pub struct BaseDisplayItem {
|
||||
pub struct BaseDisplayItem<E> {
|
||||
/// The boundaries of the display item.
|
||||
///
|
||||
/// TODO: Which coordinate system should this use?
|
||||
bounds: Rect<Au>,
|
||||
|
||||
/// Extra data: either the originating flow (for hit testing) or nothing (for rendering).
|
||||
extra: E,
|
||||
}
|
||||
|
||||
/// Renders a solid color.
|
||||
pub struct SolidColorDisplayItem {
|
||||
base: BaseDisplayItem,
|
||||
pub struct SolidColorDisplayItem<E> {
|
||||
base: BaseDisplayItem<E>,
|
||||
color: Color,
|
||||
}
|
||||
|
||||
/// Renders text.
|
||||
pub struct TextDisplayItem {
|
||||
base: BaseDisplayItem,
|
||||
pub struct TextDisplayItem<E> {
|
||||
base: BaseDisplayItem<E>,
|
||||
text_run: ~SendableTextRun,
|
||||
range: Range,
|
||||
color: Color,
|
||||
}
|
||||
|
||||
/// Renders an image.
|
||||
pub struct ImageDisplayItem {
|
||||
base: BaseDisplayItem,
|
||||
pub struct ImageDisplayItem<E> {
|
||||
base: BaseDisplayItem<E>,
|
||||
image: ARC<~Image>,
|
||||
}
|
||||
|
||||
/// Renders a border.
|
||||
pub struct BorderDisplayItem {
|
||||
base: BaseDisplayItem,
|
||||
pub struct BorderDisplayItem<E> {
|
||||
base: BaseDisplayItem<E>,
|
||||
/// The width of the border.
|
||||
width: Au,
|
||||
/// The color of the border.
|
||||
color: Color,
|
||||
}
|
||||
|
||||
impl DisplayItem {
|
||||
impl<E> DisplayItem<E> {
|
||||
/// Renders this display item into the given render context.
|
||||
fn draw_into_context(&self, render_context: &RenderContext) {
|
||||
match *self {
|
||||
|
|
|
@ -14,8 +14,12 @@ use geom::point::Point2D;
|
|||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
|
||||
/// The type representing the lack of extra display list data. This is used when sending display
|
||||
/// list data off to be rendered.
|
||||
pub type Nothing = ();
|
||||
|
||||
pub struct RenderLayer {
|
||||
display_list: DisplayList,
|
||||
display_list: DisplayList<Nothing>,
|
||||
size: Size2D<uint>
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
use layout::box::{RenderBox};
|
||||
use layout::context::LayoutContext;
|
||||
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
|
||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||
use layout::display_list_builder::{FlowDisplayListBuilderMethods};
|
||||
use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow};
|
||||
use layout::inline::InlineLayout;
|
||||
|
||||
|
@ -175,11 +176,11 @@ impl BlockFlowData {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn build_display_list_block(@mut self,
|
||||
builder: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList>) {
|
||||
pub fn build_display_list_block<E:ExtraDisplayListData>(@mut self,
|
||||
builder: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList<E>>) {
|
||||
// add box that starts block context
|
||||
self.box.map(|&box| {
|
||||
box.build_display_list(builder, dirty, offset, list)
|
||||
|
@ -195,3 +196,4 @@ impl BlockFlowData {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use css::node_style::StyledNode;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::display_list_builder::{DisplayListBuilder, ToGfxColor};
|
||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData, ToGfxColor};
|
||||
use layout::flow::FlowContext;
|
||||
use layout::model::BoxModel;
|
||||
use layout::text;
|
||||
|
@ -550,11 +550,11 @@ pub impl RenderBox {
|
|||
/// representing the box's stacking context. When asked to construct its constituent display
|
||||
/// items, each box puts its display items into the correct stack layer according to CSS 2.1
|
||||
/// Appendix E. Finally, the builder flattens the list.
|
||||
fn build_display_list(&self,
|
||||
_: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList>) {
|
||||
fn build_display_list<E:ExtraDisplayListData>(&self,
|
||||
_: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList<E>>) {
|
||||
let box_bounds = self.position();
|
||||
let absolute_box_bounds = box_bounds.translate(offset);
|
||||
debug!("RenderBox::build_display_list at rel=%?, abs=%?: %s",
|
||||
|
@ -582,6 +582,7 @@ pub impl RenderBox {
|
|||
let text_display_item = ~TextDisplayItem {
|
||||
base: BaseDisplayItem {
|
||||
bounds: absolute_box_bounds,
|
||||
extra: ExtraDisplayListData::new(*self),
|
||||
},
|
||||
// FIXME(pcwalton): Allocation? Why?!
|
||||
text_run: ~text_box.run.serialize(),
|
||||
|
@ -602,6 +603,7 @@ pub impl RenderBox {
|
|||
let border_display_item = ~BorderDisplayItem {
|
||||
base: BaseDisplayItem {
|
||||
bounds: absolute_box_bounds,
|
||||
extra: ExtraDisplayListData::new(*self),
|
||||
},
|
||||
width: Au::from_px(1),
|
||||
color: rgb(0, 0, 200).to_gfx_color(),
|
||||
|
@ -621,6 +623,7 @@ pub impl RenderBox {
|
|||
let border_display_item = ~BorderDisplayItem {
|
||||
base: BaseDisplayItem {
|
||||
bounds: baseline,
|
||||
extra: ExtraDisplayListData::new(*self),
|
||||
},
|
||||
width: Au::from_px(1),
|
||||
color: rgb(0, 200, 0).to_gfx_color(),
|
||||
|
@ -644,6 +647,7 @@ pub impl RenderBox {
|
|||
let image_display_item = ~ImageDisplayItem {
|
||||
base: BaseDisplayItem {
|
||||
bounds: absolute_box_bounds,
|
||||
extra: ExtraDisplayListData::new(*self),
|
||||
},
|
||||
image: image.clone(),
|
||||
};
|
||||
|
@ -668,9 +672,9 @@ pub impl RenderBox {
|
|||
|
||||
/// Adds the display items necessary to paint the background of this render box to the display
|
||||
/// list if necessary.
|
||||
fn paint_background_if_applicable(&self,
|
||||
list: &Cell<DisplayList>,
|
||||
absolute_bounds: &Rect<Au>) {
|
||||
fn paint_background_if_applicable<E:ExtraDisplayListData>(&self,
|
||||
list: &Cell<DisplayList<E>>,
|
||||
absolute_bounds: &Rect<Au>) {
|
||||
// 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
|
||||
// inefficient. What we really want is something like "nearest ancestor element that
|
||||
|
@ -683,6 +687,7 @@ pub impl RenderBox {
|
|||
let solid_color_display_item = ~SolidColorDisplayItem {
|
||||
base: BaseDisplayItem {
|
||||
bounds: *absolute_bounds,
|
||||
extra: ExtraDisplayListData::new(*self),
|
||||
},
|
||||
color: background_color.to_gfx_color(),
|
||||
};
|
||||
|
|
|
@ -2,15 +2,13 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
///
|
||||
/// Constructs display lists from render boxes.
|
||||
///
|
||||
|
||||
use core::cell::Cell;
|
||||
//! Constructs display lists from render boxes.
|
||||
|
||||
use layout::box::RenderBox;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::flow::FlowContext;
|
||||
|
||||
use core::cell::Cell;
|
||||
use geom::point::Point2D;
|
||||
use geom::rect::Rect;
|
||||
use gfx::display_list::DisplayList;
|
||||
|
@ -19,6 +17,28 @@ use gfx;
|
|||
use newcss;
|
||||
use servo_util::tree::TreeNodeRef;
|
||||
|
||||
/// Extra display list data is either nothing (if the display list is to be rendered) or the
|
||||
/// originating render box (if the display list is generated for hit testing).
|
||||
pub trait ExtraDisplayListData {
|
||||
fn new(box: RenderBox) -> Self;
|
||||
}
|
||||
|
||||
/// The type representing the lack of extra display list data. This is used when sending display
|
||||
/// list data off to be rendered.
|
||||
pub type Nothing = ();
|
||||
|
||||
impl ExtraDisplayListData for Nothing {
|
||||
fn new(_: RenderBox) -> Nothing {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtraDisplayListData for RenderBox {
|
||||
fn new(box: RenderBox) -> RenderBox {
|
||||
box
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder object that manages display list builder should mainly hold information about the
|
||||
/// initial request and desired result--for example, whether the `DisplayList` is to be used for
|
||||
/// painting or hit testing. This can affect which boxes are created.
|
||||
|
@ -30,30 +50,33 @@ pub struct DisplayListBuilder<'self> {
|
|||
}
|
||||
|
||||
pub trait FlowDisplayListBuilderMethods {
|
||||
fn build_display_list(&self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Cell<DisplayList>);
|
||||
fn build_display_list_for_child(&self,
|
||||
a: &DisplayListBuilder,
|
||||
b: FlowContext,
|
||||
c: &Rect<Au>,
|
||||
d: &Point2D<Au>,
|
||||
e: &Cell<DisplayList>);
|
||||
fn build_display_list<E:ExtraDisplayListData>(&self,
|
||||
a: &DisplayListBuilder,
|
||||
b: &Rect<Au>,
|
||||
c: &Cell<DisplayList<E>>);
|
||||
fn build_display_list_for_child<E:ExtraDisplayListData>(&self,
|
||||
a: &DisplayListBuilder,
|
||||
b: FlowContext,
|
||||
c: &Rect<Au>,
|
||||
d: &Point2D<Au>,
|
||||
e: &Cell<DisplayList<E>>);
|
||||
}
|
||||
|
||||
impl FlowDisplayListBuilderMethods for FlowContext {
|
||||
fn build_display_list(&self,
|
||||
builder: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
list: &Cell<DisplayList>) {
|
||||
fn build_display_list<E:ExtraDisplayListData>(&self,
|
||||
builder: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
list: &Cell<DisplayList<E>>) {
|
||||
let zero = gfx::geometry::zero_point();
|
||||
self.build_display_list_recurse(builder, dirty, &zero, list);
|
||||
}
|
||||
|
||||
fn build_display_list_for_child(&self,
|
||||
builder: &DisplayListBuilder,
|
||||
child_flow: FlowContext,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList>) {
|
||||
fn build_display_list_for_child<E:ExtraDisplayListData>(&self,
|
||||
builder: &DisplayListBuilder,
|
||||
child_flow: FlowContext,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList<E>>) {
|
||||
// Adjust the dirty rect to child flow context coordinates.
|
||||
do child_flow.with_base |child_node| {
|
||||
let abs_flow_bounds = child_node.position.translate(offset);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
use layout::block::BlockFlowData;
|
||||
use layout::box::RenderBox;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::display_list_builder::DisplayListBuilder;
|
||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||
use layout::inline::{InlineFlowData};
|
||||
|
||||
use core::cell::Cell;
|
||||
|
@ -284,11 +284,11 @@ impl<'self> FlowContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn build_display_list_recurse(&self,
|
||||
builder: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList>) {
|
||||
pub fn build_display_list_recurse<E:ExtraDisplayListData>(&self,
|
||||
builder: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList<E>>) {
|
||||
do self.with_base |info| {
|
||||
debug!("FlowContext::build_display_list at %?: %s", info.position, self.debug_str());
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use core;
|
|||
use layout::box::{CannotSplit, GenericRenderBoxClass, ImageRenderBoxClass, RenderBox};
|
||||
use layout::box::{SplitDidFit, SplitDidNotFit, TextRenderBoxClass, UnscannedTextRenderBoxClass};
|
||||
use layout::context::LayoutContext;
|
||||
use layout::display_list_builder::DisplayListBuilder;
|
||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||
use layout::flow::{FlowContext, FlowData, InlineFlow};
|
||||
use layout::text::{UnscannedMethods, adapt_textbox_with_range};
|
||||
|
||||
|
@ -864,11 +864,11 @@ impl InlineFlowData {
|
|||
self.common.position.size.height = cur_y;
|
||||
}
|
||||
|
||||
pub fn build_display_list_inline(&self,
|
||||
builder: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList>) {
|
||||
pub fn build_display_list_inline<E:ExtraDisplayListData>(&self,
|
||||
builder: &DisplayListBuilder,
|
||||
dirty: &Rect<Au>,
|
||||
offset: &Point2D<Au>,
|
||||
list: &Cell<DisplayList<E>>) {
|
||||
// TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and
|
||||
// not recurse on a line if nothing in it can intersect the dirty region.
|
||||
debug!("FlowContext[%d]: building display list for %u inline boxes",
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
//! Borders, padding, and margins.
|
||||
|
||||
use layout::display_list_builder::ToGfxColor;
|
||||
use layout::display_list_builder::{ExtraDisplayListData, ToGfxColor};
|
||||
use layout::box::RenderBox;
|
||||
|
||||
use core::cell::Cell;
|
||||
|
@ -76,7 +76,9 @@ impl BoxModel {
|
|||
impl RenderBox {
|
||||
/// Adds the display items necessary to paint the borders of this render box to a display list
|
||||
/// if necessary.
|
||||
pub fn paint_borders_if_applicable(&self, list: &Cell<DisplayList>, abs_bounds: &Rect<Au>) {
|
||||
pub fn paint_borders_if_applicable<E:ExtraDisplayListData>(&self,
|
||||
list: &Cell<DisplayList<E>>,
|
||||
abs_bounds: &Rect<Au>) {
|
||||
// Fast path.
|
||||
let border = do self.with_imm_base |base| {
|
||||
base.model.border
|
||||
|
@ -109,6 +111,7 @@ impl RenderBox {
|
|||
let border_display_item = ~BorderDisplayItem {
|
||||
base: BaseDisplayItem {
|
||||
bounds: bounds,
|
||||
extra: ExtraDisplayListData::new(*self),
|
||||
},
|
||||
width: border_width,
|
||||
color: color,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue