mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Remove dead code from the unused curves adjustment widget
This commit is contained in:
@@ -11,15 +11,6 @@ pub trait Linear {
|
||||
fn to_f32(self) -> f32;
|
||||
fn from_f64(x: f64) -> Self;
|
||||
fn to_f64(self) -> f64;
|
||||
fn lerp(self, other: Self, value: Self) -> Self
|
||||
where
|
||||
Self: Sized + Copy,
|
||||
Self: core::ops::Sub<Self, Output = Self>,
|
||||
Self: core::ops::Mul<Self, Output = Self>,
|
||||
Self: core::ops::Add<Self, Output = Self>,
|
||||
{
|
||||
self + (other - self) * value
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
@@ -174,10 +165,6 @@ pub trait Luminance {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LuminanceMut: Luminance {
|
||||
fn set_luminance(&mut self, luminance: Self::LuminanceChannel);
|
||||
}
|
||||
|
||||
// TODO: We might rename this to Raster at some point
|
||||
pub trait Sample {
|
||||
type Pixel: Pixel;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::color_traits::{Alpha, AlphaMut, AssociatedAlpha, Luminance, LuminanceMut, Pixel, RGB, RGBMut, Rec709Primaries, SRGB};
|
||||
use super::color_traits::{Alpha, AlphaMut, AssociatedAlpha, Luminance, Pixel, RGB, RGBMut, Rec709Primaries, SRGB};
|
||||
use super::discrete_srgb::{float_to_srgb_u8, srgb_u8_to_float};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use core::fmt::Debug;
|
||||
@@ -236,12 +236,6 @@ impl Luminance for Luma {
|
||||
}
|
||||
}
|
||||
|
||||
impl LuminanceMut for Luma {
|
||||
fn set_luminance(&mut self, luminance: Self::LuminanceChannel) {
|
||||
self.0 = luminance
|
||||
}
|
||||
}
|
||||
|
||||
impl RGB for Luma {
|
||||
type ColorChannel = f32;
|
||||
#[inline(always)]
|
||||
@@ -411,28 +405,6 @@ impl Luminance for Color {
|
||||
}
|
||||
}
|
||||
|
||||
impl LuminanceMut for Color {
|
||||
fn set_luminance(&mut self, luminance: f32) {
|
||||
let current = self.luminance();
|
||||
// When we have a black-ish color, we just set the color to a grey-scale value. This prohibits a divide-by-0.
|
||||
if current < f32::EPSILON {
|
||||
self.red = 0.2126 * luminance;
|
||||
self.green = 0.7152 * luminance;
|
||||
self.blue = 0.0722 * luminance;
|
||||
return;
|
||||
}
|
||||
let fac = luminance / current;
|
||||
// TODO: when we have for example the rgb color (0, 0, 1) and want to
|
||||
// TODO: do `.set_luminance(1)`, then the actual luminance is not 1 at
|
||||
// TODO: the end. With no clamp, the resulting color would be
|
||||
// TODO: (0, 0, 12.8504). The excess should be spread to the other
|
||||
// TODO: channels, but is currently just clamped away.
|
||||
self.red = (self.red * fac).clamp(0., 1.);
|
||||
self.green = (self.green * fac).clamp(0., 1.);
|
||||
self.blue = (self.blue * fac).clamp(0., 1.);
|
||||
}
|
||||
}
|
||||
|
||||
impl Rec709Primaries for Color {}
|
||||
impl SRGB for Color {}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::vector::algorithms::offset_subpath::MAX_ABSOLUTE_DIFFERENCE;
|
||||
use crate::vector::misc::{PointSpacingType, dvec2_to_point, point_to_dvec2};
|
||||
use core_types::math::polynomial::pathseg_to_parametric_polynomial;
|
||||
use glam::{DMat2, DVec2};
|
||||
use kurbo::common::{solve_cubic, solve_quadratic};
|
||||
use kurbo::{BezPath, CubicBez, DEFAULT_ACCURACY, Line, ParamCurve, ParamCurveArclen, ParamCurveDeriv, PathEl, PathSeg, Point, QuadBez, Rect, Shape, Vec2};
|
||||
use std::f64::consts::{FRAC_PI_2, PI};
|
||||
|
||||
@@ -201,39 +200,6 @@ pub fn pathseg_compute_lookup_table(segment: PathSeg, steps: Option<usize>, eucl
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns an `Iterator` containing all possible parametric `t`-values at the given `x`-coordinate.
|
||||
pub fn pathseg_find_tvalues_for_x(segment: PathSeg, x: f64) -> impl Iterator<Item = f64> + use<> {
|
||||
match segment {
|
||||
PathSeg::Line(Line { p0, p1 }) => {
|
||||
// If the transformed linear bezier is on the x-axis, `a` and `b` will both be zero and `solve_linear` will return no roots
|
||||
let a = p1.x - p0.x;
|
||||
let b = p0.x - x;
|
||||
|
||||
// Find the roots of the linear equation `ax + b`.
|
||||
// There exist roots when `a` is not 0
|
||||
if a.abs() > MAX_ABSOLUTE_DIFFERENCE { [Some(-b / a), None, None] } else { [None; 3] }
|
||||
}
|
||||
PathSeg::Quad(QuadBez { p0, p1, p2 }) => {
|
||||
let a = p2.x - 2. * p1.x + p0.x;
|
||||
let b = 2. * (p1.x - p0.x);
|
||||
let c = p0.x - x;
|
||||
let r = solve_quadratic(c, b, a);
|
||||
[r.first().copied(), r.get(1).copied(), None]
|
||||
}
|
||||
PathSeg::Cubic(CubicBez { p0, p1, p2, p3 }) => {
|
||||
let a = p3.x - 3. * p2.x + 3. * p1.x - p0.x;
|
||||
let b = 3. * (p2.x - 2. * p1.x + p0.x);
|
||||
let c = 3. * (p1.x - p0.x);
|
||||
let d = p0.x - x;
|
||||
let r = solve_cubic(d, c, b, a);
|
||||
[r.first().copied(), r.get(1).copied(), r.get(2).copied()]
|
||||
}
|
||||
}
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter(|&t| (0.0..1.).contains(&t))
|
||||
}
|
||||
|
||||
/// Find the `t`-value(s) such that the normal(s) at `t` pass through the specified point.
|
||||
pub fn pathseg_normals_to_point(segment: PathSeg, point: Point) -> Vec<f64> {
|
||||
// We solve deriv(t) dot (self(t) - point) = 0.
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
use core_types::Node;
|
||||
use core_types::color::{Channel, Linear, LuminanceMut};
|
||||
use dyn_any::{DynAny, StaticType, StaticTypeSized};
|
||||
use std::ops::{Add, Mul, Sub};
|
||||
|
||||
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
|
||||
#[derive(Debug, Clone, PartialEq, core_types::CacheHash, DynAny)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Curve {
|
||||
#[cfg_attr(feature = "serde", serde(rename = "manipulatorGroups"))]
|
||||
pub manipulator_groups: Vec<CurveManipulatorGroup>,
|
||||
#[cfg_attr(feature = "serde", serde(rename = "firstHandle"))]
|
||||
pub first_handle: [f32; 2],
|
||||
#[cfg_attr(feature = "serde", serde(rename = "lastHandle"))]
|
||||
pub last_handle: [f32; 2],
|
||||
}
|
||||
|
||||
impl Default for Curve {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
manipulator_groups: vec![],
|
||||
first_handle: [0.2; 2],
|
||||
last_handle: [0.8; 2],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, core_types::CacheHash, DynAny)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct CurveManipulatorGroup {
|
||||
pub anchor: [f32; 2],
|
||||
pub handles: [[f32; 2]; 2],
|
||||
}
|
||||
|
||||
pub struct ValueMapperNode<C> {
|
||||
lut: Vec<C>,
|
||||
}
|
||||
|
||||
unsafe impl<C: StaticTypeSized> StaticType for ValueMapperNode<C> {
|
||||
type Static = ValueMapperNode<C::Static>;
|
||||
}
|
||||
|
||||
impl<C> ValueMapperNode<C> {
|
||||
pub const fn new(lut: Vec<C>) -> Self {
|
||||
Self { lut }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i, L: LuminanceMut + 'i> Node<'i, L> for ValueMapperNode<L::LuminanceChannel>
|
||||
where
|
||||
L::LuminanceChannel: Linear + Copy,
|
||||
L::LuminanceChannel: Add<Output = L::LuminanceChannel>,
|
||||
L::LuminanceChannel: Sub<Output = L::LuminanceChannel>,
|
||||
L::LuminanceChannel: Mul<Output = L::LuminanceChannel>,
|
||||
{
|
||||
type Output = L;
|
||||
|
||||
fn eval(&'i self, mut val: L) -> L {
|
||||
let luminance: f32 = val.luminance().to_linear();
|
||||
let floating_sample_index = luminance * (self.lut.len() - 1) as f32;
|
||||
let index_in_lut = floating_sample_index.floor() as usize;
|
||||
let a = self.lut[index_in_lut];
|
||||
let b = self.lut[(index_in_lut + 1).clamp(0, self.lut.len() - 1)];
|
||||
let result = a.lerp(b, L::LuminanceChannel::from_linear(floating_sample_index.fract()));
|
||||
val.set_luminance(result);
|
||||
val
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
use crate::curve::{Curve, CurveManipulatorGroup, ValueMapperNode};
|
||||
use core_types::color::{Channel, Linear};
|
||||
use core_types::context::Ctx;
|
||||
use kurbo::{CubicBez, ParamCurve, PathSeg, Point};
|
||||
use vector_types::vector::algorithms::bezpath_algorithms::pathseg_find_tvalues_for_x;
|
||||
|
||||
const WINDOW_SIZE: usize = 1024;
|
||||
|
||||
#[node_macro::node(category(""))]
|
||||
fn generate_curves<C: Channel + Linear>(_: impl Ctx, curve: Curve, #[implementations(f32, f64)] _target_format: C) -> ValueMapperNode<C> {
|
||||
let [mut pos, mut param]: [[f32; 2]; 2] = [[0.; 2], curve.first_handle];
|
||||
let mut lut = vec![C::from_f64(0.); WINDOW_SIZE];
|
||||
let end = CurveManipulatorGroup {
|
||||
anchor: [1.; 2],
|
||||
handles: [curve.last_handle, [0.; 2]],
|
||||
};
|
||||
for sample in curve.manipulator_groups.iter().chain(std::iter::once(&end)) {
|
||||
let [x0, y0, x1, y1, x2, y2, x3, y3] = [pos[0], pos[1], param[0], param[1], sample.handles[0][0], sample.handles[0][1], sample.anchor[0], sample.anchor[1]].map(f64::from);
|
||||
|
||||
let segment = PathSeg::Cubic(CubicBez::new(Point::new(x0, y0), Point::new(x1, y1), Point::new(x2, y2), Point::new(x3, y3)));
|
||||
|
||||
let [left, right] = [pos[0], sample.anchor[0]].map(|c| c.clamp(0., 1.));
|
||||
let lut_index_left: usize = (left * (lut.len() - 1) as f32).floor() as _;
|
||||
let lut_index_right: usize = (right * (lut.len() - 1) as f32).ceil() as _;
|
||||
for index in lut_index_left..=lut_index_right {
|
||||
let x = index as f64 / (lut.len() - 1) as f64;
|
||||
let y = if x <= x0 {
|
||||
y0
|
||||
} else if x >= x3 {
|
||||
y3
|
||||
} else {
|
||||
pathseg_find_tvalues_for_x(segment, x)
|
||||
.next()
|
||||
.map(|t| segment.eval(t.clamp(0., 1.)).y)
|
||||
// Fall back to a very bad approximation if the above fails
|
||||
.unwrap_or_else(|| (x - x0) / (x3 - x0) * (y3 - y0) + y0)
|
||||
};
|
||||
lut[index] = C::from_f64(y);
|
||||
}
|
||||
|
||||
pos = sample.anchor;
|
||||
param = sample.handles[1];
|
||||
}
|
||||
ValueMapperNode::new(lut)
|
||||
}
|
||||
Reference in New Issue
Block a user