use kurbo::{Affine, BezPath, Rect, Stroke};
use pdfrum_page::BlendMode;
use crate::pixmap::{AlphaMask, Pixmap};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AntiAlias {
#[default]
On,
Off,
FullCover,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum FillRule {
#[default]
Winding,
EvenOdd,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ImageQuality {
#[default]
Nearest,
Bilinear,
}
pub type RasterImage = Pixmap;
#[derive(Debug, Clone, Copy)]
pub enum Brush<'a> {
Solid(peniko::Color),
Image(&'a RasterImage),
}
pub trait RenderDevice {
fn fill_path(
&mut self,
path: &BezPath,
t: Affine,
brush: &Brush<'_>,
rule: FillRule,
aa: AntiAlias,
);
fn stroke_path(
&mut self,
path: &BezPath,
t: Affine,
brush: &Brush<'_>,
stroke: &Stroke,
aa: AntiAlias,
);
fn draw_image(&mut self, img: &RasterImage, t: Affine, quality: ImageQuality, alpha: f32);
fn draw_glyph_lcd(
&mut self,
glyph: &crate::glyph::SubpixelBitmap,
origin: (f64, f64),
colour: peniko::Color,
) {
let Some(gray) = crate::glyph::average_to_gray(glyph) else {
return;
};
let Some(pixels) = crate::glyph::recolour(&gray, colour) else {
return;
};
self.draw_image(
&pixels,
Affine::translate(origin),
ImageQuality::Nearest,
1.0,
);
}
fn push_clip(&mut self, path: &BezPath, rule: FillRule);
fn push_clip_rect(&mut self, rect: Rect);
fn push_layer(&mut self, blend: BlendMode, alpha: f32, mask: Option<&AlphaMask>);
fn pop(&mut self);
}
pub trait RasterBackend {
type Device: RenderDevice;
fn new_target(&self, w: u32, h: u32, clear: peniko::Color) -> Self::Device;
fn new_target_with_backdrop(&self, base: &Pixmap) -> Self::Device;
fn snapshot(&self, d: &Self::Device) -> Pixmap;
fn finish(&self, d: Self::Device) -> Pixmap;
}
pub const MAX_TARGET_DIMENSION: u32 = u16::MAX as u32;
impl From<pdfrum_page::FillRule> for FillRule {
fn from(value: pdfrum_page::FillRule) -> Self {
match value {
pdfrum_page::FillRule::Winding => Self::Winding,
pdfrum_page::FillRule::EvenOdd | pdfrum_page::FillRule::None => Self::EvenOdd,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_fill_rule_reads_as_even_odd() {
assert_eq!(
FillRule::from(pdfrum_page::FillRule::None),
FillRule::EvenOdd
);
assert_eq!(
FillRule::from(pdfrum_page::FillRule::EvenOdd),
FillRule::EvenOdd
);
assert_eq!(
FillRule::from(pdfrum_page::FillRule::Winding),
FillRule::Winding
);
}
}