Skip to content

Commit

Permalink
Changed color parsing to return an option instead of defaulting to black
Browse files Browse the repository at this point in the history
  • Loading branch information
mmeyerho committed Jul 19, 2012
1 parent ed99449 commit 830a41a
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 69 deletions.
19 changes: 10 additions & 9 deletions src/servo/parser/css_builder.rs
Expand Up @@ -157,16 +157,17 @@ impl parser_methods of parser_methods for TokenReader {
alt tok {
EndDescription { break; }
Description(prop, val) {
alt prop {
let desc = alt prop {
// TODO: have color parsing return an option instead of a real value
~"background-color" { push(desc_list, BackgroundColor(parse_color(val))); }
~"color" { push(desc_list, TextColor(parse_color(val))); }
~"display" { parse_display_type(val).map(|res| push(desc_list, Display(res))); }
~"font-size" { parse_font_size(val).map(|res| push(desc_list, FontSize(res))); }
~"height" { parse_size(val).map(|res| push(desc_list, Height(res))); }
~"width" { parse_size(val).map(|res| push(desc_list, Width(res))); }
_ { #debug["Recieved unknown style property '%s'", val]; }
}
~"background-color" { parse_color(val).map(|res| BackgroundColor(res)) }
~"color" { parse_color(val).map(|res| TextColor(res)) }
~"display" { parse_display_type(val).map(|res| Display(res)) }
~"font-size" { parse_font_size(val).map(|res| FontSize(res)) }
~"height" { parse_size(val).map(|res| Height(res)) }
~"width" { parse_size(val).map(|res| Width(res)) }
_ { #debug["Recieved unknown style property '%s'", val]; none }
};
desc.map(|res| push(desc_list, res));
}
Eof { ret none; }
StartDescription | Descendant | Child | Sibling | Comma | Element(_) | Attr(_) {
Expand Down
124 changes: 64 additions & 60 deletions src/servo/util/color.rs
Expand Up @@ -66,16 +66,14 @@ impl methods for Color {
mod parsing {
export parse_color;

// TODO, fail by ignoring the rule instead of setting the
// color to black
fn fail_unrecognized(col : ~str) -> Color {
fn fail_unrecognized(col : ~str) -> option<Color> {
#warn["Unrecognized color %s", col];
ret black();
ret none;
}

#[doc="Match an exact color keyword."]
fn parse_by_name(color : ~str) -> Color {
alt color.to_lower() {
fn parse_by_name(color : ~str) -> option<Color> {
let col = alt color.to_lower() {
~"black" { black() }
~"silver" { silver() }
~"gray" { gray() }
Expand All @@ -93,12 +91,14 @@ mod parsing {
~"blue" { blue() }
~"teal" { teal() }
~"aqua" { aqua() }
_ { fail_unrecognized(color) }
}
_ { ret fail_unrecognized(color) }
};

ret some(col);
}

#[doc="Parses a color specification in the form rgb(foo,bar,baz)"]
fn parse_rgb(color : ~str) -> Color {
fn parse_rgb(color : ~str) -> option<Color> {
// Shave off the rgb( and the )
let only_colors = color.substr(4u, color.len() - 5u);

Expand All @@ -108,13 +108,13 @@ mod parsing {

alt (u8::from_str(cols[0]), u8::from_str(cols[1]),
u8::from_str(cols[2])) {
(some(r), some(g), some(b)) { rgb(r, g, b) }
_ { fail_unrecognized(color) }
(some(r), some(g), some(b)) { some(rgb(r, g, b)) }
_ { fail_unrecognized(color) }
}
}

#[doc="Parses a color specification in the form rgba(foo,bar,baz,qux)"]
fn parse_rgba(color : ~str) -> Color {
fn parse_rgba(color : ~str) -> option<Color> {
// Shave off the rgba( and the )
let only_vals = color.substr(5u, color.len() - 6u);

Expand All @@ -124,13 +124,13 @@ mod parsing {

alt (u8::from_str(cols[0]), u8::from_str(cols[1]),
u8::from_str(cols[2]), float::from_str(cols[3])) {
(some(r), some(g), some(b), some(a)) { rgba(r, g, b, a) }
(some(r), some(g), some(b), some(a)) { some(rgba(r, g, b, a)) }
_ { fail_unrecognized(color) }
}
}

#[doc="Parses a color specification in the form hsl(foo,bar,baz)"]
fn parse_hsl(color : ~str) -> Color {
fn parse_hsl(color : ~str) -> option<Color> {
// Shave off the hsl( and the )
let only_vals = color.substr(4u, color.len() - 5u);

Expand All @@ -140,13 +140,13 @@ mod parsing {

alt (float::from_str(vals[0]), float::from_str(vals[1]),
float::from_str(vals[2])) {
(some(h), some(s), some(l)) { hsl(h, s, l) }
_ { fail_unrecognized(color) }
(some(h), some(s), some(l)) { some(hsl(h, s, l)) }
_ { fail_unrecognized(color) }
}
}

#[doc="Parses a color specification in the form hsla(foo,bar,baz,qux)"]
fn parse_hsla(color : ~str) -> Color {
fn parse_hsla(color : ~str) -> option<Color> {
// Shave off the hsla( and the )
let only_vals = color.substr(5u, color.len() - 6u);

Expand All @@ -155,80 +155,84 @@ mod parsing {

alt (float::from_str(vals[0]), float::from_str(vals[1]),
float::from_str(vals[2]), float::from_str(vals[3])) {
(some(h), some(s), some(l), some(a)) { hsla(h, s, l, a) }
(some(h), some(s), some(l), some(a)) { some(hsla(h, s, l, a)) }
_ { fail_unrecognized(color) }
}
}

// Currently colors are supported in rgb(a,b,c) form and also by
// keywords for several common colors.
// TODO: extend this
fn parse_color(color : ~str) -> Color {
fn parse_color(color : ~str) -> option<Color> {
alt color {
c if c.starts_with(~"rgb(") { parse_rgb(c) }
c if c.starts_with(~"rgba(") { parse_rgba(c) }
c if c.starts_with(~"hsl(") { parse_hsl(c) }
c if c.starts_with(~"hsla(") { parse_hsla(c) }
c { parse_by_name(c) }
c { parse_by_name(c) }
}
}
}
#[cfg(test)]
mod test {
import css_colors::*;
import option::unwrap;
import parsing::parse_color;
#[test]
fn test_parse_by_name() {
assert red().eq(parse_color(~"red"));
assert lime().eq(parse_color(~"Lime"));
assert blue().eq(parse_color(~"BLUE"));
assert green().eq(parse_color(~"GreEN"));
assert white().eq(parse_color(~"white"));
assert black().eq(parse_color(~"Black"));
assert gray().eq(parse_color(~"Gray"));
assert silver().eq(parse_color(~"SiLvEr"));
assert maroon().eq(parse_color(~"maroon"));
assert purple().eq(parse_color(~"PURPLE"));
assert fuchsia().eq(parse_color(~"FUCHSIA"));
assert olive().eq(parse_color(~"oLiVe"));
assert yellow().eq(parse_color(~"yellow"));
assert navy().eq(parse_color(~"NAVY"));
assert teal().eq(parse_color(~"Teal"));
assert aqua().eq(parse_color(~"Aqua"));
assert red().eq(unwrap(parse_color(~"red")));
assert lime().eq(unwrap(parse_color(~"Lime")));
assert blue().eq(unwrap(parse_color(~"BLUE")));
assert green().eq(unwrap(parse_color(~"GreEN")));
assert white().eq(unwrap(parse_color(~"white")));
assert black().eq(unwrap(parse_color(~"Black")));
assert gray().eq(unwrap(parse_color(~"Gray")));
assert silver().eq(unwrap(parse_color(~"SiLvEr")));
assert maroon().eq(unwrap(parse_color(~"maroon")));
assert purple().eq(unwrap(parse_color(~"PURPLE")));
assert fuchsia().eq(unwrap(parse_color(~"FUCHSIA")));
assert olive().eq(unwrap(parse_color(~"oLiVe")));
assert yellow().eq(unwrap(parse_color(~"yellow")));
assert navy().eq(unwrap(parse_color(~"NAVY")));
assert teal().eq(unwrap(parse_color(~"Teal")));
assert aqua().eq(unwrap(parse_color(~"Aqua")));
assert none == parse_color(~"foobarbaz");
}

#[test]
fn test_parsing_rgb() {
assert red().eq(parse_color(~"rgb(255,0,0)"));
assert red().eq(parse_color(~"rgba(255,0,0,1.0)"));
assert red().eq(parse_color(~"rgba(255,0,0,1)"));
assert lime().eq(parse_color(~"rgba(0,255,0,1.00)"));
assert rgb(1u8,2u8,3u8).eq(parse_color(~"rgb(1,2,03)"));
assert rgba(15u8,250u8,3u8,0.5).eq(parse_color(~"rgba(15,250,3,.5)"));
assert rgba(15u8,250u8,3u8,0.5).eq(parse_color(~"rgba(15,250,3,0.5)"));
assert red().eq(unwrap(parse_color(~"rgb(255,0,0)")));
assert red().eq(unwrap(parse_color(~"rgba(255,0,0,1.0)")));
assert red().eq(unwrap(parse_color(~"rgba(255,0,0,1)")));
assert lime().eq(unwrap(parse_color(~"rgba(0,255,0,1.00)")));
assert rgb(1u8,2u8,3u8).eq(unwrap(parse_color(~"rgb(1,2,03)")));
assert rgba(15u8,250u8,3u8,0.5).eq(unwrap(parse_color(~"rgba(15,250,3,.5)")));
assert rgba(15u8,250u8,3u8,0.5).eq(unwrap(parse_color(~"rgba(15,250,3,0.5)")));
assert none == parse_color(~"rbga(1,2,3)");
}

#[test]
fn test_parsing_hsl() {
assert red().eq(parse_color(~"hsl(0,1,.5)"));
assert lime().eq(parse_color(~"hsl(120.0,1.0,.5)"));
assert blue().eq(parse_color(~"hsl(240.0,1.0,.5)"));
assert green().eq(parse_color(~"hsl(120.0,1.0,.25)"));
assert white().eq(parse_color(~"hsl(1.0,1.,1.0)"));
assert white().eq(parse_color(~"hsl(129.0,0.3,1.0)"));
assert black().eq(parse_color(~"hsl(231.2,0.75,0.0)"));
assert black().eq(parse_color(~"hsl(11.2,0.0,0.0)"));
assert gray().eq(parse_color(~"hsl(0.0,0.0,0.5)"));
assert maroon().eq(parse_color(~"hsl(0.0,1.0,0.25)"));
assert purple().eq(parse_color(~"hsl(300.0,1.0,0.25)"));
assert fuchsia().eq(parse_color(~"hsl(300,1.0,0.5)"));
assert olive().eq(parse_color(~"hsl(60.,1.0,0.25)"));
assert yellow().eq(parse_color(~"hsl(60.,1.0,0.5)"));
assert navy().eq(parse_color(~"hsl(240.0,1.0,.25)"));
assert teal().eq(parse_color(~"hsl(180.0,1.0,.25)"));
assert aqua().eq(parse_color(~"hsl(180.0,1.0,.5)"));
assert red().eq(unwrap(parse_color(~"hsl(0,1,.5)")));
assert lime().eq(unwrap(parse_color(~"hsl(120.0,1.0,.5)")));
assert blue().eq(unwrap(parse_color(~"hsl(240.0,1.0,.5)")));
assert green().eq(unwrap(parse_color(~"hsl(120.0,1.0,.25)")));
assert white().eq(unwrap(parse_color(~"hsl(1.0,1.,1.0)")));
assert white().eq(unwrap(parse_color(~"hsl(129.0,0.3,1.0)")));
assert black().eq(unwrap(parse_color(~"hsl(231.2,0.75,0.0)")));
assert black().eq(unwrap(parse_color(~"hsl(11.2,0.0,0.0)")));
assert gray().eq(unwrap(parse_color(~"hsl(0.0,0.0,0.5)")));
assert maroon().eq(unwrap(parse_color(~"hsl(0.0,1.0,0.25)")));
assert purple().eq(unwrap(parse_color(~"hsl(300.0,1.0,0.25)")));
assert fuchsia().eq(unwrap(parse_color(~"hsl(300,1.0,0.5)")));
assert olive().eq(unwrap(parse_color(~"hsl(60.,1.0,0.25)")));
assert yellow().eq(unwrap(parse_color(~"hsl(60.,1.0,0.5)")));
assert navy().eq(unwrap(parse_color(~"hsl(240.0,1.0,.25)")));
assert teal().eq(unwrap(parse_color(~"hsl(180.0,1.0,.25)")));
assert aqua().eq(unwrap(parse_color(~"hsl(180.0,1.0,.5)")));
assert none == parse_color(~"hsl(1,2,3,.4)");
}
}

Expand Down

0 comments on commit 830a41a

Please sign in to comment.