use super::ChartSpec;
use crate::chart::validation::ValidationError;
pub struct ChartRenderer {
spec: ChartSpec,
config: RenderConfig,
}
#[derive(Debug, Clone)]
pub struct RenderConfig {
pub backend: RenderBackend,
pub quality: RenderQuality,
pub optimization: RenderOptimization,
}
#[derive(Debug, Clone, PartialEq)]
pub enum RenderBackend {
Canvas2D,
WebGL2,
WebGPU,
SVG,
}
#[derive(Debug, Clone, PartialEq)]
pub enum RenderQuality {
Low,
Medium,
High,
Ultra,
}
#[derive(Debug, Clone)]
pub struct RenderOptimization {
pub enable_caching: bool,
pub enable_lazy_loading: bool,
pub enable_level_of_detail: bool,
pub max_data_points: Option<usize>,
}
impl Default for RenderConfig {
fn default() -> Self {
Self {
backend: RenderBackend::Canvas2D,
quality: RenderQuality::High,
optimization: RenderOptimization {
enable_caching: true,
enable_lazy_loading: true,
enable_level_of_detail: true,
max_data_points: Some(10000),
},
}
}
}
impl ChartRenderer {
pub fn new(spec: ChartSpec) -> Self {
Self {
spec,
config: RenderConfig::default(),
}
}
pub fn with_config(mut self, config: RenderConfig) -> Self {
self.config = config;
self
}
pub fn render(&self) -> Result<RenderResult, ValidationError> {
self.spec.validate()?;
match self.config.backend {
RenderBackend::Canvas2D => self.render_canvas2d(),
RenderBackend::WebGL2 => self.render_webgl2(),
RenderBackend::WebGPU => self.render_webgpu(),
RenderBackend::SVG => self.render_svg(),
}
}
fn render_canvas2d(&self) -> Result<RenderResult, ValidationError> {
Ok(RenderResult {
success: true,
render_time_ms: 0,
data_points_rendered: 0,
memory_usage_mb: 0.0,
warnings: Vec::new(),
})
}
fn render_webgl2(&self) -> Result<RenderResult, ValidationError> {
Ok(RenderResult {
success: true,
render_time_ms: 0,
data_points_rendered: 0,
memory_usage_mb: 0.0,
warnings: Vec::new(),
})
}
fn render_webgpu(&self) -> Result<RenderResult, ValidationError> {
Ok(RenderResult {
success: true,
render_time_ms: 0,
data_points_rendered: 0,
memory_usage_mb: 0.0,
warnings: Vec::new(),
})
}
fn render_svg(&self) -> Result<RenderResult, ValidationError> {
Ok(RenderResult {
success: true,
render_time_ms: 0,
data_points_rendered: 0,
memory_usage_mb: 0.0,
warnings: Vec::new(),
})
}
pub fn estimate_complexity(&self) -> f64 {
self.spec.complexity()
}
pub fn optimize(&mut self) {
self.spec = self.spec.clone().optimize();
}
}
#[derive(Debug, Clone)]
pub struct RenderResult {
pub success: bool,
pub render_time_ms: u64,
pub data_points_rendered: usize,
pub memory_usage_mb: f64,
pub warnings: Vec<String>,
}
pub struct ChartRenderUtils;
impl ChartRenderUtils {
pub fn choose_backend(spec: &ChartSpec) -> RenderBackend {
let complexity = spec.complexity();
if complexity > 10.0 {
RenderBackend::WebGPU
} else if complexity > 5.0 {
RenderBackend::WebGL2
} else if complexity > 2.0 {
RenderBackend::Canvas2D
} else {
RenderBackend::SVG
}
}
pub fn estimate_render_time(spec: &ChartSpec, backend: &RenderBackend) -> u64 {
let complexity = spec.complexity();
let base_time = match backend {
RenderBackend::SVG => complexity * 2.0,
RenderBackend::Canvas2D => complexity * 1.0,
RenderBackend::WebGL2 => complexity * 0.5,
RenderBackend::WebGPU => complexity * 0.3,
};
base_time as u64
}
pub fn estimate_memory_usage(spec: &ChartSpec, backend: &RenderBackend) -> f64 {
let complexity = spec.complexity();
let base_memory = match backend {
RenderBackend::SVG => complexity * 0.1,
RenderBackend::Canvas2D => complexity * 0.5,
RenderBackend::WebGL2 => complexity * 1.0,
RenderBackend::WebGPU => complexity * 0.8,
};
base_memory
}
}