Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial support for the line-height property. #521

Merged
merged 2 commits into from Jun 20, 2013
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Add initial support for the line-height property. Line height is only…

… based on the tallest box in each line and does not factor in the vertical-alignment. Improves whitespace handling by passing the whitespace state between function invocations.
  • Loading branch information
jrfeenst committed Jun 9, 2013
commit 9d7f78ac79b142bcf4c004c93375859ca578d83e
@@ -17,9 +17,9 @@ config.mk
config.stamp
config.tmp
parser.out
src/components/servo/dom/bindings/codegen/*.rs
src/components/servo/dom/bindings/codegen/_cache/
src/components/servo/dom/bindings/codegen/test/*.rs
src/components/servo/dom/bindings/codegen/PrototypeList.h
src/components/servo/dom/bindings/codegen/UnionTypes.h
src/components/servo/dom/bindings/codegen/UnionConversions.h
src/components/script/dom/bindings/codegen/*.rs
src/components/script/dom/bindings/codegen/PrototypeList.h
src/components/script/dom/bindings/codegen/UnionConversions.h
src/components/script/dom/bindings/codegen/UnionTypes.h
src/components/script/dom/bindings/codegen/_cache/
src/components/script/dom/bindings/codegen/test/*.rs
@@ -219,7 +219,7 @@ impl FontHandleMethods for FontHandle {
x_height: geometry::from_pt(0.0), //FIXME
em_size: em_size,
ascent: ascent,
descent: descent,
descent: -descent,
max_advance: max_advance
}
}
@@ -150,13 +150,17 @@ impl FontHandleMethods for FontHandle {
&glyphs[0],
ptr::null(),
1);
Some(advance as FractionalPixel)
// TODO; On mac the font spacing looks a little small. Need to figure out why.
Some(advance * 1.08f as FractionalPixel)
}

fn get_metrics(&self) -> FontMetrics {
let bounding_rect: CGRect = self.ctfont.bounding_box();
let ascent = Au::from_pt(self.ctfont.ascent() as float);
let descent = Au::from_pt(self.ctfont.descent() as float);
let em_size = Au::from_frac_px(self.ctfont.pt_size() as float);

let scale = (self.ctfont.pt_size() as float * 72f / 96f) / (self.ctfont.ascent() as float + self.ctfont.descent() as float);

let metrics = FontMetrics {
underline_size: Au::from_pt(self.ctfont.underline_thickness() as float),
@@ -168,9 +172,9 @@ impl FontHandleMethods for FontHandle {
underline_offset: Au::from_pt(self.ctfont.underline_position() as float),
leading: Au::from_pt(self.ctfont.leading() as float),
x_height: Au::from_pt(self.ctfont.x_height() as float),
em_size: ascent + descent,
ascent: ascent,
descent: descent,
em_size: em_size,
ascent: ascent.scale_by(scale),
descent: descent.scale_by(scale),
max_advance: Au::from_pt(bounding_rect.size.width as float)
};

@@ -28,15 +28,15 @@ impl Eq for CompressionMode {
//
// High level TODOs:
//
// * Issue #113: consider incoming text state (preceding spaces, arabic, etc)
// * Issue #113: consider incoming text state (arabic, etc)
// and propogate outgoing text state (dual of above)
//
// * Issue #114: record skipped and kept chars for mapping original to new text
//
// * Untracked: various edge cases for bidi, CJK, etc.
pub fn transform_text(text: &str, mode: CompressionMode) -> ~str {
pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bool) -> (~str, bool) {
let mut out_str: ~str = ~"";
match mode {
let out_whitespace = match mode {
CompressNone | DiscardNewline => {
for str::each_char(text) |ch: char| {
if is_discardable_char(ch, mode) {
@@ -49,18 +49,14 @@ pub fn transform_text(text: &str, mode: CompressionMode) -> ~str {
str::push_char(&mut out_str, ch);
}
}
text.len() > 0 && is_in_whitespace(text.char_at_reverse(0), mode)
},

CompressWhitespace | CompressWhitespaceNewline => {
let mut in_whitespace: bool = false;
let mut in_whitespace: bool = incoming_whitespace;
for str::each_char(text) |ch: char| {
// TODO: discard newlines between CJK chars
let mut next_in_whitespace: bool = match (ch, mode) {
(' ', _) => true,
('\t', _) => true,
('\n', CompressWhitespaceNewline) => true,
(_, _) => false
};
let mut next_in_whitespace: bool = is_in_whitespace(ch, mode);

if !next_in_whitespace {
if is_always_discardable_char(ch) {
@@ -82,10 +78,20 @@ pub fn transform_text(text: &str, mode: CompressionMode) -> ~str {
// save whitespace context for next char
in_whitespace = next_in_whitespace;
} /* /for str::each_char */
in_whitespace
}
}
};

return (out_str, out_whitespace);

return out_str;
fn is_in_whitespace(ch: char, mode: CompressionMode) -> bool {
match (ch, mode) {
(' ', _) => true,
('\t', _) => true,
('\n', CompressWhitespaceNewline) => true,
(_, _) => false
}
}

fn is_discardable_char(ch: char, mode: CompressionMode) -> bool {
if is_always_discardable_char(ch) {
@@ -143,7 +149,8 @@ fn test_transform_compress_none() {
let mode = CompressNone;

for uint::range(0, test_strs.len()) |i| {
assert!(transform_text(test_strs[i], mode) == test_strs[i]);
(trimmed_str, out) = transform_text(test_strs[i], mode, true);
assert!(trimmed_str == test_strs[i])
}
}

@@ -170,7 +177,8 @@ fn test_transform_discard_newline() {
let mode = DiscardNewline;

for uint::range(0, test_strs.len()) |i| {
assert!(transform_text(test_strs[i], mode) == oracle_strs[i]);
(trimmed_str, out) = transform_text(test_strs[i], mode, true);
assert!(trimmed_str == oracle_strs[i])
}
}

@@ -196,13 +204,42 @@ fn test_transform_compress_whitespace() {
let mode = CompressWhitespace;

for uint::range(0, test_strs.len()) |i| {
assert!(transform_text(test_strs[i], mode) == oracle_strs[i]);
(trimmed_str, out) = transform_text(test_strs[i], mode, true);
assert!(trimmed_str == oracle_strs[i])
}
}

#[test]
fn test_transform_compress_whitespace_newline() {
let test_strs : ~[~str] = ~[~" foo bar",
~"foo bar ",
~"foo\n bar",
~"foo \nbar",
~" foo bar \nbaz",
~"foo bar baz",
~"foobarbaz\n\n"];

let oracle_strs : ~[~str] = ~[~"foo bar",
~"foo bar ",
~"foo bar",
~"foo bar",
~" foo bar baz",
~"foo bar baz",
~"foobarbaz "];

assert!(test_strs.len() == oracle_strs.len());
let mode = CompressWhitespaceNewline;

for uint::range(0, test_strs.len()) |i| {
(trimmed_str, out) = transform_text(test_strs[i], mode, true);
assert!(trimmed_str == oracle_strs[i])
}
}

#[test]
fn test_transform_compress_whitespace_newline() {
let test_strs : ~[~str] = ~[~" foo bar",
~"\nfoo bar",
~"foo bar ",
~"foo\n bar",
~"foo \nbar",
@@ -211,6 +248,7 @@ fn test_transform_compress_whitespace_newline() {
~"foobarbaz\n\n"];

let oracle_strs : ~[~str] = ~[~" foo bar",
~" foo bar",
~"foo bar ",
~"foo bar",
~"foo bar",
@@ -222,6 +260,7 @@ fn test_transform_compress_whitespace_newline() {
let mode = CompressWhitespaceNewline;

for uint::range(0, test_strs.len()) |i| {
assert!(transform_text(test_strs[i], mode) == oracle_strs[i]);
(trimmed_str, out) = transform_text(test_strs[i], mode, false);
assert!(trimmed_str == oracle_strs[i])
}
}
@@ -27,7 +27,7 @@ use newcss::units::{Cursive, Em, Fantasy, Monospace, Pt, Px, SansSerif, Serif};
use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium};
use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily};
use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal};
use newcss::values::{CSSFontStyleOblique, CSSTextAlign, CSSTextDecoration};
use newcss::values::{CSSFontStyleOblique, CSSTextAlign, CSSTextDecoration, CSSLineHeight};
use newcss::values::{CSSTextDecorationNone, CSSFloatNone, CSSPositionStatic};
use newcss::values::{CSSDisplayInlineBlock, CSSDisplayInlineTable};
use script::dom::node::{AbstractNode, LayoutView};
@@ -560,12 +560,10 @@ pub impl RenderBox {
return;
}

// Add the background to the list, if applicable.
self.paint_background_if_applicable(list, &absolute_box_bounds);

match *self {
UnscannedTextRenderBoxClass(*) => fail!(~"Shouldn't see unscanned boxes here."),
TextRenderBoxClass(text_box) => {

let nearest_ancestor_element = self.nearest_ancestor_element();
let color = nearest_ancestor_element.style().color().to_gfx_color();

@@ -623,10 +621,34 @@ pub impl RenderBox {
()
});
},
GenericRenderBoxClass(_) => {

GenericRenderBoxClass(_) => {}
// Add the background to the list, if applicable.
self.paint_background_if_applicable(list, &absolute_box_bounds);

// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
// should have a real `SERVO_DEBUG` system.
debug!("%?", {
do list.with_mut_ref |list| {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: absolute_box_bounds,
},
width: Au::from_px(1),
color: rgb(0, 0, 200).to_gfx_color(),
};
list.append_item(BorderDisplayItemClass(border_display_item))
}

()
});

},
ImageRenderBoxClass(image_box) => {

// Add the background to the list, if applicable.
self.paint_background_if_applicable(list, &absolute_box_bounds);

match image_box.image.get_image() {
Some(image) => {
debug!("(building display list) building image box");
@@ -752,6 +774,9 @@ pub impl RenderBox {
fn font_style(&self) -> FontStyle {
let my_style = self.nearest_ancestor_element().style();

debug!("(font style) start: %?", self.nearest_ancestor_element().type_id());
self.dump();

// FIXME: Too much allocation here.
let font_families = do my_style.font_family().map |family| {
match *family {
@@ -767,12 +792,12 @@ pub impl RenderBox {
debug!("(font style) font families: `%s`", font_families);

let font_size = match my_style.font_size() {
CSSFontSizeLength(Px(length)) |
CSSFontSizeLength(Pt(length)) |
CSSFontSizeLength(Em(length)) => length,
_ => 16.0
CSSFontSizeLength(Px(length)) => length * 72f / 96f,
CSSFontSizeLength(Pt(length)) => length,
CSSFontSizeLength(Em(length)) => length * 16f,
_ => 12f // pt units
};
debug!("(font style) font size: `%f`", font_size);
debug!("(font style) font size: `%fpt`", font_size);

let (italic, oblique) = match my_style.font_style() {
CSSFontStyleNormal => (false, false),
@@ -781,7 +806,7 @@ pub impl RenderBox {
};

FontStyle {
pt_size: font_size,
pt_size: font_size * 96f / 72f, // TODO: scale to pt
weight: FontWeight300,
italic: italic,
oblique: oblique,
@@ -795,6 +820,10 @@ pub impl RenderBox {
self.nearest_ancestor_element().style().text_align()
}

fn line_height(&self) -> CSSLineHeight {
self.nearest_ancestor_element().style().line_height()
}

/// 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
@@ -862,7 +891,7 @@ pub impl RenderBox {
text_box.range.length()))
}
UnscannedTextRenderBoxClass(text_box) => {
fmt!("UnscannedTextRenderBox(%s)", text_box.text)
fmt!("UnscannedTextRenderBox(%?, %s)", text_box.base.node.type_id(), text_box.text)
}
};

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.