1use crate::{
2 color::ColorU,
3 geometry::{
4 rect::RectF,
5 vector::{vec2f, Vector2F},
6 },
7 scene, AfterLayoutContext, Element, Event, EventContext, LayoutContext, PaintContext,
8 SizeConstraint,
9};
10
11pub struct Svg {
12 path: String,
13 color: ColorU,
14}
15
16impl Svg {
17 pub fn new(path: String) -> Self {
18 Self {
19 path,
20 color: ColorU::black(),
21 }
22 }
23
24 pub fn with_color(mut self, color: ColorU) -> Self {
25 self.color = color;
26 self
27 }
28}
29
30impl Element for Svg {
31 type LayoutState = Option<usvg::Tree>;
32 type PaintState = ();
33
34 fn layout(
35 &mut self,
36 constraint: SizeConstraint,
37 ctx: &mut LayoutContext,
38 ) -> (Vector2F, Self::LayoutState) {
39 match ctx.asset_cache.svg(&self.path) {
40 Ok(tree) => {
41 let size = if constraint.max.x().is_infinite() && constraint.max.y().is_infinite() {
42 let rect = from_usvg_rect(tree.svg_node().view_box.rect);
43 rect.size()
44 } else {
45 let max_size = constraint.max;
46 let svg_size = from_usvg_rect(tree.svg_node().view_box.rect).size();
47
48 if max_size.x().is_infinite()
49 || max_size.x() / max_size.y() > svg_size.x() / svg_size.y()
50 {
51 vec2f(svg_size.x() * max_size.y() / svg_size.y(), max_size.y())
52 } else {
53 vec2f(max_size.x(), svg_size.y() * max_size.x() / svg_size.x())
54 }
55 };
56 (size, Some(tree))
57 }
58 Err(error) => {
59 log::error!("{}", error);
60 (constraint.min, None)
61 }
62 }
63 }
64
65 fn after_layout(&mut self, _: Vector2F, _: &mut Self::LayoutState, _: &mut AfterLayoutContext) {
66 }
67
68 fn paint(&mut self, bounds: RectF, svg: &mut Self::LayoutState, ctx: &mut PaintContext) {
69 if let Some(svg) = svg.clone() {
70 ctx.scene.push_icon(scene::Icon {
71 bounds,
72 svg,
73 path: self.path.clone(),
74 color: self.color,
75 });
76 }
77 }
78
79 fn dispatch_event(
80 &mut self,
81 _: &Event,
82 _: RectF,
83 _: &mut Self::LayoutState,
84 _: &mut Self::PaintState,
85 _: &mut EventContext,
86 ) -> bool {
87 false
88 }
89}
90
91fn from_usvg_rect(rect: usvg::Rect) -> RectF {
92 RectF::new(
93 vec2f(rect.x() as f32, rect.y() as f32),
94 vec2f(rect.width() as f32, rect.height() as f32),
95 )
96}