1
use crate::css::{Color, Value};
2
use crate::layout::{AnonymousBlock, BlockNode, InlineNode, LayoutBox, Rect};
3

            
4
#[derive(Debug)]
5
pub enum DisplayCommand {
6
    SolidColor(Color, Rect),
7
}
8

            
9
pub type DisplayList = Vec<DisplayCommand>;
10

            
11
pub fn build_display_list(layout_root: &LayoutBox) -> DisplayList {
12
    let mut list = Vec::new();
13
    render_layout_box(&mut list, layout_root);
14
    list
15
}
16

            
17
fn render_layout_box(list: &mut DisplayList, layout_box: &LayoutBox) {
18
    render_background(list, layout_box);
19
    render_borders(list, layout_box);
20
    for child in &layout_box.children {
21
        render_layout_box(list, child);
22
    }
23
}
24

            
25
fn render_background(list: &mut DisplayList, layout_box: &LayoutBox) {
26
    if let Some(color) = get_color(layout_box, "background") {
27
        list.push(DisplayCommand::SolidColor(
28
            color,
29
            layout_box.dimensions.border_box(),
30
        ));
31
    }
32
}
33

            
34
fn render_borders(list: &mut DisplayList, layout_box: &LayoutBox) {
35
    let color = match get_color(layout_box, "border-color") {
36
        Some(color) => color,
37
        _ => return,
38
    };
39

            
40
    let d = &layout_box.dimensions;
41
    let border_box = d.border_box();
42

            
43
    // Left border
44
    list.push(DisplayCommand::SolidColor(
45
        color.clone(),
46
        Rect {
47
            x: border_box.x,
48
            y: border_box.y,
49
            width: d.border.left,
50
            height: border_box.height,
51
        },
52
    ));
53

            
54
    // Right border
55
    list.push(DisplayCommand::SolidColor(
56
        color.clone(),
57
        Rect {
58
            x: border_box.x + border_box.width - d.border.right,
59
            y: border_box.y,
60
            width: d.border.right,
61
            height: border_box.height,
62
        },
63
    ));
64

            
65
    // Top border
66
    list.push(DisplayCommand::SolidColor(
67
        color.clone(),
68
        Rect {
69
            x: border_box.x,
70
            y: border_box.y,
71
            width: border_box.width,
72
            height: d.border.top,
73
        },
74
    ));
75

            
76
    // Bottom border
77
    list.push(DisplayCommand::SolidColor(
78
        color,
79
        Rect {
80
            x: border_box.x,
81
            y: border_box.y + border_box.height - d.border.bottom,
82
            width: border_box.width,
83
            height: d.border.bottom,
84
        },
85
    ));
86
}
87

            
88
/// Return the specified color for CSS property `name`, or None if no color was specified.
89
fn get_color(layout_box: &LayoutBox, name: &str) -> Option<Color> {
90
    match layout_box.box_type {
91
        BlockNode(style) | InlineNode(style) => match style.value(name) {
92
            Some(Value::ColorValue(color)) => Some(color),
93
            _ => None,
94
        },
95
        AnonymousBlock => None,
96
    }
97
}