mirror of
https://gitlab.com/feliix42/embedded-plots.git
synced 2024-11-23 18:36:29 +00:00
Add initial docs and clarify licence in Cargo.toml
This commit is contained in:
parent
0c7e56dddf
commit
bf0b70d96c
9 changed files with 270 additions and 7 deletions
|
@ -3,7 +3,7 @@ name = "embedded-plots"
|
|||
version = "0.1.0"
|
||||
authors = ["Michał Chodzikiewicz <mchodzikiewicz@gmail.com>"]
|
||||
edition = "2018"
|
||||
license-file = "LICENSE"
|
||||
license = "LGPL-2.1-only"
|
||||
description = "Heapless plotting library for embedded targets based on embedded-graphics crate"
|
||||
homepage = "https://gitlab.com/mchodzikiewicz/embedded-plots"
|
||||
repository = "https://gitlab.com/mchodzikiewicz/embedded-plots"
|
||||
|
|
104
README.md
104
README.md
|
@ -2,4 +2,108 @@
|
|||
Heapless plotting library for small embedded targets, based on [embedded-graphics](https://crates.io/crates/embedded-graphics)
|
||||
crate.
|
||||
|
||||
Thanks to basing it on `embedded-graphics` crate the library is very portable out of the box.
|
||||
It is not dependent on any hardware target.
|
||||
To throw it into your project, you only need to have a display that implements `DrawTarget` trait.
|
||||
For more details see [DrawTarget](https://docs.rs/embedded-graphics/latest/embedded_graphics/prelude/trait.DrawTarget.html) docs.
|
||||
|
||||
Bonus feature of `embedded-graphics` is the simulator.
|
||||
You can use it to develop your plots without your target hardware, easily create documentation and so on.
|
||||
|
||||
Library utilizes builder pattern and type states - it allows easy separation of the data and decoration in the target application.
|
||||
|
||||
## Examples
|
||||
### Single plot
|
||||
Simple plot example
|
||||
#### On color display:
|
||||
![single plot on color display](doc-resources/single-plot-color.png "Color plot of single curve")
|
||||
#### On monochromatic display:
|
||||
![single plot on monochromatic display](doc-resources/single-plot-mono.png "Monochromatic plot of single curve")
|
||||
|
||||
Code to render:
|
||||
```rust
|
||||
use embedded_plots::curve::{Curve, PlotPoint};
|
||||
use embedded_plots::single_plot::SinglePlot;
|
||||
use embedded_plots::axis::Scale;
|
||||
use embedded_graphics::geometry::{Point, Size};
|
||||
use embedded_graphics::pixelcolor::{RgbColor, Rgb565};
|
||||
use embedded_graphics::drawable::Drawable;
|
||||
|
||||
//simulator dependencies, aka screen driver
|
||||
use embedded_graphics_simulator::SimulatorDisplay;
|
||||
|
||||
let mut display: SimulatorDisplay<Rgb565> = SimulatorDisplay::new(Size::new(480, 272));
|
||||
let data = vec![
|
||||
PlotPoint { x: 0, y: 0 },
|
||||
PlotPoint { x: 1, y: 2 },
|
||||
PlotPoint { x: 2, y: 2 },
|
||||
PlotPoint { x: 3, y: 0 },
|
||||
];
|
||||
let curve = Curve::from_data(data.as_slice());
|
||||
|
||||
let plot = SinglePlot::new(
|
||||
&curve,
|
||||
Scale::RangeFraction(3),
|
||||
Scale::RangeFraction(2))
|
||||
.into_drawable(
|
||||
Point { x: 50, y: 10 },
|
||||
Point { x: 430, y: 250 })
|
||||
.set_color(RgbColor::YELLOW)
|
||||
.set_text_color(RgbColor::WHITE);
|
||||
|
||||
plot.draw(&mut display).unwrap();
|
||||
```
|
||||
|
||||
### Axis
|
||||
You can also use axis on its own, it looks like this:
|
||||
![free axis examples](doc-resources/free-axis-example.png "Free axis example")
|
||||
Code to render example axis:
|
||||
```rust
|
||||
use embedded_plots::axis::{Axis, Scale, Placement};
|
||||
use embedded_graphics::pixelcolor::{RgbColor, Rgb565};
|
||||
use embedded_graphics::drawable::Drawable;
|
||||
use embedded_graphics::geometry::Size;
|
||||
|
||||
//simulator dependencies, aka screen driver
|
||||
use embedded_graphics_simulator::SimulatorDisplay;
|
||||
use embedded_graphics::style::TextStyleBuilder;
|
||||
use embedded_graphics::fonts::Font6x8;
|
||||
|
||||
let mut display: SimulatorDisplay<Rgb565> = SimulatorDisplay::new(Size::new(480, 272));
|
||||
|
||||
let text_style_white = TextStyleBuilder::new(Font6x8)
|
||||
.text_color(RgbColor::WHITE)
|
||||
.build();
|
||||
Axis::new(0..100)
|
||||
.set_title("Title")
|
||||
.set_scale(Scale::Fixed(10))
|
||||
.into_drawable_axis(Placement::X { x1: 40, x2: 230, y: 10 })
|
||||
.set_text_style(text_style_white)
|
||||
.set_color(RgbColor::WHITE)
|
||||
.draw(&mut display).unwrap();
|
||||
```
|
||||
For more details, see `free_axis` example
|
||||
|
||||
## Current limitations and future plans
|
||||
This is very beginning of the development, however it is functional to the point where single plot can be drawn.
|
||||
|
||||
Main issue for now is that you need to predict on how much space will be occupied by axis ticks,
|
||||
numbers and titles, points passed to `.into_drawable()` are the boundaries for which curve is scaled.
|
||||
This will be fixed, please be prepared for it since it might be a breaking change for you.
|
||||
|
||||
#### Main features planned soon:
|
||||
* Drawing multiple curves that share the same X and Y domains on a single plot (take curves slice instead of single curve)
|
||||
* Dual plot - drawing curves that have two separate domains (either only on one axis or both).
|
||||
Axis on both sides, left and right (or top and bottom) will be drawn with color corresponding to plot
|
||||
* Support for floating point domains
|
||||
* Support for fixed point curve data with intermediate floating point scales (to avoid floating point calculations for each drawn point)
|
||||
|
||||
#### Features I'd love to see in the future:
|
||||
* Partial redrawing - possibility to substitute data and detect which parts of the screen needs to be redrawed
|
||||
* Oscilloscope style live mode (adding new points without any redrawing, no data retention)
|
||||
* Cursors - manual and math based (max,min,avg and so on...)
|
||||
|
||||
## Contributions
|
||||
Contributions are more than welcome, if you have particular improvement, raise an issue or submit merge request on project's Gitlab page.
|
||||
|
||||
If you just want to help but don't have anything specific in mind, please take a look at [issue tracker](https://gitlab.com/mchodzikiewicz/embedded-plots/-/issues) and pick one.
|
||||
|
|
BIN
doc-resources/free-axis-example.png
Normal file
BIN
doc-resources/free-axis-example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
BIN
doc-resources/single-plot-color.png
Normal file
BIN
doc-resources/single-plot-color.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2 KiB |
BIN
doc-resources/single-plot-mono.png
Normal file
BIN
doc-resources/single-plot-mono.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
23
src/axis.rs
23
src/axis.rs
|
@ -10,7 +10,7 @@ use embedded_graphics::{
|
|||
};
|
||||
use crate::range_conv::Scalable;
|
||||
|
||||
|
||||
/// Used to provide alignment of an axis, it will be drown exactly on the line marked by the points
|
||||
pub enum Placement {
|
||||
X {
|
||||
x1: i32,
|
||||
|
@ -24,8 +24,13 @@ pub enum Placement {
|
|||
},
|
||||
}
|
||||
|
||||
/// Used to describe how densely ticks should be drawn
|
||||
pub enum Scale {
|
||||
/// Fixed scale means that ticks will be drawn between each increment of absolute distance provided.
|
||||
/// for example, on range 0..30 and Fixed(10), ticks will be drawn for 0, 10 and 20
|
||||
Fixed(usize),
|
||||
/// RangeFraction means that provided number of ticks ticks will be drawn on entire range
|
||||
/// for example, on range 0..60 and RangeFraction(3), ticks will be drawn for 0, 20 and 40
|
||||
RangeFraction(usize),
|
||||
}
|
||||
|
||||
|
@ -35,28 +40,37 @@ impl Default for Scale {
|
|||
}
|
||||
}
|
||||
|
||||
/// Display-agnostic axis object, only contains scale range and title, can be converted to drawable axis for specific display
|
||||
pub struct Axis<'a> {
|
||||
/// range that the scale will be drawn for
|
||||
range: Range<i32>,
|
||||
/// axis title displayed right next to it
|
||||
title: Option<&'a str>,
|
||||
/// Definition on how scale ticks should be drawn
|
||||
scale: Option<Scale>,
|
||||
}
|
||||
|
||||
/// builder methods to modify axis decoration
|
||||
impl<'a> Axis<'a>
|
||||
{
|
||||
/// create new axis data
|
||||
pub fn new(range: Range<i32>) -> Axis<'a> {
|
||||
Axis { range, title: None, scale: None }
|
||||
}
|
||||
|
||||
/// define how scale ticks should be drawn
|
||||
pub fn set_scale(mut self, scale: Scale) -> Axis<'a> {
|
||||
self.scale = Some(scale);
|
||||
self
|
||||
}
|
||||
|
||||
/// set axis title
|
||||
pub fn set_title(mut self, title: &'a str) -> Axis<'a> {
|
||||
self.title = Some(title);
|
||||
self
|
||||
}
|
||||
|
||||
/// turn axis data into drawable object suitable for specific display
|
||||
pub fn into_drawable_axis<C, F>(self, placement: Placement) -> DrawableAxis<'a, C, F>
|
||||
where
|
||||
C: PixelColor + Default,
|
||||
|
@ -74,6 +88,7 @@ impl<'a> Axis<'a>
|
|||
}
|
||||
}
|
||||
|
||||
/// Drawable axis object, constructed for specific display
|
||||
pub struct DrawableAxis<'a, C, F>
|
||||
where
|
||||
C: PixelColor,
|
||||
|
@ -102,10 +117,14 @@ impl<'a, C, F> DrawableAxis<'a, C, F>
|
|||
self.text_style = Some(val);
|
||||
self
|
||||
}
|
||||
|
||||
/// set how wide tick should be drawn on the axis
|
||||
pub fn set_tick_size(mut self, val: usize) -> DrawableAxis<'a, C, F> {
|
||||
self.tick_size = Some(val);
|
||||
self
|
||||
}
|
||||
|
||||
/// set thickness of the main line of the axis
|
||||
pub fn set_thickness(mut self, val: usize) -> DrawableAxis<'a, C, F> {
|
||||
self.thickness = Some(val);
|
||||
self
|
||||
|
@ -119,6 +138,8 @@ impl<'a, C, F> Drawable<C> for DrawableAxis<'a, C, F>
|
|||
F: Font + Copy,
|
||||
TextStyle<C, F>: Clone + Default,
|
||||
{
|
||||
|
||||
/// most important function - draw the axis on the display
|
||||
fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error> {
|
||||
let color = self.color.unwrap_or_default();
|
||||
let text_style = self.text_style.unwrap_or_default();
|
||||
|
|
13
src/curve.rs
13
src/curve.rs
|
@ -10,23 +10,27 @@ use embedded_graphics::pixelcolor::{PixelColor};
|
|||
use embedded_graphics::primitives::{Line, Primitive};
|
||||
use embedded_graphics::style::PrimitiveStyle;
|
||||
|
||||
|
||||
/// representation of the single point on the curve
|
||||
pub struct PlotPoint {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
/// curve object that contains data to be plotted
|
||||
pub struct Curve<'a> {
|
||||
/// slice of points to be drawn
|
||||
points: &'a [PlotPoint],
|
||||
pub x_range: Range<i32>,
|
||||
pub y_range: Range<i32>,
|
||||
}
|
||||
|
||||
impl<'a> Curve<'a> {
|
||||
/// create new curve data with manual ranges
|
||||
pub fn new(points: &'a [PlotPoint], x_range: Range<i32>, y_range: Range<i32>) -> Curve {
|
||||
Curve { points, x_range, y_range }
|
||||
}
|
||||
|
||||
/// create new curve data with ranges automatically deducted based on provided points
|
||||
pub fn from_data(points: &'a [PlotPoint]) -> Curve {
|
||||
let x_range = match points
|
||||
.iter()
|
||||
|
@ -46,6 +50,7 @@ impl<'a> Curve<'a> {
|
|||
Curve { points, x_range, y_range }
|
||||
}
|
||||
|
||||
/// create curve that can be drawed on specific display
|
||||
pub fn into_drawable_curve<C>(&self,
|
||||
top_left: &'a Point,
|
||||
bottom_right: &'a Point,
|
||||
|
@ -76,6 +81,7 @@ impl<'a> Curve<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Drawable curve object, constructed for specific display
|
||||
pub struct DrawableCurve<C, I>
|
||||
{
|
||||
scaled_data: I,
|
||||
|
@ -83,15 +89,19 @@ pub struct DrawableCurve<C, I>
|
|||
thickness: Option<usize>,
|
||||
}
|
||||
|
||||
/// builder methods to modify curve decoration
|
||||
impl<C, I> DrawableCurve<C, I>
|
||||
where
|
||||
C: PixelColor,
|
||||
I: Iterator<Item=Point>,
|
||||
{
|
||||
/// set curve color
|
||||
pub fn set_color(mut self, color: C) -> DrawableCurve<C, I> {
|
||||
self.color = Some(color);
|
||||
self
|
||||
}
|
||||
|
||||
/// set curve line thickness
|
||||
pub fn set_thickness(mut self, thickness: usize) -> DrawableCurve<C,I> {
|
||||
self.thickness = Some(thickness);
|
||||
self
|
||||
|
@ -102,6 +112,7 @@ impl<C, I> Drawable<C> for DrawableCurve<C, I>
|
|||
where C: PixelColor + Default,
|
||||
I: Iterator<Item=Point>,
|
||||
{
|
||||
/// most important function - draw the curve on the display
|
||||
fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error> {
|
||||
let color = match self.color {
|
||||
None => C::default(),
|
||||
|
|
112
src/lib.rs
112
src/lib.rs
|
@ -1,7 +1,117 @@
|
|||
#![no_std]
|
||||
//!# Embedded Plots
|
||||
//! Heapless plotting library for small embedded targets, based on [embedded-graphics](https://crates.io/crates/embedded-graphics)
|
||||
//! crate.
|
||||
//!
|
||||
//! Thanks to basing it on `embedded-graphics` crate the library is very portable out of the box.
|
||||
//! It is not dependent on any hardware target.
|
||||
//! To throw it into your project, you only need to have a display that implements `DrawTarget` trait.
|
||||
//! For more details see [DrawTarget](https://docs.rs/embedded-graphics/latest/embedded_graphics/prelude/trait.DrawTarget.html) docs.
|
||||
//!
|
||||
//! Bonus feature of `embedded-graphics` is the simulator.
|
||||
//! You can use it to develop your plots without your target hardware, easily create documentation and so on.
|
||||
//!
|
||||
//! Library utilizes builder pattern and type states - it allows easy separation of the data and decoration in the target application.
|
||||
//!
|
||||
//! ## Examples
|
||||
//! ### Single plot
|
||||
//! Simple plot example
|
||||
//! #### On color display:
|
||||
//! ![single plot on color display](doc-resources/single-plot-color.png "Color plot of single curve")
|
||||
//! #### On monochromatic display:
|
||||
//! ![single plot on monochromatic display](doc-resources/single-plot-mono.png "Monochromatic plot of single curve")
|
||||
//!
|
||||
//! Code to render:
|
||||
//! ```rust
|
||||
//! use embedded_plots::curve::{Curve, PlotPoint};
|
||||
//! use embedded_plots::single_plot::SinglePlot;
|
||||
//! use embedded_plots::axis::Scale;
|
||||
//! use embedded_graphics::geometry::{Point, Size};
|
||||
//! use embedded_graphics::pixelcolor::{RgbColor, Rgb565};
|
||||
//! use embedded_graphics::drawable::Drawable;
|
||||
//!
|
||||
//! //simulator dependencies, aka screen driver
|
||||
//! use embedded_graphics_simulator::SimulatorDisplay;
|
||||
//!
|
||||
//! let mut display: SimulatorDisplay<Rgb565> = SimulatorDisplay::new(Size::new(480, 272));
|
||||
//! let data = vec![
|
||||
//! PlotPoint { x: 0, y: 0 },
|
||||
//! PlotPoint { x: 1, y: 2 },
|
||||
//! PlotPoint { x: 2, y: 2 },
|
||||
//! PlotPoint { x: 3, y: 0 },
|
||||
//! ];
|
||||
//! let curve = Curve::from_data(data.as_slice());
|
||||
//!
|
||||
//! let plot = SinglePlot::new(
|
||||
//! &curve,
|
||||
//! Scale::RangeFraction(3),
|
||||
//! Scale::RangeFraction(2))
|
||||
//! .into_drawable(
|
||||
//! Point { x: 50, y: 10 },
|
||||
//! Point { x: 430, y: 250 })
|
||||
//! .set_color(RgbColor::YELLOW)
|
||||
//! .set_text_color(RgbColor::WHITE);
|
||||
//!
|
||||
//! plot.draw(&mut display).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! ### Axis
|
||||
//! You can also use axis on its own, it looks like this:
|
||||
//! ![free axis examples](doc-resources/free-axis-example.png "Free axis example")
|
||||
//! Code to render example axis:
|
||||
//! ```rust
|
||||
//! use embedded_plots::axis::{Axis, Scale, Placement};
|
||||
//! use embedded_graphics::pixelcolor::{RgbColor, Rgb565};
|
||||
//! use embedded_graphics::drawable::Drawable;
|
||||
//! use embedded_graphics::geometry::Size;
|
||||
//!
|
||||
//! //simulator dependencies, aka screen driver
|
||||
//! use embedded_graphics_simulator::SimulatorDisplay;
|
||||
//! use embedded_graphics::style::TextStyleBuilder;
|
||||
//! use embedded_graphics::fonts::Font6x8;
|
||||
//!
|
||||
//! let mut display: SimulatorDisplay<Rgb565> = SimulatorDisplay::new(Size::new(480, 272));
|
||||
//!
|
||||
//! let text_style_white = TextStyleBuilder::new(Font6x8)
|
||||
//! .text_color(RgbColor::WHITE)
|
||||
//! .build();
|
||||
//! Axis::new(0..100)
|
||||
//! .set_title("Title")
|
||||
//! .set_scale(Scale::Fixed(10))
|
||||
//! .into_drawable_axis(Placement::X { x1: 40, x2: 230, y: 10 })
|
||||
//! .set_text_style(text_style_white)
|
||||
//! .set_color(RgbColor::WHITE)
|
||||
//! .draw(&mut display).unwrap();
|
||||
//! ```
|
||||
//! For more details, see `free_axis` example
|
||||
//!
|
||||
//! ## Current limitations and future plans
|
||||
//! This is very beginning of the development, however it is functional to the point where single plot can be drawn.
|
||||
//!
|
||||
//! Main issue for now is that you need to predict on how much space will be occupied by axis ticks,
|
||||
//! numbers and titles, points passed to `.into_drawable()` are the boundaries for which curve is scaled.
|
||||
//! This will be fixed, please be prepared for it since it might be a breaking change for you.
|
||||
//!
|
||||
//! #### Main features planned soon:
|
||||
//! * Drawing multiple curves that share the same X and Y domains on a single plot (take curves slice instead of single curve)
|
||||
//! * Dual plot - drawing curves that have two separate domains (either only on one axis or both).
|
||||
//! Axis on both sides, left and right (or top and bottom) will be drawn with color corresponding to plot
|
||||
//! * Support for floating point domains
|
||||
//! * Support for fixed point curve data with intermediate floating point scales (to avoid floating point calculations for each drawn point)
|
||||
//!
|
||||
//! #### Features I'd love to see in the future:
|
||||
//! * Partial redrawing - possibility to substitute data and detect which parts of the screen needs to be redrawed
|
||||
//! * Oscilloscope style live mode (adding new points without any redrawing, no data retention)
|
||||
//! * Cursors - manual and math based (max,min,avg and so on...)
|
||||
//!
|
||||
//! ## Contributions
|
||||
//! Contributions are more than welcome, if you have particular improvement, raise an issue or submit merge request on project's Gitlab page.
|
||||
//!
|
||||
//! If you just want to help but don't have anything specific in mind, please take a look at [issue tracker](https://gitlab.com/mchodzikiewicz/embedded-plots/-/issues) and pick one.
|
||||
|
||||
#![no_std]
|
||||
pub mod curve;
|
||||
pub mod axis;
|
||||
/// plot that draws single data series
|
||||
pub mod single_plot;
|
||||
|
||||
mod range_conv;
|
|
@ -7,22 +7,31 @@ use crate::axis::{Scale, Placement, Axis};
|
|||
use embedded_graphics::style::TextStyleBuilder;
|
||||
use embedded_graphics::fonts::Font6x8;
|
||||
|
||||
/// Display agnostic single curve plot object
|
||||
pub struct SinglePlot<'a> {
|
||||
/// curve to be drawn on the plot
|
||||
curve: &'a Curve<'a>,
|
||||
/// range of X axis on which curve will be drawn
|
||||
x_scale: Scale,
|
||||
/// range of Y axis on which curve will be drawn
|
||||
y_scale: Scale,
|
||||
}
|
||||
|
||||
impl<'a> SinglePlot<'a> {
|
||||
/// create SinglePlot object with manual range
|
||||
pub fn new(curve: &'a Curve<'a>, x_scale: Scale, y_scale: Scale) -> SinglePlot {
|
||||
SinglePlot { curve, x_scale, y_scale }
|
||||
}
|
||||
|
||||
//TODO: add auto range plot constructor
|
||||
|
||||
/// convert to drawable form for specific display
|
||||
pub fn into_drawable<C: PixelColor + Default>(self, top_left: Point, bottom_right: Point) -> DrawableSinglePlot<'a, C> {
|
||||
DrawableSinglePlot { plot: self, color: None, text_color: None, axis_color: None, thickness: None, axis_thickness: None, top_left, bottom_right }
|
||||
}
|
||||
}
|
||||
|
||||
/// Drawable single plot object, constructed for specific display
|
||||
pub struct DrawableSinglePlot<'a, C>
|
||||
where
|
||||
C: PixelColor + Default,
|
||||
|
@ -37,6 +46,7 @@ pub struct DrawableSinglePlot<'a, C>
|
|||
bottom_right: Point,
|
||||
}
|
||||
|
||||
/// builder methods to modify plot decoration
|
||||
impl<'a, C> DrawableSinglePlot<'a, C>
|
||||
where
|
||||
C: PixelColor + Default,
|
||||
|
@ -46,32 +56,39 @@ impl<'a, C> DrawableSinglePlot<'a, C>
|
|||
self
|
||||
}
|
||||
|
||||
/// if not set, main color will be used
|
||||
pub fn set_text_color(mut self, color: C) -> DrawableSinglePlot<'a, C> {
|
||||
self.text_color = Some(color);
|
||||
self
|
||||
}
|
||||
|
||||
/// if not set, main color will be used
|
||||
pub fn set_axis_color(mut self, color: C) -> DrawableSinglePlot<'a, C> {
|
||||
self.axis_color = Some(color);
|
||||
self
|
||||
}
|
||||
|
||||
/// set curve thickness
|
||||
pub fn set_thickness(mut self, thickness: usize) -> DrawableSinglePlot<'a, C> {
|
||||
self.thickness = Some(thickness);
|
||||
self
|
||||
}
|
||||
|
||||
///set axis thickness
|
||||
pub fn set_axis_thickness(mut self, thickness: usize) -> DrawableSinglePlot<'a, C> {
|
||||
self.axis_thickness = Some(thickness);
|
||||
self
|
||||
}
|
||||
|
||||
//TODO: add axis ticks thickness
|
||||
|
||||
}
|
||||
|
||||
impl<'a, C> Drawable<C> for DrawableSinglePlot<'a, C>
|
||||
where
|
||||
C: PixelColor + Default,
|
||||
{
|
||||
/// most important function - draw the plot on the display
|
||||
fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error> {
|
||||
let color = self.color.unwrap_or_default();
|
||||
let text_color = self.text_color.unwrap_or(color);
|
||||
|
|
Loading…
Reference in a new issue