pub use pdf::{PdfDocumentGenerator, PdfRenderer};
pub use pixmap::{PixmapDocumentGenerator, PixmapRenderer};
pub use svg::{SvgDocumentGenerator, SvgRenderer};
use vello_cpu::kurbo::{BezPath, Point, Rect};
use crate::visual::{FillStrokeStyle, GradientDef, Stroke, StrokeStyle, Transform, VisualElement};
pub mod pdf;
mod pixmap;
mod svg;
pub trait PageRenderer {
fn draw_rect(&mut self, rect: Rect, style: &FillStrokeStyle);
fn draw_circle(&mut self, center: Point, radius: f64, style: &FillStrokeStyle);
fn draw_line(&mut self, start: Point, end: Point, style: &StrokeStyle);
fn draw_polyline(&mut self, points: &[Point], style: &StrokeStyle);
fn draw_path(&mut self, path: &BezPath, style: &FillStrokeStyle);
fn draw_gradient_path(
&mut self,
path: &BezPath,
gradient: &GradientDef,
stroke: Option<&Stroke>,
);
fn draw_text_run(&mut self, run: &crate::text::TextRun, position: Point);
fn draw_image(&mut self, data: &[u8], format: &str, position: Point, size: (f64, f64));
fn begin_group(&mut self, transform: Option<&Transform>);
fn end_group(&mut self);
fn render_elements(&mut self, elements: &[VisualElement])
where
Self: Sized,
{
let mut flat: Vec<(i32, &VisualElement)> = Vec::new();
for element in elements {
match element {
VisualElement::ZGroup { z_index, children } => {
for child in children {
flat.push((*z_index, child));
}
}
other => {
flat.push((0, other));
}
}
}
flat.sort_by_key(|(z, _)| *z);
for (_, element) in flat {
self.render_element(element);
}
}
fn render_element(&mut self, element: &VisualElement)
where
Self: Sized,
{
match element {
VisualElement::Rect { rect, style } => {
self.draw_rect(*rect, style);
}
VisualElement::Circle {
center,
radius,
style,
} => {
self.draw_circle(*center, *radius, style);
}
VisualElement::Line { start, end, style } => {
self.draw_line(*start, *end, style);
}
VisualElement::Polyline { points, style } => {
self.draw_polyline(points, style);
}
VisualElement::Path { path, style } => {
self.draw_path(path, style);
}
VisualElement::GradientPath {
path,
gradient,
stroke,
} => {
self.draw_gradient_path(path, gradient, stroke.as_ref());
}
VisualElement::TextLine {
runs,
bounds,
line_height: _,
} => {
let position = bounds.origin();
for run in runs {
self.draw_text_run(run, position);
}
}
VisualElement::Group {
children,
transform,
} => {
self.begin_group(transform.as_ref());
self.render_elements(children);
self.end_group();
}
VisualElement::Image {
position,
size,
pixel_size: _,
data,
format,
alt: _,
} => {
self.draw_image(data, format, *position, (size.x, size.y));
}
VisualElement::ZGroup { children, .. } => {
self.render_elements(children);
}
}
}
}