Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra display list data #482

Closed
wants to merge 11 commits into from

ExtraDisplayListData trait, added to DisplayItems, build_display_list…

… now parameterized by Extra
  • Loading branch information
Tim Kuehn authored and pcwalton committed May 25, 2013
commit 4b5f7c35e7df21e290717ef64b71c637dde152a4
@@ -28,20 +28,20 @@ use servo_util::range::Range;
use std::arc::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)
@@ -60,51 +60,52 @@ 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: 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 {
@@ -15,7 +15,7 @@ use geom::rect::Rect;
use geom::size::Size2D;

pub struct RenderLayer {
display_list: DisplayList,
display_list: DisplayList<()>,
size: Size2D<uint>
}

@@ -6,7 +6,7 @@

use layout::box::{RenderBox};
use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods, ExtraDisplayListData};
use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow};
use layout::inline::InlineLayout;

@@ -23,7 +23,7 @@ pub struct BlockFlowData {
common: FlowData,

/// The associated render box.
box: Option<RenderBox>,
box: Option<@RenderBox>,

/// Whether this block flow is the root flow.
is_root: bool
@@ -172,14 +172,14 @@ impl BlockFlowData {
});
}

pub fn build_display_list_block(@mut self,
pub fn build_display_list_block<E: ExtraDisplayListData>(@mut self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
offset: &Point2D<Au>,
list: &Cell<DisplayList>) {
list: &Cell<DisplayList<E>>) {
// add box that starts block context
self.box.map(|&box| {
box.build_display_list(builder, dirty, offset, list)
box.build_display_list::<E>(builder, dirty, offset, list)
});


@@ -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::text::TextBoxData;
use layout::text;
@@ -137,11 +137,11 @@ pub enum RenderBoxType {

/// Represents the outcome of attempting to split a render box.
pub enum SplitBoxResult {
CannotSplit(RenderBox),
CannotSplit(@RenderBox),
// in general, when splitting the left or right side can
// be zero length, due to leading/trailing trimmable whitespace
SplitDidFit(Option<RenderBox>, Option<RenderBox>),
SplitDidNotFit(Option<RenderBox>, Option<RenderBox>)
SplitDidFit(Option<@RenderBox>, Option<@RenderBox>),
SplitDidNotFit(Option<@RenderBox>, Option<@RenderBox>)
}

/// Data common to all render boxes.
@@ -271,10 +271,10 @@ pub impl RenderBox {

/// Attempts to split this box so that its width is no more than `max_width`. Fails if this box
/// is an unscanned text box.
fn split_to_width(&self, _: &LayoutContext, max_width: Au, starts_line: bool)
fn split_to_width(@self, _: &LayoutContext, max_width: Au, starts_line: bool)
-> SplitBoxResult {
match *self {
GenericRenderBoxClass(*) | ImageRenderBoxClass(*) => CannotSplit(*self),
GenericRenderBoxClass(*) | ImageRenderBoxClass(*) => CannotSplit(self),
UnscannedTextRenderBoxClass(*) => {
fail!(~"WAT: shouldn't be an unscanned text box here.")
}
@@ -351,7 +351,7 @@ pub impl RenderBox {
let new_text_box = @mut text::adapt_textbox_with_range(text_box.base,
text_box.text_data.run,
left_range);
Some(TextRenderBoxClass(new_text_box))
Some(@TextRenderBoxClass(new_text_box))
} else {
None
};
@@ -360,7 +360,7 @@ pub impl RenderBox {
let new_text_box = @mut text::adapt_textbox_with_range(text_box.base,
text_box.text_data.run,
*range);
Some(TextRenderBoxClass(new_text_box))
Some(@TextRenderBoxClass(new_text_box))
};

if pieces_processed_count == 1 || left_box.is_none() {
@@ -549,11 +549,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",
@@ -581,6 +581,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.text_data.run.serialize(),
@@ -601,6 +602,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(),
@@ -620,6 +622,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(),
@@ -643,6 +646,7 @@ pub impl RenderBox {
let image_display_item = ~ImageDisplayItem {
base: BaseDisplayItem {
bounds: absolute_box_bounds,
extra: ExtraDisplayListData::new(self),
},
image: image.clone(),
};
@@ -667,8 +671,8 @@ 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>,
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
@@ -682,6 +686,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(),
};
@@ -693,7 +698,9 @@ pub impl RenderBox {

/// Adds the display items necessary to paint the borders of this render box to the display
/// list if necessary.
fn paint_borders_if_applicable(&self, list: &Cell<DisplayList>, abs_bounds: &Rect<Au>) {
fn paint_borders_if_applicable<E: ExtraDisplayListData>(@self,
list: &Cell<DisplayList<E>>,
abs_bounds: &Rect<Au>) {
if !self.is_element() {
return
}
@@ -733,6 +740,7 @@ pub impl RenderBox {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: bounds,
extra: ExtraDisplayListData::new(self),
},
width: border_width,
color: color,
@@ -104,7 +104,7 @@ impl BoxGenerator {
_: &LayoutContext,
_: AbstractNode<LayoutView>,
_: InlineSpacerSide)
-> Option<RenderBox> {
-> Option<@RenderBox> {
None
}

@@ -129,20 +129,20 @@ impl BoxGenerator {

// if a leaf, make a box.
if node.is_leaf() {
let new_box = builder.make_box(ctx, box_type, node, self.flow);
let new_box = @builder.make_box(ctx, box_type, node, self.flow);
inline.boxes.push(new_box);
} else if self.inline_spacers_needed_for_node(node) {
// else, maybe make a spacer for "left" margin, border, padding
for self.make_inline_spacer_for_node_side(ctx, node, LogicalBefore).each
|spacer: &RenderBox| {
|spacer: &@RenderBox| {
inline.boxes.push(*spacer);
}
}
// TODO: cases for inline-block, etc.
},
BlockFlow(block) => {
debug!("BoxGenerator[f%d]: point b", block.common.id);
let new_box = builder.make_box(ctx, box_type, node, self.flow);
let new_box = @builder.make_box(ctx, box_type, node, self.flow);

debug!("BoxGenerator[f%d]: attaching box[b%d] to block flow (node: %s)",
block.common.id,
@@ -10,6 +10,7 @@ use core::cell::Cell;

use layout::context::LayoutContext;
use layout::flow::FlowContext;
use layout::box::RenderBox;

use geom::point::Point2D;
use geom::rect::Rect;
@@ -19,6 +20,22 @@ use gfx;
use newcss;
use servo_util::tree::TreeNodeRef;

pub trait ExtraDisplayListData {
fn new(box: @RenderBox) -> Self;
}

impl ExtraDisplayListData for () {
fn new(box: @RenderBox) -> () {
()
}
}

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 +47,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,
fn build_display_list<E: ExtraDisplayListData>(&self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
list: &Cell<DisplayList>) {
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,
fn build_display_list_for_child<E: ExtraDisplayListData>(&self,
builder: &DisplayListBuilder,
child_flow: FlowContext,
dirty: &Rect<Au>,
offset: &Point2D<Au>,
list: &Cell<DisplayList>) {
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);
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.