Skip to content

Commit

Permalink
Added OKLAB graph
Browse files Browse the repository at this point in the history
Use alpha `0.1` when rgb value is outside SRGB (`OKLCH` graph)
Added `show_graphs` variable
  • Loading branch information
PixelDoted committed Jun 6, 2024
1 parent f177be9 commit 85f3ab3
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 47 deletions.
32 changes: 27 additions & 5 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use log::info;
pub struct ColorPicker {
pub spaces: Vec<ColorSpace>,
last_edited: usize,
show_graphs: bool,

colorspace_combo: widget::combo_box::State<ColorSpaceCombo>,
core: Core,
Expand Down Expand Up @@ -94,6 +95,7 @@ impl Application for ColorPicker {
let mut app = ColorPicker {
spaces: vec![ColorSpace::default()],
last_edited: 0,
show_graphs: true,

colorspace_combo: widget::combo_box::State::new(vec![
ColorSpaceCombo::Rgb,
Expand Down Expand Up @@ -163,11 +165,31 @@ impl Application for ColorPicker {

for (colorspace, index) in self.spaces.iter().zip(0..) {
let (rgb, content, combo_selection) = match colorspace {
ColorSpace::Rgb(rgb) => (rgb.to_rgb(), rgb.view(), ColorSpaceCombo::Rgb),
ColorSpace::Hsv(hsv) => (hsv.to_rgb(), hsv.view(), ColorSpaceCombo::Hsv),
ColorSpace::Oklab(oklab) => (oklab.to_rgb(), oklab.view(), ColorSpaceCombo::Oklab),
ColorSpace::Oklch(oklch) => (oklch.to_rgb(), oklch.view(), ColorSpaceCombo::Oklch),
ColorSpace::Cmyk(cmyk) => (cmyk.to_rgb(), cmyk.view(), ColorSpaceCombo::Cmyk),
ColorSpace::Rgb(rgb) => (
rgb.to_rgb(),
rgb.view(self.show_graphs),
ColorSpaceCombo::Rgb,
),
ColorSpace::Hsv(hsv) => (
hsv.to_rgb(),
hsv.view(self.show_graphs),
ColorSpaceCombo::Hsv,
),
ColorSpace::Oklab(oklab) => (
oklab.to_rgb(),
oklab.view(self.show_graphs),
ColorSpaceCombo::Oklab,
),
ColorSpace::Oklch(oklch) => (
oklch.to_rgb(),
oklch.view(self.show_graphs),
ColorSpaceCombo::Oklch,
),
ColorSpace::Cmyk(cmyk) => (
cmyk.to_rgb(),
cmyk.view(self.show_graphs),
ColorSpaceCombo::Cmyk,
),
};

let min_rgb = rgb[0].min(rgb[1]).min(rgb[2]).min(0.0);
Expand Down
2 changes: 1 addition & 1 deletion src/colorspace/cmyk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl Cmyk {
self.strings[index] = string;
}

pub fn view<'a>(&self) -> cosmic::Element<'a, Message> {
pub fn view<'a>(&self, _show_graphs: bool) -> cosmic::Element<'a, Message> {
let values = &self.values;
let strings = &self.strings;

Expand Down
13 changes: 8 additions & 5 deletions src/colorspace/hsv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl Hsv {
self.strings[index] = string;
}

pub fn view<'a>(&self) -> cosmic::Element<'a, Message> {
pub fn view<'a>(&self, show_graphs: bool) -> cosmic::Element<'a, Message> {
let values = &self.values;
let strings = &self.strings;

Expand Down Expand Up @@ -161,11 +161,14 @@ impl Hsv {
.spacing(10.0)
.padding(10.0);

let content = widget::column::with_capacity(3)
let mut content = widget::column::with_capacity(3)
.push(widget::container(red).style(cosmic::style::Container::Card))
.push(widget::container(green).style(cosmic::style::Container::Card))
.push(widget::container(blue).style(cosmic::style::Container::Card))
.push(
.spacing(10.0);

if show_graphs {
content = content.push(
widget::container(
widget::container(
cosmic::iced_widget::shader(shader::ColorGraph {
Expand All @@ -179,8 +182,8 @@ impl Hsv {
.padding(10.0),
)
.style(cosmic::style::Container::Card),
)
.spacing(10.0);
);
}

content.into()
}
Expand Down
41 changes: 35 additions & 6 deletions src/colorspace/oklab.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-only

use cosmic::{
iced::{gradient::ColorStop, Alignment, Color},
iced::{gradient::ColorStop, Alignment, Color, Length},
widget,
};

use crate::{colorspace::ColorSpaceMessage as Message, fl, widgets::color_slider};
use crate::{
colorspace::ColorSpaceMessage as Message, fl, shaders::oklab as shader, widgets::color_slider,
};

const COLOR_STOPS_LIGHTNESS: [ColorStop; 2] = [
ColorStop {
Expand Down Expand Up @@ -77,11 +79,11 @@ impl Oklab {
self.strings[index] = string;
}

pub fn view<'a>(&self) -> cosmic::Element<'a, Message> {
pub fn view<'a>(&self, show_graphs: bool) -> cosmic::Element<'a, Message> {
let values = &self.values;
let strings = &self.strings;

let lightness = widget::column::with_capacity(3)
let mut lightness = widget::column::with_capacity(3)
.push(
widget::row::with_capacity(2)
.push(widget::text(fl!("lightness")).size(20.0))
Expand All @@ -100,7 +102,7 @@ impl Oklab {
))
.spacing(10.0)
.padding(10.0);
let green_red = widget::column::with_capacity(3)
let mut green_red = widget::column::with_capacity(3)
.push(
widget::row::with_capacity(2)
.push(widget::text(fl!("green-red")).size(20.0))
Expand All @@ -119,7 +121,7 @@ impl Oklab {
))
.spacing(10.0)
.padding(10.0);
let blue_yellow = widget::column::with_capacity(3)
let mut blue_yellow = widget::column::with_capacity(3)
.push(
widget::row::with_capacity(2)
.push(widget::text(fl!("blue-yellow")).size(20.0))
Expand All @@ -139,6 +141,33 @@ impl Oklab {
.spacing(10.0)
.padding(10.0);

if show_graphs {
lightness = lightness.push(
cosmic::iced_widget::shader(shader::ColorGraph::<0> {
lightness: self.values[0],
green_red: self.values[1],
blue_yellow: self.values[2],
})
.width(Length::Fill),
);
green_red = green_red.push(
cosmic::iced_widget::shader(shader::ColorGraph::<1> {
lightness: self.values[0],
green_red: self.values[1],
blue_yellow: self.values[2],
})
.width(Length::Fill),
);
blue_yellow = blue_yellow.push(
cosmic::iced_widget::shader(shader::ColorGraph::<2> {
lightness: self.values[0],
green_red: self.values[1],
blue_yellow: self.values[2],
})
.width(Length::Fill),
);
}

let content = widget::column::with_capacity(3)
.push(widget::container(lightness).style(cosmic::style::Container::Card))
.push(widget::container(green_red).style(cosmic::style::Container::Card))
Expand Down
59 changes: 31 additions & 28 deletions src/colorspace/oklch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ impl Oklch {
self.strings[index] = string;
}

pub fn view<'a>(&self) -> cosmic::Element<'a, Message> {
pub fn view<'a>(&self, show_graphs: bool) -> cosmic::Element<'a, Message> {
let values = &self.values;
let strings = &self.strings;

let lightness = widget::column::with_capacity(3)
let mut lightness = widget::column::with_capacity(3)
.push(
widget::row::with_capacity(2)
.push(widget::text(fl!("lightness")).size(20.0))
Expand All @@ -114,14 +114,6 @@ impl Oklch {
.align_items(Alignment::Center)
.spacing(10.0),
)
.push(
cosmic::iced_widget::shader(shader::ColorGraph::<0> {
lightness: self.values[0],
chroma: self.values[1],
hue: self.values[2],
})
.width(Length::Fill),
)
.push(color_slider(
0f32..=1.0f32,
values[0],
Expand All @@ -130,7 +122,7 @@ impl Oklch {
))
.spacing(10.0)
.padding(10.0);
let chroma = widget::column::with_capacity(3)
let mut chroma = widget::column::with_capacity(3)
.push(
widget::row::with_capacity(2)
.push(widget::text(fl!("chroma")).size(20.0))
Expand All @@ -141,14 +133,6 @@ impl Oklch {
.align_items(Alignment::Center)
.spacing(10.0),
)
.push(
cosmic::iced_widget::shader(shader::ColorGraph::<1> {
lightness: self.values[0],
chroma: self.values[1],
hue: self.values[2],
})
.width(Length::Fill),
)
.push(color_slider(
0f32..=0.37f32,
values[1],
Expand All @@ -157,7 +141,7 @@ impl Oklch {
))
.spacing(10.0)
.padding(10.0);
let hue = widget::column::with_capacity(3)
let mut hue = widget::column::with_capacity(3)
.push(
widget::row::with_capacity(2)
.push(widget::text(fl!("hue")).size(20.0))
Expand All @@ -168,14 +152,6 @@ impl Oklch {
.align_items(Alignment::Center)
.spacing(10.0),
)
.push(
cosmic::iced_widget::shader(shader::ColorGraph::<2> {
lightness: self.values[0],
chroma: self.values[1],
hue: self.values[2],
})
.width(Length::Fill),
)
.push(color_slider(
0f32..=360f32,
values[2],
Expand All @@ -185,6 +161,33 @@ impl Oklch {
.spacing(10.0)
.padding(10.0);

if show_graphs {
lightness = lightness.push(
cosmic::iced_widget::shader(shader::ColorGraph::<0> {
lightness: self.values[0],
chroma: self.values[1],
hue: self.values[2],
})
.width(Length::Fill),
);
chroma = chroma.push(
cosmic::iced_widget::shader(shader::ColorGraph::<1> {
lightness: self.values[0],
chroma: self.values[1],
hue: self.values[2],
})
.width(Length::Fill),
);
hue = hue.push(
cosmic::iced_widget::shader(shader::ColorGraph::<2> {
lightness: self.values[0],
chroma: self.values[1],
hue: self.values[2],
})
.width(Length::Fill),
);
}

let content = widget::column::with_capacity(3)
.push(widget::container(lightness).style(cosmic::style::Container::Card))
.push(widget::container(chroma).style(cosmic::style::Container::Card))
Expand Down
2 changes: 1 addition & 1 deletion src/colorspace/rgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Rgb {
self.strings[index] = string;
}

pub fn view<'a>(&self) -> cosmic::Element<'a, Message> {
pub fn view<'a>(&self, _show_graphs: bool) -> cosmic::Element<'a, Message> {
let values = &self.values;
let strings = &self.strings;

Expand Down
1 change: 1 addition & 0 deletions src/shaders/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod hsv;
pub mod oklab;
pub mod oklch;

use std::marker::PhantomData;
Expand Down
88 changes: 88 additions & 0 deletions src/shaders/oklab.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use cosmic::iced_widget::shader::{self};

use crate::shaders::ShaderPipeline;

// ---- Shader ----
pub struct ColorGraph<const MODE: u32> {
pub lightness: f32,
pub green_red: f32,
pub blue_yellow: f32,
}

impl<const M: u32, Message> shader::Program<Message> for ColorGraph<M> {
type State = ();
type Primitive = Primitive<M>;

fn draw(
&self,
state: &Self::State,
cursor: cosmic::iced_core::mouse::Cursor,
bounds: cosmic::iced::Rectangle,
) -> Self::Primitive {
Primitive::<M>::new(self.lightness, self.green_red, self.blue_yellow)
}
}

#[derive(Debug)]
pub struct Primitive<const M: u32> {
uniforms: Uniforms,
}

impl<const M: u32> Primitive<M> {
pub fn new(lightness: f32, green_red: f32, blue_yellow: f32) -> Self {
Self {
uniforms: Uniforms {
lightness,
green_red,
blue_yellow,
mode: M,
},
}
}
}

impl<const M: u32> shader::Primitive for Primitive<M> {
fn prepare(
&self,
format: shader::wgpu::TextureFormat,
device: &shader::wgpu::Device,
queue: &shader::wgpu::Queue,
bounds: cosmic::iced::Rectangle,
target_size: cosmic::iced::Size<u32>,
scale_factor: f32,
storage: &mut shader::Storage,
) {
if !storage.has::<ShaderPipeline<Uniforms, M>>() {
storage.store(ShaderPipeline::<Uniforms, M>::new(
device,
queue,
format,
include_str!("oklab.wgsl"),
));
}

let pipeline = storage.get_mut::<ShaderPipeline<Uniforms, M>>().unwrap();
pipeline.write(queue, &self.uniforms);
}

fn render(
&self,
storage: &shader::Storage,
target: &shader::wgpu::TextureView,
target_size: cosmic::iced::Size<u32>,
viewport: cosmic::iced::Rectangle<u32>,
encoder: &mut shader::wgpu::CommandEncoder,
) {
let pipeline = storage.get::<ShaderPipeline<Uniforms, M>>().unwrap();
pipeline.render(target, encoder, viewport);
}
}

#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
#[repr(C)]
struct Uniforms {
lightness: f32,
green_red: f32,
blue_yellow: f32,
mode: u32,
}
Loading

0 comments on commit 85f3ab3

Please sign in to comment.