Repository: GraphiteEditor/Graphite
File: node-graph/gcore/src/raster/adjustments.rs (Rust)

Code before:
					.next()
					.map(|t| bezier.evaluate(TValue::Parametric(t.clamp(0., 1.))).y)
					// a very bad approximation if bezier_rs failes
					.unwrap_or_else(|| (x - x0) / (x3 - x0) * (y3 - y0) + y0)
			};
			lut[index] = _Channel::from_f64(y);
		}

		pos = sample.anchor;
		param = sample.handles[1];
	}
	ValueMapperNode::new(lut)
}

#[derive(Debug, Clone)]
pub struct ColorFillNode<C> {
	color: C,
}

#[node_macro::node_fn(ColorFillNode)]
pub fn color_fill_node(image_frame: ImageFrame<Color>, color: Color) -> ImageFrame<Color> {
	let target_width = (image_frame.transform.transform_vector2((1., 0.).into()).length() as usize).min(image_frame.image.width as usize);
	let target_height = (image_frame.transform.transform_vector2((0., 1.).into()).length() as usize).min(image_frame.image.height as usize);

	for mut pixel in &image_frame.image.data {
		pixel = &color;
	}

	ImageFrame {
		transform: image_frame.transform,
		image: image_frame.image,
	}
}

#[cfg(feature = "alloc")]
pub use index_node::IndexNode;

#[cfg(feature = "alloc")]
mod index_node {
	use crate::raster::{Color, ImageFrame};
	use crate::Node;

	#[derive(Debug)]
	pub struct IndexNode<Index> {
		pub index: Index,
	}

	#[node_macro::node_fn(IndexNode)]
	pub fn index_node(input: Vec<ImageFrame<Color>>, index: u32) -> ImageFrame<Color> {
		if (index as usize) < input.len() {
			input[index as usize].clone()

Review comment (suggestion):
This doesn't work how you might have expected it to because the `pixel` variable is a reference - a pointer to the location of the colour struct.

This code here changes the pixel variable so it points to a different colour struct (whilst the original colour remains the same). What you actually wanted to do was to modify the existing colour struct.

Code after:
		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 {
				bezier.find_tvalues_for_x(x)
					.next()
					.map(|t| bezier.evaluate(TValue::Parametric(t.clamp(0., 1.))).y)
					// Fall back to a very bad approximation if Bezier-rs fails
					.unwrap_or_else(|| (x - x0) / (x3 - x0) * (y3 - y0) + y0)
			};
			lut[index] = _Channel::from_f64(y);
		}

		pos = sample.anchor;
		param = sample.handles[1];
	}
	ValueMapperNode::new(lut)
}

#[derive(Debug, Clone)]
pub struct ColorFillNode<C> {
	color: C,
}

#[node_macro::node_fn(ColorFillNode)]
pub fn color_fill_node(mut image_frame: ImageFrame<Color>, color: Color) -> ImageFrame<Color> {
	for pixel in &mut image_frame.image.data {
		pixel.set_red(color.r());
		pixel.set_blue(color.b());
		pixel.set_green(color.g());
		pixel.alpha_multiply(color);
	}

	image_frame
}

pub struct ColorOverlayNode<Color, BlendMode, Opacity> {
	color: Color,
	blend_mode: BlendMode,
	opacity: Opacity,
}

#[node_macro::node_fn(ColorOverlayNode)]
pub fn color_overlay_node(mut image: ImageFrame<Color>, color: Color, blend_mode: BlendMode, opacity: f32) -> ImageFrame<Color> {
	let opacity = (opacity / 100.).clamp(0., 1.);
	for pixel in &mut image.image.data {