diff --git a/src/servo/layout/box.rs b/src/servo/layout/box.rs index ab2126661fb..627bd944c15 100644 --- a/src/servo/layout/box.rs +++ b/src/servo/layout/box.rs @@ -16,6 +16,7 @@ use core::rand; use core::task::spawn; use geom::{Point2D, Rect, Size2D}; use gfx::display_list::{DisplayItem, DisplayList}; +use gfx::font::{FontStyle, FontWeight300}; use gfx::geometry::Au; use gfx::image::base::Image; use gfx::image::holder::ImageHolder; @@ -23,9 +24,10 @@ use gfx::text::text_run::TextRun; use gfx::util::range::*; use newcss::color::{Color, rgba, rgb}; use newcss::complete::CompleteStyle; -use newcss::units::{BoxSizing, Length, Px}; +use newcss::units::{BoxSizing, Cursive, Fantasy, Length, Monospace, Px, SansSerif, Serif}; use newcss::values::{CSSBackgroundColorColor, CSSBackgroundColorTransparent, CSSBorderColor}; -use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium, CSSDisplay, CSSPositionAbsolute}; +use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium, CSSDisplay}; +use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily, CSSPositionAbsolute}; use newcss::values::{Specified}; use std::arc::ARC; use std::net::url::Url; @@ -118,8 +120,12 @@ trait RenderBoxMethods { fn get_pref_width(&LayoutContext) -> Au; fn get_used_width() -> (Au, Au); fn get_used_height() -> (Au, Au); - fn build_display_list(@self, &DisplayListBuilder, dirty: &Rect, - offset: &Point2D, dl: &mut DisplayList); + + fn build_display_list(@self, + builder: &DisplayListBuilder, + dirty: &Rect, + offset: &Point2D, + dl: &mut DisplayList); } fn RenderBoxData(node: Node, ctx: @FlowContext, id: int) -> RenderBoxData { @@ -368,6 +374,14 @@ impl RenderBox : RenderBoxMethods { d.node.style() } + fn with_style_of_nearest_element(@self, f: &fn(CompleteStyle) -> R) -> R { + let mut node = self.d().node; + while !node.is_element() { + node = NodeTree.get_parent(&node).get(); + } + f(node.style()) + } + // TODO: to implement stacking contexts correctly, we need to // create a set of display lists, one per each layer of a stacking // context. (CSS 2.1, Section 9.9.1). Each box is passed the list @@ -502,6 +516,36 @@ impl RenderBox : RenderBoxMethods { _ => warn!("ignoring unimplemented border widths") } } + + // Converts this node's ComputedStyle to a font style used in the graphics code. + // + // FIXME: Do we really need two structures here? Perhaps we can just use the structures from + // rust-css in the graphics code. + fn font_style(@self) -> FontStyle { + do self.with_style_of_nearest_element |my_style| { + let font_families = do my_style.font_family().map |family| { + match *family { + CSSFontFamilyFamilyName(ref family_str) => copy *family_str, + CSSFontFamilyGenericFamily(Serif) => ~"serif", + CSSFontFamilyGenericFamily(SansSerif) => ~"sans-serif", + CSSFontFamilyGenericFamily(Cursive) => ~"cursive", + CSSFontFamilyGenericFamily(Fantasy) => ~"fantasy", + CSSFontFamilyGenericFamily(Monospace) => ~"monospace", + } + }; + let font_families = str::connect(font_families, ~", "); + + debug!("(font style) font families: `%s`", font_families); + + FontStyle { + pt_size: 20f, + weight: FontWeight300, + italic: false, + oblique: false, + families: move font_families, + } + } + } } impl RenderBox : BoxedDebugMethods { diff --git a/src/servo/layout/inline.rs b/src/servo/layout/inline.rs index 84a1d109c1d..30a378c5d40 100644 --- a/src/servo/layout/inline.rs +++ b/src/servo/layout/inline.rs @@ -212,7 +212,8 @@ impl TextRunScanner { // recursively borrow or swap the flow's dvec of boxes. When all // boxes are appended, the caller swaps the flow's box list. fn flush_clump_to_list(ctx: &LayoutContext, - in_boxes: &[@RenderBox], out_boxes: &DVec<@RenderBox>) { + in_boxes: &[@RenderBox], + out_boxes: &DVec<@RenderBox>) { assert self.clump.length() > 0; debug!("TextRunScanner: flushing boxes in range=%?", self.clump); @@ -228,8 +229,10 @@ impl TextRunScanner { debug!("TextRunScanner: pushing single non-text box in range: %?", self.clump); out_boxes.push(in_boxes[self.clump.begin()]); }, - (true, true) => { - let text = in_boxes[self.clump.begin()].raw_text(); + (true, true) => { + let old_box = in_boxes[self.clump.begin()]; + let text = old_box.raw_text(); + let font_style = old_box.font_style(); // TODO(Issue #115): use actual CSS 'white-space' property of relevant style. let compression = CompressWhitespaceNewline; let transformed_text = transform_text(text, compression); @@ -238,10 +241,11 @@ impl TextRunScanner { // TODO(Issue #177): text run creation must account for text-renderability by fontgroup fonts. // this is probably achieved by creating fontgroup above, and then letting FontGroup decide // which Font to stick into the TextRun. - let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&gfx::font_context::dummy_style()); + let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style); let run = @fontgroup.create_textrun(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, + let new_box = layout::text::adapt_textbox_with_range(old_box.d(), + run, Range(0, run.text.len())); out_boxes.push(new_box); }, @@ -275,7 +279,9 @@ impl TextRunScanner { // TODO(Issue #177): text run creation must account for text-renderability by fontgroup fonts. // this is probably achieved by creating fontgroup above, and then letting FontGroup decide // which Font to stick into the TextRun. - let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&gfx::font_context::dummy_style()); + // FIXME: Is this right? --pcwalton + let font_style = in_boxes[self.clump.begin()].font_style(); + let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style); let run = @TextRun::new(fontgroup.fonts[0], move run_str); debug!("TextRunScanner: pushing box(es) in range: %?", self.clump); for self.clump.eachi |i| {