mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
auto merge of #4311 : pcwalton/servo/text-transform, r=SimonSapin
The Unicode awareness of `text-transform` is implemented as well as possible given the Rust standard library's Unicode support. In particular, the notion of an alphabetic character is used instead of a letter. Gecko has a subclass of text run to handle text transforms, but I implemented this in a simpler way. r? @SimonSapin
This commit is contained in:
commit
9bf1d1862a
11 changed files with 132 additions and 2 deletions
|
@ -22,7 +22,7 @@ use servo_util::smallvec::{SmallVec, SmallVec1};
|
||||||
use std::collections::DList;
|
use std::collections::DList;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use style::ComputedValues;
|
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 style::style_structs::Font as FontStyle;
|
||||||
use sync::Arc;
|
use sync::Arc;
|
||||||
|
|
||||||
|
@ -104,6 +104,7 @@ impl TextRunScanner {
|
||||||
let run = {
|
let run = {
|
||||||
let fontgroup;
|
let fontgroup;
|
||||||
let compression;
|
let compression;
|
||||||
|
let text_transform;
|
||||||
{
|
{
|
||||||
let in_fragment = self.clump.front().unwrap();
|
let in_fragment = self.clump.front().unwrap();
|
||||||
let font_style = in_fragment.style().get_font_arc();
|
let font_style = in_fragment.style().get_font_arc();
|
||||||
|
@ -111,7 +112,8 @@ impl TextRunScanner {
|
||||||
compression = match in_fragment.white_space() {
|
compression = match in_fragment.white_space() {
|
||||||
white_space::normal | white_space::nowrap => CompressWhitespaceNewline,
|
white_space::normal | white_space::nowrap => CompressWhitespaceNewline,
|
||||||
white_space::pre => CompressNone,
|
white_space::pre => CompressNone,
|
||||||
}
|
};
|
||||||
|
text_transform = in_fragment.style().get_inheritedtext().text_transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, transform/compress text of all the nodes.
|
// First, transform/compress text of all the nodes.
|
||||||
|
@ -136,6 +138,10 @@ impl TextRunScanner {
|
||||||
char_total = char_total + added_chars;
|
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.
|
// Now create the run.
|
||||||
//
|
//
|
||||||
// TextRuns contain a cycle which is usually resolved by the teardown sequence.
|
// TextRuns contain a cycle which is usually resolved by the teardown sequence.
|
||||||
|
@ -176,6 +182,55 @@ impl TextRunScanner {
|
||||||
|
|
||||||
last_whitespace
|
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<CharIndex>);
|
struct NewLinePositions(Vec<CharIndex>);
|
||||||
|
|
|
@ -1185,6 +1185,9 @@ pub mod longhands {
|
||||||
|
|
||||||
${single_keyword("white-space", "normal pre nowrap")}
|
${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
|
// CSS 2.1, Section 17 - Tables
|
||||||
${new_style_struct("Table", is_inherited=False)}
|
${new_style_struct("Table", is_inherited=False)}
|
||||||
|
|
||||||
|
|
|
@ -187,3 +187,7 @@ fragment=top != ../html/acid2.html acid2_ref.html
|
||||||
== incremental_float_a.html incremental_float_ref.html
|
== incremental_float_a.html incremental_float_ref.html
|
||||||
== opacity_simple_a.html opacity_simple_ref.html
|
== opacity_simple_a.html opacity_simple_ref.html
|
||||||
== opacity_stacking_context_a.html opacity_stacking_context_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
|
||||||
|
|
8
tests/ref/text_transform_capitalize_a.html
Normal file
8
tests/ref/text_transform_capitalize_a.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Tests that `text-transform: capitalize` works. -->
|
||||||
|
<body>
|
||||||
|
<h1 style='text-transform: capitalize; font-family: Hiragino Maru Gothic Pro'>ュゥゥゥゥ can do ányThing at ゾムボ.cOm</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
9
tests/ref/text_transform_capitalize_ref.html
Normal file
9
tests/ref/text_transform_capitalize_ref.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Tests that `text-transform: capitalize` works. -->
|
||||||
|
<body>
|
||||||
|
<h1 style='font-family: Hiragino Maru Gothic Pro'>ュゥゥゥゥ Can Do ÁnyThing At ゾムボ.cOm</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
8
tests/ref/text_transform_lowercase_a.html
Normal file
8
tests/ref/text_transform_lowercase_a.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Tests that `text-transform: lowercase` works. -->
|
||||||
|
<body>
|
||||||
|
<h1 style='text-transform: lowercase; font-family: Hiragino Maru Gothic Pro'>YoU CaN dO ÁnYtHiNg At ゾムボ.cOm</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
9
tests/ref/text_transform_lowercase_ref.html
Normal file
9
tests/ref/text_transform_lowercase_ref.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Tests that `text-transform: lowercase` works. -->
|
||||||
|
<body>
|
||||||
|
<h1 style='font-family: Hiragino Maru Gothic Pro'>you can do ánything at ゾムボ.com</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
8
tests/ref/text_transform_none_a.html
Normal file
8
tests/ref/text_transform_none_a.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Tests that `text-transform: none` works. -->
|
||||||
|
<body>
|
||||||
|
<h1 style='text-transform: none; font-family: Hiragino Maru Gothic Pro'>You can do anything at ゾムボ.com</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
9
tests/ref/text_transform_none_ref.html
Normal file
9
tests/ref/text_transform_none_ref.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Tests that `text-transform: none` works. -->
|
||||||
|
<body>
|
||||||
|
<h1 style='font-family: Hiragino Maru Gothic Pro'>You can do anything at ゾムボ.com</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
8
tests/ref/text_transform_uppercase_a.html
Normal file
8
tests/ref/text_transform_uppercase_a.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Tests that `text-transform: uppercase` works. -->
|
||||||
|
<body>
|
||||||
|
<h1 style='text-transform: uppercase; font-family: Hiragino Maru Gothic Pro'>You çan do anything at ゾムボ.com</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
9
tests/ref/text_transform_uppercase_ref.html
Normal file
9
tests/ref/text_transform_uppercase_ref.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- Tests that `text-transform: uppercase` works. -->
|
||||||
|
<body>
|
||||||
|
<h1 style='font-family: Hiragino Maru Gothic Pro'>YOU ÇAN DO ANYTHING AT ゾムボ.COM</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue