aboutsummaryrefslogtreecommitdiffstats
path: root/components/util/str.rs
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2014-12-07 22:59:38 -0800
committerPatrick Walton <pcwalton@mimiga.net>2014-12-15 17:41:44 -0800
commit14bafb11bec973cd1362ff38a8e4aa2385c6ff37 (patch)
treee1dd41c6f1a2829e2be800cb27e7bdd4ee5f0a4f /components/util/str.rs
parent10f1ed5e311e7092d3e24b58c4960f5e8a511ac0 (diff)
downloadservo-14bafb11bec973cd1362ff38a8e4aa2385c6ff37.tar.gz
servo-14bafb11bec973cd1362ff38a8e4aa2385c6ff37.zip
style: Parse the legacy `bgcolor` attribute per the HTML5 specification.
Additionally, this patch cleans up some miscellaneous formatting issues.
Diffstat (limited to 'components/util/str.rs')
-rw-r--r--components/util/str.rs133
1 files changed, 133 insertions, 0 deletions
diff --git a/components/util/str.rs b/components/util/str.rs
index 0428d0db5b2..ebc494c2642 100644
--- a/components/util/str.rs
+++ b/components/util/str.rs
@@ -4,6 +4,8 @@
use geometry::Au;
+use cssparser::{mod, RGBAColor};
+use std::ascii::AsciiExt;
use std::from_str::FromStr;
use std::iter::Filter;
use std::str::{CharEq, CharSplits};
@@ -184,6 +186,137 @@ pub fn parse_length(mut value: &str) -> LengthOrPercentageOrAuto {
}
}
+/// A "simple color" per HTML5 § 2.4.6.
+#[deriving(Show)]
+pub struct SimpleColor {
+ /// The red component of the color, [0, 255].
+ pub red: u8,
+ /// The green component of the color, [0, 255].
+ pub green: u8,
+ /// The blue component of the color, [0, 255].
+ pub blue: u8,
+}
+
+/// Parses a legacy color per HTML5 § 2.4.6. If unparseable, `Err` is returned.
+pub fn parse_legacy_color(mut input: &str) -> Result<SimpleColor,()> {
+ // Steps 1 and 2.
+ if input.len() == 0 {
+ return Err(())
+ }
+
+ // Step 3.
+ input = input.trim_left_chars(Whitespace).trim_right_chars(Whitespace);
+
+ // Step 4.
+ if input.eq_ignore_ascii_case("transparent") {
+ return Err(())
+ }
+
+ // Step 5.
+ match cssparser::parse_color_keyword(input) {
+ Ok(RGBAColor(rgba)) => {
+ return Ok(SimpleColor {
+ red: (rgba.red * 255.0) as u8,
+ green: (rgba.green * 255.0) as u8,
+ blue: (rgba.blue * 255.0) as u8,
+ })
+ }
+ _ => {}
+ }
+
+ // Step 6.
+ if input.len() == 4 {
+ match (input.char_at(0),
+ hex(input.char_at(1)),
+ hex(input.char_at(2)),
+ hex(input.char_at(3))) {
+ ('#', Ok(r), Ok(g), Ok(b)) => {
+ return Ok(SimpleColor {
+ red: r * 17,
+ green: g * 17,
+ blue: b * 17,
+ })
+ }
+ _ => {}
+ }
+ }
+
+ // Step 7.
+ let mut new_input = String::new();
+ for ch in input.chars() {
+ if ch as u32 > 0xffff {
+ new_input.push_str("00")
+ } else {
+ new_input.push(ch)
+ }
+ }
+ let mut input = new_input.as_slice();
+
+ // Step 8.
+ if input.len() > 128 {
+ input = input.slice_to(128)
+ }
+
+ // Step 9.
+ if input.char_at(0) == '#' {
+ input = input.slice_from(1)
+ }
+
+ // Step 10.
+ let mut new_input = Vec::new();
+ for ch in input.chars() {
+ if hex(ch).is_ok() {
+ new_input.push(ch as u8)
+ } else {
+ new_input.push(b'0')
+ }
+ }
+ let mut input = new_input;
+
+ // Step 11.
+ while input.len() == 0 || (input.len() % 3) != 0 {
+ input.push(b'0')
+ }
+
+ // Step 12.
+ let mut length = input.len() / 3;
+ let (mut red, mut green, mut blue) = (input.slice_to(length),
+ input.slice(length, length * 2),
+ input.slice_from(length * 2));
+
+ // Step 13.
+ if length > 8 {
+ red = red.slice_from(length - 8);
+ green = green.slice_from(length - 8);
+ blue = blue.slice_from(length - 8);
+ length = 8
+ }
+
+ // Step 14.
+ while length > 2 && red[0] == b'0' && green[0] == b'0' && blue[0] == b'0' {
+ red = red.slice_from(1);
+ green = green.slice_from(1);
+ blue = blue.slice_from(1);
+ length -= 1
+ }
+
+ // Steps 15-20.
+ return Ok(SimpleColor {
+ red: (hex(red[0] as char).unwrap() << 4) | hex(red[1] as char).unwrap(),
+ green: (hex(green[0] as char).unwrap() << 4) | hex(green[1] as char).unwrap(),
+ blue: (hex(blue[0] as char).unwrap() << 4) | hex(blue[1] as char).unwrap(),
+ });
+
+ fn hex(ch: char) -> Result<u8,()> {
+ match ch {
+ '0'...'9' => Ok((ch as u8) - b'0'),
+ 'a'...'f' => Ok((ch as u8) - b'a' + 10),
+ 'A'...'F' => Ok((ch as u8) - b'A' + 10),
+ _ => Err(()),
+ }
+ }
+}
+
#[deriving(Clone, Eq, PartialEq, Hash, Show)]
pub struct LowercaseString {