Invert DisplayItem enum variant data nesting, and add some TextRun static new's. Fixes #96.

This commit is contained in:
Brian J. Burg 2012-10-23 10:05:18 -07:00
parent a3c653f046
commit 14388d6b47
5 changed files with 84 additions and 113 deletions

View file

@ -13,91 +13,70 @@ use dvec::DVec;
pub use layout::display_list_builder::DisplayListBuilder;
// TODO: invert this so common data is nested inside each variant as first arg.
struct DisplayItem {
draw: ~fn((&DisplayItem), (&RenderContext)),
struct DisplayItemData {
bounds : Rect<Au>, // TODO: whose coordinate system should this use?
data : DisplayItemData
}
pub enum DisplayItemData {
SolidColorData(u8, u8, u8),
impl DisplayItemData {
static pure fn new(bounds: &Rect<Au>) -> DisplayItemData {
DisplayItemData { bounds: copy *bounds }
}
}
pub enum DisplayItem {
SolidColor(DisplayItemData, u8, u8, u8),
// TODO: need to provide spacing data for text run.
// (i.e, to support rendering of CSS 'word-spacing' and 'letter-spacing')
// TODO: don't copy text runs, ever.
TextData(~SendableTextRun, Range),
ImageData(ARC<~image::base::Image>),
BorderData(Au, u8, u8, u8)
Text(DisplayItemData, ~SendableTextRun, Range),
Image(DisplayItemData, ARC<~image::base::Image>),
Border(DisplayItemData, Au, u8, u8, u8)
}
fn draw_SolidColor(self: &DisplayItem, ctx: &RenderContext) {
match self.data {
SolidColorData(r,g,b) => ctx.draw_solid_color(&self.bounds, r, g, b),
_ => fail
}
}
fn draw_Text(self: &DisplayItem, ctx: &RenderContext) {
match self.data {
TextData(run, range) => {
let new_run = text_run::deserialize(ctx.font_cache, run);
ctx.draw_text(self.bounds, new_run, range)
},
_ => fail
}
}
fn draw_Image(self: &DisplayItem, ctx: &RenderContext) {
match self.data {
ImageData(ref img) => ctx.draw_image(self.bounds, clone_arc(img)),
_ => fail
}
}
fn draw_Border(self: &DisplayItem, ctx: &RenderContext) {
match self.data {
BorderData(width, r, g, b) => ctx.draw_border(&self.bounds, width, r, g, b),
_ => fail
impl DisplayItem {
pure fn d(&self) -> &self/DisplayItemData {
match *self {
SolidColor(ref d, _, _, _) => d,
Text(ref d, _, _) => d,
Image(ref d, _) => d,
Border(ref d, _, _, _, _) => d
}
}
}
pub fn SolidColor(bounds: Rect<Au>, r: u8, g: u8, b: u8) -> DisplayItem {
DisplayItem {
draw: |self, ctx| draw_SolidColor(self, ctx),
bounds: bounds,
data: SolidColorData(r, g, b)
fn draw_into_context(&self, ctx: &RenderContext) {
match *self {
SolidColor(_, r,g,b) => ctx.draw_solid_color(&self.d().bounds, r, g, b),
Text(_, run, range) => {
let new_run = @run.deserialize(ctx.font_cache);
ctx.draw_text(self.d().bounds, new_run, range)
},
Image(_, ref img) => ctx.draw_image(self.d().bounds, clone_arc(img)),
Border(_, width, r, g, b) => ctx.draw_border(&self.d().bounds, width, r, g, b),
}
}
}
pub fn Border(bounds: Rect<Au>, width: Au, r: u8, g: u8, b: u8) -> DisplayItem {
DisplayItem {
draw: |self, ctx| draw_Border(self, ctx),
bounds: bounds,
data: BorderData(width, r, g, b)
static pure fn new_SolidColor(bounds: &Rect<Au>, r: u8, g: u8, b: u8) -> DisplayItem {
SolidColor(DisplayItemData::new(bounds), r, g, b)
}
}
pub fn Text(bounds: Rect<Au>, run: ~SendableTextRun, range: Range) -> DisplayItem {
DisplayItem {
draw: |self, ctx| draw_Text(self, ctx),
bounds: bounds,
data: TextData(move run, move range)
static pure fn new_Border(bounds: &Rect<Au>, width: Au, r: u8, g: u8, b: u8) -> DisplayItem {
Border(DisplayItemData::new(bounds), width, r, g, b)
}
}
// ARC should be cloned into ImageData, but Images are not sendable
pub fn Image(bounds: Rect<Au>, image: ARC<~image::base::Image>) -> DisplayItem {
DisplayItem {
draw: |self, ctx| draw_Image(self, ctx),
bounds: bounds,
data: ImageData(move image)
static pure fn new_Text(bounds: &Rect<Au>, run: ~SendableTextRun, range: Range) -> DisplayItem {
Text(DisplayItemData::new(bounds), move run, range)
}
// ARC should be cloned into ImageData, but Images are not sendable
static pure fn new_Image(bounds: &Rect<Au>, image: ARC<~image::base::Image>) -> DisplayItem {
Image(DisplayItemData::new(bounds), move image)
}
}
pub type DisplayList = DVec<~DisplayItem>;
trait DisplayListMethods {
fn draw(ctx: &RenderContext);
fn draw_into_context(ctx: &RenderContext);
}
impl DisplayList : DisplayListMethods {
@ -106,11 +85,11 @@ impl DisplayList : DisplayListMethods {
self.push(move item);
}
fn draw(ctx: &RenderContext) {
fn draw_into_context(ctx: &RenderContext) {
debug!("beginning display list");
for self.each |item| {
debug!("drawing %?", *item);
item.draw(*item, ctx);
item.draw_into_context(ctx);
}
debug!("ending display list");
}

View file

@ -92,7 +92,7 @@ impl<C: Compositor Send> Renderer<C> {
};
ctx.clear();
render_layer.display_list.draw(&ctx);
render_layer.display_list.draw_into_context(&ctx);
};
#debug("renderer: returning surface");

View file

@ -11,6 +11,7 @@ use core::rand;
use css::styles::SpecifiedStyle;
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent, BdrColor, PosAbsolute};
use dl = gfx::display_list;
use dl::DisplayItem;
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
use dom::node::{Element, Node, NodeData, NodeKind, NodeTree};
use geom::rect::Rect;
@ -417,22 +418,23 @@ impl RenderBox : RenderBoxMethods {
match *self {
UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here.",
TextBox(_,d) => {
list.append_item(~dl::Text(copy abs_box_bounds, text_run::serialize(builder.ctx.font_cache, d.run),
d.range))
list.append_item(~DisplayItem::new_Text(&abs_box_bounds,
~d.run.serialize(builder.ctx.font_cache),
d.range))
},
// TODO: items for background, border, outline
GenericBox(_) => {
},
ImageBox(_,i) => {
match i.get_image() {
Some(image) => list.append_item(~dl::Image(copy abs_box_bounds, arc::clone(&image))),
Some(image) => list.append_item(~DisplayItem::new_Image(&abs_box_bounds, arc::clone(&image))),
/* No image data at all? Okay, add some fallback content instead. */
None => ()
}
}
}
self.add_border_to_list(list, abs_box_bounds);
self.add_border_to_list(list, &abs_box_bounds);
}
fn add_bgcolor_to_list(list: &dl::DisplayList, abs_bounds: &Rect<Au>) {
@ -444,11 +446,11 @@ impl RenderBox : RenderBoxMethods {
Specified(BgColorTransparent) | _ => util::color::rgba(0,0,0,0.0)
};
if !bgcolor.alpha.fuzzy_eq(&0.0) {
list.append_item(~dl::SolidColor(copy *abs_bounds, bgcolor.red, bgcolor.green, bgcolor.blue));
list.append_item(~DisplayItem::new_SolidColor(abs_bounds, bgcolor.red, bgcolor.green, bgcolor.blue));
}
}
fn add_border_to_list(list: &dl::DisplayList, abs_bounds: Rect<Au>) {
fn add_border_to_list(list: &dl::DisplayList, abs_bounds: &Rect<Au>) {
let style = self.d().node.style();
match style.border_width {
Specified(Px(px)) => {
@ -468,7 +470,7 @@ impl RenderBox : RenderBoxMethods {
Specified(BdrColor(color)) => color,
_ => rgb(0, 0, 0) // FIXME
};
list.push(~dl::Border(abs_bounds, border_width, color.red, color.green, color.blue));
list.push(~DisplayItem::new_Border(&abs_bounds, border_width, color.red, color.green, color.blue));
}
_ => () // TODO
}

View file

@ -237,7 +237,7 @@ impl TextRunScanner {
let compression = CompressWhitespaceNewline;
let transformed_text = transform_text(text, compression);
// TODO(Issue #116): use actual font for corresponding DOM node to create text run.
let run = @TextRun(ctx.font_cache.get_test_font(), move transformed_text);
let run = @TextRun::new(ctx.font_cache.get_test_font(), move transformed_text);
debug!("TextRunScanner: pushing single text box in range: %?", self.clump);
let new_box = layout::text::adapt_textbox_with_range(in_boxes[self.clump.begin()].d(), run,
Range(0, run.text.len()));
@ -270,7 +270,7 @@ impl TextRunScanner {
// create the run, then make new boxes with the run and adjusted text indices
// TODO(Issue #116): use actual font for corresponding DOM node to create text run.
let run = @TextRun(ctx.font_cache.get_test_font(), move run_str);
let run = @TextRun::new(ctx.font_cache.get_test_font(), move run_str);
debug!("TextRunScanner: pushing box(es) in range: %?", self.clump);
for self.clump.eachi |i| {
let range = new_ranges[i - self.clump.begin()];

View file

@ -28,37 +28,39 @@ pub struct SendableTextRun {
priv glyphs: GlyphStore,
}
pub fn serialize(_cache: @FontCache, run: &TextRun) -> ~SendableTextRun {
~SendableTextRun {
text: copy run.text,
// TODO: actually serialize a font descriptor thingy
font_descriptor: (),
glyphs: copy run.glyphs,
impl SendableTextRun {
pub fn deserialize(&self, cache: @FontCache) -> TextRun {
TextRun {
text: copy self.text,
// TODO: actually deserialize a font descriptor thingy
font: cache.get_test_font(),
glyphs: copy self.glyphs
}
}
}
pub fn deserialize(cache: @FontCache, run: &SendableTextRun) -> @TextRun {
@TextRun {
text: copy run.text,
// TODO: actually deserialize a font descriptor thingy
font: cache.get_test_font(),
glyphs: copy run.glyphs
impl TextRun {
pub static fn new(font: @Font, text: ~str) -> TextRun {
let glyph_store = GlyphStore(text.len());
let run = TextRun {
text: move text,
font: font,
glyphs: move glyph_store,
};
shape_textrun(&run);
return move run;
}
}
trait TextRunMethods {
pure fn glyphs(&self) -> &self/GlyphStore;
fn iter_indivisible_pieces_for_range(&self, range: Range, f: fn&(Range) -> bool);
// TODO: needs to take box style as argument, or move to TextBox.
// see Gecko's IsTrimmableSpace methods for details.
pure fn range_is_trimmable_whitespace(&self, range: Range) -> bool;
pub pure fn serialize(&self, _cache: @FontCache) -> SendableTextRun {
SendableTextRun {
text: copy self.text,
// TODO: actually serialize a font descriptor thingy
font_descriptor: (),
glyphs: copy self.glyphs,
}
}
fn metrics_for_range(&self, range: Range) -> RunMetrics;
fn min_width_for_range(&self, range: Range) -> Au;
fn iter_natural_lines_for_range(&self, range: Range, f: fn&(Range) -> bool);
}
impl TextRun : TextRunMethods {
pure fn glyphs(&self) -> &self/GlyphStore { &self.glyphs }
pure fn range_is_trimmable_whitespace(&self, range: Range) -> bool {
@ -160,18 +162,6 @@ impl TextRun : TextRunMethods {
}
}
fn TextRun(font: @Font, text: ~str) -> TextRun {
let glyph_store = GlyphStore(text.len());
let run = TextRun {
text: move text,
font: font,
glyphs: move glyph_store,
};
shape_textrun(&run);
return move run;
}
// this test can't run until LayoutContext is removed as an argument
// to min_width_for_range.
/*