diff options
author | bors-servo <release+servo@mozilla.com> | 2013-09-16 06:06:45 -0700 |
---|---|---|
committer | bors-servo <release+servo@mozilla.com> | 2013-09-16 06:06:45 -0700 |
commit | 77a09b2003f000537c4f87f50fb45b6e2fd6eb75 (patch) | |
tree | b49faf3aaa48d7e2c53d603f68335d59505e9703 | |
parent | 849fba27ab7b02407d4c9ae6230a2176bf658725 (diff) | |
parent | d4ab2fc5208216d2b94a915b32fafe3d9d0888be (diff) | |
download | servo-77a09b2003f000537c4f87f50fb45b6e2fd6eb75.tar.gz servo-77a09b2003f000537c4f87f50fb45b6e2fd6eb75.zip |
auto merge of #932 : june0cho/servo/text_deco, r=metajack
Implement 'overline' and 'line-through' in 'text-decoration' property. Add a test case.
-rw-r--r-- | src/components/gfx/display_list.rs | 35 | ||||
-rw-r--r-- | src/components/gfx/font.rs | 8 | ||||
-rw-r--r-- | src/components/gfx/platform/android/font.rs | 18 | ||||
-rw-r--r-- | src/components/gfx/platform/linux/font.rs | 18 | ||||
-rw-r--r-- | src/components/gfx/platform/macos/font.rs | 3 | ||||
-rw-r--r-- | src/components/gfx/text/text_run.rs | 13 | ||||
-rw-r--r-- | src/components/main/layout/text.rs | 16 | ||||
-rw-r--r-- | src/test/html/text_deco_simple.html | 17 |
8 files changed, 98 insertions, 30 deletions
diff --git a/src/components/gfx/display_list.rs b/src/components/gfx/display_list.rs index 7e73a31a2bc..e81bd4a2d1e 100644 --- a/src/components/gfx/display_list.rs +++ b/src/components/gfx/display_list.rs @@ -26,6 +26,8 @@ use servo_net::image::base::Image; use servo_util::range::Range; use extra::arc::Arc; +use newcss::values::{CSSTextDecorationUnderline, CSSTextDecorationOverline, CSSTextDecorationLineThrough}; + /// A list of rendering operations to be performed. pub struct DisplayList<E> { list: ~[DisplayItem<E>] @@ -135,14 +137,31 @@ impl<E> DisplayItem<E> { baseline_origin, text.color); - if new_run.underline { - // TODO(eatkinson): Use the font metrics to properly position the underline - // bar. - let width = text.base.bounds.size.width; - let underline_size = font.metrics.underline_size; - let underline_bounds = Rect(Point2D(baseline_origin.x, baseline_origin.y), - Size2D(width, underline_size)); - render_context.draw_solid_color(&underline_bounds, text.color); + let width = text.base.bounds.size.width; + let underline_size = font.metrics.underline_size; + let underline_offset = font.metrics.underline_offset; + let strikeout_size = font.metrics.strikeout_size; + let strikeout_offset = font.metrics.strikeout_offset; + + match new_run.decoration { + CSSTextDecorationUnderline => { + let underline_y = baseline_origin.y - underline_offset; + let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y), + Size2D(width, underline_size)); + render_context.draw_solid_color(&underline_bounds, text.color); + }, + CSSTextDecorationOverline => { + let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y), + Size2D(width, underline_size)); + render_context.draw_solid_color(&overline_bounds, text.color); + }, + CSSTextDecorationLineThrough => { + let strikeout_y = baseline_origin.y - strikeout_offset; + let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y), + Size2D(width, strikeout_size)); + render_context.draw_solid_color(&strikeout_bounds, text.color); + }, + _ => () } } diff --git a/src/components/gfx/font.rs b/src/components/gfx/font.rs index f79d6ca06f6..9dcf7772334 100644 --- a/src/components/gfx/font.rs +++ b/src/components/gfx/font.rs @@ -28,6 +28,8 @@ use servo_util::time; use servo_util::time::profile; use servo_util::time::ProfilerChan; +use newcss::values::CSSTextDecoration; + // FontHandle encapsulates access to the platform's font API, // e.g. quartz, FreeType. It provides access to metrics and tables // needed by the text shaper as well as access to the underlying font @@ -80,6 +82,8 @@ pub trait FontTableMethods { pub struct FontMetrics { underline_size: Au, underline_offset: Au, + strikeout_size: Au, + strikeout_offset: Au, leading: Au, x_height: Au, em_size: Au, @@ -191,11 +195,11 @@ impl FontGroup { self.fonts = ~[]; } - pub fn create_textrun(&self, text: ~str, underline: bool) -> TextRun { + pub fn create_textrun(&self, text: ~str, decoration: CSSTextDecoration) -> TextRun { assert!(self.fonts.len() > 0); // TODO(Issue #177): Actually fall back through the FontGroup when a font is unsuitable. - return TextRun::new(self.fonts[0], text, underline); + return TextRun::new(self.fonts[0], text, decoration); } } diff --git a/src/components/gfx/platform/android/font.rs b/src/components/gfx/platform/android/font.rs index 2bc62b76a53..b8b08cc9599 100644 --- a/src/components/gfx/platform/android/font.rs +++ b/src/components/gfx/platform/android/font.rs @@ -219,6 +219,7 @@ impl FontHandleMethods for FontHandle { } } + #[fixed_stack_segment] fn get_metrics(&self) -> FontMetrics { /* TODO(Issue #76): complete me */ let face = self.get_face_rec(); @@ -230,11 +231,26 @@ impl FontHandleMethods for FontHandle { let descent = self.font_units_to_au(face.descender as float); let max_advance = self.font_units_to_au(face.max_advance_width as float); + let mut strikeout_size = geometry::from_pt(0.0); + let mut strikeout_offset = geometry::from_pt(0.0); + let mut x_height = geometry::from_pt(0.0); + unsafe { + let os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2) as *TT_OS2; + let valid = os2.is_not_null() && (*os2).version != 0xffff; + if valid { + strikeout_size = self.font_units_to_au((*os2).yStrikeoutSize as float); + strikeout_offset = self.font_units_to_au((*os2).yStrikeoutPosition as float); + x_height = self.font_units_to_au((*os2).sxHeight as float); + } + } + return FontMetrics { underline_size: underline_size, underline_offset: underline_offset, + strikeout_size: strikeout_size, + strikeout_offset: strikeout_offset, leading: geometry::from_pt(0.0), //FIXME - x_height: geometry::from_pt(0.0), //FIXME + x_height: x_height, em_size: em_size, ascent: ascent, descent: -descent, // linux font's seem to use the opposite sign from mac diff --git a/src/components/gfx/platform/linux/font.rs b/src/components/gfx/platform/linux/font.rs index 2bc62b76a53..b8b08cc9599 100644 --- a/src/components/gfx/platform/linux/font.rs +++ b/src/components/gfx/platform/linux/font.rs @@ -219,6 +219,7 @@ impl FontHandleMethods for FontHandle { } } + #[fixed_stack_segment] fn get_metrics(&self) -> FontMetrics { /* TODO(Issue #76): complete me */ let face = self.get_face_rec(); @@ -230,11 +231,26 @@ impl FontHandleMethods for FontHandle { let descent = self.font_units_to_au(face.descender as float); let max_advance = self.font_units_to_au(face.max_advance_width as float); + let mut strikeout_size = geometry::from_pt(0.0); + let mut strikeout_offset = geometry::from_pt(0.0); + let mut x_height = geometry::from_pt(0.0); + unsafe { + let os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2) as *TT_OS2; + let valid = os2.is_not_null() && (*os2).version != 0xffff; + if valid { + strikeout_size = self.font_units_to_au((*os2).yStrikeoutSize as float); + strikeout_offset = self.font_units_to_au((*os2).yStrikeoutPosition as float); + x_height = self.font_units_to_au((*os2).sxHeight as float); + } + } + return FontMetrics { underline_size: underline_size, underline_offset: underline_offset, + strikeout_size: strikeout_size, + strikeout_offset: strikeout_offset, leading: geometry::from_pt(0.0), //FIXME - x_height: geometry::from_pt(0.0), //FIXME + x_height: x_height, em_size: em_size, ascent: ascent, descent: -descent, // linux font's seem to use the opposite sign from mac diff --git a/src/components/gfx/platform/macos/font.rs b/src/components/gfx/platform/macos/font.rs index 793fa9a7589..08978c5d063 100644 --- a/src/components/gfx/platform/macos/font.rs +++ b/src/components/gfx/platform/macos/font.rs @@ -13,6 +13,7 @@ use font::{FontTableTag, FontWeight100, FontWeight200, FontWeight300, FontWeight use font::{FontWeight500, FontWeight600, FontWeight700, FontWeight800, FontWeight900}; use font::{FractionalPixel, SpecifiedFontStyle}; use geometry::{Au, px_to_pt}; +use geometry; use platform::macos::font_context::FontContextHandle; use text::glyph::GlyphIndex; @@ -171,6 +172,8 @@ impl FontHandleMethods for FontHandle { // see also: https://bugs.webkit.org/show_bug.cgi?id=16768 // see also: https://bugreports.qt-project.org/browse/QTBUG-13364 underline_offset: Au::from_pt(self.ctfont.underline_position() as float), + strikeout_size: geometry::from_pt(0.0), // FIXME(Issue #942) + strikeout_offset: geometry::from_pt(0.0), // FIXME(Issue #942) leading: Au::from_pt(self.ctfont.leading() as float), x_height: Au::from_pt(self.ctfont.x_height() as float), em_size: em_size, diff --git a/src/components/gfx/text/text_run.rs b/src/components/gfx/text/text_run.rs index f22b0d94d28..c02bd1bd397 100644 --- a/src/components/gfx/text/text_run.rs +++ b/src/components/gfx/text/text_run.rs @@ -10,12 +10,13 @@ use text::glyph::GlyphStore; use font::{Font, FontDescriptor, RunMetrics}; use servo_util::range::Range; use extra::arc::Arc; +use newcss::values::CSSTextDecoration; /// A text run. pub struct TextRun { text: ~str, font: @mut Font, - underline: bool, + decoration: CSSTextDecoration, glyphs: ~[Arc<GlyphStore>], } @@ -23,7 +24,7 @@ pub struct TextRun { pub struct SendableTextRun { text: ~str, font: FontDescriptor, - underline: bool, + decoration: CSSTextDecoration, priv glyphs: ~[Arc<GlyphStore>], } @@ -37,7 +38,7 @@ impl SendableTextRun { TextRun { text: self.text.clone(), font: font, - underline: self.underline, + decoration: self.decoration, glyphs: self.glyphs.clone(), } } @@ -116,13 +117,13 @@ impl<'self> Iterator<Range> for LineIterator<'self> { } impl<'self> TextRun { - pub fn new(font: @mut Font, text: ~str, underline: bool) -> TextRun { + pub fn new(font: @mut Font, text: ~str, decoration: CSSTextDecoration) -> TextRun { let glyphs = TextRun::break_and_shape(font, text); let run = TextRun { text: text, font: font, - underline: underline, + decoration: decoration, glyphs: glyphs, }; return run; @@ -191,7 +192,7 @@ impl<'self> TextRun { SendableTextRun { text: self.text.clone(), font: self.font.get_descriptor(), - underline: self.underline, + decoration: self.decoration, glyphs: self.glyphs.clone(), } } diff --git a/src/components/main/layout/text.rs b/src/components/main/layout/text.rs index 56651c67067..5dd9306c26d 100644 --- a/src/components/main/layout/text.rs +++ b/src/components/main/layout/text.rs @@ -12,7 +12,6 @@ use layout::box::{RenderBox, RenderBoxBase, TextRenderBox}; use layout::box::{TextRenderBoxClass, UnscannedTextRenderBoxClass}; use layout::context::LayoutContext; use layout::flow::FlowContext; -use newcss::values::{CSSTextDecoration, CSSTextDecorationUnderline}; use servo_util::range::Range; @@ -128,13 +127,6 @@ impl TextRunScanner { let inline = flow.inline(); let in_boxes = &inline.boxes; - fn has_underline(decoration: CSSTextDecoration) -> bool{ - match decoration { - CSSTextDecorationUnderline => true, - _ => false - } - } - assert!(self.clump.length() > 0); debug!("TextRunScanner: flushing boxes in range=%?", self.clump); @@ -158,7 +150,7 @@ impl TextRunScanner { let old_box = in_boxes[self.clump.begin()]; let text = old_box.raw_text(); let font_style = old_box.font_style(); - let underline = has_underline(old_box.text_decoration()); + let decoration = old_box.text_decoration(); // TODO(#115): Use the actual CSS `white-space` property of the relevant style. let compression = CompressWhitespaceNewline; @@ -171,7 +163,7 @@ impl TextRunScanner { // font group fonts. This is probably achieved by creating the font group above // and then letting `FontGroup` decide which `Font` to stick into the text run. let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style); - let run = @fontgroup.create_textrun(transformed_text, underline); + let run = @fontgroup.create_textrun(transformed_text, decoration); debug!("TextRunScanner: pushing single text box in range: %? (%?)", self.clump, text); let new_box = do old_box.with_base |old_box_base| { @@ -220,13 +212,13 @@ impl TextRunScanner { // and then letting `FontGroup` decide which `Font` to stick into the text run. let font_style = in_boxes[self.clump.begin()].font_style(); let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style); - let underline = has_underline(in_boxes[self.clump.begin()].text_decoration()); + let decoration = in_boxes[self.clump.begin()].text_decoration(); // TextRuns contain a cycle which is usually resolved by the teardown // sequence. If no clump takes ownership, however, it will leak. let clump = self.clump; let run = if clump.length() != 0 && run_str.len() > 0 { - Some(@TextRun::new(fontgroup.fonts[0], run_str, underline)) + Some(@TextRun::new(fontgroup.fonts[0], run_str, decoration)) } else { None }; diff --git a/src/test/html/text_deco_simple.html b/src/test/html/text_deco_simple.html new file mode 100644 index 00000000000..73d48199c96 --- /dev/null +++ b/src/test/html/text_deco_simple.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> +<head> +<title></title> +</head> +<body> + <p style="text-decoration:none;"> none </p> + <p style="text-decoration:underline;"> text underline </p> + <p style="text-decoration:overline;"> text underline </p> + <p style="text-decoration:line-through;"> text underline </p> + <p> + <p style="font-size:40px; text-decoration:underline; font-family:Verdana;"> text underline pqrstg </p> + <p style="text-decoration:overline;"> text overline xxxxxxxxXXXXXXX</p> + <p style="font-size:50px; text-decoration:line-through;"> text line-through xxxxxxxxXXXXX</p> + <p style="text-decoration:blink;"> text blink </p> +</body> +</html> |