1use super::constrain_size_preserving_aspect_ratio;
2use crate::{
3 geometry::{
4 rect::RectF,
5 vector::{vec2f, Vector2F},
6 },
7 json::{json, ToJson},
8 presenter::MeasurementContext,
9 scene, Border, DebugContext, Element, ImageData, LayoutContext, PaintContext, SizeConstraint,
10};
11use serde::Deserialize;
12use std::{ops::Range, sync::Arc};
13
14pub struct Image {
15 data: Arc<ImageData>,
16 style: ImageStyle,
17}
18
19#[derive(Copy, Clone, Default, Deserialize)]
20pub struct ImageStyle {
21 #[serde(default)]
22 pub border: Border,
23 #[serde(default)]
24 pub corner_radius: f32,
25 #[serde(default)]
26 pub height: Option<f32>,
27 #[serde(default)]
28 pub width: Option<f32>,
29 #[serde(default)]
30 pub grayscale: bool,
31}
32
33impl Image {
34 pub fn new(data: Arc<ImageData>) -> Self {
35 Self {
36 data,
37 style: Default::default(),
38 }
39 }
40
41 pub fn with_style(mut self, style: ImageStyle) -> Self {
42 self.style = style;
43 self
44 }
45}
46
47impl Element for Image {
48 type LayoutState = ();
49 type PaintState = ();
50
51 fn layout(
52 &mut self,
53 constraint: SizeConstraint,
54 _: &mut LayoutContext,
55 ) -> (Vector2F, Self::LayoutState) {
56 let desired_size = vec2f(
57 self.style.width.unwrap_or_else(|| constraint.max.x()),
58 self.style.height.unwrap_or_else(|| constraint.max.y()),
59 );
60 let size = constrain_size_preserving_aspect_ratio(
61 constraint.constrain(desired_size),
62 self.data.size().to_f32(),
63 );
64 (size, ())
65 }
66
67 fn paint(
68 &mut self,
69 bounds: RectF,
70 _: RectF,
71 _: &mut Self::LayoutState,
72 cx: &mut PaintContext,
73 ) -> Self::PaintState {
74 cx.scene.push_image(scene::Image {
75 bounds,
76 border: self.style.border,
77 corner_radius: self.style.corner_radius,
78 grayscale: self.style.grayscale,
79 data: self.data.clone(),
80 });
81 }
82
83 fn rect_for_text_range(
84 &self,
85 _: Range<usize>,
86 _: RectF,
87 _: RectF,
88 _: &Self::LayoutState,
89 _: &Self::PaintState,
90 _: &MeasurementContext,
91 ) -> Option<RectF> {
92 None
93 }
94
95 fn debug(
96 &self,
97 bounds: RectF,
98 _: &Self::LayoutState,
99 _: &Self::PaintState,
100 _: &DebugContext,
101 ) -> serde_json::Value {
102 json!({
103 "type": "Image",
104 "bounds": bounds.to_json(),
105 })
106 }
107}