mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 06:38:03 +08:00
* Move the Subpath type to graphene-std * Add the transform subpath node * Delete selected nodes * Inserting node list on right click * Add several bitmap manipulator nodes * Convert add node to use f64 * Add posterize node * Rename names randomly * Fix naming * Exposure node * Fix typo * Adjust exposure node range * Comment out vector nodes * Adjust exposure range again * Posterise as ints * Rename input * Use >= in the to hsl function
110 lines
3.1 KiB
Rust
110 lines
3.1 KiB
Rust
use dyn_any::StaticType;
|
|
use dyn_any::{DynAny, Upcast};
|
|
use dyn_clone::DynClone;
|
|
use glam::DVec2;
|
|
use std::sync::Arc;
|
|
|
|
/// A type that is known, allowing serialization (serde::Deserialize is not object safe)
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
pub enum TaggedValue {
|
|
None,
|
|
String(String),
|
|
U32(u32),
|
|
F32(f32),
|
|
F64(f64),
|
|
Bool(bool),
|
|
DVec2(DVec2),
|
|
Image(graphene_std::raster::Image),
|
|
Color(graphene_core::raster::color::Color),
|
|
Subpath(graphene_std::vector::subpath::Subpath),
|
|
RcSubpath(Arc<graphene_std::vector::subpath::Subpath>),
|
|
}
|
|
|
|
impl TaggedValue {
|
|
pub fn to_value(self) -> Value {
|
|
match self {
|
|
TaggedValue::None => Box::new(()),
|
|
TaggedValue::String(x) => Box::new(x),
|
|
TaggedValue::U32(x) => Box::new(x),
|
|
TaggedValue::F32(x) => Box::new(x),
|
|
TaggedValue::F64(x) => Box::new(x),
|
|
TaggedValue::Bool(x) => Box::new(x),
|
|
TaggedValue::DVec2(x) => Box::new(x),
|
|
TaggedValue::Image(x) => Box::new(x),
|
|
TaggedValue::Color(x) => Box::new(x),
|
|
TaggedValue::Subpath(x) => Box::new(x),
|
|
TaggedValue::RcSubpath(x) => Box::new(x),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub type Value = Box<dyn ValueTrait>;
|
|
|
|
pub trait ValueTrait: DynAny<'static> + Upcast<dyn DynAny<'static>> + std::fmt::Debug + DynClone {}
|
|
|
|
pub trait IntoValue: Sized + ValueTrait + 'static {
|
|
fn into_any(self) -> Value {
|
|
Box::new(self)
|
|
}
|
|
}
|
|
|
|
impl<T: 'static + StaticType + Upcast<dyn DynAny<'static>> + std::fmt::Debug + PartialEq + Clone> ValueTrait for T {}
|
|
|
|
impl<T: 'static + ValueTrait> IntoValue for T {}
|
|
|
|
#[repr(C)]
|
|
pub(crate) struct Vtable {
|
|
pub(crate) destructor: unsafe fn(*mut ()),
|
|
pub(crate) size: usize,
|
|
pub(crate) align: usize,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub(crate) struct TraitObject {
|
|
pub(crate) self_ptr: *mut u8,
|
|
pub(crate) vtable: &'static Vtable,
|
|
}
|
|
|
|
impl PartialEq for Box<dyn ValueTrait> {
|
|
#[cfg_attr(miri, ignore)]
|
|
fn eq(&self, other: &Self) -> bool {
|
|
if self.type_id() != other.type_id() {
|
|
return false;
|
|
}
|
|
let self_trait_object = unsafe { std::mem::transmute::<&dyn ValueTrait, TraitObject>(self.as_ref()) };
|
|
let other_trait_object = unsafe { std::mem::transmute::<&dyn ValueTrait, TraitObject>(other.as_ref()) };
|
|
let size = self_trait_object.vtable.size;
|
|
let self_mem = unsafe { std::slice::from_raw_parts(self_trait_object.self_ptr, size) };
|
|
let other_mem = unsafe { std::slice::from_raw_parts(other_trait_object.self_ptr, size) };
|
|
self_mem == other_mem
|
|
}
|
|
}
|
|
|
|
impl Clone for Value {
|
|
fn clone(&self) -> Self {
|
|
let self_trait_object = unsafe { std::mem::transmute::<&dyn ValueTrait, TraitObject>(self.as_ref()) };
|
|
let size = self_trait_object.vtable.size;
|
|
let self_mem = unsafe { std::slice::from_raw_parts(self_trait_object.self_ptr, size) }.to_owned();
|
|
let ptr = Vec::leak(self_mem);
|
|
unsafe {
|
|
std::mem::transmute(TraitObject {
|
|
self_ptr: ptr as *mut [u8] as *mut u8,
|
|
vtable: self_trait_object.vtable,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_any_src() {
|
|
assert!(2_u32.into_any() == 2_u32.into_any());
|
|
assert!(2_u32.into_any() != 3_u32.into_any());
|
|
assert!(2_u32.into_any() != 3_i32.into_any());
|
|
}
|
|
}
|