dataviz\figure\drawers/drawer.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
use ab_glyph::{FontRef, PxScale};
use imageproc::drawing::text_size;
use crate::figure::{
canvas::{pixelcanvas::PixelCanvas, svgcanvas::SvgCanvas},
configuration::figureconfig::FigureConfig,
utilities::{axistype::AxisType, linetype::LineType},
};
/// A trait for rendering charts and graphs, supporting multiple output formats.
pub trait Drawer {
/// Draws the main content of the plot on a `PixelCanvas`.
///
/// # Parameters
/// - `canvas`: The `PixelCanvas` to draw the plot on.
fn draw(&mut self, canvas: &mut PixelCanvas);
/// Draws the legend for the plot on a `PixelCanvas`.
///
/// # Parameters
/// - `canvas`: The `PixelCanvas` to draw the legend on.
fn draw_legend(&self, canvas: &mut PixelCanvas);
/// Draws the plot content on an `SvgCanvas`.
///
/// # Parameters
/// - `svg_canvas`: The `SvgCanvas` to render the plot on.
fn draw_svg(&mut self, svg_canvas: &mut SvgCanvas);
/// Draws the grid for the plot based on the provided configuration.
///
/// # Parameters
/// - `canvas`: The `PixelCanvas` to draw the grid on.
/// - `config`: The `FigureConfig` containing grid appearance settings.
fn draw_grid(&self, canvas: &mut PixelCanvas, config: &FigureConfig) {
canvas.draw_grid(
&[config.num_grid_horizontal, config.num_grid_vertical],
config.color_grid,
);
}
/// Draws an axis line on the canvas.
///
/// # Parameters
/// - `canvas`: The `PixelCanvas` to draw the axis on.
/// - `config`: The `FigureConfig` containing axis appearance settings.
/// - `x1`, `y1`: The starting coordinates of the axis.
/// - `x2`, `y2`: The ending coordinates of the axis.
fn draw_axis(
&self,
canvas: &mut PixelCanvas,
config: &FigureConfig,
x1: i32,
y1: i32,
x2: i32,
y2: i32,
) {
canvas.draw_line(x1, y1, x2, y2, config.color_axis, LineType::Solid);
}
/// Draws a text label on the canvas.
///
/// # Parameters
/// - `canvas`: The `PixelCanvas` to draw the label on.
/// - `config`: The `FigureConfig` containing label appearance settings.
/// - `x`, `y`: The position to draw the label, centered on `(x, y)`.
/// - `text`: The label text.
fn draw_label(
&self,
canvas: &mut PixelCanvas,
config: &FigureConfig,
x: u32,
y: u32,
text: &str,
) {
let font_bytes = std::fs::read(&config.font_title).expect("Failed to read font file");
let font = FontRef::try_from_slice(&font_bytes).unwrap();
let scale = ab_glyph::PxScale {
x: config.font_size_label,
y: config.font_size_label,
};
let (w, h) = text_size(scale, &font, &text);
canvas.draw_text(
x.saturating_sub(w / 2),
y.saturating_sub(h / 2),
text,
config.color_axis,
&font,
scale,
);
}
/// Draws the plot title on the canvas.
///
/// # Parameters
/// - `canvas`: The `PixelCanvas` to draw the title on.
/// - `config`: The `FigureConfig` containing title appearance settings.
/// - `x`, `y`: The position to draw the title, centered on `(x, y)`.
/// - `text`: The title text.
fn draw_title(
&self,
canvas: &mut PixelCanvas,
config: &FigureConfig,
x: u32,
y: u32,
text: &str,
) {
let font_bytes = std::fs::read(&config.font_title).expect("Failed to read font file");
let font = FontRef::try_from_slice(&font_bytes).unwrap();
let scale = PxScale {
x: config.font_size_title,
y: config.font_size_title,
};
let (w, h) = text_size(scale, &font, &text);
canvas.draw_text(
x.saturating_sub(w / 2),
y.saturating_sub(h / 2),
text,
config.color_title,
&font,
scale,
);
}
/// Draws a value on the axis (tick label) based on its type.
///
/// # Parameters
/// - `canvas`: The `PixelCanvas` to draw the axis value on.
/// - `config`: The `FigureConfig` containing axis value appearance settings.
/// - `x`, `y`: The position to draw the value.
/// - `text`: The text of the axis value.
/// - `axis`: The type of axis (`AxisType::AxisX` or `AxisType::AxisY`).
fn draw_axis_value(
&self,
canvas: &mut PixelCanvas,
config: &FigureConfig,
x: u32,
y: u32,
text: &str,
axis: AxisType,
) {
let font_bytes = std::fs::read(&config.font_title).expect("Failed to read font file");
let font = FontRef::try_from_slice(&font_bytes).unwrap();
let scale = ab_glyph::PxScale {
x: config.font_size_axis,
y: config.font_size_axis,
};
let (w, h) = text_size(scale, &font, &text);
let mut x = x;
let mut y = y;
match axis {
AxisType::AxisX => {
x = x.saturating_sub(w / 2);
y = y.saturating_add(h);
}
AxisType::AxisY => {
x = x.saturating_sub(w);
y = y.saturating_sub(h / 2);
}
}
canvas.draw_text(x, y, text, config.color_axis, &font, scale);
}
}