use crate::CacheKey;
use crate::color::Color;
use crate::pattern::Pattern;
use crate::util::hash128;
use crate::x_object::ImageXObject;
use hayro_syntax::object::Stream;
use kurbo::{BezPath, Cap, Join};
use smallvec::{SmallVec, smallvec};
#[derive(Debug, Clone)]
pub struct ClipPath {
pub path: BezPath,
pub fill: FillRule,
}
impl CacheKey for ClipPath {
fn cache_key(&self) -> u128 {
hash128(&(&self.path.to_svg(), &self.fill))
}
}
pub struct StencilImage<'a, 'b> {
pub(crate) paint: Paint<'a>,
pub(crate) image_xobject: ImageXObject<'b>,
}
impl<'a, 'b> StencilImage<'a, 'b> {
pub fn with_stencil(
&self,
func: impl FnOnce(LumaData, &Paint<'a>),
target_dimension: Option<(u32, u32)>,
) {
if let Some(decoded) = self.image_xobject.decoded_mask(target_dimension) {
func(decoded.luma, &self.paint);
}
}
#[doc(hidden)]
pub fn width(&self) -> u32 {
self.image_xobject.width()
}
#[doc(hidden)]
pub fn height(&self) -> u32 {
self.image_xobject.height()
}
}
impl CacheKey for StencilImage<'_, '_> {
fn cache_key(&self) -> u128 {
self.image_xobject.cache_key()
}
}
pub struct RasterImage<'a>(pub(crate) ImageXObject<'a>);
impl RasterImage<'_> {
pub fn with_rgba(
&self,
func: impl FnOnce(ImageData, Option<LumaData>),
target_dimension: Option<(u32, u32)>,
) {
if let Some(decoded) = self.0.decoded_raster(target_dimension) {
func(decoded.image, decoded.alpha);
}
}
pub fn stream(&self) -> &Stream<'_> {
self.0.stream()
}
#[doc(hidden)]
pub fn width(&self) -> u32 {
self.0.width()
}
#[doc(hidden)]
pub fn height(&self) -> u32 {
self.0.height()
}
}
impl CacheKey for RasterImage<'_> {
fn cache_key(&self) -> u128 {
self.0.cache_key()
}
}
pub enum Image<'a, 'b> {
Stencil(StencilImage<'a, 'b>),
Raster(RasterImage<'b>),
}
impl Image<'_, '_> {
#[doc(hidden)]
pub fn width(&self) -> u32 {
match self {
Image::Stencil(s) => s.width(),
Image::Raster(r) => r.width(),
}
}
#[doc(hidden)]
pub fn height(&self) -> u32 {
match self {
Image::Stencil(s) => s.height(),
Image::Raster(r) => r.height(),
}
}
}
impl CacheKey for Image<'_, '_> {
fn cache_key(&self) -> u128 {
match self {
Image::Stencil(i) => i.cache_key(),
Image::Raster(i) => i.cache_key(),
}
}
}
#[derive(Clone)]
pub struct RgbData {
pub data: Vec<u8>,
pub width: u32,
pub height: u32,
pub interpolate: bool,
pub scale_factors: (f32, f32),
}
#[derive(Clone)]
pub struct LumaData {
pub data: Vec<u8>,
pub width: u32,
pub height: u32,
pub interpolate: bool,
pub scale_factors: (f32, f32),
}
#[derive(Clone)]
pub enum ImageData {
Rgb(RgbData),
Luma(LumaData),
}
impl ImageData {
pub fn width(&self) -> u32 {
match self {
Self::Rgb(d) => d.width,
Self::Luma(d) => d.width,
}
}
pub fn height(&self) -> u32 {
match self {
Self::Rgb(d) => d.height,
Self::Luma(d) => d.height,
}
}
pub fn interpolate(&self) -> bool {
match self {
Self::Rgb(d) => d.interpolate,
Self::Luma(d) => d.interpolate,
}
}
pub fn scale_factors(&self) -> (f32, f32) {
match self {
Self::Rgb(d) => d.scale_factors,
Self::Luma(d) => d.scale_factors,
}
}
}
#[derive(Clone, Debug)]
pub enum Paint<'a> {
Color(Color),
Pattern(Box<Pattern<'a>>),
}
impl CacheKey for Paint<'_> {
fn cache_key(&self) -> u128 {
match self {
Paint::Color(c) => {
hash128(&c.to_rgba().to_rgba8())
}
Paint::Pattern(p) => p.cache_key(),
}
}
}
#[derive(Clone, Debug)]
pub enum PathDrawMode {
Fill(FillRule),
Stroke(StrokeProps),
}
#[derive(Clone, Debug)]
pub enum GlyphDrawMode {
Fill,
Stroke(StrokeProps),
Invisible,
}
#[derive(Clone, Debug)]
pub struct StrokeProps {
pub line_width: f32,
pub line_cap: Cap,
pub line_join: Join,
pub miter_limit: f32,
pub dash_array: SmallVec<[f32; 4]>,
pub dash_offset: f32,
}
impl Default for StrokeProps {
fn default() -> Self {
Self {
line_width: 1.0,
line_cap: Cap::Butt,
line_join: Join::Miter,
miter_limit: 10.0,
dash_array: smallvec![],
dash_offset: 0.0,
}
}
}
#[derive(Clone, Debug, Copy, Hash, PartialEq, Eq)]
pub enum FillRule {
NonZero,
EvenOdd,
}
#[derive(Clone, Debug, Copy, Hash, PartialEq, Eq, Default)]
pub enum BlendMode {
#[default]
Normal,
Multiply,
Screen,
Overlay,
Darken,
Lighten,
ColorDodge,
ColorBurn,
HardLight,
SoftLight,
Difference,
Exclusion,
Hue,
Saturation,
Color,
Luminosity,
}