aboutsummaryrefslogtreecommitdiffstats
path: root/src/servo/css/parser_util.rs
blob: 74d4e395d4a9796496c3a621deffe66a6abab0a1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#[doc = "Helper functions to parse values of specific attributes."]

use css::values::*;
use str::{pop_char, from_chars};
use float::from_str;
use option::map;

export parse_font_size;
export parse_size;
export parse_box_sizing;
export parse_display_type;


fn parse_length(str : &str) -> Option<Length> {
    // TODO: use these once we stop lexing below
    const PTS_PER_INCH: float = 72.0;
    const CM_PER_INCH: float = 2.54;
    const PX_PER_PT: float = 1.0 / 0.75;

    match str {
      s if s.ends_with("in") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * 72.0 * *f)),
      s if s.ends_with("cm") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(*f / 2.54 * 72.0 * 1.0/0.75)),
      s if s.ends_with("mm") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(*f * 0.1 / 2.54 * 72.0 * 1.0/0.75)),
      s if s.ends_with("pt") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * *f)),
      s if s.ends_with("pc") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * 12.0 * *f)),
      s if s.ends_with("px") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(*f)),
      s if s.ends_with("em") => from_str(str.substr(0, str.len() - 2)).map(|f| Em(*f)),
      s if s.ends_with("ex") => from_str(str.substr(0, str.len() - 2)).map(|f| Em(0.5 * *f)),
      _ => None,
    }
}

fn parse_absolute_size(str : &str) -> ParseResult<AbsoluteSize> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"xx-small" => Value(XXSmall),
      ~"x-small" => Value(XSmall),
      ~"small" => Value(Small),
      ~"medium" => Value(Medium),
      ~"large" => Value(Large),
      ~"x-large" => Value(XLarge),
      ~"xx-large" => Value(XXLarge),
      _  => Fail
    }
}

fn parse_relative_size(str: &str) -> ParseResult<RelativeSize> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"smaller" => Value(Smaller),
      ~"larger" => Value(Larger),
      _ => Fail
    }
}

fn parse_font_size(_str: &str) -> ParseResult<CSSFontSize> {
    // TODO: complete me
    Value(LengthSize(Px(14.0)))
}

// For width / height, and anything else with the same attribute values
fn parse_box_sizing(str : &str) -> ParseResult<BoxSizing> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"auto" => Value(BoxAuto),
      ~"inherit" => CSSInherit,
      _ => Fail,
    }
}

fn parse_display_type(str : &str) -> ParseResult<CSSDisplay> {
    // FIXME: Bad copy. Can't match &str
    match str.to_str() {
      ~"inline" => Value(DisplayInline),
      ~"block" => Value(DisplayBlock),
      ~"none" => Value(DisplayNone),
      _ => { #debug["Recieved unknown display value '%s'", str]; Fail }
    }
}

#[cfg(test)]
mod test {
    use css::lexer::spawn_css_lexer_from_string;
    use css::parser::build_stylesheet;
    use css::values::{Stylesheet, Element, FontSize, Width, Height};
    
    // TODO: use helper methods to create test values

    #[test]
    fn should_match_font_sizes() {
        let input = ~"* {font-size:12px; font-size:inherit; font-size:200%; font-size:x-small}";
        let token_port = spawn_css_lexer_from_string(input);
        let _actual_rule = build_stylesheet(token_port);
        let _expected_rule : Stylesheet = ~[~(~[~Element(~"*", ~[])],
                                             ~[FontSize(Specified(LengthSize(Px(12.0)))),
                                               FontSize(Specified(PercentSize(100.0))),
                                               FontSize(Specified(PercentSize(200.0))),
                                               FontSize(Specified(LengthSize(Px(12.0))))])];

        // TODO: fix me once StyleDeclaration is a trait, not an enum
        //assert actual_rule == expected_rule;
    }

    #[test]
    fn should_match_width_height() {
        let input = ~"* {width:20%; height:auto; width:20px; width:3in; height:70px; height:30px}";
        let token_port = spawn_css_lexer_from_string(input);
        let _actual_rule = build_stylesheet(token_port);
        let _expected_rule : Stylesheet = ~[~(~[~Element(~"*", ~[])],
                                             ~[Width(Specified(BoxPercent(20.0))),
                                               Height(Specified(BoxAuto)),
                                               Width(Specified(BoxLength(Px(20.0)))),
                                               Width(Specified(BoxLength(Px(216.0)))),
                                               Height(Specified(BoxLength(Px(70.0)))),
                                               Height(Specified(BoxLength(Px(30.0))))])];

        // TODO: fix me once StyleDeclaration is a trait, not an enum
        //assert actual_rule == expected_rule;
    }
}