From e9a12b34a561206905f0068c435d47411b980c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Thu, 26 Dec 2024 14:56:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E5=AE=8C=E6=88=90WASM?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=86=85=E5=AE=B9=E7=9A=84=E7=BC=96=E5=86=99?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- color-module/Cargo.toml | 8 ++ color-module/src/errors.rs | 14 ++++ color-module/src/lib.rs | 140 ++++++++++++++++++++++++++++++++ color-module/src/main.rs | 3 - color-module/tests/lib_tests.rs | 0 5 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 color-module/src/errors.rs create mode 100644 color-module/src/lib.rs delete mode 100644 color-module/src/main.rs create mode 100644 color-module/tests/lib_tests.rs diff --git a/color-module/Cargo.toml b/color-module/Cargo.toml index 01435fa..103012f 100644 --- a/color-module/Cargo.toml +++ b/color-module/Cargo.toml @@ -3,8 +3,16 @@ name = "color-module" version = "0.1.0" edition = "2021" +[lib] +crate-type = ["cdylib"] + [dependencies] color-name = "1.1.0" palette = { version = "0.7.6", features = ["serde"] } serde = { version = "1.0.216", features = ["derive"] } serde_json = "1.0.134" +thiserror = "2.0.9" +wasm-bindgen = { version = "0.2.99", features = ["serde", "serde_json", "serde-serialize"] } + +[dev-dependencies] +wasm-bindgen-test = "0.3.49" diff --git a/color-module/src/errors.rs b/color-module/src/errors.rs new file mode 100644 index 0000000..bdf88e3 --- /dev/null +++ b/color-module/src/errors.rs @@ -0,0 +1,14 @@ +use thiserror::Error; +use wasm_bindgen::JsValue; + +#[derive(Debug, Error)] +pub enum ColorError { + #[error("Invalid RGB value: {0}")] + UnrecogniazedRGB(String), +} + +impl Into for ColorError { + fn into(self) -> JsValue { + JsValue::from_str(&self.to_string()) + } +} diff --git a/color-module/src/lib.rs b/color-module/src/lib.rs new file mode 100644 index 0000000..701c62b --- /dev/null +++ b/color-module/src/lib.rs @@ -0,0 +1,140 @@ +use std::str::FromStr; + +use palette::{ + color_difference::Wcag21RelativeContrast, Darken, FromColor, Hsl, Lab, Lighten, Mix, Oklch, + ShiftHue, Srgb, +}; +use wasm_bindgen::prelude::*; + +mod errors; + +#[wasm_bindgen] +pub fn represent_hsl(color: &str) -> Result, errors::ColorError> { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let hsl = Hsl::from_color(origin_color); + Ok(Box::new([ + hsl.hue.into_positive_degrees(), + hsl.saturation, + hsl.lightness, + ])) +} + +#[wasm_bindgen] +pub fn represent_lab(color: &str) -> Result, errors::ColorError> { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let lab = Lab::from_color(origin_color); + Ok(Box::new([lab.l, lab.a, lab.b])) +} + +#[wasm_bindgen] +pub fn represent_oklch(color: &str) -> Result, errors::ColorError> { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let lch = Oklch::from_color(origin_color); + Ok(Box::new([ + lch.l, + lch.chroma, + lch.hue.into_positive_degrees(), + ])) +} + +#[wasm_bindgen] +pub fn shift_hue(color: &str, degree: f32) -> Result { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let hsl = Hsl::from_color(origin_color); + let shifted_color = hsl.shift_hue(degree); + let srgb = Srgb::from_color(shifted_color); + Ok(format!("{:x}", srgb.into_format::())) +} + +#[wasm_bindgen] +pub fn lighten(color: &str, percent: f32) -> Result { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let hsl = Hsl::from_color(origin_color); + let lightened_color = hsl.lighten(percent); + let srgb = Srgb::from_color(lightened_color); + Ok(format!("{:x}", srgb.into_format::())) +} + +#[wasm_bindgen] +pub fn lighten_absolute(color: &str, value: f32) -> Result { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let hsl = Hsl::from_color(origin_color); + let lightened_color = hsl.lighten_fixed(value); + let srgb = Srgb::from_color(lightened_color); + Ok(format!("{:x}", srgb.into_format::())) +} + +#[wasm_bindgen] +pub fn darken(color: &str, percent: f32) -> Result { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let hsl = Hsl::from_color(origin_color); + let darkened_color = hsl.darken(percent); + let srgb = Srgb::from_color(darkened_color); + Ok(format!("{:x}", srgb.into_format::())) +} + +#[wasm_bindgen] +pub fn darken_absolute(color: &str, value: f32) -> Result { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let hsl = Hsl::from_color(origin_color); + let darkened_color = hsl.darken_fixed(value); + let srgb = Srgb::from_color(darkened_color); + Ok(format!("{:x}", srgb.into_format::())) +} + +#[wasm_bindgen] +pub fn mix(color1: &str, color2: &str, percent: f32) -> Result { + let srgb1 = Srgb::from_str(color1) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color1.to_string()))? + .into_format::(); + let srgb2 = Srgb::from_str(color2) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color2.to_string()))? + .into_format::(); + let mixed_color = srgb1.mix(srgb2, percent); + Ok(format!("{:x}", mixed_color.into_format::())) +} + +#[wasm_bindgen] +pub fn tint(color: &str, percent: f32) -> Result { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let tinted_color = origin_color.mix(Srgb::new(1.0, 1.0, 1.0), percent); + Ok(format!("{:x}", tinted_color.into_format::())) +} + +#[wasm_bindgen] +pub fn shade(color: &str, percent: f32) -> Result { + let origin_color = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let shaded_color = origin_color.mix(Srgb::new(0.0, 0.0, 0.0), percent); + Ok(format!("{:x}", shaded_color.into_format::())) +} + +#[wasm_bindgen] +pub fn wacg_relative_contrast(fg_color: &str, bg_color: &str) -> Result { + let fg_srgb = Srgb::from_str(fg_color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(fg_color.to_string()))? + .into_format::(); + let bg_srgb = Srgb::from_str(bg_color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(bg_color.to_string()))? + .into_format::(); + Ok(fg_srgb.relative_contrast(bg_srgb)) +} diff --git a/color-module/src/main.rs b/color-module/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/color-module/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/color-module/tests/lib_tests.rs b/color-module/tests/lib_tests.rs new file mode 100644 index 0000000..e69de29