use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use valo_geometry::{FillRule, Matrix, Path, Rect};
use crate::{Image, Paint, Sampling};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ClipOp {
#[default]
Intersect,
Difference,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub enum Op {
Save,
SaveLayer {
paint: Paint,
mask_composite: Option<MaskKind>,
scope_bounds: Rect,
base_slot: u32,
composite_slot: u32,
can_elide: bool,
},
Restore,
Transform(Matrix),
DrawRect {
rect: Rect,
paint: Paint,
bounds: Rect,
slot: u32,
},
DrawPath {
path: Arc<Path>,
fill_rule: FillRule,
paint: Paint,
bounds: Rect,
slot: u32,
},
RRectBlur {
rect: Rect,
radii: [f32; 4],
paint: Paint,
bounds: Rect,
slot: u32,
},
BackdropBlur {
rect: Rect,
sigma: f32,
shared_key: Option<u64>,
bounds: Rect,
slot: u32,
},
ClipPath {
path: Arc<Path>,
fill_rule: FillRule,
op: ClipOp,
bounds: Rect,
expiry_slot: u32,
},
DrawImage {
image: Image,
src: Rect,
dst: Rect,
sampling: Sampling,
paint: Paint,
bounds: Rect,
slot: u32,
},
GlyphRun {
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_font_uid"))]
font: std::sync::Arc<valo_text::Font>,
size: f32,
paint: Paint,
glyphs: Arc<Vec<GlyphPos>>,
bounds: Rect,
slot: u32,
},
DrawDisplayList {
list: Arc<DisplayList>,
bounds: Rect,
base_slot: u32,
cache: bool,
},
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub enum MaskKind {
Luminance,
Alpha,
}
static NEXT_ID: AtomicU64 = AtomicU64::new(1);
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct DisplayList {
id: u64,
pub(crate) ops: Vec<Op>,
pub(crate) bounds: Option<Rect>,
pub(crate) draw_count: u32,
pub(crate) depth_slots: u32,
pub(crate) backdrop_groups: Vec<BackdropGroup>,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct GlyphPos {
pub id: u32,
pub x: f32,
pub y: f32,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct BackdropGroup {
pub key: u64,
pub union_bounds: Rect,
pub tiles: u32,
pub sigma: Option<f32>,
}
fn next_id() -> u64 {
NEXT_ID.fetch_add(1, Ordering::Relaxed)
}
impl DisplayList {
pub(crate) fn new(
ops: Vec<Op>,
bounds: Option<Rect>,
draw_count: u32,
depth_slots: u32,
backdrop_groups: Vec<BackdropGroup>,
) -> Self {
Self {
id: next_id(),
ops,
bounds,
draw_count,
depth_slots,
backdrop_groups,
}
}
pub fn id(&self) -> u64 {
self.id
}
pub fn ops(&self) -> &[Op] {
&self.ops
}
pub fn bounds(&self) -> Option<Rect> {
self.bounds
}
pub fn draw_count(&self) -> u32 {
self.draw_count
}
pub fn depth_slots(&self) -> u32 {
self.depth_slots
}
pub fn backdrop_group_count(&self) -> usize {
self.backdrop_groups.len()
}
pub fn backdrop_group(&self, key: u64) -> Option<&BackdropGroup> {
self.backdrop_groups.iter().find(|g| g.key == key)
}
}
#[cfg(feature = "serde")]
fn serialize_font_uid<S: serde::Serializer>(
font: &std::sync::Arc<valo_text::Font>,
serializer: S,
) -> Result<S::Ok, S::Error> {
serializer.serialize_u64(font.uid().0)
}