From 357905c202d4a43fe624d4dd24c1fe53f25d48a7 Mon Sep 17 00:00:00 2001 From: "Brian J. Burg" Date: Mon, 15 Oct 2012 16:42:37 -0700 Subject: [PATCH] Store text run's font on the TextRun object; write a dummy serialize/deserialize method so textruns can still be copied into/out of display list. --- src/servo/gfx/display_list.rs | 12 ++++++++---- src/servo/gfx/render_task.rs | 3 +-- src/servo/layout/box.rs | 5 +++-- src/servo/layout/inline.rs | 4 ++-- src/servo/text/font.rs | 1 - src/servo/text/shaper.rs | 12 ++++++------ src/servo/text/text_run.rs | 32 ++++++++++++++++++++++++++++++-- 7 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/servo/gfx/display_list.rs b/src/servo/gfx/display_list.rs index 217bf225e81..d3abb70696b 100644 --- a/src/servo/gfx/display_list.rs +++ b/src/servo/gfx/display_list.rs @@ -4,11 +4,12 @@ use gfx::geometry::*; use geom::rect::Rect; use image::base::Image; use render_task::RenderContext; +use servo_text::text_run; use std::arc::ARC; use clone_arc = std::arc::clone; use dvec::DVec; -use text::text_run::TextRun; +use text::text_run::SendableTextRun; pub use layout::display_list_builder::DisplayListBuilder; @@ -24,7 +25,7 @@ pub enum DisplayItemData { // 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(~TextRun, uint, uint), + TextData(~SendableTextRun, uint, uint), ImageData(ARC<~image::base::Image>), } @@ -37,7 +38,10 @@ fn draw_SolidColor(self: &DisplayItem, ctx: &RenderContext) { fn draw_Text(self: &DisplayItem, ctx: &RenderContext) { match self.data { - TextData(~run, offset, len) => draw_text(ctx, self.bounds, &run, offset, len), + TextData(run, offset, len) => { + let new_run = text_run::deserialize(ctx.font_cache, run); + draw_text(ctx, self.bounds, new_run, offset, len) + }, _ => fail } } @@ -57,7 +61,7 @@ pub fn SolidColor(bounds: Rect, r: u8, g: u8, b: u8) -> DisplayItem { } } -pub fn Text(bounds: Rect, run: ~TextRun, offset: uint, length: uint) -> DisplayItem { +pub fn Text(bounds: Rect, run: ~SendableTextRun, offset: uint, length: uint) -> DisplayItem { DisplayItem { draw: |self, ctx| draw_Text(self, ctx), bounds: bounds, diff --git a/src/servo/gfx/render_task.rs b/src/servo/gfx/render_task.rs index caf22f8d4c5..ac8a4901162 100644 --- a/src/servo/gfx/render_task.rs +++ b/src/servo/gfx/render_task.rs @@ -172,8 +172,7 @@ pub fn draw_text(ctx: &RenderContext, bounds: Rect, run: &TextRun, offset: u AzReleaseColorPattern}; use azure::cairo::bindgen::cairo_scaled_font_destroy; - // FIXME: font should be accessible from TextRun - let font = ctx.font_cache.get_test_font(); + let font = run.font; let nfont: AzNativeFont = { mType: AZ_NATIVE_FONT_CAIRO_FONT_FACE, diff --git a/src/servo/layout/box.rs b/src/servo/layout/box.rs index 8cf6cad3add..2a3a4640f91 100644 --- a/src/servo/layout/box.rs +++ b/src/servo/layout/box.rs @@ -20,6 +20,7 @@ use layout::context::LayoutContext; use layout::debug::BoxedDebugMethods; use layout::flow::FlowContext; use layout::text::TextBoxData; +use servo_text::text_run; use servo_text::text_run::TextRun; use std::net::url::Url; use task::spawn; @@ -331,7 +332,7 @@ impl RenderBox : RenderBoxMethods { * `origin` - Total offset from display list root flow to this box's owning flow * `list` - List to which items should be appended */ - fn build_display_list(_builder: &dl::DisplayListBuilder, dirty: &Rect, + fn build_display_list(builder: &dl::DisplayListBuilder, dirty: &Rect, offset: &Point2D, list: &dl::DisplayList) { if !self.d().position.intersects(dirty) { return; @@ -345,7 +346,7 @@ impl RenderBox : RenderBoxMethods { match self { UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here.", TextBox(_,d) => { - list.push(~dl::Text(bounds, ~(copy *d.run), d.offset, d.length)) + list.push(~dl::Text(bounds, text_run::serialize(builder.ctx.font_cache, d.run), d.offset, d.length)) }, // TODO: items for background, border, outline GenericBox(_) => { diff --git a/src/servo/layout/inline.rs b/src/servo/layout/inline.rs index 7d4961347b4..dfa34ea8917 100644 --- a/src/servo/layout/inline.rs +++ b/src/servo/layout/inline.rs @@ -161,7 +161,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(ctx.font_cache.get_test_font(), move transformed_text); let box_guts = TextBoxData(run, 0, run.text.len()); debug!("TextRunScanner: pushing single text box when start=%u,end=%u", self.clump_start, self.clump_end); @@ -214,7 +214,7 @@ impl TextRunScanner { } // 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(ctx.font_cache.get_test_font(), move run_str); let box_guts = TextBoxData(run, 0, run.text.len()); debug!("TextRunScanner: pushing box(es) when start=%u,end=%u", self.clump_start, self.clump_end); diff --git a/src/servo/text/font.rs b/src/servo/text/font.rs index 32e3f5db8d7..da75d040348 100644 --- a/src/servo/text/font.rs +++ b/src/servo/text/font.rs @@ -105,7 +105,6 @@ fn Font(lib: @FontCache, fontbuf: @~[u8], native_font: NativeFont) -> Font { } } -// Most of these metrics are in terms of em. Use em_size to convert to au. struct FontMetrics { underline_size: au, underline_offset: au, diff --git a/src/servo/text/shaper.rs b/src/servo/text/shaper.rs index 78a85294966..089c465c87d 100644 --- a/src/servo/text/shaper.rs +++ b/src/servo/text/shaper.rs @@ -52,12 +52,12 @@ fn fixed_to_rounded_int_hb(f: hb_position_t) -> int { Calculate the layout metrics associated with a some given text when rendered in a specific font. */ -pub fn shape_textrun(font: &Font, run: &TextRun) { +pub fn shape_textrun(run: &TextRun) { debug!("shaping text '%s'", run.text); // TODO: harfbuzz fonts and faces should be cached on the Font object. // TODO: font tables should be stored in Font object and cached by FontCache (Issue #92) - let face_blob: *hb_blob_t = vec::as_imm_buf(*(*font).fontbuf, |buf: *u8, len: uint| { + let face_blob: *hb_blob_t = vec::as_imm_buf(*(run.font).fontbuf, |buf: *u8, len: uint| { hb_blob_create(buf as *c_char, len as c_uint, HB_MEMORY_MODE_READONLY, @@ -79,7 +79,7 @@ pub fn shape_textrun(font: &Font, run: &TextRun) { hb_font_funcs_set_glyph_h_advance_func(funcs, glyph_h_advance_func, null(), null()); unsafe { - let font_data: *c_void = cast::transmute(font); + let font_data: *c_void = core::ptr::addr_of(run.font) as *c_void; hb_font_set_funcs(hb_font, funcs, font_data, null()); }; @@ -140,9 +140,8 @@ extern fn glyph_func(_font: *hb_font_t, glyph: *mut hb_codepoint_t, _user_data: *c_void) -> hb_bool_t unsafe { - let font: *Font = cast::transmute(font_data); + let font: *Font = font_data as *Font; assert font.is_not_null(); - return match (*font).glyph_index(unicode as char) { Some(g) => { *glyph = g as hb_codepoint_t; true }, None => false @@ -153,8 +152,9 @@ extern fn glyph_h_advance_func(_font: *hb_font_t, font_data: *c_void, glyph: hb_codepoint_t, _user_data: *c_void) -> hb_position_t unsafe { - let font: *Font = cast::transmute(font_data); + let font: *Font = font_data as *Font; assert font.is_not_null(); + debug!("font_data = %?", font_data); let advance = (*font).glyph_h_advance(glyph as GlyphIndex); float_to_fixed_hb(advance) diff --git a/src/servo/text/text_run.rs b/src/servo/text/text_run.rs index 31e42477c81..60e2ffc3ed6 100644 --- a/src/servo/text/text_run.rs +++ b/src/servo/text/text_run.rs @@ -15,9 +15,36 @@ use std::arc; pub struct TextRun { text: ~str, + font: @Font, priv glyphs: GlyphStore, } +// This is a hack until TextRuns are normally sendable, or +// we instead use ARC everywhere. +pub struct SendableTextRun { + text: ~str, + font_descriptor: (), + 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, + } +} + +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 + } +} + trait TextRunMethods { pure fn glyphs(&self) -> &self/GlyphStore; pure fn iter_indivisible_pieces_for_range(&self, offset: uint, length: uint, f: fn(uint, uint) -> bool); @@ -128,14 +155,15 @@ impl TextRun : TextRunMethods { } } -fn TextRun(font: &Font, text: ~str) -> TextRun { +fn TextRun(font: @Font, text: ~str) -> TextRun { let glyph_store = GlyphStore(text.len()); let run = TextRun { text: text, + font: font, glyphs: glyph_store, }; - shape_textrun(font, &run); + shape_textrun(&run); return run; }