From 0c8886f6f61781cdbe388f9a3922ab17bef53041 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 18 Oct 2012 00:29:56 -0700 Subject: [PATCH] Extract RenderContext from render_task --- src/servo/gfx/compositor.rs | 13 +- src/servo/gfx/display_list.rs | 11 +- src/servo/gfx/png_compositor.rs | 2 +- src/servo/gfx/render_context.rs | 231 +++++++++++++++++++++++++++++++ src/servo/gfx/render_layers.rs | 2 +- src/servo/gfx/render_task.rs | 235 +------------------------------- src/servo/platform/osmain.rs | 3 +- src/servo/servo.rc | 1 + 8 files changed, 254 insertions(+), 244 deletions(-) create mode 100644 src/servo/gfx/render_context.rs diff --git a/src/servo/gfx/compositor.rs b/src/servo/gfx/compositor.rs index 8a5f541e92e..9d1be507303 100644 --- a/src/servo/gfx/compositor.rs +++ b/src/servo/gfx/compositor.rs @@ -1,5 +1,16 @@ use dom::event::Event; -use gfx::render_task::LayerBuffer; +use azure::cairo_hl::ImageSurface; +use azure::azure_hl::{DrawTarget}; +use geom::size::Size2D; + +struct LayerBuffer { + // TODO: We should not be coupled to Cairo this tightly. Instead we should pull the buffer out + // of the draw target with the Azure API. + cairo_surface: ImageSurface, + + draw_target: DrawTarget, + size: Size2D +} /** The interface used to by the renderer to aquire draw targets for diff --git a/src/servo/gfx/display_list.rs b/src/servo/gfx/display_list.rs index aff3b30e1fc..ceb83d38198 100644 --- a/src/servo/gfx/display_list.rs +++ b/src/servo/gfx/display_list.rs @@ -1,9 +1,8 @@ use azure::azure_hl::DrawTarget; -use gfx::render_task::{draw_solid_color, draw_image, draw_text, draw_border}; use gfx::geometry::*; use geom::rect::Rect; use image::base::Image; -use render_task::RenderContext; +use render_context::RenderContext; use servo_text::text_run; use std::arc::ARC; @@ -32,7 +31,7 @@ pub enum DisplayItemData { fn draw_SolidColor(self: &DisplayItem, ctx: &RenderContext) { match self.data { - SolidColorData(r,g,b) => draw_solid_color(ctx, &self.bounds, r, g, b), + SolidColorData(r,g,b) => ctx.draw_solid_color(&self.bounds, r, g, b), _ => fail } } @@ -41,7 +40,7 @@ fn draw_Text(self: &DisplayItem, ctx: &RenderContext) { match self.data { TextData(run, offset, len) => { let new_run = text_run::deserialize(ctx.font_cache, run); - draw_text(ctx, self.bounds, new_run, offset, len) + ctx.draw_text(self.bounds, new_run, offset, len) }, _ => fail } @@ -49,14 +48,14 @@ fn draw_Text(self: &DisplayItem, ctx: &RenderContext) { fn draw_Image(self: &DisplayItem, ctx: &RenderContext) { match self.data { - ImageData(ref img) => draw_image(ctx, self.bounds, clone_arc(img)), + 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) => draw_border(ctx, &self.bounds, width, r, g, b), + BorderData(width, r, g, b) => ctx.draw_border(&self.bounds, width, r, g, b), _ => fail } } diff --git a/src/servo/gfx/png_compositor.rs b/src/servo/gfx/png_compositor.rs index 8b70978965a..d3f177efc69 100644 --- a/src/servo/gfx/png_compositor.rs +++ b/src/servo/gfx/png_compositor.rs @@ -26,7 +26,7 @@ use dvec::DVec; use display_list::DisplayList; use std::cell::Cell; use core::io::BytesWriter; -use gfx::render_task::LayerBuffer; +use gfx::compositor::LayerBuffer; use geom::size::Size2D; use gfx::render_layers::RenderLayer; diff --git a/src/servo/gfx/render_context.rs b/src/servo/gfx/render_context.rs new file mode 100644 index 00000000000..aa936dca34f --- /dev/null +++ b/src/servo/gfx/render_context.rs @@ -0,0 +1,231 @@ +use mod au = geometry; + +use compositor::LayerBuffer; +use text::font::Font; +use text::text_run::TextRun; +use text::font_cache::FontCache; +use image::base::Image; +use au = au::au; + +use core::libc::types::common::c99::uint16_t; +use core::ptr::to_unsafe_ptr; +use core::dvec::DVec; +use std::arc::ARC; +use geom::size::Size2D; +use geom::point::Point2D; +use geom::rect::Rect; +use azure::bindgen::AzDrawTargetFillGlyphs; +use azure::cairo::{cairo_font_face_t, cairo_scaled_font_t}; +use azure::cairo_hl::ImageSurface; +use azure::{AzDrawOptions, AzFloat, AzGlyph, AzGlyphBuffer}; +use azure::azure_hl::{AsAzureRect, B8G8R8A8, Color, ColorPattern, DrawOptions, DrawSurfaceOptions, StrokeOptions}; +use azure::azure_hl::{DrawTarget, Linear}; + +struct RenderContext { + canvas: &LayerBuffer, + font_cache: @FontCache, +} + +impl RenderContext { + pub fn draw_solid_color(&self, bounds: &Rect, r: u8, g: u8, b: u8) { + let color = Color(r.to_float() as AzFloat, + g.to_float() as AzFloat, + b.to_float() as AzFloat, + 1f as AzFloat); + + self.canvas.draw_target.fill_rect(&bounds.to_azure_rect(), &ColorPattern(color)); + } + + pub fn draw_border(&self, bounds: &Rect, width: au, r: u8, g: u8, b: u8) { + let rect = bounds.to_azure_rect(); + let color = Color(r.to_float() as AzFloat, + g.to_float() as AzFloat, + b.to_float() as AzFloat, + 1f as AzFloat); + let pattern = ColorPattern(color); + let stroke_fields = 2; // CAP_SQUARE + let stroke_opts = StrokeOptions(au::to_px(width) as AzFloat, 10 as AzFloat, stroke_fields); + let draw_opts = DrawOptions(1 as AzFloat, 0 as uint16_t); + + self.canvas.draw_target.stroke_rect(&rect, &pattern, &stroke_opts, &draw_opts); + } + + pub fn draw_image(&self, bounds: Rect, image: ARC<~Image>) { + let image = std::arc::get(&image); + let size = Size2D(image.width as i32, image.height as i32); + let stride = image.width * 4; + + let draw_target_ref = &self.canvas.draw_target; + let azure_surface = draw_target_ref.create_source_surface_from_data(image.data, size, + stride as i32, B8G8R8A8); + let source_rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat), + Size2D(image.width as AzFloat, image.height as AzFloat)); + let dest_rect = bounds.to_azure_rect(); + let draw_surface_options = DrawSurfaceOptions(Linear, true); + let draw_options = DrawOptions(1.0f as AzFloat, 0); + draw_target_ref.draw_surface(azure_surface, dest_rect, source_rect, draw_surface_options, + draw_options); + } + + pub fn draw_text(&self, bounds: Rect, run: &TextRun, offset: uint, length: uint) { + use ptr::{null}; + use vec::raw::to_ptr; + use libc::types::common::c99::{uint16_t, uint32_t}; + use geom::point::Point2D; + use text::font_cache::FontCache; + use text::font::Font; + use azure::{AzNativeFont, AzFloat, AZ_NATIVE_FONT_CAIRO_FONT_FACE}; + use azure::bindgen::{AzCreateScaledFontWithCairo, + AzReleaseScaledFont, + AzCreateColorPattern, + AzReleaseColorPattern}; + use azure::cairo::bindgen::cairo_scaled_font_destroy; + + let font = run.font; + + let nfont: AzNativeFont = { + mType: AZ_NATIVE_FONT_CAIRO_FONT_FACE, + mFont: null() + }; + + let cfont = get_cairo_font(font); + let azfont = AzCreateScaledFontWithCairo(to_unsafe_ptr(&nfont), 1f as AzFloat, cfont); + assert azfont.is_not_null(); + cairo_scaled_font_destroy(cfont); + + let color = { + r: 0f as AzFloat, + g: 0f as AzFloat, + b: 0f as AzFloat, + a: 1f as AzFloat + }; + let pattern = AzCreateColorPattern(to_unsafe_ptr(&color)); + assert pattern.is_not_null(); + + let options: AzDrawOptions = { + mAlpha: 1f as AzFloat, + fields: 0 as uint16_t + }; + + let mut origin = Point2D(bounds.origin.x, bounds.origin.y.add(&bounds.size.height)); + let azglyphs = DVec(); + azglyphs.reserve(length); + + do run.glyphs.iter_glyphs_for_range(offset, length) |_i, glyph| { + let glyph_advance = glyph.advance(); + let glyph_offset = glyph.offset().get_default(au::zero_point()); + + let azglyph: AzGlyph = { + mIndex: glyph.index() as uint32_t, + mPosition: { + x: au::to_px(origin.x + glyph_offset.x) as AzFloat, + y: au::to_px(origin.y + glyph_offset.y) as AzFloat + } + }; + origin = Point2D(origin.x + glyph_advance, origin.y); + azglyphs.push(move azglyph) + }; + + let azglyph_buf_len = azglyphs.len(); + let azglyph_buf = dvec::unwrap(move azglyphs); + let glyphbuf: AzGlyphBuffer = unsafe {{ + mGlyphs: to_ptr(azglyph_buf), + mNumGlyphs: azglyph_buf_len as uint32_t + }}; + + // TODO: this call needs to move into azure_hl.rs + AzDrawTargetFillGlyphs(self.canvas.draw_target.azure_draw_target, azfont, + to_unsafe_ptr(&glyphbuf), pattern, to_unsafe_ptr(&options), null()); + + AzReleaseColorPattern(pattern); + AzReleaseScaledFont(azfont); + } + + fn clear(&self) { + let pattern = ColorPattern(Color(1f as AzFloat, 1f as AzFloat, 1f as AzFloat, 1f as AzFloat)); + let rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat), + Size2D(self.canvas.size.width as AzFloat, self.canvas.size.height as AzFloat)); + self.canvas.draw_target.fill_rect(&rect, &pattern); + } +} + +trait to_float { + fn to_float() -> float; +} + +impl u8 : to_float { + fn to_float() -> float { + (self as float) / 255f + } +} + +trait ToAzureRect { + fn to_azure_rect() -> Rect; +} + +impl Rect : ToAzureRect { + fn to_azure_rect() -> Rect { + Rect(Point2D(au::to_px(self.origin.x) as AzFloat, au::to_px(self.origin.y) as AzFloat), + Size2D(au::to_px(self.size.width) as AzFloat, au::to_px(self.size.height) as AzFloat)) + } +} + +#[cfg(target_os = "linux")] +fn get_cairo_face(font: &Font) -> *cairo_font_face_t { + + use libc::c_int; + use azure::cairo_ft::bindgen::{cairo_ft_font_face_create_for_ft_face}; + + let ftface = font.native_font.face; + let cface = cairo_ft_font_face_create_for_ft_face(ftface, 0 as c_int); + // FIXME: error handling + return cface; +} + +#[cfg(target_os = "macos")] +fn get_cairo_face(font: &Font) -> *cairo_font_face_t { + use azure::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont; + + let cgfont = font.native_font.cgfont; + let face = cairo_quartz_font_face_create_for_cgfont(cgfont); + // FIXME: error handling + return face; +} + +fn get_cairo_font(font: &Font) -> *cairo_scaled_font_t { + + use libc::c_double; + use azure::cairo; + use cairo::cairo_matrix_t; + use cairo::bindgen::{cairo_matrix_init_identity, + cairo_matrix_scale, + cairo_font_options_create, + cairo_scaled_font_create, + cairo_font_options_destroy, + cairo_font_face_destroy}; + + // FIXME: error handling + + let face = get_cairo_face(font); + + let idmatrix: cairo_matrix_t = { + xx: 0 as c_double, + yx: 0 as c_double, + xy: 0 as c_double, + yy: 0 as c_double, + x0: 0 as c_double, + y0: 0 as c_double + }; + cairo_matrix_init_identity(to_unsafe_ptr(&idmatrix)); + + let fontmatrix = idmatrix; + cairo_matrix_scale(to_unsafe_ptr(&fontmatrix), 20f as c_double, 20f as c_double); + let options = cairo_font_options_create(); + let cfont = cairo_scaled_font_create(face, to_unsafe_ptr(&fontmatrix), + to_unsafe_ptr(&idmatrix), options); + cairo_font_options_destroy(options); + cairo_font_face_destroy(face); + + return cfont; +} + diff --git a/src/servo/gfx/render_layers.rs b/src/servo/gfx/render_layers.rs index e39dafa2e2c..b381b66eb03 100644 --- a/src/servo/gfx/render_layers.rs +++ b/src/servo/gfx/render_layers.rs @@ -1,5 +1,5 @@ use gfx::display_list::DisplayList; -use gfx::render_task::LayerBuffer; +use gfx::compositor::LayerBuffer; use azure::azure_hl::DrawTarget; use azure::cairo::CAIRO_FORMAT_RGB24; diff --git a/src/servo/gfx/render_task.rs b/src/servo/gfx/render_task.rs index 06a0f41f33d..cb03de53ea4 100644 --- a/src/servo/gfx/render_task.rs +++ b/src/servo/gfx/render_task.rs @@ -1,33 +1,17 @@ -use mod azure::azure_hl; - use au = gfx::geometry; use au::au; -use azure::bindgen::AzDrawTargetFillGlyphs; -use azure::cairo::{cairo_font_face_t, cairo_scaled_font_t}; -use azure::cairo_hl::ImageSurface; -use azure::{AzDrawOptions, AzFloat, AzGlyph, AzGlyphBuffer}; -use azure_hl::{AsAzureRect, B8G8R8A8, Color, ColorPattern, DrawOptions, DrawSurfaceOptions, StrokeOptions}; -use azure_hl::{DrawTarget, Linear}; use comm::*; use compositor::Compositor; -use core::dvec::DVec; use dl = display_list; -use geom::point::Point2D; -use geom::rect::Rect; -use geom::size::Size2D; use mod gfx::render_layers; use gfx::render_layers::RenderLayer; -use image::base::Image; use libc::size_t; use libc::types::common::c99::uint16_t; use pipes::{Port, Chan}; use platform::osmain; -use ptr::to_unsafe_ptr; -use std::arc::ARC; use std::cell::Cell; -use text::text_run::TextRun; -use text::font::Font; use text::font_cache::FontCache; +use render_context::RenderContext; pub type Renderer = comm::Chan; @@ -36,20 +20,6 @@ pub enum Msg { ExitMsg(pipes::Chan<()>) } -struct LayerBuffer { - // TODO: We should not be coupled to Cairo this tightly. Instead we should pull the buffer out - // of the draw target with the Azure API. - cairo_surface: ImageSurface, - - draw_target: DrawTarget, - size: Size2D -} - -struct RenderContext { - canvas: &LayerBuffer, - font_cache: @FontCache, -} - pub type RenderTask = comm::Chan; pub fn RenderTask(compositor: C) -> RenderTask { @@ -95,7 +65,7 @@ pub fn RenderTask(compositor: C) -> RenderTask { font_cache: font_cache }; - clear(&ctx); + ctx.clear(); render_layer.display_list.draw(&ctx); }; @@ -111,204 +81,3 @@ pub fn RenderTask(compositor: C) -> RenderTask { } } } - -trait to_float { - fn to_float() -> float; -} - -impl u8 : to_float { - fn to_float() -> float { - (self as float) / 255f - } -} - -trait ToAzureRect { - fn to_azure_rect() -> Rect; -} - -impl Rect : ToAzureRect { - fn to_azure_rect() -> Rect { - Rect(Point2D(au::to_px(self.origin.x) as AzFloat, au::to_px(self.origin.y) as AzFloat), - Size2D(au::to_px(self.size.width) as AzFloat, au::to_px(self.size.height) as AzFloat)) - } -} - -pub fn draw_solid_color(ctx: &RenderContext, bounds: &Rect, r: u8, g: u8, b: u8) { - let color = Color(r.to_float() as AzFloat, - g.to_float() as AzFloat, - b.to_float() as AzFloat, - 1f as AzFloat); - - ctx.canvas.draw_target.fill_rect(&bounds.to_azure_rect(), &ColorPattern(color)); -} - -pub fn draw_border(ctx: &RenderContext, bounds: &Rect, width: au, r: u8, g: u8, b: u8) { - let rect = bounds.to_azure_rect(); - let color = Color(r.to_float() as AzFloat, - g.to_float() as AzFloat, - b.to_float() as AzFloat, - 1f as AzFloat); - let pattern = ColorPattern(color); - let stroke_fields = 2; // CAP_SQUARE - let stroke_opts = StrokeOptions(au::to_px(width) as AzFloat, 10 as AzFloat, stroke_fields); - let draw_opts = DrawOptions(1 as AzFloat, 0 as uint16_t); - - ctx.canvas.draw_target.stroke_rect(&rect, &pattern, &stroke_opts, &draw_opts); -} - -pub fn draw_image(ctx: &RenderContext, bounds: Rect, image: ARC<~Image>) { - let image = std::arc::get(&image); - let size = Size2D(image.width as i32, image.height as i32); - let stride = image.width * 4; - - let draw_target_ref = &ctx.canvas.draw_target; - let azure_surface = draw_target_ref.create_source_surface_from_data(image.data, size, - stride as i32, B8G8R8A8); - let source_rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat), - Size2D(image.width as AzFloat, image.height as AzFloat)); - let dest_rect = bounds.to_azure_rect(); - let draw_surface_options = DrawSurfaceOptions(Linear, true); - let draw_options = DrawOptions(1.0f as AzFloat, 0); - draw_target_ref.draw_surface(azure_surface, dest_rect, source_rect, draw_surface_options, - draw_options); -} - -pub fn draw_text(ctx: &RenderContext, bounds: Rect, run: &TextRun, offset: uint, length: uint) { - use ptr::{null}; - use vec::raw::to_ptr; - use libc::types::common::c99::{uint16_t, uint32_t}; - use geom::point::Point2D; - use text::font_cache::FontCache; - use text::font::Font; - use azure::{AzNativeFont, AzFloat, AZ_NATIVE_FONT_CAIRO_FONT_FACE}; - use azure::bindgen::{AzCreateScaledFontWithCairo, - AzReleaseScaledFont, - AzCreateColorPattern, - AzReleaseColorPattern}; - use azure::cairo::bindgen::cairo_scaled_font_destroy; - - let font = run.font; - - let nfont: AzNativeFont = { - mType: AZ_NATIVE_FONT_CAIRO_FONT_FACE, - mFont: null() - }; - - let cfont = get_cairo_font(font); - let azfont = AzCreateScaledFontWithCairo(to_unsafe_ptr(&nfont), 1f as AzFloat, cfont); - assert azfont.is_not_null(); - cairo_scaled_font_destroy(cfont); - - let color = { - r: 0f as AzFloat, - g: 0f as AzFloat, - b: 0f as AzFloat, - a: 1f as AzFloat - }; - let pattern = AzCreateColorPattern(to_unsafe_ptr(&color)); - assert pattern.is_not_null(); - - let options: AzDrawOptions = { - mAlpha: 1f as AzFloat, - fields: 0 as uint16_t - }; - - let mut origin = Point2D(bounds.origin.x, bounds.origin.y.add(&bounds.size.height)); - let azglyphs = DVec(); - azglyphs.reserve(length); - - do run.glyphs.iter_glyphs_for_range(offset, length) |_i, glyph| { - let glyph_advance = glyph.advance(); - let glyph_offset = glyph.offset().get_default(au::zero_point()); - - let azglyph: AzGlyph = { - mIndex: glyph.index() as uint32_t, - mPosition: { - x: au::to_px(origin.x + glyph_offset.x) as AzFloat, - y: au::to_px(origin.y + glyph_offset.y) as AzFloat - } - }; - origin = Point2D(origin.x + glyph_advance, origin.y); - azglyphs.push(move azglyph) - }; - - let azglyph_buf_len = azglyphs.len(); - let azglyph_buf = dvec::unwrap(move azglyphs); - let glyphbuf: AzGlyphBuffer = unsafe {{ - mGlyphs: to_ptr(azglyph_buf), - mNumGlyphs: azglyph_buf_len as uint32_t - }}; - - // TODO: this call needs to move into azure_hl.rs - AzDrawTargetFillGlyphs(ctx.canvas.draw_target.azure_draw_target, azfont, - to_unsafe_ptr(&glyphbuf), pattern, to_unsafe_ptr(&options), null()); - - AzReleaseColorPattern(pattern); - AzReleaseScaledFont(azfont); -} - -#[cfg(target_os = "linux")] -fn get_cairo_face(font: &Font) -> *cairo_font_face_t { - - use libc::c_int; - use azure::cairo_ft::bindgen::{cairo_ft_font_face_create_for_ft_face}; - - let ftface = font.native_font.face; - let cface = cairo_ft_font_face_create_for_ft_face(ftface, 0 as c_int); - // FIXME: error handling - return cface; -} - -#[cfg(target_os = "macos")] -fn get_cairo_face(font: &Font) -> *cairo_font_face_t { - use azure::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont; - - let cgfont = font.native_font.cgfont; - let face = cairo_quartz_font_face_create_for_cgfont(cgfont); - // FIXME: error handling - return face; -} - -fn get_cairo_font(font: &Font) -> *cairo_scaled_font_t { - - use libc::c_double; - use azure::cairo; - use cairo::cairo_matrix_t; - use cairo::bindgen::{cairo_matrix_init_identity, - cairo_matrix_scale, - cairo_font_options_create, - cairo_scaled_font_create, - cairo_font_options_destroy, - cairo_font_face_destroy}; - - // FIXME: error handling - - let face = get_cairo_face(font); - - let idmatrix: cairo_matrix_t = { - xx: 0 as c_double, - yx: 0 as c_double, - xy: 0 as c_double, - yy: 0 as c_double, - x0: 0 as c_double, - y0: 0 as c_double - }; - cairo_matrix_init_identity(to_unsafe_ptr(&idmatrix)); - - let fontmatrix = idmatrix; - cairo_matrix_scale(to_unsafe_ptr(&fontmatrix), 20f as c_double, 20f as c_double); - let options = cairo_font_options_create(); - let cfont = cairo_scaled_font_create(face, to_unsafe_ptr(&fontmatrix), - to_unsafe_ptr(&idmatrix), options); - cairo_font_options_destroy(options); - cairo_font_face_destroy(face); - - return cfont; -} - -fn clear(ctx: &RenderContext) { - let pattern = ColorPattern(Color(1f as AzFloat, 1f as AzFloat, 1f as AzFloat, 1f as AzFloat)); - let rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat), - Size2D(ctx.canvas.size.width as AzFloat, ctx.canvas.size.height as AzFloat)); - ctx.canvas.draw_target.fill_rect(&rect, &pattern); -} diff --git a/src/servo/platform/osmain.rs b/src/servo/platform/osmain.rs index 7c0ee701bae..0fa917fc7d5 100644 --- a/src/servo/platform/osmain.rs +++ b/src/servo/platform/osmain.rs @@ -4,8 +4,7 @@ use azure::cairo; use azure::cairo_hl::ImageSurface; use dvec::DVec; use azure::cairo::cairo_surface_t; -use gfx::compositor::Compositor; -use gfx::render_task::LayerBuffer; +use gfx::compositor::{LayerBuffer, Compositor}; use dom::event::{Event, ResizeEvent}; use layers::ImageLayer; use geom::size::Size2D; diff --git a/src/servo/servo.rc b/src/servo/servo.rc index 30be7d471d8..87504256dbf 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -78,6 +78,7 @@ pub mod gfx { pub mod png_compositor; pub mod display_list; pub mod render_layers; + priv mod render_context; } pub mod image {