mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
auto merge of #932 : june0cho/servo/text_deco, r=metajack
Implement 'overline' and 'line-through' in 'text-decoration' property. Add a test case.
This commit is contained in:
commit
77a09b2003
8 changed files with 98 additions and 30 deletions
|
@ -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);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
17
src/test/html/text_deco_simple.html
Normal file
17
src/test/html/text_deco_simple.html
Normal file
|
@ -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>
|
Loading…
Add table
Add a link
Reference in a new issue