auto merge of #481 : eric93/servo/underline_tweak, r=metajack

Fix style problems with last PR. Also better propagation of text-decoration.
This commit is contained in:
bors-servo 2013-05-24 16:42:28 -07:00
commit 40cb22d270
10 changed files with 210 additions and 10 deletions

View file

@ -9,7 +9,7 @@ use text::SendableTextRun;
use clone_arc = std::arc::clone;
use geom::Rect;
use geom::Point2D;
use geom::{Point2D, Size2D};
use std::arc::ARC;
use servo_net::image::base::Image;
use servo_util::range::Range;
@ -56,6 +56,16 @@ pub impl<'self> DisplayItem {
let origin = self.d().bounds.origin;
let baseline_origin = Point2D(origin.x, origin.y + font.metrics.ascent);
font.draw_text_into_context(ctx, new_run, range, baseline_origin, color);
if(new_run.underline){
//TODO: Use the font metrics to properly position the underline bar
let width = self.d().bounds.size.width;
let u_size = font.metrics.underline_size;
let u_bounds = Rect(
Point2D(baseline_origin.x, baseline_origin.y),
Size2D(width, u_size)
);
ctx.draw_solid_color(&u_bounds, color);
}
},
&Image(_, ref img) => {
debug!("drawing image at %?", self.d().bounds);

View file

@ -181,11 +181,11 @@ pub impl FontGroup {
self.fonts = ~[];
}
fn create_textrun(&self, text: ~str) -> TextRun {
fn create_textrun(&self, text: ~str, underline: bool) -> 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);
return TextRun::new(self.fonts[0], text, underline);
}
}

View file

@ -12,6 +12,7 @@ use servo_util::range::Range;
pub struct TextRun {
text: ~str,
font: @mut Font,
underline: bool,
glyphs: GlyphStore,
}
@ -19,6 +20,7 @@ pub struct TextRun {
pub struct SendableTextRun {
text: ~str,
font: FontDescriptor,
underline: bool,
priv glyphs: GlyphStore,
}
@ -32,13 +34,14 @@ impl SendableTextRun {
TextRun {
text: copy self.text,
font: font,
underline: self.underline,
glyphs: copy self.glyphs
}
}
}
pub impl<'self> TextRun {
fn new(font: @mut Font, text: ~str) -> TextRun {
fn new(font: @mut Font, text: ~str, underline: bool) -> TextRun {
let mut glyph_store = GlyphStore::new(str::char_len(text));
TextRun::compute_potential_breaks(text, &mut glyph_store);
font.shape_text(text, &mut glyph_store);
@ -46,6 +49,7 @@ pub impl<'self> TextRun {
let run = TextRun {
text: text,
font: font,
underline: underline,
glyphs: glyph_store,
};
return run;
@ -101,6 +105,7 @@ pub impl<'self> TextRun {
SendableTextRun {
text: copy self.text,
font: self.font.get_descriptor(),
underline: self.underline,
glyphs: copy self.glyphs,
}
}

View file

@ -26,7 +26,9 @@ use newcss::units::{Cursive, Em, Fantasy, Length, Monospace, Pt, Px, SansSerif,
use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium};
use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily};
use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal};
use newcss::values::{CSSFontStyleOblique, CSSTextAlign};
use newcss::values::{CSSFontStyleOblique, CSSTextAlign, CSSTextDecoration};
use newcss::values::{CSSTextDecorationNone, CSSFloatNone, CSSPositionStatic};
use newcss::values::{CSSDisplayInlineBlock, CSSDisplayInlineTable};
use servo_net::image::holder::ImageHolder;
use servo_net::local_image_cache::LocalImageCache;
use servo_util::range::*;
@ -256,7 +258,7 @@ pub impl RenderBox {
fn can_merge_with_box(&self, other: RenderBox) -> bool {
match (self, &other) {
(&UnscannedTextRenderBoxClass(*), &UnscannedTextRenderBoxClass(*)) => {
self.font_style() == other.font_style()
self.font_style() == other.font_style() && self.text_decoration() == other.text_decoration()
},
(&TextRenderBoxClass(text_box_a), &TextRenderBoxClass(text_box_b)) => {
managed::ptr_eq(text_box_a.text_data.run, text_box_b.text_data.run)
@ -759,6 +761,46 @@ pub impl RenderBox {
fn text_align(&self) -> CSSTextAlign {
self.nearest_ancestor_element().style().text_align()
}
/// Returns the text decoration of the computed style of the nearest `Element` node
fn text_decoration(&self) -> CSSTextDecoration {
/// Computes the propagated value of text-decoration, as specified in CSS 2.1 § 16.3.1
/// TODO: make sure this works with anonymous box generation.
fn get_propagated_text_decoration(element: AbstractNode) -> CSSTextDecoration {
//Skip over non-element nodes in the DOM
if(!element.is_element()){
return match element.parent_node() {
None => CSSTextDecorationNone,
Some(parent) => get_propagated_text_decoration(parent),
};
}
//FIXME: is the root param on display() important?
let display_in_flow = match element.style().display(false) {
CSSDisplayInlineTable | CSSDisplayInlineBlock => false,
_ => true,
};
let position = element.style().position();
let float = element.style().float();
let in_flow = (position == CSSPositionStatic) && (float == CSSFloatNone) &&
display_in_flow;
let text_decoration = element.style().text_decoration();
if(text_decoration == CSSTextDecorationNone && in_flow){
match element.parent_node() {
None => CSSTextDecorationNone,
Some(parent) => get_propagated_text_decoration(parent),
}
}
else {
text_decoration
}
}
get_propagated_text_decoration(self.nearest_ancestor_element())
}
}
impl DebugMethods for RenderBox {

View file

@ -21,6 +21,8 @@ use gfx::text::text_run::TextRun;
use gfx::text::util::*;
use newcss::values::{CSSTextAlignCenter, CSSTextAlignJustify, CSSTextAlignLeft};
use newcss::values::{CSSTextAlignRight};
use newcss::values::CSSTextDecorationUnderline;
use newcss::values::CSSTextDecoration;
use servo_util::range::Range;
use std::deque::Deque;
@ -243,6 +245,13 @@ impl TextRunScanner {
let inline = &mut *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);
@ -264,6 +273,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());
// TODO(#115): Use the actual CSS `white-space` property of the relevant style.
let compression = CompressWhitespaceNewline;
@ -274,7 +284,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);
let run = @fontgroup.create_textrun(transformed_text, underline);
debug!("TextRunScanner: pushing single text box in range: %?", self.clump);
let new_box = do old_box.with_imm_base |old_box_base| {
@ -316,12 +326,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());
// 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 {
Some(@TextRun::new(fontgroup.fonts[0], run_str))
Some(@TextRun::new(fontgroup.fonts[0], run_str, underline))
} else {
None
};

@ -1 +1 @@
Subproject commit 83ab48961487dc65d8921cc5ea829430e4e46f5e
Subproject commit e3057f02d48bf43856a0c13ad17372647f3b934f

@ -1 +1 @@
Subproject commit 01a90ed6771560ef4a84c42c0419c3e7e3b21abb
Subproject commit 36a651dd83089c01da888ee9b5fff14437d4bcb8

View file

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<title>The Book of Mozilla, 11:9</title>
<style type="text/css">
html {
background: maroon;
color: white;
font-style: italic;
}
#moztext {
margin-top: 15%;
font-size: 1.1em;
font-family: serif;
text-align: center;
line-height: 1.5;
}
#from {
font-size: 1.95em;
font-family: serif;
text-align: right;
}
em {
font-size: 1.3em;
line-height: 0;
font-style: oblique;
}
a {
text-decoration: none;
color: white;
}
</style>
</head>
<body>
<p id="moztext">
Mammon slept. And the <em>beast reborn</em> spread over the earth and its numbers
grew legion. And they proclaimed the times and <em>sacrificed</em> crops unto the
fire, with the <em>cunning of foxes</em>. And they built a new world in their own
image as promised by the <em><a href="http://www.mozilla.org/about/mozilla-manifesto.html">
sacred words</a></em>, and <em><a href="http://wiki.mozilla.org/About:mozilla">spoke
</a></em> of the beast with their children. Mammon awoke, and lo! it was
<em>naught</em> but a follower.
</p>
<p id="from">
from <strong>The Book of Mozilla,</strong> 11:9<br/><small>(10th Edition)</small>
</p>
</body>
</html>

View file

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<title>The Book of Mozilla, 11:9</title>
<style type="text/css">
html {
background: maroon;
color: white;
font-style: italic;
}
#moztext {
margin-top: 15%;
font-size: 1.1em;
font-family: serif;
text-align: center;
line-height: 1.5;
text-decoration: underline;
}
#from {
font-size: 1.95em;
font-family: serif;
text-align: right;
}
em {
font-size: 1.3em;
line-height: 0;
}
a {
text-decoration: none;
color: white;
}
strong{
text-decoration: underline;
}
</style>
</head>
<body>
<p id="moztext">
Mammon slept. And the <em>beast reborn</em> spread over the earth and its numbers
grew legion. And they proclaimed the times and <em>sacrificed</em> crops unto the
fire, with the <em>cunning of foxes</em>. And they built a new world in their own
image as promised by the <em><a href="http://www.mozilla.org/about/mozilla-manifesto.html">
sacred words</a></em>, and <em><a href="http://wiki.mozilla.org/About:mozilla">spoke
</a></em> of the beast with their children. Mammon awoke, and lo! it was
<em>naught</em> but a follower.
</p>
<p id="from">
from <strong>The Book of Mozilla,</strong> 11:9<br/><small>(10th Edition)</small>
</p>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<title>The Book of Mozilla, 11:9</title>
<style type="text/css">
div { text-decoration: underline; }
</style>
</head>
<body>
<div>
<div>Hello</div>
<div>World</div>
</div>
</body>
</html>