|
use crate::raster::Image; |
|
use crate::raster_types::{CPU, RasterDataTable}; |
|
use crate::registry::types::Percentage; |
|
use crate::vector::VectorDataTable; |
|
use crate::{BlendMode, Color, Ctx, GraphicElement, GraphicGroupTable}; |
|
|
|
pub(super) trait MultiplyAlpha { |
|
fn multiply_alpha(&mut self, factor: f64); |
|
} |
|
|
|
impl MultiplyAlpha for Color { |
|
fn multiply_alpha(&mut self, factor: f64) { |
|
*self = Color::from_rgbaf32_unchecked(self.r(), self.g(), self.b(), (self.a() * factor as f32).clamp(0., 1.)) |
|
} |
|
} |
|
impl MultiplyAlpha for VectorDataTable { |
|
fn multiply_alpha(&mut self, factor: f64) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.opacity *= factor as f32; |
|
} |
|
} |
|
} |
|
impl MultiplyAlpha for GraphicGroupTable { |
|
fn multiply_alpha(&mut self, factor: f64) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.opacity *= factor as f32; |
|
} |
|
} |
|
} |
|
impl MultiplyAlpha for RasterDataTable<CPU> |
|
where |
|
GraphicElement: From<Image<Color>>, |
|
{ |
|
fn multiply_alpha(&mut self, factor: f64) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.opacity *= factor as f32; |
|
} |
|
} |
|
} |
|
|
|
pub(super) trait MultiplyFill { |
|
fn multiply_fill(&mut self, factor: f64); |
|
} |
|
impl MultiplyFill for Color { |
|
fn multiply_fill(&mut self, factor: f64) { |
|
*self = Color::from_rgbaf32_unchecked(self.r(), self.g(), self.b(), (self.a() * factor as f32).clamp(0., 1.)) |
|
} |
|
} |
|
impl MultiplyFill for VectorDataTable { |
|
fn multiply_fill(&mut self, factor: f64) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.fill *= factor as f32; |
|
} |
|
} |
|
} |
|
impl MultiplyFill for GraphicGroupTable { |
|
fn multiply_fill(&mut self, factor: f64) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.fill *= factor as f32; |
|
} |
|
} |
|
} |
|
impl MultiplyFill for RasterDataTable<CPU> { |
|
fn multiply_fill(&mut self, factor: f64) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.fill *= factor as f32; |
|
} |
|
} |
|
} |
|
|
|
trait SetBlendMode { |
|
fn set_blend_mode(&mut self, blend_mode: BlendMode); |
|
} |
|
|
|
impl SetBlendMode for VectorDataTable { |
|
fn set_blend_mode(&mut self, blend_mode: BlendMode) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.blend_mode = blend_mode; |
|
} |
|
} |
|
} |
|
impl SetBlendMode for GraphicGroupTable { |
|
fn set_blend_mode(&mut self, blend_mode: BlendMode) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.blend_mode = blend_mode; |
|
} |
|
} |
|
} |
|
impl SetBlendMode for RasterDataTable<CPU> { |
|
fn set_blend_mode(&mut self, blend_mode: BlendMode) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.blend_mode = blend_mode; |
|
} |
|
} |
|
} |
|
|
|
trait SetClip { |
|
fn set_clip(&mut self, clip: bool); |
|
} |
|
|
|
impl SetClip for VectorDataTable { |
|
fn set_clip(&mut self, clip: bool) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.clip = clip; |
|
} |
|
} |
|
} |
|
impl SetClip for GraphicGroupTable { |
|
fn set_clip(&mut self, clip: bool) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.clip = clip; |
|
} |
|
} |
|
} |
|
impl SetClip for RasterDataTable<CPU> { |
|
fn set_clip(&mut self, clip: bool) { |
|
for instance in self.instance_mut_iter() { |
|
instance.alpha_blending.clip = clip; |
|
} |
|
} |
|
} |
|
|
|
#[node_macro::node(category("Style"))] |
|
fn blend_mode<T: SetBlendMode>( |
|
_: impl Ctx, |
|
#[implementations( |
|
GraphicGroupTable, |
|
VectorDataTable, |
|
RasterDataTable<CPU>, |
|
)] |
|
mut value: T, |
|
blend_mode: BlendMode, |
|
) -> T { |
|
|
|
value.set_blend_mode(blend_mode); |
|
value |
|
} |
|
|
|
#[node_macro::node(category("Style"))] |
|
fn opacity<T: MultiplyAlpha>( |
|
_: impl Ctx, |
|
#[implementations( |
|
GraphicGroupTable, |
|
VectorDataTable, |
|
RasterDataTable<CPU>, |
|
)] |
|
mut value: T, |
|
#[default(100.)] opacity: Percentage, |
|
) -> T { |
|
|
|
value.multiply_alpha(opacity / 100.); |
|
value |
|
} |
|
|
|
#[node_macro::node(category("Style"))] |
|
fn blending<T: SetBlendMode + MultiplyAlpha + MultiplyFill + SetClip>( |
|
_: impl Ctx, |
|
#[implementations( |
|
GraphicGroupTable, |
|
VectorDataTable, |
|
RasterDataTable<CPU>, |
|
)] |
|
mut value: T, |
|
blend_mode: BlendMode, |
|
#[default(100.)] opacity: Percentage, |
|
#[default(100.)] fill: Percentage, |
|
#[default(false)] clip: bool, |
|
) -> T { |
|
|
|
value.set_blend_mode(blend_mode); |
|
value.multiply_alpha(opacity / 100.); |
|
value.multiply_fill(fill / 100.); |
|
value.set_clip(clip); |
|
value |
|
} |
|
|