diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2014-12-07 22:59:38 -0800 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2014-12-15 17:41:44 -0800 |
commit | 14bafb11bec973cd1362ff38a8e4aa2385c6ff37 (patch) | |
tree | e1dd41c6f1a2829e2be800cb27e7bdd4ee5f0a4f /components/util/str.rs | |
parent | 10f1ed5e311e7092d3e24b58c4960f5e8a511ac0 (diff) | |
download | servo-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.rs | 133 |
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 { |