aboutsummaryrefslogtreecommitdiffstats
path: root/src/servo/parser/parser_util.rs
blob: 5d7813ca569001105a4762775ab7def4623e92d2 (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
#[doc = "Helper functions to parse values of specific attributes."]

import dom::style::*;
import str::{pop_char, from_chars};
import float::from_str;
import option::map;

export parse_font_size;
export parse_size;
export parse_display_type;

fn parse_unit(str : ~str) -> option<Unit> {
    alt str {
      s if s.ends_with(~"%")  { from_str(str.substr(0, str.len() - 1)).map(|f| Percent(f)) }
      s if s.ends_with(~"in") { from_str(str.substr(0, str.len() - 2)).map(|f| In(f)) }
      s if s.ends_with(~"cm") { from_str(str.substr(0, str.len() - 2)).map(|f| Cm(f)) }
      s if s.ends_with(~"mm") { from_str(str.substr(0, str.len() - 2)).map(|f| Mm(f)) }
      s if s.ends_with(~"pt") { from_str(str.substr(0, str.len() - 2)).map(|f| Pt(f)) }
      s if s.ends_with(~"pc") { from_str(str.substr(0, str.len() - 2)).map(|f| Pc(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| Ex(f)) }
      _ { none }
    }
}

fn parse_font_size(str : ~str) -> option<Unit> {
    // The default pixel size, not sure if this is accurate.
    let default = 16.0;

    alt str {
      ~"xx-small"  { some(Px(0.6*default)) }
      ~"x-small"  { some(Px(0.75*default)) }
      ~"small"  { some(Px(8.0/9.0*default)) }
      ~"medium"  { some(Px(default)) }
      ~"large"  { some(Px(1.2*default)) }
      ~"x-large"  { some(Px(1.5*default)) }
      ~"xx-large"  { some(Px(2.0*default)) }
      ~"smaller"  { some(Em(0.8)) }
      ~"larger"  { some(Em(1.25)) }
      ~"inherit"  { some(Em(1.0)) }
      _  { parse_unit(str) }
    }
}

// For width / height, and anything else with the same attribute values
fn parse_size(str : ~str) -> option<Unit> {
    alt str {
      ~"auto" { some(Auto) }
      ~"inherit" { some(Em(1.0)) }
      _ { parse_unit(str) }
    }
}

fn parse_display_type(str : ~str) -> option<DisplayType> {
    alt str {
      ~"inline"   { some(DisInline) }
      ~"block"    { some(DisBlock) }
      ~"none"     { some(DisNone) }
      _           { #debug["Recieved unknown display value '%s'", str]; none }
    }
}

#[cfg(test)]
mod test {
    import css_lexer::spawn_css_lexer_from_string;
    import css_builder::build_stylesheet;
    
    #[test]
    fn should_match_font_sizes() {
        let input = ~"* {font-size:12pt; font-size:inherit; font-size:2em; 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(Pt(12.0)),
                                               FontSize(Em(1.0)),
                                               FontSize(Em(2.0)),
                                               FontSize(Px(12.0))])];

        assert actual_rule == expected_rule;
    }

    #[test]
    fn should_match_width_height() {
        let input = ~"* {width:20%; height:auto; width:20px; width:3in; height:70mm; height:3cm}";
        let token_port = spawn_css_lexer_from_string(input);
        let actual_rule = build_stylesheet(token_port);
        let expected_rule : Stylesheet = ~[~(~[~Element(~"*", ~[])],
                                             ~[Width(Percent(20.0)),
                                               Height(Auto),
                                               Width(Px(20.0)),
                                               Width(In(3.0)),
                                               Height(Mm(70.0)),
                                               Height(Cm(3.0))])];

        assert actual_rule == expected_rule;
    }
}