1use crate::{DrawCommand, LayoutNode, NodeContent, Point, Rect, TextAlign};
2
3pub fn paint(node: &LayoutNode, commands: &mut Vec<DrawCommand>) {
4 if let Some(bg) = node.style.background_color {
5 commands.push(DrawCommand::FillRect {
6 rect: node.rect,
7 color: bg,
8 });
9 }
10
11 paint_borders(node, commands);
12
13 if let Some(origin) = node.bullet_origin {
14 commands.push(DrawCommand::DrawText {
15 text: "•".to_string(),
16 origin,
17 color: node.style.color,
18 font_size: node.style.font_size,
19 });
20 }
21
22 match &node.content {
23 NodeContent::Box => {}
24 NodeContent::Hr => {
25 commands.push(DrawCommand::DrawLine {
26 start: Point {
27 x: node.rect.x,
28 y: node.rect.y + node.rect.height / 2.0,
29 },
30 end: Point {
31 x: node.rect.right(),
32 y: node.rect.y + node.rect.height / 2.0,
33 },
34 color: node.style.border.top.color,
35 width: node.style.border.top.width.max(1.0),
36 });
37 }
38 NodeContent::Text(layout) => {
39 for (index, line) in layout.lines.iter().enumerate() {
40 let y = node.rect.y + (index as f32 * layout.line_height);
41 let line_width = line.chars().count() as f32 * layout.font_size * 0.55;
42 let x = match node.style.text_align {
43 TextAlign::Left => node.rect.x,
44 TextAlign::Center => node.rect.x + (node.rect.width - line_width) / 2.0,
45 TextAlign::Right => node.rect.x + node.rect.width - line_width,
46 };
47 commands.push(DrawCommand::DrawText {
48 text: line.clone(),
49 origin: Point { x, y },
50 color: node.style.color,
51 font_size: layout.font_size,
52 });
53 }
54 }
55 NodeContent::Image {
56 width,
57 height,
58 source,
59 } => {
60 let rect = Rect {
61 x: node.rect.x,
62 y: node.rect.y,
63 width: *width,
64 height: *height,
65 };
66 if matches!(source, crate::image::ImageSource::Invalid) {
67 commands.push(DrawCommand::DrawImagePlaceholder { rect });
68 } else {
69 commands.push(DrawCommand::DrawImage {
70 rect,
71 source: source.clone(),
72 });
73 }
74 }
75 }
76
77 if let Some(href) = &node.style.href {
78 commands.push(DrawCommand::Link {
79 rect: node.rect,
80 href: href.clone(),
81 });
82 }
83
84 for child in &node.children {
85 paint(child, commands);
86 }
87}
88
89fn paint_borders(node: &LayoutNode, commands: &mut Vec<DrawCommand>) {
90 let border = node.style.border;
91 if border.top.width > 0.0 {
92 commands.push(DrawCommand::DrawLine {
93 start: Point {
94 x: node.rect.x,
95 y: node.rect.y,
96 },
97 end: Point {
98 x: node.rect.right(),
99 y: node.rect.y,
100 },
101 color: border.top.color,
102 width: border.top.width,
103 });
104 }
105 if border.right.width > 0.0 {
106 commands.push(DrawCommand::DrawLine {
107 start: Point {
108 x: node.rect.right(),
109 y: node.rect.y,
110 },
111 end: Point {
112 x: node.rect.right(),
113 y: node.rect.bottom(),
114 },
115 color: border.right.color,
116 width: border.right.width,
117 });
118 }
119 if border.bottom.width > 0.0 {
120 commands.push(DrawCommand::DrawLine {
121 start: Point {
122 x: node.rect.x,
123 y: node.rect.bottom(),
124 },
125 end: Point {
126 x: node.rect.right(),
127 y: node.rect.bottom(),
128 },
129 color: border.bottom.color,
130 width: border.bottom.width,
131 });
132 }
133 if border.left.width > 0.0 {
134 commands.push(DrawCommand::DrawLine {
135 start: Point {
136 x: node.rect.x,
137 y: node.rect.y,
138 },
139 end: Point {
140 x: node.rect.x,
141 y: node.rect.bottom(),
142 },
143 color: border.left.color,
144 width: border.left.width,
145 });
146 }
147}