mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-20 03:18:06 +08:00
Improve type compatibility and clean up new node macro usages (#2002)
* Improve type compatibility * More
This commit is contained in:
@@ -19,6 +19,21 @@ use core::fmt::Debug;
|
||||
#[cfg(target_arch = "spirv")]
|
||||
use spirv_std::num_traits::float::Float;
|
||||
|
||||
// TODO: Implement the following:
|
||||
// Color Balance
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27blnc%27%20%3D%20Color%20Balance
|
||||
//
|
||||
// Photo Filter
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27phfl%27%20%3D%20Photo%20Filter
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=of%20the%20file.-,Photo%20Filter,-Key%20is%20%27phfl
|
||||
//
|
||||
// Color Lookup
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27clrL%27%20%3D%20Color%20Lookup
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Color%20Lookup%20(Photoshop%20CS6
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, DynAny, Hash)]
|
||||
@@ -268,10 +283,24 @@ impl From<BlendMode> for vello::peniko::Mix {
|
||||
}
|
||||
}
|
||||
|
||||
#[node_macro::node(category("Raster: Adjustment"))] // Unique to Graphite
|
||||
async fn luminance<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn luminance<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
input: impl Node<F, Output = T>,
|
||||
luminance_calc: LuminanceCalculation,
|
||||
) -> T {
|
||||
let mut input = input.eval(footprint).await;
|
||||
@@ -289,9 +318,23 @@ async fn luminance<T: Adjust<Color>>(
|
||||
}
|
||||
|
||||
#[node_macro::node(category("Raster"))]
|
||||
async fn extract_channel<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
|
||||
async fn extract_channel<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
input: impl Node<F, Output = T>,
|
||||
channel: RedGreenBlueAlpha,
|
||||
) -> T {
|
||||
let mut input = input.eval(footprint).await;
|
||||
@@ -308,7 +351,24 @@ async fn extract_channel<T: Adjust<Color>>(
|
||||
}
|
||||
|
||||
#[node_macro::node(category("Raster"))]
|
||||
async fn make_opaque<T: Adjust<Color>>(footprint: Footprint, #[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>) -> T {
|
||||
async fn make_opaque<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
input: impl Node<F, Output = T>,
|
||||
) -> T {
|
||||
let mut input = input.eval(footprint).await;
|
||||
input.adjust(|color| {
|
||||
if color.a() == 0. {
|
||||
@@ -319,11 +379,29 @@ async fn make_opaque<T: Adjust<Color>>(footprint: Footprint, #[implementations(F
|
||||
input
|
||||
}
|
||||
|
||||
// From https://stackoverflow.com/questions/39510072/algorithm-for-adjustment-of-image-levels
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27%20%3D%20Brightness/Contrast-,%27levl%27%20%3D%20Levels,-%27curv%27%20%3D%20Curves
|
||||
//
|
||||
// Algorithm from:
|
||||
// https://stackoverflow.com/questions/39510072/algorithm-for-adjustment-of-image-levels
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn levels<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
|
||||
async fn levels<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
image: impl Node<F, Output = T>,
|
||||
#[default(0.)] shadows: Percentage,
|
||||
#[default(50.)] midtones: Percentage,
|
||||
#[default(100.)] highlights: Percentage,
|
||||
@@ -376,13 +454,32 @@ async fn levels<T: Adjust<Color>>(
|
||||
input
|
||||
}
|
||||
|
||||
// From <https://stackoverflow.com/a/55233732/775283>
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27blwh%27%20%3D%20Black%20and%20White
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Black%20White%20(Photoshop%20CS3)
|
||||
//
|
||||
// Algorithm from:
|
||||
// https://stackoverflow.com/a/55233732/775283
|
||||
// Works the same for gamma and linear color
|
||||
#[node_macro::node(name("Black & White"), category("Raster: Adjustment"))]
|
||||
async fn black_and_white<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
|
||||
#[default(000000ff)] tint: Color,
|
||||
async fn black_and_white<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
image: impl Node<F, Output = T>,
|
||||
#[default(Color::BLACK)] tint: Color,
|
||||
#[default(40.)]
|
||||
#[range((-200., 300.))]
|
||||
reds: Percentage,
|
||||
@@ -443,10 +540,27 @@ async fn black_and_white<T: Adjust<Color>>(
|
||||
input
|
||||
}
|
||||
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27hue%20%27%20%3D%20Old,saturation%2C%20Photoshop%205.0
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=0%20%3D%20Use%20other.-,Hue/Saturation,-Hue/Saturation%20settings
|
||||
#[node_macro::node(name("Hue/Saturation"), category("Raster: Adjustment"))]
|
||||
async fn hue_saturation<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
|
||||
async fn hue_saturation<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
input: impl Node<F, Output = T>,
|
||||
hue_shift: Angle,
|
||||
saturation_shift: SignedPercentage,
|
||||
lightness_shift: SignedPercentage,
|
||||
@@ -471,8 +585,27 @@ async fn hue_saturation<T: Adjust<Color>>(
|
||||
input
|
||||
}
|
||||
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27%20%3D%20Color%20Lookup-,%27nvrt%27%20%3D%20Invert,-%27post%27%20%3D%20Posterize
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn invert<T: Adjust<Color>>(footprint: Footprint, #[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>) -> T {
|
||||
async fn invert<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
input: impl Node<F, Output = T>,
|
||||
) -> T {
|
||||
let mut input = input.eval(footprint).await;
|
||||
input.adjust(|color| {
|
||||
let color = color.to_gamma_srgb();
|
||||
@@ -484,10 +617,26 @@ async fn invert<T: Adjust<Color>>(footprint: Footprint, #[implementations(Footpr
|
||||
input
|
||||
}
|
||||
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=post%27%20%3D%20Posterize-,%27thrs%27%20%3D%20Threshold,-%27grdm%27%20%3D%20Gradient
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn threshold<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
|
||||
async fn threshold<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
image: impl Node<F, Output = T>,
|
||||
#[default(50.)] min_luminance: Percentage,
|
||||
#[default(100.)] max_luminance: Percentage,
|
||||
luminance_calc: LuminanceCalculation,
|
||||
@@ -571,8 +720,14 @@ impl Blend<Color> for GradientStops {
|
||||
}
|
||||
|
||||
#[node_macro::node(category("Raster"))]
|
||||
async fn blend<F: 'n + Copy + Send, T: Blend<Color> + Send>(
|
||||
#[implementations((), (), (), Footprint)] footprint: F,
|
||||
async fn blend<F: 'n + Send + Copy, T: Blend<Color> + Send>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
@@ -689,9 +844,18 @@ pub fn blend_colors(foreground: Color, background: Color, blend_mode: BlendMode,
|
||||
background.alpha_blend(target_color.to_associated_alpha(opacity as f32))
|
||||
}
|
||||
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27grdm%27%20%3D%20Gradient%20Map
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Gradient%20settings%20(Photoshop%206.0)
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn gradient_map<F: 'n + Copy + Send, T: Adjust<Color>>(
|
||||
#[implementations((), (), (), Footprint)] footprint: F,
|
||||
async fn gradient_map<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
@@ -715,12 +879,31 @@ async fn gradient_map<F: 'n + Copy + Send, T: Adjust<Color>>(
|
||||
input
|
||||
}
|
||||
|
||||
// Based on <https://stackoverflow.com/questions/33966121/what-is-the-algorithm-for-vibrance-filters>
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27-,vibA%27%20%3D%20Vibrance,-%27hue%20%27%20%3D%20Old
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Vibrance%20(Photoshop%20CS3)
|
||||
//
|
||||
// Algorithm based on:
|
||||
// https://stackoverflow.com/questions/33966121/what-is-the-algorithm-for-vibrance-filters
|
||||
// The results of this implementation are very close to correct, but not quite perfect
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn vibrance<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
|
||||
async fn vibrance<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
image: impl Node<F, Output = T>,
|
||||
vibrance: SignedPercentage,
|
||||
) -> T {
|
||||
let mut input = image.eval(footprint).await;
|
||||
@@ -1000,10 +1183,27 @@ impl DomainWarpType {
|
||||
}
|
||||
}
|
||||
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27mixr%27%20%3D%20Channel%20Mixer
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Lab%20color%20only-,Channel%20Mixer,-Key%20is%20%27mixr
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn channel_mixer<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
|
||||
async fn channel_mixer<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
image: impl Node<F, Output = T>,
|
||||
|
||||
monochrome: bool,
|
||||
#[default(40.)]
|
||||
@@ -1141,11 +1341,30 @@ impl core::fmt::Display for SelectiveColorChoice {
|
||||
}
|
||||
}
|
||||
|
||||
// Based on https://blog.pkh.me/p/22-understanding-selective-coloring-in-adobe-photoshop.html
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27selc%27%20%3D%20Selective%20color
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=from%20%2D100...100.%20.-,Selective%20Color,-Selective%20Color%20settings
|
||||
//
|
||||
// Algorithm based on:
|
||||
// https://blog.pkh.me/p/22-understanding-selective-coloring-in-adobe-photoshop.html
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn selective_color<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] image: impl Node<Footprint, Output = T>,
|
||||
async fn selective_color<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
image: impl Node<F, Output = T>,
|
||||
mode: RelativeAbsolute,
|
||||
#[name("(Reds) Cyan")] r_c: f64,
|
||||
#[name("(Reds) Magenta")] r_m: f64,
|
||||
@@ -1288,12 +1507,30 @@ impl<P: Pixel> MultiplyAlpha for ImageFrame<P> {
|
||||
}
|
||||
}
|
||||
|
||||
// Based on https://www.axiomx.com/posterize.htm
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=nvrt%27%20%3D%20Invert-,%27post%27%20%3D%20Posterize,-%27thrs%27%20%3D%20Threshold
|
||||
//
|
||||
// Algorithm based on:
|
||||
// https://www.axiomx.com/posterize.htm
|
||||
// This algorithm produces fully accurate output in relation to the industry standard.
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn posterize<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
|
||||
async fn posterize<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
input: impl Node<F, Output = T>,
|
||||
#[default(4)]
|
||||
#[min(2.)]
|
||||
levels: u32,
|
||||
@@ -1313,11 +1550,30 @@ async fn posterize<T: Adjust<Color>>(
|
||||
input
|
||||
}
|
||||
|
||||
// Based on https://geraldbakker.nl/psnumbers/exposure.html
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=curv%27%20%3D%20Curves-,%27expA%27%20%3D%20Exposure,-%27vibA%27%20%3D%20Vibrance
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Flag%20(%20%3D%20128%20)-,Exposure,-Key%20is%20%27expA
|
||||
//
|
||||
// Algorithm based on:
|
||||
// https://geraldbakker.nl/psnumbers/exposure.html
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn exposure<T: Adjust<Color>>(
|
||||
footprint: Footprint,
|
||||
#[implementations(Footprint -> Color, Footprint -> ImageFrame<Color>)] input: impl Node<Footprint, Output = T>,
|
||||
async fn exposure<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
() -> GradientStops,
|
||||
Footprint -> Color,
|
||||
Footprint -> ImageFrame<Color>,
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
input: impl Node<F, Output = T>,
|
||||
exposure: f64,
|
||||
offset: f64,
|
||||
#[default(1.)]
|
||||
@@ -1343,7 +1599,7 @@ const WINDOW_SIZE: usize = 1024;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[node_macro::node(category(""))]
|
||||
fn generate_curves<C: Channel + super::Linear>(_: (), curve: Curve, #[implementations(f32)] _target_format: C) -> ValueMapperNode<C> {
|
||||
fn generate_curves<C: Channel + super::Linear>(_: (), curve: Curve, #[implementations(f32, f64)] _target_format: C) -> ValueMapperNode<C> {
|
||||
use bezier_rs::{Bezier, TValue};
|
||||
|
||||
let [mut pos, mut param]: [[f32; 2]; 2] = [[0.; 2], curve.first_handle];
|
||||
@@ -1383,9 +1639,15 @@ fn generate_curves<C: Channel + super::Linear>(_: (), curve: Curve, #[implementa
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[node_macro::node(category("Raster: Adjustment"))] // Unique to Graphite
|
||||
async fn color_overlay<F: 'n + Copy + Send, T: Adjust<Color>>(
|
||||
#[implementations((), (), (), Footprint)] footprint: F,
|
||||
#[node_macro::node(category("Raster: Adjustment"))]
|
||||
async fn color_overlay<F: 'n + Send, T: Adjust<Color>>(
|
||||
#[implementations(
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
Footprint,
|
||||
)]
|
||||
footprint: F,
|
||||
#[implementations(
|
||||
() -> Color,
|
||||
() -> ImageFrame<Color>,
|
||||
@@ -1395,7 +1657,7 @@ async fn color_overlay<F: 'n + Copy + Send, T: Adjust<Color>>(
|
||||
Footprint -> GradientStops,
|
||||
)]
|
||||
image: impl Node<F, Output = T>,
|
||||
#[default(000000ff)] color: Color,
|
||||
#[default(Color::BLACK)] color: Color,
|
||||
blend_mode: BlendMode,
|
||||
#[default(100.)] opacity: Percentage,
|
||||
) -> T {
|
||||
|
||||
Reference in New Issue
Block a user