1use crate::geom::{Bounds, Point as GPoint};
2use crate::gfx::{DrawingContext, TextStyle};
3use crate::view::Align;
4use core::ops::Add;
5use embedded_graphics::Drawable;
6use embedded_graphics::draw_target::DrawTargetExt;
7use embedded_graphics::geometry::{Point as EPoint, Size as ESize};
8use embedded_graphics::mono_font::MonoTextStyleBuilder;
9use embedded_graphics::mono_font::ascii::FONT_6X10;
10use embedded_graphics::pixelcolor::Rgb565;
11use embedded_graphics::prelude::DrawTarget;
12use embedded_graphics::primitives::{Line, Primitive, PrimitiveStyle, Rectangle};
13use embedded_graphics::text::{Alignment, Baseline, Text, TextStyleBuilder};
14
15pub struct EmbeddedDrawingContext<'a, T>
16where
17 T: DrawTarget<Color = Rgb565>,
18{
19 pub display: &'a mut T,
20 pub clip: Bounds,
21 offset: EPoint,
22}
23
24impl<'a, T> EmbeddedDrawingContext<'a, T>
25where
26 T: DrawTarget<Color = Rgb565>,
27{
28 pub fn new(display: &'a mut T) -> Self {
29 EmbeddedDrawingContext {
30 display,
31 clip: Bounds::new_empty(),
32 offset: EPoint::new(0, 0),
33 }
34 }
35}
36
37fn bounds_to_rect(bounds: &Bounds) -> Rectangle {
38 Rectangle::new(
39 EPoint::new(bounds.position.x, bounds.position.y),
40 ESize::new(bounds.size.w as u32, bounds.size.h as u32),
41 )
42}
43
44impl<'a, T> DrawingContext for EmbeddedDrawingContext<'a, T>
45where
46 T: DrawTarget<Color = Rgb565>,
47{
48 fn fill_rect(&mut self, bounds: &Bounds, color: &Rgb565) {
49 let mut display = self.display.clipped(&bounds_to_rect(&self.clip));
50 let mut display = display.translated(self.offset);
51 bounds_to_rect(bounds)
52 .into_styled(PrimitiveStyle::with_fill(*color))
53 .draw(&mut display);
54 }
55 fn stroke_rect(&mut self, bounds: &Bounds, color: &Rgb565) {
56 let mut display = self.display.clipped(&bounds_to_rect(&self.clip));
57 let mut display = display.translated(self.offset);
58 bounds_to_rect(bounds)
59 .into_styled(PrimitiveStyle::with_stroke(*color, 1))
60 .draw(&mut display);
61 }
62 fn line(&mut self, start: &GPoint, end: &GPoint, color: &Rgb565) {
63 let mut display = self.display.clipped(&bounds_to_rect(&self.clip));
64 let mut display = display.translated(self.offset);
65 let line = Line::new(EPoint::new(start.x, start.y), EPoint::new(end.x, end.y));
66 line.into_styled(PrimitiveStyle::with_stroke(*color, 1))
67 .draw(&mut display);
68 }
69 fn fill_text(&mut self, bounds: &Bounds, text: &str, text_style: &TextStyle) {
70 let mut display = self.display.clipped(&bounds_to_rect(&self.clip));
71 let mut display = display.translated(self.offset);
72
73 let mut text_builder = MonoTextStyleBuilder::new()
74 .font(text_style.font)
75 .text_color(*text_style.color);
76 if text_style.underline {
77 text_builder = text_builder.underline();
78 }
79 let style = text_builder.build(); let mut pt = EPoint::new(bounds.position.x, bounds.position.y);
81 pt.y += bounds.size.h / 2;
82 pt.y += (FONT_6X10.baseline as i32) / 2;
83
84 let w = (FONT_6X10.character_size.width as i32) * (text.len() as i32);
85
86 match text_style.halign {
87 Align::Start => {
88 pt.x += 5;
89 }
90 Align::Center => {
91 pt.x += (bounds.size.w - w) / 2;
92 }
93 Align::End => {}
94 }
95
96 Text::new(text, pt, style).draw(&mut display);
97 }
98 fn text(&mut self, text: &str, position: &GPoint, style: &TextStyle) {
99 let mut display = self.display.clipped(&bounds_to_rect(&self.clip));
100 let mut display = display.translated(self.offset);
101 let mut pt = EPoint::new(position.x, position.y);
102 let mut text_builder = MonoTextStyleBuilder::new()
103 .font(style.font)
104 .text_color(*style.color);
105 if style.underline {
106 text_builder = text_builder.underline();
107 }
108 let estyle = text_builder.build();
109 let etext = Text {
110 position: pt,
111 text,
112 character_style: estyle,
113 text_style: TextStyleBuilder::new()
114 .alignment(Alignment::Center)
115 .baseline(Baseline::Middle)
116 .build(),
117 };
118 etext.draw(&mut display);
119 }
120 fn translate(&mut self, offset: &GPoint) {
121 self.offset = self.offset.add(EPoint::new(offset.x, offset.y));
122 }
123}