aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <release+servo@mozilla.com>2013-09-16 06:06:45 -0700
committerbors-servo <release+servo@mozilla.com>2013-09-16 06:06:45 -0700
commit77a09b2003f000537c4f87f50fb45b6e2fd6eb75 (patch)
treeb49faf3aaa48d7e2c53d603f68335d59505e9703
parent849fba27ab7b02407d4c9ae6230a2176bf658725 (diff)
parentd4ab2fc5208216d2b94a915b32fafe3d9d0888be (diff)
downloadservo-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.rs35
-rw-r--r--src/components/gfx/font.rs8
-rw-r--r--src/components/gfx/platform/android/font.rs18
-rw-r--r--src/components/gfx/platform/linux/font.rs18
-rw-r--r--src/components/gfx/platform/macos/font.rs3
-rw-r--r--src/components/gfx/text/text_run.rs13
-rw-r--r--src/components/main/layout/text.rs16
-rw-r--r--src/test/html/text_deco_simple.html17
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>