diff --git a/src/servo/gfx/renderer.rs b/src/servo/gfx/renderer.rs index 9e819663982..f1651e9029a 100644 --- a/src/servo/gfx/renderer.rs +++ b/src/servo/gfx/renderer.rs @@ -1,6 +1,7 @@ import platform::osmain; import geom::*; import comm::*; +import image::base::image; import dl = layout::display_list; import azure::*; import azure::bindgen::*; @@ -45,6 +46,83 @@ fn renderer(sink: S) -> chan { } } +impl to_float for u8 { + fn to_float() -> float { + (self as float) / 255f + } +} + +fn draw_solid_color(draw_target: AzDrawTargetRef, item: dl::display_item, + r: u8, g: u8, b: u8) { + let bounds = (*item).bounds; + + let red_color = { + r: r.to_float() as AzFloat, + g: g.to_float() as AzFloat, + b: b.to_float() as AzFloat, + a: 1f as AzFloat + }; + let red_pattern = AzCreateColorPattern(ptr::addr_of(red_color)); + + let red_rect = { + x: au_to_px(bounds.origin.x) as AzFloat, + y: au_to_px(bounds.origin.y) as AzFloat, + width: au_to_px(bounds.size.width) as AzFloat, + height: au_to_px(bounds.size.height) as AzFloat + }; + AzDrawTargetFillRect( + draw_target, + ptr::addr_of(red_rect), + unsafe { unsafe::reinterpret_cast(red_pattern) } + ); + + AzReleaseColorPattern(red_pattern); +} + +fn draw_image(draw_target: AzDrawTargetRef, item: dl::display_item, + -image: ~image) { + // FIXME: This is hideously inefficient. + + let bounds = (*item).bounds; + + if (image.depth < 3u) { + #debug("TODO: can't draw images with depth less than 3 yet"); + ret; + } + + let stride = image.width * image.depth; + uint::range(0u, image.height) { + |y| + uint::range(0u, image.width) { + |x| + let color = { + r: image.data[y * stride + x * image.depth].to_float() + as AzFloat, + g: image.data[y * stride + x * image.depth + 1u].to_float() + as AzFloat, + b: image.data[y * stride + x * image.depth + 2u].to_float() + as AzFloat, + a: 1f as AzFloat + }; + let pattern = AzCreateColorPattern(ptr::addr_of(color)); + + let pixel_rect = { + x: (au_to_px(bounds.origin.x) + (x as int)) as AzFloat, + y: (au_to_px(bounds.origin.y) + (y as int)) as AzFloat, + width: 1f as AzFloat, + height: 1f as AzFloat + }; + AzDrawTargetFillRect( + draw_target, + ptr::addr_of(pixel_rect), + unsafe { unsafe::reinterpret_cast(pattern) } + ); + + AzReleaseColorPattern(pattern); + } + } +} + fn draw_display_list( draw_target: AzDrawTargetRef, display_list: dl::display_list @@ -53,36 +131,18 @@ fn draw_display_list( for display_list.each {|item| #debug["drawing %?", item]; - let (r, g, b) = alt check item.item_type { - dl::display_item_solid_color(r, g, b) { (r, g, b) } - }; - let bounds = (*item).bounds; - let to_float = fn@(u: u8) -> float { - (u as float) / 255f - }; - - let red_color = { - r: to_float(r) as AzFloat, - g: to_float(g) as AzFloat, - b: to_float(b) as AzFloat, - a: 1f as AzFloat - }; - let red_pattern = AzCreateColorPattern(ptr::addr_of(red_color)); - - let red_rect = { - x: au_to_px(bounds.origin.x) as AzFloat, - y: au_to_px(bounds.origin.y) as AzFloat, - width: au_to_px(bounds.size.width) as AzFloat, - height: au_to_px(bounds.size.height) as AzFloat - }; - AzDrawTargetFillRect( - draw_target, - ptr::addr_of(red_rect), - unsafe { unsafe::reinterpret_cast(red_pattern) } - ); - - AzReleaseColorPattern(red_pattern); + alt item.item_type { + dl::display_item_solid_color(r, g, b) { + draw_solid_color(draw_target, item, r, g, b); + } + dl::display_item_image(image) { + draw_image(draw_target, item, image); + } + dl::padding(*) { + fail "should never see padding"; + } + } } } diff --git a/src/servo/image/base.rs b/src/servo/image/base.rs index 9de3c84d5e8..7fd380045e9 100644 --- a/src/servo/image/base.rs +++ b/src/servo/image/base.rs @@ -2,3 +2,6 @@ export image; export load; import stb_image::image::{image, load}; +// FIXME: Images must not be copied every frame. Instead we should atomically +// reference count them. + diff --git a/src/servo/layout/display_list.rs b/src/servo/layout/display_list.rs index 81475f2bce7..d159f368079 100644 --- a/src/servo/layout/display_list.rs +++ b/src/servo/layout/display_list.rs @@ -1,7 +1,9 @@ import gfx::geom::*; +import image::base::image; enum item_type { display_item_solid_color(u8, u8, u8), + display_item_image(~image), // FIXME: Shape code does not understand the alignment without this padding(u8, u8, u8, u8) } diff --git a/src/servo/layout/layout.rs b/src/servo/layout/layout.rs index 0f92864c57a..bff3f5be059 100644 --- a/src/servo/layout/layout.rs +++ b/src/servo/layout/layout.rs @@ -61,13 +61,25 @@ fn build_display_list(box: @base::box) -> display_list::display_list { } fn box_to_display_item(box: @base::box) -> dl::display_item { - let r = rand::rng(); - let item = dl::display_item({ - item_type: dl::display_item_solid_color(r.next() as u8, - r.next() as u8, - r.next() as u8), - bounds: box.bounds - }); - #debug("layout: display item: %?", item); + let mut item; + alt box.appearance.background_image { + some(image) { + item = dl::display_item({ + item_type: dl::display_item_image(~copy *image), + bounds: box.bounds + }); + } + none { + let r = rand::rng(); + item = dl::display_item({ + item_type: dl::display_item_solid_color(r.next() as u8, + r.next() as u8, + r.next() as u8), + bounds: box.bounds + }); + } + } + + #debug("layout: display item: %?", item); ret item; }