diff --git a/components/layout/text.rs b/components/layout/text.rs index 86f3dd164d5..757d7cb18bf 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -22,7 +22,7 @@ use servo_util::smallvec::{SmallVec, SmallVec1}; use std::collections::DList; use std::mem; use style::ComputedValues; -use style::computed_values::{line_height, text_orientation, white_space}; +use style::computed_values::{line_height, text_orientation, text_transform, white_space}; use style::style_structs::Font as FontStyle; use sync::Arc; @@ -104,6 +104,7 @@ impl TextRunScanner { let run = { let fontgroup; let compression; + let text_transform; { let in_fragment = self.clump.front().unwrap(); let font_style = in_fragment.style().get_font_arc(); @@ -111,7 +112,8 @@ impl TextRunScanner { compression = match in_fragment.white_space() { white_space::normal | white_space::nowrap => CompressWhitespaceNewline, white_space::pre => CompressNone, - } + }; + text_transform = in_fragment.style().get_inheritedtext().text_transform; } // First, transform/compress text of all the nodes. @@ -136,6 +138,10 @@ impl TextRunScanner { char_total = char_total + added_chars; } + // Account for `text-transform`. (Confusingly, this is not handled in "text + // transformation" above, but we follow Gecko in the naming.) + self.apply_style_transform_if_necessary(&mut run_text, text_transform); + // Now create the run. // // TextRuns contain a cycle which is usually resolved by the teardown sequence. @@ -176,6 +182,55 @@ impl TextRunScanner { last_whitespace } + + /// Accounts for `text-transform`. + /// + /// FIXME(#4311, pcwalton): Case mapping can change length of the string; case mapping should + /// be language-specific; `full-width`; use graphemes instead of characters. + fn apply_style_transform_if_necessary(&mut self, + string: &mut String, + text_transform: text_transform::T) { + match text_transform { + text_transform::none => {} + text_transform::uppercase => { + let length = string.len(); + let original = mem::replace(string, String::with_capacity(length)); + for character in original.chars() { + string.push(character.to_uppercase()) + } + } + text_transform::lowercase => { + let length = string.len(); + let original = mem::replace(string, String::with_capacity(length)); + for character in original.chars() { + string.push(character.to_lowercase()) + } + } + text_transform::capitalize => { + let length = string.len(); + let original = mem::replace(string, String::with_capacity(length)); + let mut capitalize_next_letter = true; + for character in original.chars() { + // FIXME(#4311, pcwalton): Should be the CSS/Unicode notion of a *typographic + // letter unit*, not an *alphabetic* character: + // + // http://dev.w3.org/csswg/css-text/#typographic-letter-unit + if capitalize_next_letter && character.is_alphabetic() { + string.push(character.to_uppercase()); + capitalize_next_letter = false; + continue + } + + string.push(character); + + // FIXME(#4311, pcwalton): Try UAX29 instead of just whitespace. + if character.is_whitespace() { + capitalize_next_letter = true + } + } + } + } + } } struct NewLinePositions(Vec); diff --git a/components/style/properties/mod.rs.mako b/components/style/properties/mod.rs.mako index bb3e35e8886..5dc02d89a9d 100644 --- a/components/style/properties/mod.rs.mako +++ b/components/style/properties/mod.rs.mako @@ -1185,6 +1185,9 @@ pub mod longhands { ${single_keyword("white-space", "normal pre nowrap")} + // TODO(pcwalton): `full-width` + ${single_keyword("text-transform", "none capitalize uppercase lowercase")} + // CSS 2.1, Section 17 - Tables ${new_style_struct("Table", is_inherited=False)} diff --git a/tests/ref/basic.list b/tests/ref/basic.list index 4170c574013..52a115fa547 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -187,3 +187,7 @@ fragment=top != ../html/acid2.html acid2_ref.html == incremental_float_a.html incremental_float_ref.html == opacity_simple_a.html opacity_simple_ref.html == opacity_stacking_context_a.html opacity_stacking_context_ref.html +== text_transform_none_a.html text_transform_none_ref.html +== text_transform_uppercase_a.html text_transform_uppercase_ref.html +== text_transform_lowercase_a.html text_transform_lowercase_ref.html +== text_transform_capitalize_a.html text_transform_capitalize_ref.html diff --git a/tests/ref/text_transform_capitalize_a.html b/tests/ref/text_transform_capitalize_a.html new file mode 100644 index 00000000000..b4ad9c2ff46 --- /dev/null +++ b/tests/ref/text_transform_capitalize_a.html @@ -0,0 +1,8 @@ + + + + +

ュゥゥゥゥ can do ányThing at ゾムボ.cOm

+ + + diff --git a/tests/ref/text_transform_capitalize_ref.html b/tests/ref/text_transform_capitalize_ref.html new file mode 100644 index 00000000000..a585003eb9a --- /dev/null +++ b/tests/ref/text_transform_capitalize_ref.html @@ -0,0 +1,9 @@ + + + + +

ュゥゥゥゥ Can Do ÁnyThing At ゾムボ.cOm

+ + + + diff --git a/tests/ref/text_transform_lowercase_a.html b/tests/ref/text_transform_lowercase_a.html new file mode 100644 index 00000000000..3e32a24dc6e --- /dev/null +++ b/tests/ref/text_transform_lowercase_a.html @@ -0,0 +1,8 @@ + + + + +

YoU CaN dO ÁnYtHiNg At ゾムボ.cOm

+ + + diff --git a/tests/ref/text_transform_lowercase_ref.html b/tests/ref/text_transform_lowercase_ref.html new file mode 100644 index 00000000000..d8d3bec39f7 --- /dev/null +++ b/tests/ref/text_transform_lowercase_ref.html @@ -0,0 +1,9 @@ + + + + +

you can do ánything at ゾムボ.com

+ + + + diff --git a/tests/ref/text_transform_none_a.html b/tests/ref/text_transform_none_a.html new file mode 100644 index 00000000000..80ec1a26e93 --- /dev/null +++ b/tests/ref/text_transform_none_a.html @@ -0,0 +1,8 @@ + + + + +

You can do anything at ゾムボ.com

+ + + diff --git a/tests/ref/text_transform_none_ref.html b/tests/ref/text_transform_none_ref.html new file mode 100644 index 00000000000..6eaaf7e9832 --- /dev/null +++ b/tests/ref/text_transform_none_ref.html @@ -0,0 +1,9 @@ + + + + +

You can do anything at ゾムボ.com

+ + + + diff --git a/tests/ref/text_transform_uppercase_a.html b/tests/ref/text_transform_uppercase_a.html new file mode 100644 index 00000000000..e70ba05cd6c --- /dev/null +++ b/tests/ref/text_transform_uppercase_a.html @@ -0,0 +1,8 @@ + + + + +

You çan do anything at ゾムボ.com

+ + + diff --git a/tests/ref/text_transform_uppercase_ref.html b/tests/ref/text_transform_uppercase_ref.html new file mode 100644 index 00000000000..97d2f366ea3 --- /dev/null +++ b/tests/ref/text_transform_uppercase_ref.html @@ -0,0 +1,9 @@ + + + + +

YOU ÇAN DO ANYTHING AT ゾムボ.COM

+ + + +