use std::collections::HashMap;
use std::sync::OnceLock;
use crate::coord::CanvasRect;
use crate::document::filters::mask::MaskFilter;
use crate::document::filters::selection::SelectionFilter;
use crate::document::layer_kind::{IdMap, SerializedEntity};
use crate::format::error::LoadError;
use crate::layer::{LayerId, NodeCommon, PixelBuffer};
pub struct FilterEntityRegistration {
pub type_id: &'static str,
pub display_name: &'static str,
pub serialize: fn(&Filter) -> SerializedEntity,
pub deserialize: fn(body: &serde_json::Value, id: LayerId) -> Result<Filter, LoadError>,
pub remap_ids: fn(&mut Filter, &IdMap),
}
pub struct FilterRegistry {
entries: Vec<FilterEntityRegistration>,
by_type_id: HashMap<&'static str, usize>,
}
impl Default for FilterRegistry {
fn default() -> Self {
Self::new()
}
}
impl FilterRegistry {
pub fn new() -> Self {
let entries: Vec<FilterEntityRegistration> = super::filters::registrations();
let mut by_type_id = HashMap::with_capacity(entries.len());
for (i, reg) in entries.iter().enumerate() {
by_type_id.insert(reg.type_id, i);
}
FilterRegistry {
entries,
by_type_id,
}
}
pub fn get(&'static self, type_id: &str) -> Option<&'static FilterEntityRegistration> {
self.by_type_id.get(type_id).map(|&i| &self.entries[i])
}
pub fn all(&'static self) -> Vec<&'static FilterEntityRegistration> {
let mut v: Vec<_> = self.entries.iter().collect();
v.sort_by_key(|reg| reg.type_id);
v
}
}
pub fn registry() -> &'static FilterRegistry {
static REGISTRY: OnceLock<FilterRegistry> = OnceLock::new();
REGISTRY.get_or_init(FilterRegistry::new)
}
pub struct Filter {
pub id: LayerId,
pub common: NodeCommon,
pub kind: FilterKind,
}
pub enum FilterKind {
Mask(MaskFilter),
Selection(SelectionFilter),
}
impl Filter {
pub fn pixels(&self) -> Option<&PixelBuffer> {
match &self.kind {
FilterKind::Mask(m) => Some(&m.pixels),
FilterKind::Selection(s) => Some(&s.pixels),
}
}
pub fn pixels_mut(&mut self) -> Option<&mut PixelBuffer> {
match &mut self.kind {
FilterKind::Mask(m) => Some(&mut m.pixels),
FilterKind::Selection(s) => Some(&mut s.pixels),
}
}
pub fn kind_reg(&self) -> &'static FilterEntityRegistration {
self.kind.kind_reg()
}
pub fn type_id(&self) -> &'static str {
self.kind_reg().type_id
}
pub fn is_mask(&self) -> bool {
matches!(&self.kind, FilterKind::Mask(_))
}
pub fn as_selection(&self) -> Option<&SelectionFilter> {
match &self.kind {
FilterKind::Selection(s) => Some(s),
_ => None,
}
}
pub fn as_selection_mut(&mut self) -> Option<&mut SelectionFilter> {
match &mut self.kind {
FilterKind::Selection(s) => Some(s),
_ => None,
}
}
}
impl FilterKind {
pub fn mask_with_bounds(bounds: CanvasRect) -> Self {
FilterKind::Mask(MaskFilter::new(bounds))
}
pub fn selection_with_bounds(bounds: CanvasRect) -> Self {
FilterKind::Selection(SelectionFilter::new(bounds))
}
pub fn kind_reg(&self) -> &'static FilterEntityRegistration {
use super::filters::{mask, selection};
match self {
FilterKind::Mask(_) => registry().get(mask::TYPE_ID).unwrap(),
FilterKind::Selection(_) => registry().get(selection::TYPE_ID).unwrap(),
}
}
pub fn type_id(&self) -> &'static str {
self.kind_reg().type_id
}
}