aboutsummaryrefslogtreecommitdiffstats
path: root/components/util/str.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/util/str.rs')
-rw-r--r--components/util/str.rs137
1 files changed, 135 insertions, 2 deletions
diff --git a/components/util/str.rs b/components/util/str.rs
index 28aedee4f30..7b2cfdf5107 100644
--- a/components/util/str.rs
+++ b/components/util/str.rs
@@ -4,6 +4,8 @@
use geometry::Au;
+use cssparser::{mod, RGBA, RGBAColor};
+use std::ascii::AsciiExt;
use std::from_str::FromStr;
use std::iter::Filter;
use std::str::{CharEq, CharSplits};
@@ -61,7 +63,8 @@ pub static HTML_SPACE_CHARACTERS: StaticCharVec = &[
'\u000d',
];
-pub fn split_html_space_chars<'a>(s: &'a str) -> Filter<'a, &'a str, CharSplits<'a, StaticCharVec>> {
+pub fn split_html_space_chars<'a>(s: &'a str)
+ -> Filter<'a, &'a str, CharSplits<'a, StaticCharVec>> {
s.split(HTML_SPACE_CHARACTERS).filter(|&split| !split.is_empty())
}
@@ -76,7 +79,6 @@ fn do_parse_integer<T: Iterator<char>>(input: T) -> Option<i64> {
}
}
-
let mut input = input.skip_while(|c| {
HTML_SPACE_CHARACTERS.iter().any(|s| s == c)
}).peekable();
@@ -184,6 +186,137 @@ pub fn parse_length(mut value: &str) -> LengthOrPercentageOrAuto {
}
}
+/// Parses a legacy color per HTML5 § 2.4.6. If unparseable, `Err` is returned.
+pub fn parse_legacy_color(mut input: &str) -> Result<RGBA,()> {
+ // 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(rgba),
+ _ => {}
+ }
+
+ // Step 6.
+ if input.len() == 4 {
+ match (input.as_bytes()[0],
+ hex(input.as_bytes()[1] as char),
+ hex(input.as_bytes()[2] as char),
+ hex(input.as_bytes()[3] as char)) {
+ (b'#', Ok(r), Ok(g), Ok(b)) => {
+ return Ok(RGBA {
+ red: (r as f32) * 17.0 / 255.0,
+ green: (g as f32) * 17.0 / 255.0,
+ blue: (b as f32) * 17.0 / 255.0,
+ alpha: 1.0,
+ })
+ }
+ _ => {}
+ }
+ }
+
+ // 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.
+ for (char_count, (index, _)) in input.char_indices().enumerate() {
+ if char_count == 128 {
+ input = input.slice_to(index);
+ break
+ }
+ }
+
+ // 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(RGBA {
+ red: hex_string(red).unwrap() as f32 / 255.0,
+ green: hex_string(green).unwrap() as f32 / 255.0,
+ blue: hex_string(blue).unwrap() as f32 / 255.0,
+ alpha: 1.0,
+ });
+
+ 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(()),
+ }
+ }
+
+ fn hex_string(string: &[u8]) -> Result<u8,()> {
+ match string.len() {
+ 0 => Err(()),
+ 1 => hex(string[0] as char),
+ _ => {
+ let upper = try!(hex(string[0] as char));
+ let lower = try!(hex(string[1] as char));
+ Ok((upper << 4) | lower)
+ }
+ }
+ }
+}
+
#[deriving(Clone, Eq, PartialEq, Hash, Show)]
pub struct LowercaseString {